From e128c8cbde63ae42329943adf3a7265b193656a4 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Fri, 10 Jun 2022 10:47:38 +0200 Subject: [PATCH 01/94] CppEditor: Fix looking up containing function for search result - Move look-up to CplusPlus::FindUsages, where we are guaranteed that we actually have the document source. - Use the same straightforward algorithm as with clangd. - Undo the changes to CppDocument::functionAt(), which broke the autotest. Amends 6f7e7980d2b604c79507f9165098f783db8ab2e3. Change-Id: I008d05ba41a3b63b71e3131d7021e0d4e7d0641f Reviewed-by: Qt CI Bot Reviewed-by: Christian Stenger --- src/libs/cplusplus/CppDocument.cpp | 90 +++------------------ src/libs/cplusplus/FindUsages.cpp | 21 ++++- src/libs/cplusplus/FindUsages.h | 8 +- src/plugins/cppeditor/cppfindreferences.cpp | 36 +-------- 4 files changed, 37 insertions(+), 118 deletions(-) diff --git a/src/libs/cplusplus/CppDocument.cpp b/src/libs/cplusplus/CppDocument.cpp index 60144b23204..90660f2b554 100644 --- a/src/libs/cplusplus/CppDocument.cpp +++ b/src/libs/cplusplus/CppDocument.cpp @@ -96,86 +96,6 @@ protected: } }; -class ContainingFunctionAt: protected SymbolVisitor -{ - TranslationUnit *translationUnit; - Symbol *root; - int line; - int column; - Symbol *functionSymbol; - bool foundFunction; - bool foundBlock; - - bool scopeContains(Scope* scope, int line, int column){ - if (!scope) - return false; - - int scopeStartLine{-1}, scopeStartColumn{-1}, scopeEndLine{-1}, scopeEndColumn{-1}; - translationUnit->getPosition(scope->startOffset(), &scopeStartLine, &scopeStartColumn); - translationUnit->getPosition(scope->endOffset(), &scopeEndLine, &scopeEndColumn); - - if (line < scopeStartLine || line > scopeEndLine) - return false; - - if (line > scopeStartLine && line < scopeEndLine) - return true; - - if (scopeStartLine == line && column >= scopeStartColumn) - return true; - - if (scopeEndLine == line && column <= scopeEndColumn) - return true; - - return false; - } - -public: - ContainingFunctionAt(TranslationUnit *unit, Symbol *root) - : translationUnit(unit), root(root), line(0), column(0), functionSymbol(nullptr) - , foundFunction(false), foundBlock(false) {} - - Symbol *operator()(int line, int column) - { - this->line = line; - this->column = column; - this->functionSymbol = nullptr; - accept(root); - - return foundBlock ? functionSymbol : nullptr; - } - -protected: - bool preVisit(Symbol *s) final - { - if (foundBlock) - return false; - - if (foundFunction) { - auto block = s->asBlock(); - if (!block) - return true; - - if (scopeContains(block->asScope(), line, column)) { - foundBlock = true; - return false; - } - return true; - } - - auto asFunction = s->asFunction(); - if (asFunction) { - if (s->line() < line || (s->line() == line && s->column() <= column)) { - foundFunction = scopeContains(s->asScope(), line, column); - if (foundFunction) - functionSymbol = asFunction; - } - } - - return true; - } -}; - - class FindScopeAt: protected SymbolVisitor { TranslationUnit *_unit; @@ -592,11 +512,19 @@ QString Document::functionAt(int line, int column, int *lineOpeningDeclaratorPar if (line < 1 || column < 1) return QString(); - Symbol *symbol = ContainingFunctionAt{translationUnit(), globalNamespace()}(line, column); + Symbol *symbol = lastVisibleSymbolAt(line, column); if (!symbol) return QString(); + // Find the enclosing function scope (which might be several levels up, or we might be standing + // on it) Scope *scope = symbol->asScope(); + if (!scope) + scope = symbol->enclosingScope(); + + while (scope && !scope->isFunction() ) + scope = scope->enclosingScope(); + if (!scope) return QString(); diff --git a/src/libs/cplusplus/FindUsages.cpp b/src/libs/cplusplus/FindUsages.cpp index df3f6f89f95..c82bbbf1fca 100644 --- a/src/libs/cplusplus/FindUsages.cpp +++ b/src/libs/cplusplus/FindUsages.cpp @@ -142,11 +142,30 @@ void FindUsages::reportResult(unsigned tokenIndex, const QList &cand const int len = tk.utf16chars(); const Usage u(Utils::FilePath::fromString(_doc->fileName()), lineText, - getType(line, col, tokenIndex), line, col - 1, len); + getContainingFunction(line, col), getType(line, col, tokenIndex), + line, col - 1, len); _usages.append(u); _references.append(tokenIndex); } +QString FindUsages::getContainingFunction(int line, int column) +{ + const QList astPath = ASTPath(_doc)(line, column); + bool hasBlock = false; + for (auto it = astPath.crbegin(); it != astPath.crend(); ++it) { + if (!hasBlock && (*it)->asCompoundStatement()) + hasBlock = true; + if (const auto func = (*it)->asFunctionDefinition()) { + if (!hasBlock) + return {}; + if (!func->symbol) + return {}; + return Overview().prettyName(func->symbol->name()); + } + } + return {}; +} + class FindUsages::GetUsageType { public: diff --git a/src/libs/cplusplus/FindUsages.h b/src/libs/cplusplus/FindUsages.h index 87d1cbaef52..1210a745dae 100644 --- a/src/libs/cplusplus/FindUsages.h +++ b/src/libs/cplusplus/FindUsages.h @@ -42,11 +42,14 @@ public: enum class Type { Declaration, Initialization, Read, Write, WritableRef, Other }; Usage() = default; - Usage(const Utils::FilePath &path, const QString &lineText, Type t, int line, int col, int len) - : path(path), lineText(lineText), type(t), line(line), col(col), len(len) {} + Usage(const Utils::FilePath &path, const QString &lineText, const QString &func, Type t, + int line, int col, int len) + : path(path), lineText(lineText), containingFunction(func), type(t), + line(line), col(col), len(len) {} Utils::FilePath path; QString lineText; + QString containingFunction; Type type = Type::Other; int line = 0; int col = 0; @@ -75,6 +78,7 @@ protected: void reportResult(unsigned tokenIndex, const Name *name, Scope *scope = nullptr); void reportResult(unsigned tokenIndex, const QList &candidates); Usage::Type getType(int line, int column, int tokenIndex); + QString getContainingFunction(int line, int column); bool checkCandidates(const QList &candidates) const; void checkExpression(unsigned startToken, unsigned endToken, Scope *scope = nullptr); diff --git a/src/plugins/cppeditor/cppfindreferences.cpp b/src/plugins/cppeditor/cppfindreferences.cpp index b5e88f1ccd7..44f40505d16 100644 --- a/src/plugins/cppeditor/cppfindreferences.cpp +++ b/src/plugins/cppeditor/cppfindreferences.cpp @@ -632,25 +632,6 @@ CPlusPlus::Symbol *CppFindReferences::findSymbol(const CppFindReferencesParamete return nullptr; } -Utils::optional getContainingFunctionName(const Utils::FilePath &fileName, - int line, - int column) -{ - const CPlusPlus::Snapshot snapshot = CppModelManager::instance()->snapshot(); - auto document = snapshot.document(fileName); - - // context properties need lookup inside function scope, and thus require a full check - CPlusPlus::Document::Ptr localDoc = document; - if (document->checkMode() != CPlusPlus::Document::FullCheck) { - localDoc = snapshot.documentFromSource(document->utf8Source(), document->fileName()); - localDoc->check(); - } - - auto funcName = localDoc->functionAt(line, column); - - return funcName.size() ? Utils::make_optional(funcName) : Utils::nullopt; -} - static void displayResults(SearchResult *search, QFutureWatcher *watcher, int first, @@ -665,24 +646,11 @@ static void displayResults(SearchResult *search, item.setMainRange(result.line, result.col, result.len); item.setLineText(result.lineText); item.setUserData(int(result.type)); + item.setContainingFunctionName(result.containingFunction); item.setStyle(colorStyleForUsageType(result.type)); item.setUseTextEditorFont(true); if (search->supportsReplace()) item.setSelectForReplacement(SessionManager::projectForFile(result.path)); - - // In case we're looking for a function, we need to look at the symbol near the end. This - // is needed to avoid following corner-cases: - // 1) if we're looking at the beginning of the function declaration, we can get the - // declaration of the previous function - // 2) if we're looking somewhere at the middle of the function declaration, we can still - // get the declaration of the previous function if the cursor is located at the - // namespace declaration, i.e. CppReference>|addResult(item); if (parameters.prettySymbolName.isEmpty()) @@ -777,7 +745,7 @@ restart_search: if (macro.name() == useMacro.name()) { unsigned column; const QString &lineSource = matchingLine(use.bytesBegin(), source, &column); - usages.append(CPlusPlus::Usage(fileName, lineSource, + usages.append(CPlusPlus::Usage(fileName, lineSource, {}, CPlusPlus::Usage::Type::Other, use.beginLine(), column, useMacro.nameToQString().size())); } From 4612a052f462be8cecb7977efc398010ddd92bf9 Mon Sep 17 00:00:00 2001 From: David Schulz Date: Mon, 13 Jun 2022 08:31:03 +0200 Subject: [PATCH 02/94] TextEditor: fix typo Change-Id: Ibad6729f5281a1b7036af7483a82eae7e22649a5 Reviewed-by: Christian Stenger --- src/plugins/texteditor/texteditorsettings.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/texteditor/texteditorsettings.cpp b/src/plugins/texteditor/texteditorsettings.cpp index 5a0df2d1de1..630fbd440a9 100644 --- a/src/plugins/texteditor/texteditorsettings.cpp +++ b/src/plugins/texteditor/texteditorsettings.cpp @@ -398,7 +398,7 @@ FormatDescriptions TextEditorSettingsPrivate::initialFormats() tr("Unreachable code."), FormatDescription::ShowAllControls); formatDescr.emplace_back(C_COCO_EXECUTION_COUNT_TOO_LOW, - tr("Code Coverage Execution Count To Low"), + tr("Code Coverage Execution Count Too Low"), tr("Minimum count not reached."), FormatDescription::ShowAllControls); formatDescr.emplace_back(C_COCO_NOT_COVERED_INFO, From 948f0070fabef91c721a32fd4c1f1e9c0087e4d4 Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Wed, 8 Jun 2022 16:00:13 +0200 Subject: [PATCH 03/94] macOS: Fix importing command line builds with CMake When configuring a CMake project on the command line, CMake will (correctly) find and use the compiler from the current developer directory, usually somewhere in /Applications/Xcode.app/Contents/Developer But Qt Creator auto-detects and sets up the compiler /usr/bin/clang(++) for desktop kits. This leads to a compiler mismatch between kits and the imported build, and to new kits registered in Qt Creator for the import. Since /usr/bin/clang(++) is just a thin wrapper that resolves to the compiler in the current developer directory, resolve that in Qt Creator with "xcrun -f " too (caching the result), and include that when comparing toolchains for importing builds. Fixes: QTCREATORBUG-27591 Change-Id: I301e2a4e267450b488b49d0c32d4ce89001bb5ec Reviewed-by: Reviewed-by: Qt CI Bot Reviewed-by: Mitch Curtis Reviewed-by: Christian Stenger Reviewed-by: Cristian Adam --- .../cmakeprojectimporter.cpp | 5 +---- src/plugins/projectexplorer/gcctoolchain.cpp | 21 +++++++++++++++++++ src/plugins/projectexplorer/gcctoolchain.h | 8 +++++++ .../projectexplorer/projectimporter.cpp | 4 +--- src/plugins/projectexplorer/toolchain.cpp | 5 +++++ src/plugins/projectexplorer/toolchain.h | 3 +++ .../qmakeprojectmanager/qmakeproject.cpp | 2 +- 7 files changed, 40 insertions(+), 8 deletions(-) diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectimporter.cpp b/src/plugins/cmakeprojectmanager/cmakeprojectimporter.cpp index 59f1d3796b0..e4e9ef90598 100644 --- a/src/plugins/cmakeprojectmanager/cmakeprojectimporter.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeprojectimporter.cpp @@ -394,10 +394,7 @@ bool CMakeProjectImporter::matchKit(void *directoryData, const Kit *k) const if (!Utils::contains(allLanguages, [&tcd](const Id& language) {return language == tcd.language;})) continue; ToolChain *tc = ToolChainKitAspect::toolChain(k, tcd.language); - if (!tc - || !Utils::Environment::systemEnvironment() - .isSameExecutable(tc->compilerCommand().toString(), - tcd.compilerPath.toString())) { + if (!tc || !tc->matchesCompilerCommand(tcd.compilerPath)) { return false; } } diff --git a/src/plugins/projectexplorer/gcctoolchain.cpp b/src/plugins/projectexplorer/gcctoolchain.cpp index 168062d154f..355ff2d7fc6 100644 --- a/src/plugins/projectexplorer/gcctoolchain.cpp +++ b/src/plugins/projectexplorer/gcctoolchain.cpp @@ -1580,6 +1580,27 @@ ClangToolChain::~ClangToolChain() QObject::disconnect(m_mingwToolchainAddedConnection); } +bool ClangToolChain::matchesCompilerCommand(const Utils::FilePath &command, + const Utils::Environment &env) const +{ + if (!m_resolvedCompilerCommand) { + m_resolvedCompilerCommand = FilePath(); + if (HostOsInfo::isMacHost() + && compilerCommand().parentDir() == FilePath::fromString("/usr/bin")) { + std::unique_ptr xcrun(new QtcProcess); + xcrun->setCommand({"/usr/bin/xcrun", {"-f", compilerCommand().fileName()}}); + xcrun->runBlocking(); + const FilePath output = FilePath::fromString(xcrun->stdOut().trimmed()); + if (output.isExecutableFile() && output != compilerCommand()) + m_resolvedCompilerCommand = output; + } + } + if (!m_resolvedCompilerCommand->isEmpty() + && env.isSameExecutable(m_resolvedCompilerCommand->toString(), command.toString())) + return true; + return GccToolChain::matchesCompilerCommand(command, env); +} + static FilePath mingwAwareMakeCommand(const Environment &environment) { const QStringList makes diff --git a/src/plugins/projectexplorer/gcctoolchain.h b/src/plugins/projectexplorer/gcctoolchain.h index 7bd83d0a1b2..bad26674e23 100644 --- a/src/plugins/projectexplorer/gcctoolchain.h +++ b/src/plugins/projectexplorer/gcctoolchain.h @@ -33,6 +33,7 @@ #include "headerpath.h" #include +#include #include #include @@ -211,6 +212,10 @@ public: explicit ClangToolChain(Utils::Id typeId); ~ClangToolChain() override; + bool matchesCompilerCommand( + const Utils::FilePath &command, + const Utils::Environment &env = Utils::Environment::systemEnvironment()) const override; + Utils::FilePath makeCommand(const Utils::Environment &environment) const override; Utils::LanguageExtensions languageExtensions(const QStringList &cxxflags) const override; @@ -237,6 +242,9 @@ protected: void syncAutodetectedWithParentToolchains(); private: + // "resolved" on macOS from /usr/bin/clang(++) etc to /usr/bin/clang(++) + // which is used for comparison with matchesCompileCommand + mutable Utils::optional m_resolvedCompilerCommand; QByteArray m_parentToolChainId; QMetaObject::Connection m_mingwToolchainAddedConnection; QMetaObject::Connection m_thisToolchainRemovedConnection; diff --git a/src/plugins/projectexplorer/projectimporter.cpp b/src/plugins/projectexplorer/projectimporter.cpp index 2db6dafa2b6..e51aaa2c968 100644 --- a/src/plugins/projectexplorer/projectimporter.cpp +++ b/src/plugins/projectexplorer/projectimporter.cpp @@ -414,9 +414,7 @@ ProjectImporter::findOrCreateToolChains(const ToolChainDescription &tcd) const { ToolChainData result; result.tcs = ToolChainManager::toolchains([&tcd](const ToolChain *tc) { - return tc->language() == tcd.language && - Utils::Environment::systemEnvironment().isSameExecutable( - tc->compilerCommand().toString(), tcd.compilerPath.toString()); + return tc->language() == tcd.language && tc->matchesCompilerCommand(tcd.compilerPath); }); for (const ToolChain *tc : qAsConst(result.tcs)) { const QByteArray tcId = tc->id(); diff --git a/src/plugins/projectexplorer/toolchain.cpp b/src/plugins/projectexplorer/toolchain.cpp index f36ce9414b6..32d39fc0806 100644 --- a/src/plugins/projectexplorer/toolchain.cpp +++ b/src/plugins/projectexplorer/toolchain.cpp @@ -343,6 +343,11 @@ void ToolChain::setCompilerCommand(const FilePath &command) toolChainUpdated(); } +bool ToolChain::matchesCompilerCommand(const Utils::FilePath &command, const Environment &env) const +{ + return env.isSameExecutable(compilerCommand().toString(), command.toString()); +} + void ToolChain::setCompilerCommandKey(const QString &commandKey) { d->m_compilerCommandKey = commandKey; diff --git a/src/plugins/projectexplorer/toolchain.h b/src/plugins/projectexplorer/toolchain.h index 2e41313f2ec..6a3ced00535 100644 --- a/src/plugins/projectexplorer/toolchain.h +++ b/src/plugins/projectexplorer/toolchain.h @@ -156,6 +156,9 @@ public: virtual Utils::FilePath compilerCommand() const; // FIXME: De-virtualize. void setCompilerCommand(const Utils::FilePath &command); + virtual bool matchesCompilerCommand( + const Utils::FilePath &command, + const Utils::Environment &env = Utils::Environment::systemEnvironment()) const; virtual QList createOutputParsers() const = 0; diff --git a/src/plugins/qmakeprojectmanager/qmakeproject.cpp b/src/plugins/qmakeprojectmanager/qmakeproject.cpp index c77f468ae23..bff8df79024 100644 --- a/src/plugins/qmakeprojectmanager/qmakeproject.cpp +++ b/src/plugins/qmakeprojectmanager/qmakeproject.cpp @@ -1390,7 +1390,7 @@ void QmakeBuildSystem::testToolChain(ToolChain *tc, const FilePath &path) const const Utils::FilePath expected = tc->compilerCommand(); Environment env = buildConfiguration()->environment(); - if (env.isSameExecutable(path.toString(), expected.toString())) + if (tc->matchesCompilerCommand(expected, env)) return; const QPair pair = qMakePair(expected, path); if (m_toolChainWarnings.contains(pair)) From a760d5ad818df2564b76e53f7e49501329c31f7b Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Tue, 7 Jun 2022 10:18:34 +0200 Subject: [PATCH 04/94] CMake: Make QML debugging state reflect build system state After parsing the CMake response, we make the configuration variables table reflect the actual configuration in the build directory. It is one of our "promises" that we do not break an existing build configuration, to avoid unexpected rebuilds. This was not quite true for the "QML debugging and profiling" setting. When that setting and the actual build directory disagreed, the user would get a dialog asking for running CMake with additional parameters, and when running CMake via the button in projects mode or the menu, it would just change these configuration parameters, potentially leading to an unexpected complete rebuild of the application. So, after parsing check if the actual CMake configuration matches our QML debugging setting, and if not, change the setting to "Leave at Default", to ensure that we don't mess with the build. Fix the "Run CMake" button state (in the "Current Configuration") when changing the QML debugging option, which should become bold, if the CMake parameters change. Amends 2577ce8ba1a69ad716c2fc2a5d0d5cc742c3c4cf and fixes the drawback mentioned there, i.e. setting the build directory of a "Debug" build configuration to an existing build directory with QML debugging disabled, will now simply set the QML debugging option to "Leave at Default" instead of forcing it to "Enabled". Change-Id: Ie6d4875d59319687d94e44e459ca76038e5813c0 Reviewed-by: Qt CI Bot Reviewed-by: Christian Stenger Reviewed-by: Cristian Adam --- .../cmakebuildconfiguration.cpp | 24 +++++++++++++++++-- .../cmakebuildconfiguration.h | 1 + .../cmakeprojectimporter.cpp | 8 +------ 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp index e8ebeda2f66..66fa741c10b 100644 --- a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp +++ b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp @@ -379,7 +379,16 @@ CMakeBuildSettingsWidget::CMakeBuildSettingsWidget(CMakeBuildSystem *bs) : } connect(m_buildSystem, &BuildSystem::parsingFinished, this, [this] { - m_configModel->setConfiguration(m_buildSystem->configurationFromCMake()); + const CMakeConfig config = m_buildSystem->configurationFromCMake(); + auto qmlDebugAspect = m_buildSystem->buildConfiguration() + ->aspect(); + const TriState qmlDebugSetting = qmlDebugAspect->value(); + bool qmlDebugConfig = CMakeBuildConfiguration::hasQmlDebugging(config); + if ((qmlDebugSetting == TriState::Enabled && !qmlDebugConfig) + || (qmlDebugSetting == TriState::Disabled && qmlDebugConfig)) { + qmlDebugAspect->setValue(TriState::Default); + } + m_configModel->setConfiguration(config); m_configModel->setInitialParametersConfiguration( m_buildSystem->initialCMakeConfiguration()); m_buildSystem->filterConfigArgumentsFromAdditionalCMakeArguments(); @@ -738,7 +747,8 @@ void CMakeBuildSettingsWidget::updateButtonState() } else { m_reconfigureButton->setText(tr("Run CMake")); } - reconfigureButtonFont.setBold(m_configModel->hasChanges(isInitial)); + reconfigureButtonFont.setBold(isInitial ? m_configModel->hasChanges(isInitial) + : !configChanges.isEmpty()); } m_reconfigureButton->setFont(reconfigureButtonFont); @@ -1388,6 +1398,16 @@ bool CMakeBuildConfiguration::isIos(const Kit *k) || deviceType == Ios::Constants::IOS_SIMULATOR_TYPE; } +bool CMakeBuildConfiguration::hasQmlDebugging(const CMakeConfig &config) +{ + // Determine QML debugging flags. This must match what we do in + // CMakeBuildSettingsWidget::getQmlDebugCxxFlags() + // such that in doubt we leave the QML Debugging setting at "Leave at default" + const QString cxxFlagsInit = config.stringValueOf("CMAKE_CXX_FLAGS_INIT"); + const QString cxxFlags = config.stringValueOf("CMAKE_CXX_FLAGS"); + return cxxFlagsInit.contains("-DQT_QML_DEBUG") && cxxFlags.contains("-DQT_QML_DEBUG"); +} + void CMakeBuildConfiguration::buildTarget(const QString &buildTarget) { auto cmBs = qobject_cast(findOrDefault( diff --git a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.h b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.h index 3121cbcc6fe..bba266ca36a 100644 --- a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.h +++ b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.h @@ -55,6 +55,7 @@ public: shadowBuildDirectory(const Utils::FilePath &projectFilePath, const ProjectExplorer::Kit *k, const QString &bcName, BuildConfiguration::BuildType buildType); static bool isIos(const ProjectExplorer::Kit *k); + static bool hasQmlDebugging(const CMakeConfig &config); // Context menu action: void buildTarget(const QString &buildTarget); diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectimporter.cpp b/src/plugins/cmakeprojectmanager/cmakeprojectimporter.cpp index e4e9ef90598..ae970887fb7 100644 --- a/src/plugins/cmakeprojectmanager/cmakeprojectimporter.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeprojectimporter.cpp @@ -337,13 +337,7 @@ QList CMakeProjectImporter::examineDirectory(const FilePath &importPath, canonicalProjectDirectory.toUserOutput()); } - // Determine QML debugging flags. This must match what we do in - // CMakeBuildSettingsWidget::getQmlDebugCxxFlags() - // such that in doubt we leave the QML Debugging setting at "Leave at default" - const QString cxxFlagsInit = config.stringValueOf("CMAKE_CXX_FLAGS_INIT"); - const QString cxxFlags = config.stringValueOf("CMAKE_CXX_FLAGS"); - data->hasQmlDebugging = cxxFlagsInit.contains("-DQT_QML_DEBUG") - && cxxFlags.contains("-DQT_QML_DEBUG"); + data->hasQmlDebugging = CMakeBuildConfiguration::hasQmlDebugging(config); data->buildDirectory = importPath; data->cmakeBuildType = buildType; From 9a411245d3f35c232be0affe4137e7a922101b8f Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Fri, 10 Jun 2022 12:28:49 +0200 Subject: [PATCH 05/94] qbs build: Require Qt 6.2 for QmlDesigner As in the cmake build. Change-Id: Iedd7032093682e7cf6f423909724201f6c5840d0 Reviewed-by: Christian Stenger --- .../assetexporterplugin/assetexporterplugin.qbs | 3 ++- .../qmldesigner/componentsplugin/componentsplugin.qbs | 3 ++- src/plugins/qmldesigner/qmldesignerplugin.qbs | 7 +++---- .../qmldesigner/qmlpreviewplugin/qmlpreviewplugin.qbs | 3 ++- src/plugins/studiowelcome/studiowelcome.qbs | 3 ++- tests/unit/unittest/unittest.qbs | 5 +++-- 6 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/plugins/qmldesigner/assetexporterplugin/assetexporterplugin.qbs b/src/plugins/qmldesigner/assetexporterplugin/assetexporterplugin.qbs index 031b0977bc5..a8bc03685f3 100644 --- a/src/plugins/qmldesigner/assetexporterplugin/assetexporterplugin.qbs +++ b/src/plugins/qmldesigner/assetexporterplugin/assetexporterplugin.qbs @@ -2,13 +2,14 @@ import qbs QtcProduct { name: "assetexporterplugin" + condition: QmlDesigner.present type: ["dynamiclibrary"] installDir: qtc.ide_plugin_path + '/' + installDirName property string installDirName: qbs.targetOS.contains("macos") ? "QmlDesigner" : "qmldesigner" Depends { name: "Core" } Depends { name: "ProjectExplorer" } - Depends { name: "QmlDesigner" } + Depends { name: "QmlDesigner"; required: false } Depends { name: "Utils" } Depends { name: "Qt" diff --git a/src/plugins/qmldesigner/componentsplugin/componentsplugin.qbs b/src/plugins/qmldesigner/componentsplugin/componentsplugin.qbs index 84adc2b5304..520e533af5b 100644 --- a/src/plugins/qmldesigner/componentsplugin/componentsplugin.qbs +++ b/src/plugins/qmldesigner/componentsplugin/componentsplugin.qbs @@ -2,12 +2,13 @@ import qbs QtcProduct { name: "componentsplugin" + condition: QmlDesigner.present type: ["dynamiclibrary"] installDir: qtc.ide_plugin_path + '/' + installDirName property string installDirName: qbs.targetOS.contains("macos") ? "QmlDesigner" : "qmldesigner" Depends { name: "Core" } - Depends { name: "QmlDesigner" } + Depends { name: "QmlDesigner"; required: false } Depends { name: "Utils" } Depends { name: "Qt.qml" } diff --git a/src/plugins/qmldesigner/qmldesignerplugin.qbs b/src/plugins/qmldesigner/qmldesignerplugin.qbs index 0ea3b5008a1..7b8ef977751 100644 --- a/src/plugins/qmldesigner/qmldesignerplugin.qbs +++ b/src/plugins/qmldesigner/qmldesignerplugin.qbs @@ -5,13 +5,12 @@ Project { name: "QmlDesigner" QtcPlugin { + condition: Qt.quickwidgets.present && Qt.svg.present fileName: FileInfo.fileName(filePath) Depends { - name: "Qt"; - submodules: [ - "core-private", "quickwidgets", "xml", "svg" - ] + name: "Qt"; versionAtLeast: "6.2"; required: false + submodules: ["core-private", "quickwidgets", "xml", "svg"] } Depends { name: "AdvancedDockingSystem" } Depends { name: "Core" } diff --git a/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.qbs b/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.qbs index 8e48e6aa850..05e809d4331 100644 --- a/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.qbs +++ b/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.qbs @@ -2,6 +2,7 @@ import qbs QtcProduct { name: "qmlpreviewplugin" + condition: QmlDesigner.present type: ["dynamiclibrary"] installDir: qtc.ide_plugin_path + '/' + installDirName property string installDirName: qbs.targetOS.contains("macos") ? "QmlDesigner" : "qmldesigner" @@ -15,7 +16,7 @@ QtcProduct { Depends { name: "Core" } Depends { name: "ProjectExplorer" } - Depends { name: "QmlDesigner" } + Depends { name: "QmlDesigner"; required: false } Depends { name: "Qt.qml" } Depends { name: "Utils" } diff --git a/src/plugins/studiowelcome/studiowelcome.qbs b/src/plugins/studiowelcome/studiowelcome.qbs index 4c82c8112ec..7d254824ba5 100644 --- a/src/plugins/studiowelcome/studiowelcome.qbs +++ b/src/plugins/studiowelcome/studiowelcome.qbs @@ -2,6 +2,7 @@ import qbs.FileInfo QtcPlugin { name: "StudioWelcome" + condition: QmlDesigner.present Depends { name: "Qt"; submodules: ["qml", "qml-private", "quick", "quickwidgets"] } Depends { name: "Utils" } @@ -9,7 +10,7 @@ QtcPlugin { Depends { name: "Core" } Depends { name: "ProjectExplorer" } Depends { name: "QtSupport" } - Depends { name: "QmlDesigner" } + Depends { name: "QmlDesigner"; required: false } Depends { name: "QmlProjectManager" } Depends { name: "app_version_header" } diff --git a/tests/unit/unittest/unittest.qbs b/tests/unit/unittest/unittest.qbs index 00f3e2a8c64..3828063b783 100644 --- a/tests/unit/unittest/unittest.qbs +++ b/tests/unit/unittest/unittest.qbs @@ -6,7 +6,8 @@ Project { QtcProduct { name: "Unit test" - condition: qtc_gtest_gmock.hasRepo || qtc_gtest_gmock.externalLibsPresent + condition: (qtc_gtest_gmock.hasRepo || qtc_gtest_gmock.externalLibsPresent) + && QmlDesigner.present type: ["application", "autotest"] consoleApplication: true @@ -17,7 +18,7 @@ Project { Depends { name: "libclang"; required: false } Depends { name: "clang_defines" } - Depends { name: "QmlDesigner" } + Depends { name: "QmlDesigner"; required: false } Depends { name: "sqlite_sources" } Depends { name: "Core" } From f97448812860c682e5e7cf716478c8ee24a577be Mon Sep 17 00:00:00 2001 From: hjk Date: Fri, 10 Jun 2022 16:41:27 +0200 Subject: [PATCH 06/94] ProjectExplorer: Move makeInstallCommand() ... from Project to BuildSystem. More direct and less use of Target::activeBuildConfiguration(). Change-Id: I148381d23be0f9ab0750ed1440e1b2b3e25aded0 Reviewed-by: Christian Kandeler --- .../cmakeprojectmanager/cmakebuildsystem.cpp | 33 ++++++++++++++++- .../cmakeprojectmanager/cmakebuildsystem.h | 3 ++ .../cmakeprojectmanager/cmakeproject.cpp | 36 ------------------- .../cmakeprojectmanager/cmakeproject.h | 2 -- .../project/mesonproject.cpp | 9 ----- .../project/mesonproject.h | 2 -- src/plugins/projectexplorer/buildsteplist.cpp | 2 +- src/plugins/projectexplorer/buildsteplist.h | 4 +-- src/plugins/projectexplorer/buildsystem.cpp | 20 +++++++++++ src/plugins/projectexplorer/buildsystem.h | 3 ++ src/plugins/projectexplorer/project.cpp | 15 -------- src/plugins/projectexplorer/project.h | 2 -- src/plugins/projectexplorer/target.cpp | 5 --- src/plugins/projectexplorer/target.h | 7 ++-- src/plugins/remotelinux/makeinstallstep.cpp | 9 ++--- 15 files changed, 70 insertions(+), 82 deletions(-) diff --git a/src/plugins/cmakeprojectmanager/cmakebuildsystem.cpp b/src/plugins/cmakeprojectmanager/cmakebuildsystem.cpp index 0ce9e360e29..5add4f4e559 100644 --- a/src/plugins/cmakeprojectmanager/cmakebuildsystem.cpp +++ b/src/plugins/cmakeprojectmanager/cmakebuildsystem.cpp @@ -36,26 +36,31 @@ #include "cmakeprojectplugin.h" #include "cmakespecificsettings.h" #include "projecttreehelper.h" -#include "utils/algorithm.h" #include + #include #include + #include #include #include + +#include #include #include #include #include #include #include + #include #include #include #include +#include #include #include #include @@ -1314,5 +1319,31 @@ void CMakeBuildSystem::updateInitialCMakeExpandableVars() emit configurationChanged(config); } +MakeInstallCommand CMakeBuildSystem::makeInstallCommand(const FilePath &installRoot) const +{ + MakeInstallCommand cmd; + if (CMakeTool *tool = CMakeKitAspect::cmakeTool(target()->kit())) + cmd.command.setExecutable(tool->cmakeExecutable()); + + QString installTarget = "install"; + if (usesAllCapsTargets()) + installTarget = "INSTALL"; + + FilePath buildDirectory = "."; + if (auto bc = buildConfiguration()) + buildDirectory = bc->buildDirectory(); + + cmd.command.addArg("--build"); + cmd.command.addArg(buildDirectory.onDevice(cmd.command.executable()).path()); + cmd.command.addArg("--target"); + cmd.command.addArg(installTarget); + + if (isMultiConfigReader()) + cmd.command.addArgs({"--config", cmakeBuildType()}); + + cmd.environment.set("DESTDIR", installRoot.nativePath()); + return cmd; +} + } // namespace Internal } // namespace CMakeProjectManager diff --git a/src/plugins/cmakeprojectmanager/cmakebuildsystem.h b/src/plugins/cmakeprojectmanager/cmakebuildsystem.h index bb505b65f34..5ebfd6dfbe0 100644 --- a/src/plugins/cmakeprojectmanager/cmakebuildsystem.h +++ b/src/plugins/cmakeprojectmanager/cmakebuildsystem.h @@ -98,6 +98,9 @@ public: Utils::CommandLine commandLineForTests(const QList &tests, const QStringList &options) const final; + ProjectExplorer::MakeInstallCommand makeInstallCommand( + const Utils::FilePath &installRoot) const final; + static bool filteredOutTarget(const CMakeBuildTarget &target); bool isMultiConfig() const; diff --git a/src/plugins/cmakeprojectmanager/cmakeproject.cpp b/src/plugins/cmakeprojectmanager/cmakeproject.cpp index 445e9b1ab3b..ee6696b0e62 100644 --- a/src/plugins/cmakeprojectmanager/cmakeproject.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeproject.cpp @@ -116,40 +116,4 @@ ProjectExplorer::DeploymentKnowledge CMakeProject::deploymentKnowledge() const : DeploymentKnowledge::Bad; } -MakeInstallCommand CMakeProject::makeInstallCommand(const Target *target, - const FilePath &installRoot) -{ - MakeInstallCommand cmd; - if (const BuildConfiguration * const bc = target->activeBuildConfiguration()) { - if (const auto cmakeStep = bc->buildSteps()->firstOfType()) { - if (CMakeTool *tool = CMakeKitAspect::cmakeTool(target->kit())) - cmd.command.setExecutable(tool->cmakeExecutable()); - } - } - - QString installTarget = "install"; - QStringList config; - - auto bs = qobject_cast(target->buildSystem()); - QTC_ASSERT(bs, return {}); - - if (bs->usesAllCapsTargets()) - installTarget = "INSTALL"; - if (bs->isMultiConfigReader()) - config << "--config" << bs->cmakeBuildType(); - - FilePath buildDirectory = "."; - if (auto bc = bs->buildConfiguration()) - buildDirectory = bc->buildDirectory(); - - cmd.command.addArg("--build"); - cmd.command.addArg(buildDirectory.onDevice(cmd.command.executable()).path()); - cmd.command.addArg("--target"); - cmd.command.addArg(installTarget); - cmd.command.addArgs(config); - - cmd.environment.set("DESTDIR", installRoot.nativePath()); - return cmd; -} - } // namespace CMakeProjectManager diff --git a/src/plugins/cmakeprojectmanager/cmakeproject.h b/src/plugins/cmakeprojectmanager/cmakeproject.h index a1f1db439d4..33239234046 100644 --- a/src/plugins/cmakeprojectmanager/cmakeproject.h +++ b/src/plugins/cmakeprojectmanager/cmakeproject.h @@ -54,8 +54,6 @@ protected: private: ProjectExplorer::DeploymentKnowledge deploymentKnowledge() const override; - ProjectExplorer::MakeInstallCommand makeInstallCommand(const ProjectExplorer::Target *target, - const Utils::FilePath &installRoot) final; mutable Internal::CMakeProjectImporter *m_projectImporter = nullptr; diff --git a/src/plugins/mesonprojectmanager/project/mesonproject.cpp b/src/plugins/mesonprojectmanager/project/mesonproject.cpp index 2406e35755f..4b770f2793f 100644 --- a/src/plugins/mesonprojectmanager/project/mesonproject.cpp +++ b/src/plugins/mesonprojectmanager/project/mesonproject.cpp @@ -77,14 +77,5 @@ ProjectExplorer::DeploymentKnowledge MesonProject::deploymentKnowledge() const return ProjectExplorer::DeploymentKnowledge::Bad; } -ProjectExplorer::MakeInstallCommand MesonProject::makeInstallCommand(const ProjectExplorer::Target *target, - const Utils::FilePath &installRoot) -{ - Q_UNUSED(target) - Q_UNUSED(installRoot) - // TODO in next releases - return {}; -} - } // namespace Internal } // namespace MesonProjectManager diff --git a/src/plugins/mesonprojectmanager/project/mesonproject.h b/src/plugins/mesonprojectmanager/project/mesonproject.h index e07b82aa56b..29920b03fa7 100644 --- a/src/plugins/mesonprojectmanager/project/mesonproject.h +++ b/src/plugins/mesonprojectmanager/project/mesonproject.h @@ -46,8 +46,6 @@ public: private: ProjectExplorer::DeploymentKnowledge deploymentKnowledge() const override; - ProjectExplorer::MakeInstallCommand makeInstallCommand(const ProjectExplorer::Target *target, - const Utils::FilePath &installRoot) final; mutable std::unique_ptr m_projectImporter; }; diff --git a/src/plugins/projectexplorer/buildsteplist.cpp b/src/plugins/projectexplorer/buildsteplist.cpp index 0a60422dbb1..de9f7611717 100644 --- a/src/plugins/projectexplorer/buildsteplist.cpp +++ b/src/plugins/projectexplorer/buildsteplist.cpp @@ -196,7 +196,7 @@ void BuildStepList::moveStepUp(int position) emit stepMoved(position, position - 1); } -BuildStep *BuildStepList::at(int position) +BuildStep *BuildStepList::at(int position) const { return m_steps.at(position); } diff --git a/src/plugins/projectexplorer/buildsteplist.h b/src/plugins/projectexplorer/buildsteplist.h index 49c0f8b206b..4d55a4a023f 100644 --- a/src/plugins/projectexplorer/buildsteplist.h +++ b/src/plugins/projectexplorer/buildsteplist.h @@ -49,7 +49,7 @@ public: QList steps() const; - template BS *firstOfType() { + template BS *firstOfType() const { BS *bs = nullptr; for (int i = 0; i < count(); ++i) { bs = qobject_cast(at(i)); @@ -76,7 +76,7 @@ public: bool removeStep(int position); void moveStepUp(int position); - BuildStep *at(int position); + BuildStep *at(int position) const; Target *target() { return m_target; } diff --git a/src/plugins/projectexplorer/buildsystem.cpp b/src/plugins/projectexplorer/buildsystem.cpp index 1cfeec74c23..930416f3bef 100644 --- a/src/plugins/projectexplorer/buildsystem.cpp +++ b/src/plugins/projectexplorer/buildsystem.cpp @@ -34,7 +34,11 @@ #include #include + #include +#include +#include + #include #include @@ -253,6 +257,22 @@ bool BuildSystem::supportsAction(Node *, ProjectAction, const Node *) const return false; } +MakeInstallCommand BuildSystem::makeInstallCommand(const FilePath &installRoot) const +{ + QTC_ASSERT(target()->project()->hasMakeInstallEquivalent(), return {}); + + BuildStepList *buildSteps = buildConfiguration()->buildSteps(); + QTC_ASSERT(buildSteps, return {}); + + MakeInstallCommand cmd; + if (const auto makeStep = buildSteps->firstOfType()) { + cmd.command.setExecutable(makeStep->makeExecutable()); + cmd.command.addArg("install"); + cmd.command.addArg("INSTALL_ROOT=" + installRoot.nativePath()); + } + return cmd; +} + FilePaths BuildSystem::filesGeneratedFrom(const FilePath &sourceFile) const { Q_UNUSED(sourceFile) diff --git a/src/plugins/projectexplorer/buildsystem.h b/src/plugins/projectexplorer/buildsystem.h index 263738d8e45..e9bcd90edaf 100644 --- a/src/plugins/projectexplorer/buildsystem.h +++ b/src/plugins/projectexplorer/buildsystem.h @@ -40,6 +40,7 @@ class CommandLine; namespace ProjectExplorer { class BuildConfiguration; +class BuildStepList; class Node; struct TestCaseInfo @@ -103,6 +104,8 @@ public: virtual bool supportsAction(Node *context, ProjectAction action, const Node *node) const; virtual QString name() const = 0; + virtual MakeInstallCommand makeInstallCommand(const Utils::FilePath &installRoot) const; + virtual Utils::FilePaths filesGeneratedFrom(const Utils::FilePath &sourceFile) const; virtual QVariant additionalData(Utils::Id id) const; diff --git a/src/plugins/projectexplorer/project.cpp b/src/plugins/projectexplorer/project.cpp index 23998359fb4..cd0c64aec34 100644 --- a/src/plugins/projectexplorer/project.cpp +++ b/src/plugins/projectexplorer/project.cpp @@ -32,11 +32,9 @@ #include "editorconfiguration.h" #include "kit.h" #include "kitinformation.h" -#include "makestep.h" #include "projectexplorer.h" #include "projectnodes.h" #include "runconfiguration.h" -#include "runcontrol.h" #include "session.h" #include "target.h" #include "taskhub.h" @@ -971,19 +969,6 @@ bool Project::hasMakeInstallEquivalent() const return d->m_hasMakeInstallEquivalent; } -MakeInstallCommand Project::makeInstallCommand(const Target *target, const FilePath &installRoot) -{ - QTC_ASSERT(hasMakeInstallEquivalent(), return MakeInstallCommand()); - MakeInstallCommand cmd; - if (const BuildConfiguration * const bc = target->activeBuildConfiguration()) { - if (const auto makeStep = bc->buildSteps()->firstOfType()) - cmd.command.setExecutable(makeStep->makeExecutable()); - } - cmd.command.addArg("install"); - cmd.command.addArg("INSTALL_ROOT=" + installRoot.nativePath()); - return cmd; -} - void Project::setup(const QList &infoList) { std::vector> toRegister; diff --git a/src/plugins/projectexplorer/project.h b/src/plugins/projectexplorer/project.h index 36cb94feeb0..039d191c1be 100644 --- a/src/plugins/projectexplorer/project.h +++ b/src/plugins/projectexplorer/project.h @@ -149,8 +149,6 @@ public: virtual DeploymentKnowledge deploymentKnowledge() const { return DeploymentKnowledge::Bad; } bool hasMakeInstallEquivalent() const; - virtual MakeInstallCommand makeInstallCommand(const Target *target, - const Utils::FilePath &installRoot); void setup(const QList &infoList); Utils::MacroExpander *macroExpander() const; diff --git a/src/plugins/projectexplorer/target.cpp b/src/plugins/projectexplorer/target.cpp index 76de5d0da66..964461bfb5a 100644 --- a/src/plugins/projectexplorer/target.cpp +++ b/src/plugins/projectexplorer/target.cpp @@ -803,11 +803,6 @@ QVariant Target::additionalData(Utils::Id id) const return {}; } -MakeInstallCommand Target::makeInstallCommand(const FilePath &installRoot) const -{ - return project()->makeInstallCommand(this, installRoot); -} - MacroExpander *Target::macroExpander() const { return &d->m_macroExpander; diff --git a/src/plugins/projectexplorer/target.h b/src/plugins/projectexplorer/target.h index a5503ff833b..b1ff67c2d2f 100644 --- a/src/plugins/projectexplorer/target.h +++ b/src/plugins/projectexplorer/target.h @@ -25,9 +25,12 @@ #pragma once -#include "projectconfiguration.h" #include "projectexplorer_export.h" +#include + +#include + #include QT_FORWARD_DECLARE_CLASS(QIcon) @@ -41,7 +44,6 @@ class BuildSystem; class DeployConfiguration; class DeploymentData; class Kit; -class MakeInstallCommand; class Project; class ProjectConfigurationModel; class RunConfiguration; @@ -114,7 +116,6 @@ public: void setNamedSettings(const QString &name, const QVariant &value); QVariant additionalData(Utils::Id id) const; - MakeInstallCommand makeInstallCommand(const Utils::FilePath &installRoot) const; Utils::MacroExpander *macroExpander() const; diff --git a/src/plugins/remotelinux/makeinstallstep.cpp b/src/plugins/remotelinux/makeinstallstep.cpp index c61df08f6cc..d676a26f46d 100644 --- a/src/plugins/remotelinux/makeinstallstep.cpp +++ b/src/plugins/remotelinux/makeinstallstep.cpp @@ -119,7 +119,8 @@ MakeInstallStep::MakeInstallStep(BuildStepList *parent, Id id) : MakeStep(parent QTemporaryDir tmpDir; installRootAspect->setFilePath(FilePath::fromString(tmpDir.path())); - const MakeInstallCommand cmd = target()->makeInstallCommand(FilePath::fromString(tmpDir.path())); + const MakeInstallCommand cmd = + buildSystem()->makeInstallCommand(FilePath::fromString(tmpDir.path())); QTC_ASSERT(!cmd.command.isEmpty(), return); makeAspect->setExecutable(cmd.command.executable()); } @@ -168,7 +169,8 @@ bool MakeInstallStep::init() "last in the list of deploy steps. " "Consider moving it up."))); } - const MakeInstallCommand cmd = target()->makeInstallCommand(rootDir); + + const MakeInstallCommand cmd = buildSystem()->makeInstallCommand(rootDir); if (cmd.environment.isValid()) { Environment env = processParameters()->environment(); for (auto it = cmd.environment.constBegin(); it != cmd.environment.constEnd(); ++it) { @@ -255,8 +257,7 @@ void MakeInstallStep::updateArgsFromAspect() { if (customCommandLineAspect()->isChecked()) return; - - const CommandLine cmd = target()->makeInstallCommand(installRoot()).command; + const CommandLine cmd = buildSystem()->makeInstallCommand(installRoot()).command; setUserArguments(cmd.arguments()); updateFullCommandLine(); } From a1bb539c50a70eb194ce76125fde70ca87160fd0 Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Mon, 13 Jun 2022 11:01:16 +0200 Subject: [PATCH 07/94] LiteHtmlHelpViewer: Handle mouse back/forward buttons Fixes: QTCREATORBUG-25168 Change-Id: I856743040e81a0164e666f14ea7efd10f208f865 Reviewed-by: Eike Ziller --- src/plugins/help/litehtmlhelpviewer.cpp | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/plugins/help/litehtmlhelpviewer.cpp b/src/plugins/help/litehtmlhelpviewer.cpp index 61139aacbd1..4e1c697bed2 100644 --- a/src/plugins/help/litehtmlhelpviewer.cpp +++ b/src/plugins/help/litehtmlhelpviewer.cpp @@ -205,11 +205,14 @@ void LiteHtmlHelpViewer::backward() { goBackward(1); } + void LiteHtmlHelpViewer::goForward(int count) { + const int steps = qMin(count, int(m_forwardItems.size())); + if (steps == 0) + return; HistoryItem nextItem = currentHistoryItem(); - for (int i = 0; i < count; ++i) { - QTC_ASSERT(!m_forwardItems.empty(), return ); + for (int i = 0; i < steps; ++i) { m_backItems.push_back(nextItem); nextItem = m_forwardItems.front(); m_forwardItems.erase(m_forwardItems.begin()); @@ -221,9 +224,11 @@ void LiteHtmlHelpViewer::goForward(int count) void LiteHtmlHelpViewer::goBackward(int count) { + const int steps = qMin(count, int(m_backItems.size())); + if (steps == 0) + return; HistoryItem previousItem = currentHistoryItem(); - for (int i = 0; i < count; ++i) { - QTC_ASSERT(!m_backItems.empty(), return ); + for (int i = 0; i < steps; ++i) { m_forwardItems.insert(m_forwardItems.begin(), previousItem); previousItem = m_backItems.back(); m_backItems.pop_back(); @@ -247,6 +252,15 @@ bool LiteHtmlHelpViewer::eventFilter(QObject *src, QEvent *e) e->ignore(); return true; } + } else if (e->type() == QEvent::MouseButtonPress) { + auto me = static_cast(e); + if (me->button() == Qt::BackButton) { + goBackward(1); + return true; + } else if (me->button() == Qt::ForwardButton) { + goForward(1); + return true; + } } return HelpViewer::eventFilter(src, e); } From 9c13db448b91af947113e7e559bcececb0fade3e Mon Sep 17 00:00:00 2001 From: David Schulz Date: Mon, 13 Jun 2022 13:38:30 +0200 Subject: [PATCH 08/94] CppEditor: remove unused function hint provider Since we removed the libclang based backend both implementations of ModelManagerSupport::functionHintAssistProvider returned a nullptr. Change-Id: I113c5a08cf604eb1bb2a64a851f022ecd5c908d6 Reviewed-by: Christian Kandeler --- .../clangcodemodel/clangmodelmanagersupport.cpp | 5 ----- .../clangcodemodel/clangmodelmanagersupport.h | 1 - .../cppeditor/cppbuiltinmodelmanagersupport.cpp | 5 ----- .../cppeditor/cppbuiltinmodelmanagersupport.h | 1 - src/plugins/cppeditor/cppeditordocument.cpp | 13 ------------- src/plugins/cppeditor/cppeditordocument.h | 3 --- src/plugins/cppeditor/cppmodelmanager.cpp | 5 ----- src/plugins/cppeditor/cppmodelmanager.h | 1 - src/plugins/cppeditor/cppmodelmanagersupport.h | 1 - 9 files changed, 35 deletions(-) diff --git a/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp b/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp index 66ff519725b..a33d2863563 100644 --- a/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp +++ b/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp @@ -185,11 +185,6 @@ CppEditor::CppCompletionAssistProvider *ClangModelManagerSupport::completionAssi return nullptr; } -CppEditor::CppCompletionAssistProvider *ClangModelManagerSupport::functionHintAssistProvider() -{ - return nullptr; -} - void ClangModelManagerSupport::followSymbol(const CppEditor::CursorInEditor &data, const Utils::LinkHandler &processLinkCallback, bool resolveTarget, bool inNextSplit) diff --git a/src/plugins/clangcodemodel/clangmodelmanagersupport.h b/src/plugins/clangcodemodel/clangmodelmanagersupport.h index 01a4d7429ce..64db859d388 100644 --- a/src/plugins/clangcodemodel/clangmodelmanagersupport.h +++ b/src/plugins/clangcodemodel/clangmodelmanagersupport.h @@ -63,7 +63,6 @@ public: ~ClangModelManagerSupport() override; CppEditor::CppCompletionAssistProvider *completionAssistProvider() override; - CppEditor::CppCompletionAssistProvider *functionHintAssistProvider() override; TextEditor::BaseHoverHandler *createHoverHandler() override { return nullptr; } CppEditor::BaseEditorDocumentProcessor *createEditorDocumentProcessor( TextEditor::TextDocument *baseTextDocument) override; diff --git a/src/plugins/cppeditor/cppbuiltinmodelmanagersupport.cpp b/src/plugins/cppeditor/cppbuiltinmodelmanagersupport.cpp index 50e8387a232..425ff3f657c 100644 --- a/src/plugins/cppeditor/cppbuiltinmodelmanagersupport.cpp +++ b/src/plugins/cppeditor/cppbuiltinmodelmanagersupport.cpp @@ -124,11 +124,6 @@ CppCompletionAssistProvider *BuiltinModelManagerSupport::completionAssistProvide } -CppCompletionAssistProvider *BuiltinModelManagerSupport::functionHintAssistProvider() -{ - return nullptr; -} - TextEditor::BaseHoverHandler *BuiltinModelManagerSupport::createHoverHandler() { return new CppHoverHandler; diff --git a/src/plugins/cppeditor/cppbuiltinmodelmanagersupport.h b/src/plugins/cppeditor/cppbuiltinmodelmanagersupport.h index e6583cb09a0..fed35cf89cc 100644 --- a/src/plugins/cppeditor/cppbuiltinmodelmanagersupport.h +++ b/src/plugins/cppeditor/cppbuiltinmodelmanagersupport.h @@ -42,7 +42,6 @@ public: ~BuiltinModelManagerSupport() override; CppCompletionAssistProvider *completionAssistProvider() final; - CppCompletionAssistProvider *functionHintAssistProvider() override; TextEditor::BaseHoverHandler *createHoverHandler() final; BaseEditorDocumentProcessor *createEditorDocumentProcessor( TextEditor::TextDocument *baseTextDocument) final; diff --git a/src/plugins/cppeditor/cppeditordocument.cpp b/src/plugins/cppeditor/cppeditordocument.cpp index edd776f5375..e203bd3cdb9 100644 --- a/src/plugins/cppeditor/cppeditordocument.cpp +++ b/src/plugins/cppeditor/cppeditordocument.cpp @@ -150,24 +150,12 @@ void CppEditorDocument::setCompletionAssistProvider(TextEditor::CompletionAssist m_completionAssistProvider = nullptr; } -void CppEditorDocument::setFunctionHintAssistProvider(TextEditor::CompletionAssistProvider *provider) -{ - TextDocument::setFunctionHintAssistProvider(provider); - m_functionHintAssistProvider = nullptr; -} - CompletionAssistProvider *CppEditorDocument::completionAssistProvider() const { return m_completionAssistProvider ? m_completionAssistProvider : TextDocument::completionAssistProvider(); } -CompletionAssistProvider *CppEditorDocument::functionHintAssistProvider() const -{ - return m_functionHintAssistProvider - ? m_functionHintAssistProvider : TextDocument::functionHintAssistProvider(); -} - TextEditor::IAssistProvider *CppEditorDocument::quickFixAssistProvider() const { if (const auto baseProvider = TextDocument::quickFixAssistProvider()) @@ -223,7 +211,6 @@ void CppEditorDocument::onMimeTypeChanged() m_isObjCEnabled = (mt == QLatin1String(Constants::OBJECTIVE_C_SOURCE_MIMETYPE) || mt == QLatin1String(Constants::OBJECTIVE_CPP_SOURCE_MIMETYPE)); m_completionAssistProvider = mm()->completionAssistProvider(); - m_functionHintAssistProvider = mm()->functionHintAssistProvider(); initializeTimer(); } diff --git a/src/plugins/cppeditor/cppeditordocument.h b/src/plugins/cppeditor/cppeditordocument.h index 471ba99c9b2..54009a04ebd 100644 --- a/src/plugins/cppeditor/cppeditordocument.h +++ b/src/plugins/cppeditor/cppeditordocument.h @@ -51,9 +51,7 @@ public: bool isObjCEnabled() const; void setCompletionAssistProvider(TextEditor::CompletionAssistProvider *provider) override; - void setFunctionHintAssistProvider(TextEditor::CompletionAssistProvider *provider) override; TextEditor::CompletionAssistProvider *completionAssistProvider() const override; - TextEditor::CompletionAssistProvider *functionHintAssistProvider() const override; TextEditor::IAssistProvider *quickFixAssistProvider() const override; void recalculateSemanticInfoDetached(); @@ -128,7 +126,6 @@ private: QScopedPointer m_processor; CppCompletionAssistProvider *m_completionAssistProvider = nullptr; - CppCompletionAssistProvider *m_functionHintAssistProvider = nullptr; // (Un)Registration in CppModelManager QScopedPointer m_editorDocumentHandle; diff --git a/src/plugins/cppeditor/cppmodelmanager.cpp b/src/plugins/cppeditor/cppmodelmanager.cpp index 6afbe669e60..f646631a90e 100644 --- a/src/plugins/cppeditor/cppmodelmanager.cpp +++ b/src/plugins/cppeditor/cppmodelmanager.cpp @@ -1620,11 +1620,6 @@ CppCompletionAssistProvider *CppModelManager::completionAssistProvider() const return d->m_builtinModelManagerSupport->completionAssistProvider(); } -CppCompletionAssistProvider *CppModelManager::functionHintAssistProvider() const -{ - return d->m_builtinModelManagerSupport->functionHintAssistProvider(); -} - TextEditor::BaseHoverHandler *CppModelManager::createHoverHandler() const { return d->m_builtinModelManagerSupport->createHoverHandler(); diff --git a/src/plugins/cppeditor/cppmodelmanager.h b/src/plugins/cppeditor/cppmodelmanager.h index 0177d43d5b7..3526bb5fbe0 100644 --- a/src/plugins/cppeditor/cppmodelmanager.h +++ b/src/plugins/cppeditor/cppmodelmanager.h @@ -162,7 +162,6 @@ public: void activateClangCodeModel(ModelManagerSupportProvider *modelManagerSupportProvider); CppCompletionAssistProvider *completionAssistProvider() const; - CppCompletionAssistProvider *functionHintAssistProvider() const; BaseEditorDocumentProcessor *createEditorDocumentProcessor( TextEditor::TextDocument *baseTextDocument) const; TextEditor::BaseHoverHandler *createHoverHandler() const; diff --git a/src/plugins/cppeditor/cppmodelmanagersupport.h b/src/plugins/cppeditor/cppmodelmanagersupport.h index 5be236c5d52..2889cf7b67d 100644 --- a/src/plugins/cppeditor/cppmodelmanagersupport.h +++ b/src/plugins/cppeditor/cppmodelmanagersupport.h @@ -57,7 +57,6 @@ public: virtual ~ModelManagerSupport() = 0; virtual CppCompletionAssistProvider *completionAssistProvider() = 0; - virtual CppCompletionAssistProvider *functionHintAssistProvider() = 0; virtual TextEditor::BaseHoverHandler *createHoverHandler() = 0; virtual BaseEditorDocumentProcessor *createEditorDocumentProcessor( TextEditor::TextDocument *baseTextDocument) = 0; From 75502f2998b740fc3688759cb37cf3fef85bcada Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Mon, 13 Jun 2022 13:49:41 +0200 Subject: [PATCH 09/94] CppEditor: Fix check for static-ness ... in generate getter/setter quickfixes. Fixes: QTCREATORBUG-27547 Change-Id: I29e937ae28c0bce7cd7745b92f371b97876f3e01 Reviewed-by: Qt CI Bot Reviewed-by: Christian Stenger --- src/plugins/cppeditor/cppquickfixes.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/cppeditor/cppquickfixes.cpp b/src/plugins/cppeditor/cppquickfixes.cpp index c14fe66255c..b63d8f115f9 100644 --- a/src/plugins/cppeditor/cppquickfixes.cpp +++ b/src/plugins/cppeditor/cppquickfixes.cpp @@ -3853,7 +3853,7 @@ void GetterSetterRefactoringHelper::performGeneration(ExistingGetterSetterData d FullySpecifiedType memberVariableType = data.declarationSymbol->type(); memberVariableType.setConst(false); - const bool isMemberVariableStatic = memberVariableType.isStatic(); + const bool isMemberVariableStatic = data.declarationSymbol->isStatic(); memberVariableType.setStatic(false); Overview overview = CppCodeStyleSettings::currentProjectCodeStyleOverview(); overview.showTemplateParameters = false; From f4bf5f5cd715aa7a98e129bbfee9e51075b62387 Mon Sep 17 00:00:00 2001 From: Cristian Adam Date: Thu, 2 Jun 2022 16:20:38 +0200 Subject: [PATCH 10/94] GitHub: Add pull request template Add a pull request template to inform the potential contributor that the github Qt Creator presence a mirror is, and that the only way to contribuite is through gerrit. Change-Id: I5ddc93f182aaaa87e465677a28705ac5efa04f7f Reviewed-by: Eike Ziller Reviewed-by: Alessandro Portale --- .github/pull_request_template.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .github/pull_request_template.md diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 00000000000..277028cbb2d --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,7 @@ +Thank you for contributing to Qt Creator! Unfortunately the GitHub Qt Creator +presence is only a git mirror. + +Please submit your patch via gerrit: +https://wiki.qt.io/Qt_Creator#Setting_up_Gerrit_to_contribute_back_to_Qt_Creator + +We are sorry for the inconvenience. From db2cc2ba2745dfdc268698582610eb11e3bbb91b Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Mon, 13 Jun 2022 09:42:34 +0200 Subject: [PATCH 11/94] Add install command to wizard generated CMake files Add a default install(TARGETS ...) command. It doesn't hurt on desktop and mobile targets, and it is required for deployment on remote Linux devices. Change-Id: Ib39c6130b63a9a699ff5cd81756c2913b1246142 Reviewed-by: Cristian Adam Reviewed-by: --- .../templates/wizards/projects/consoleapp/CMakeLists.txt | 2 ++ .../qtcreator/templates/wizards/projects/plainc/CMakeLists.txt | 2 ++ .../templates/wizards/projects/plaincpp/CMakeLists.txt | 2 ++ .../wizards/projects/qtquickapplication/CMakeLists.6.x.txt | 2 ++ .../wizards/projects/qtquickapplication/CMakeLists.txt | 2 ++ .../wizards/projects/qtwidgetsapplication/CMakeLists.txt | 2 ++ 6 files changed, 12 insertions(+) diff --git a/share/qtcreator/templates/wizards/projects/consoleapp/CMakeLists.txt b/share/qtcreator/templates/wizards/projects/consoleapp/CMakeLists.txt index b27ac6d8cab..1af66d937b6 100644 --- a/share/qtcreator/templates/wizards/projects/consoleapp/CMakeLists.txt +++ b/share/qtcreator/templates/wizards/projects/consoleapp/CMakeLists.txt @@ -36,3 +36,5 @@ else() qt5_create_translation(QM_FILES ${CMAKE_SOURCE_DIR} ${TS_FILES}) endif() @endif + +install(TARGETS %{ProjectName}) diff --git a/share/qtcreator/templates/wizards/projects/plainc/CMakeLists.txt b/share/qtcreator/templates/wizards/projects/plainc/CMakeLists.txt index 5af2f09fb67..d33adb59eb8 100644 --- a/share/qtcreator/templates/wizards/projects/plainc/CMakeLists.txt +++ b/share/qtcreator/templates/wizards/projects/plainc/CMakeLists.txt @@ -3,3 +3,5 @@ cmake_minimum_required(VERSION 3.5) project(%{ProjectName} LANGUAGES C) add_executable(%{ProjectName} %{CFileName}) + +install(TARGETS %{ProjectName}) diff --git a/share/qtcreator/templates/wizards/projects/plaincpp/CMakeLists.txt b/share/qtcreator/templates/wizards/projects/plaincpp/CMakeLists.txt index 214e8979d4a..c8a95f5a4ce 100644 --- a/share/qtcreator/templates/wizards/projects/plaincpp/CMakeLists.txt +++ b/share/qtcreator/templates/wizards/projects/plaincpp/CMakeLists.txt @@ -6,3 +6,5 @@ set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) add_executable(%{ProjectName} %{CppFileName}) + +install(TARGETS %{ProjectName}) diff --git a/share/qtcreator/templates/wizards/projects/qtquickapplication/CMakeLists.6.x.txt b/share/qtcreator/templates/wizards/projects/qtquickapplication/CMakeLists.6.x.txt index d47f49ab3bd..a59656b3733 100644 --- a/share/qtcreator/templates/wizards/projects/qtquickapplication/CMakeLists.6.x.txt +++ b/share/qtcreator/templates/wizards/projects/qtquickapplication/CMakeLists.6.x.txt @@ -27,3 +27,5 @@ set_target_properties(%{TargetName} PROPERTIES target_link_libraries(%{TargetName} PRIVATE Qt6::Quick) + +install(TARGETS %{ProjectName} BUNDLE DESTINATION .) diff --git a/share/qtcreator/templates/wizards/projects/qtquickapplication/CMakeLists.txt b/share/qtcreator/templates/wizards/projects/qtquickapplication/CMakeLists.txt index cac41d7c1e7..79ad6ad2991 100644 --- a/share/qtcreator/templates/wizards/projects/qtquickapplication/CMakeLists.txt +++ b/share/qtcreator/templates/wizards/projects/qtquickapplication/CMakeLists.txt @@ -71,6 +71,8 @@ set_target_properties(%{ProjectName} PROPERTIES WIN32_EXECUTABLE TRUE ) +install(TARGETS %{ProjectName} BUNDLE DESTINATION .) + if(QT_VERSION_MAJOR EQUAL 6) qt_import_qml_plugins(%{ProjectName}) qt_finalize_executable(%{ProjectName}) diff --git a/share/qtcreator/templates/wizards/projects/qtwidgetsapplication/CMakeLists.txt b/share/qtcreator/templates/wizards/projects/qtwidgetsapplication/CMakeLists.txt index 32ceeffc55b..9dc83c698c0 100644 --- a/share/qtcreator/templates/wizards/projects/qtwidgetsapplication/CMakeLists.txt +++ b/share/qtcreator/templates/wizards/projects/qtwidgetsapplication/CMakeLists.txt @@ -74,6 +74,8 @@ set_target_properties(%{ProjectName} PROPERTIES WIN32_EXECUTABLE TRUE ) +install(TARGETS %{ProjectName} BUNDLE DESTINATION .) + if(QT_VERSION_MAJOR EQUAL 6) qt_finalize_executable(%{ProjectName}) endif() From 1bc188222a5520dd9e40fddebcc46f624667f5af Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Mon, 13 Jun 2022 16:11:39 +0200 Subject: [PATCH 12/94] ProjectExplorer: Fix crash in toolchain widget Amends d73d5fe0b1431b913e8cc763d5cf86471755b9ba Fixes: QTCREATORBUG-27696 Change-Id: Id94f39cd4fc6768af3f66039f808ed7c974cfeed Reviewed-by: Qt CI Bot Reviewed-by: Reviewed-by: Eike Ziller --- src/libs/utils/algorithm.h | 12 +++++++++- .../projectexplorer/toolchainoptionspage.cpp | 23 ++++++++----------- 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/src/libs/utils/algorithm.h b/src/libs/utils/algorithm.h index ae4a718c836..32ad6d3e46f 100644 --- a/src/libs/utils/algorithm.h +++ b/src/libs/utils/algorithm.h @@ -76,6 +76,8 @@ bool allOf(const T &container, F predicate); ///////////////////////// template void erase(T &container, F predicate); +template +bool eraseOne(T &container, F predicate); ///////////////////////// // contains @@ -442,7 +444,15 @@ void erase(T &container, F predicate) container.erase(std::remove_if(std::begin(container), std::end(container), predicate), std::end(container)); } - +template +bool eraseOne(T &container, F predicate) +{ + const auto it = std::find_if(std::begin(container), std::end(container), predicate); + if (it == std::end(container)) + return false; + container.erase(it); + return true; +} ////////////////// // contains diff --git a/src/plugins/projectexplorer/toolchainoptionspage.cpp b/src/plugins/projectexplorer/toolchainoptionspage.cpp index 7f0c17a5c63..b8dccb01998 100644 --- a/src/plugins/projectexplorer/toolchainoptionspage.cpp +++ b/src/plugins/projectexplorer/toolchainoptionspage.cpp @@ -363,27 +363,24 @@ ToolChainTreeItem *ToolChainOptionsWidget::insertToolChain(ToolChain *tc, bool c void ToolChainOptionsWidget::addToolChain(ToolChain *tc) { - for (int i = 0; i < m_toAddList.size(); ++i) { - if (m_toAddList.at(i)->toolChain == tc) { - // do not delete i element: Still used elsewhere! - m_toAddList.removeAt(i); - return; - } + if (Utils::eraseOne(m_toAddList, [tc](const ToolChainTreeItem *item) { + return item->toolChain == tc; })) { + // do not delete here! + return; } insertToolChain(tc); - updateState(); } void ToolChainOptionsWidget::removeToolChain(ToolChain *tc) { - for (int i = 0; i < m_toRemoveList.size(); ++i) { - if (m_toRemoveList.at(i)->toolChain == tc) { - m_toRemoveList.removeAt(i); - delete m_toRemoveList.at(i); - return; - } + if (auto it = std::find_if(m_toRemoveList.begin(), m_toRemoveList.end(), + [tc](const ToolChainTreeItem *item) { return item->toolChain == tc; }); + it != m_toRemoveList.end()) { + m_toRemoveList.erase(it); + delete *it; + return; } StaticTreeItem *parent = parentForToolChain(tc); From 50bbe41acc225e7c9c9b9423fdf15c0bb7ea4a4d Mon Sep 17 00:00:00 2001 From: Cristian Adam Date: Mon, 13 Jun 2022 19:26:20 +0200 Subject: [PATCH 13/94] GitHub Actions: Update Qt version to 6.3.0 To be in sync with coin and packaging jobs. Change-Id: I71e95e8283c70a17c42dadeb893ad4b24977f574 Reviewed-by: Reviewed-by: Eike Ziller --- .github/workflows/build_cmake.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build_cmake.yml b/.github/workflows/build_cmake.yml index ab0cbacd8b1..7e7c91d6a21 100644 --- a/.github/workflows/build_cmake.yml +++ b/.github/workflows/build_cmake.yml @@ -7,7 +7,7 @@ on: - 'doc/**' env: - QT_VERSION: 6.2.3 + QT_VERSION: 6.3.0 CLANG_VERSION: 14.0.3 ELFUTILS_VERSION: 0.175 CMAKE_VERSION: 3.21.1 From 17ebce2a7d6347348d4a67ed22772e179e0e24ea Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Fri, 10 Jun 2022 13:10:41 +0200 Subject: [PATCH 14/94] Fix public key deployment in device wizard Since there is no easy way to make device temporary added into cloned device manager, we construct a full ssh command manually inside PublicKeyDeploymentDialog. Fixes: QTCREATORBUG-27706 Change-Id: I28e368a5bff0d89094115e9eaee1395b388359fa Reviewed-by: Eike Ziller --- .../remotelinux/publickeydeploymentdialog.cpp | 31 +++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/src/plugins/remotelinux/publickeydeploymentdialog.cpp b/src/plugins/remotelinux/publickeydeploymentdialog.cpp index 14d856a37ef..e8c0c3b6ce2 100644 --- a/src/plugins/remotelinux/publickeydeploymentdialog.cpp +++ b/src/plugins/remotelinux/publickeydeploymentdialog.cpp @@ -27,6 +27,7 @@ #include #include +#include #include #include #include @@ -74,7 +75,7 @@ PublicKeyDeploymentDialog::PublicKeyDeploymentDialog(const IDevice::ConstPtr &de connect(this, &PublicKeyDeploymentDialog::canceled, this, [this] { d->m_done ? accept() : reject(); }); connect(&d->m_process, &QtcProcess::done, this, [this] { - const bool succeeded = d->m_process.error() == QProcess::UnknownError; + const bool succeeded = d->m_process.result() == ProcessResult::FinishedWithSuccess; QString finalMessage; if (!succeeded) { QString errorMessage = d->m_process.errorString(); @@ -98,7 +99,33 @@ PublicKeyDeploymentDialog::PublicKeyDeploymentDialog(const IDevice::ConstPtr &de const QString command = "test -d .ssh || mkdir -p ~/.ssh && chmod 0700 .ssh && echo '" + QString::fromLocal8Bit(reader.data()) + "' >> .ssh/authorized_keys && chmod 0600 .ssh/authorized_keys"; - d->m_process.setCommand({deviceConfig->filePath("/bin/sh"), {"-c", command}}); + + const SshParameters params = deviceConfig->sshParameters(); + const QString hostKeyCheckingString = params.hostKeyCheckingMode == SshHostKeyCheckingStrict + ? QLatin1String("yes") : QLatin1String("no"); + const bool isWindows = HostOsInfo::isWindowsHost() + && SshSettings::sshFilePath().toString().toLower().contains("/system32/"); + const bool useTimeout = (params.timeout != 0) && !isWindows; + + Utils::CommandLine cmd{SshSettings::sshFilePath()}; + QStringList args{"-q", + "-o", "StrictHostKeyChecking=" + hostKeyCheckingString, + "-o", "Port=" + QString::number(params.port())}; + if (!params.userName().isEmpty()) + args << "-o" << "User=" + params.userName(); + args << "-o" << "BatchMode=no"; + if (useTimeout) + args << "-o" << "ConnectTimeout=" + QString::number(params.timeout); + args << params.host(); + cmd.addArgs(args); + + CommandLine execCmd; + execCmd.addArg("exec"); + execCmd.addCommandLineAsArgs({"/bin/sh", {"-c", command}}, CommandLine::Raw); + + cmd.addArg(execCmd.arguments()); + d->m_process.setCommand(cmd); + SshParameters::setupSshEnvironment(&d->m_process); d->m_process.start(); } From 12dde16e3e220541e3f448e747435002730687eb Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Fri, 10 Jun 2022 14:33:01 +0200 Subject: [PATCH 15/94] DeviceSettingsWidget: Fix testing newly added device Save settings before starting a test, otherwise the test for newly created device fails since the new device was added only for the clone of device manager. Change-Id: Ia36d2ef68740907d7fce51e31c352328de83421c Reviewed-by: hjk Reviewed-by: Eike Ziller --- .../projectexplorer/devicesupport/devicesettingswidget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/projectexplorer/devicesupport/devicesettingswidget.cpp b/src/plugins/projectexplorer/devicesupport/devicesettingswidget.cpp index 13892ceb3b1..fb7ccf70460 100644 --- a/src/plugins/projectexplorer/devicesupport/devicesettingswidget.cpp +++ b/src/plugins/projectexplorer/devicesupport/devicesettingswidget.cpp @@ -153,9 +153,9 @@ void DeviceSettingsWidget::addDevice() m_deviceManager->addDevice(device); m_ui->removeConfigButton->setEnabled(true); m_ui->configurationComboBox->setCurrentIndex(m_deviceManagerModel->indexOf(device)); + saveSettings(); if (device->hasDeviceTester()) testDevice(); - saveSettings(); } void DeviceSettingsWidget::removeDevice() From 0efb8d33460c29c06779669d80b0f60899724bd2 Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Fri, 10 Jun 2022 15:25:28 +0200 Subject: [PATCH 16/94] GenericLinuxDeviceTester: Don't continue testing when echo fails Change-Id: I4b21e1b914816271d59f9001122aedf1eda342dc Reviewed-by: Eike Ziller --- src/plugins/remotelinux/linuxdevicetester.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/plugins/remotelinux/linuxdevicetester.cpp b/src/plugins/remotelinux/linuxdevicetester.cpp index 4c7ac4302b5..869ac90b3e8 100644 --- a/src/plugins/remotelinux/linuxdevicetester.cpp +++ b/src/plugins/remotelinux/linuxdevicetester.cpp @@ -134,14 +134,15 @@ void GenericLinuxDeviceTester::handleEchoDone() else emit errorMessage(tr("echo failed.") + '\n'); setFinished(TestFailure); - } else { - const QString reply = d->echoProcess.stdOut().chopped(1); // Remove trailing \n - if (reply != s_echoContents) - emit errorMessage(tr("Device replied to echo with unexpected contents.") + '\n'); - else - emit progressMessage(tr("Device replied to echo with expected contents.") + '\n'); + return; } + const QString reply = d->echoProcess.stdOut().chopped(1); // Remove trailing \n + if (reply != s_echoContents) + emit errorMessage(tr("Device replied to echo with unexpected contents.") + '\n'); + else + emit progressMessage(tr("Device replied to echo with expected contents.") + '\n'); + testUname(); } From 0b2899215fe89e154e9c484d75107f977c766ec2 Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Wed, 8 Jun 2022 14:24:40 +0200 Subject: [PATCH 17/94] Introduce ProcessBlockingInterface This replaces the ProcessInterface::waitFor...() methods. It's not obligatory to provide this interface when implementing ProcessInterface subclass. In this case generic blocking implementation will be used. The generic implementation usually isn't as efficient as the custom one, however, for some sophisticated implementations of process interface, like e.g. SshProcessInterface, providing custom implementation is really difficult and error prone. That's why we try to keep a balance: we provide two custom implementations for QProcessImpl and for ProcessLauncherImpl, as they are relatively easy to implement, and rely on generic implementation for others. Change-Id: Ifc8bd354479ec67b2e8f74f1510f8de8883e9b94 Reviewed-by: Reviewed-by: hjk --- src/libs/utils/launchersocket.cpp | 21 +- src/libs/utils/launchersocket.h | 8 +- src/libs/utils/processinterface.h | 24 +- src/libs/utils/qtcprocess.cpp | 262 ++++++++++++------ src/libs/utils/terminalprocess_p.h | 6 - src/plugins/docker/dockerdevice.cpp | 25 -- src/plugins/remotelinux/linuxdevice.cpp | 21 -- src/plugins/remotelinux/sshprocessinterface.h | 4 - 8 files changed, 190 insertions(+), 181 deletions(-) diff --git a/src/libs/utils/launchersocket.cpp b/src/libs/utils/launchersocket.cpp index fc8ea36042f..c3d2b8942ab 100644 --- a/src/libs/utils/launchersocket.cpp +++ b/src/libs/utils/launchersocket.cpp @@ -89,21 +89,6 @@ CallerHandle::~CallerHandle() qDeleteAll(m_signals); } -bool CallerHandle::waitForStarted(int msecs) -{ - return waitForSignal(msecs, SignalType::Started); -} - -bool CallerHandle::waitForReadyRead(int msces) -{ - return waitForSignal(msces, SignalType::ReadyRead); -} - -bool CallerHandle::waitForFinished(int msecs) -{ - return waitForSignal(msecs, SignalType::Done); -} - void CallerHandle::flush() { flushFor(SignalType::NoSignal); @@ -329,11 +314,11 @@ void CallerHandle::setProcessSetupData(ProcessSetupData *setup) m_setup = setup; } -bool CallerHandle::waitForSignal(int msecs, SignalType newSignal) +bool CallerHandle::waitForSignal(SignalType signalType, int msecs) { QTC_ASSERT(isCalledFromCallersThread(), return false); QTC_ASSERT(m_launcherHandle, return false); - return m_launcherHandle->waitForSignal(msecs, newSignal); + return m_launcherHandle->waitForSignal(signalType, msecs); } // Called from caller's or launcher's thread. @@ -351,7 +336,7 @@ bool CallerHandle::isCalledFromLaunchersThread() const } // Called from caller's thread exclusively. -bool LauncherHandle::waitForSignal(int msecs, CallerHandle::SignalType newSignal) +bool LauncherHandle::waitForSignal(CallerHandle::SignalType newSignal, int msecs) { QTC_ASSERT(!isCalledFromLaunchersThread(), return false); QDeadlineTimer deadline(msecs); diff --git a/src/libs/utils/launchersocket.h b/src/libs/utils/launchersocket.h index 081cd314659..4956bf652bf 100644 --- a/src/libs/utils/launchersocket.h +++ b/src/libs/utils/launchersocket.h @@ -73,9 +73,7 @@ public: LauncherHandle *launcherHandle() const { return m_launcherHandle; } void setLauncherHandle(LauncherHandle *handle) { QMutexLocker locker(&m_mutex); m_launcherHandle = handle; } - bool waitForStarted(int msecs); - bool waitForReadyRead(int msces); - bool waitForFinished(int msecs); + bool waitForSignal(CallerHandle::SignalType signalType, int msecs); // Returns the list of flushed signals. void flush(); @@ -109,8 +107,6 @@ signals: void done(const Utils::ProcessResultData &resultData); private: - bool waitForSignal(int msecs, SignalType newSignal); - // Called from caller's thread exclusively. void sendPacket(const Internal::LauncherPacket &packet); // Called from caller's or launcher's thread. @@ -158,7 +154,7 @@ public: // Called from caller's thread, moved to launcher's thread afterwards. LauncherHandle(quintptr token) : m_token(token) {} // Called from caller's thread exclusively. - bool waitForSignal(int msecs, CallerHandle::SignalType newSignal); + bool waitForSignal(CallerHandle::SignalType newSignal, int msecs); CallerHandle *callerHandle() const { return m_callerHandle; } void setCallerHandle(CallerHandle *handle) { QMutexLocker locker(&m_mutex); m_callerHandle = handle; } diff --git a/src/libs/utils/processinterface.h b/src/libs/utils/processinterface.h index 727d3caf946..0ca1cc1f15d 100644 --- a/src/libs/utils/processinterface.h +++ b/src/libs/utils/processinterface.h @@ -85,13 +85,22 @@ enum class ProcessSignalType { Done }; +class QTCREATOR_UTILS_EXPORT ProcessBlockingInterface : public QObject +{ +private: + // Wait for: + // - Started is being called only in Starting state. + // - ReadyRead is being called in Starting or Running state. + // - Done is being called in Starting or Running state. + virtual bool waitForSignal(ProcessSignalType signalType, int msecs) = 0; + + friend class Internal::QtcProcessPrivate; +}; + class QTCREATOR_UTILS_EXPORT ProcessInterface : public QObject { Q_OBJECT -public: - ProcessInterface(QObject *parent = nullptr) : QObject(parent) {} - signals: // This should be emitted when being in Starting state only. // After emitting this signal the process enters Running state. @@ -121,14 +130,7 @@ private: // It's being called in Starting or Running state. virtual void sendControlSignal(ControlSignal controlSignal) = 0; - // It's being called only in Starting state. - virtual bool waitForStarted(int msecs) = 0; - - // It's being called in Starting or Running state. - virtual bool waitForReadyRead(int msecs) = 0; - - // It's being called in Starting or Running state. - virtual bool waitForFinished(int msecs) = 0; + virtual ProcessBlockingInterface *processBlockingInterface() const { return nullptr; } friend class QtcProcess; friend class Internal::QtcProcessPrivate; diff --git a/src/libs/utils/qtcprocess.cpp b/src/libs/utils/qtcprocess.cpp index b309106f6be..6aeb7cac897 100644 --- a/src/libs/utils/qtcprocess.cpp +++ b/src/libs/utils/qtcprocess.cpp @@ -322,10 +322,34 @@ bool DefaultImpl::ensureProgramExists(const QString &program) return false; } +class QProcessBlockingImpl : public ProcessBlockingInterface +{ +public: + QProcessBlockingImpl(QProcess *process) : m_process(process) {} + +private: + bool waitForSignal(ProcessSignalType signalType, int msecs) final + { + switch (signalType) { + case ProcessSignalType::Started: + return m_process->waitForStarted(msecs); + case ProcessSignalType::ReadyRead: + return m_process->waitForReadyRead(msecs); + case ProcessSignalType::Done: + return m_process->waitForFinished(msecs); + } + return false; + } + + QProcess *m_process = nullptr; +}; + class QProcessImpl final : public DefaultImpl { public: - QProcessImpl() : m_process(new ProcessHelper(this)) + QProcessImpl() + : m_process(new ProcessHelper(this)) + , m_blockingImpl(new QProcessBlockingImpl(m_process)) { connect(m_process, &QProcess::started, this, &QProcessImpl::handleStarted); @@ -361,9 +385,7 @@ private: } } - bool waitForStarted(int msecs) final { return m_process->waitForStarted(msecs); } - bool waitForReadyRead(int msecs) final { return m_process->waitForReadyRead(msecs); } - bool waitForFinished(int msecs) final { return m_process->waitForFinished(msecs); } + virtual ProcessBlockingInterface *processBlockingInterface() const { return m_blockingImpl; } void doDefaultStart(const QString &program, const QStringList &arguments) final { @@ -411,7 +433,8 @@ private: emit done(result); } - ProcessHelper *m_process; + ProcessHelper *m_process = nullptr; + QProcessBlockingImpl *m_blockingImpl = nullptr; }; static uint uniqueToken() @@ -420,6 +443,33 @@ static uint uniqueToken() return ++globalUniqueToken; } +class ProcessLauncherBlockingImpl : public ProcessBlockingInterface +{ +public: + ProcessLauncherBlockingImpl(CallerHandle *caller) : m_caller(caller) {} + +private: + bool waitForSignal(ProcessSignalType signalType, int msecs) final + { + // TODO: Remove CallerHandle::SignalType + const CallerHandle::SignalType type = [signalType] { + switch (signalType) { + case ProcessSignalType::Started: + return CallerHandle::SignalType::Started; + case ProcessSignalType::ReadyRead: + return CallerHandle::SignalType::ReadyRead; + case ProcessSignalType::Done: + return CallerHandle::SignalType::Done; + } + QTC_CHECK(false); + return CallerHandle::SignalType::NoSignal; + }(); + return m_caller->waitForSignal(type, msecs); + } + + CallerHandle *m_caller = nullptr; +}; + class ProcessLauncherImpl final : public DefaultImpl { Q_OBJECT @@ -434,6 +484,7 @@ public: this, &ProcessInterface::readyRead); connect(m_handle, &CallerHandle::done, this, &ProcessInterface::done); + m_blockingImpl = new ProcessLauncherBlockingImpl(m_handle); } ~ProcessLauncherImpl() final { @@ -462,9 +513,7 @@ private: } } - bool waitForStarted(int msecs) final { return m_handle->waitForStarted(msecs); } - bool waitForReadyRead(int msecs) final { return m_handle->waitForReadyRead(msecs); } - bool waitForFinished(int msecs) final { return m_handle->waitForFinished(msecs); } + virtual ProcessBlockingInterface *processBlockingInterface() const { return m_blockingImpl; } void doDefaultStart(const QString &program, const QStringList &arguments) final { @@ -476,6 +525,7 @@ private: const uint m_token = 0; // Lives in caller's thread. CallerHandle *m_handle = nullptr; + ProcessLauncherBlockingImpl *m_blockingImpl = nullptr; }; static ProcessImpl defaultProcessImpl() @@ -535,13 +585,15 @@ private: const ProcessResultData m_resultData; }; +class GeneralProcessBlockingImpl; + class ProcessInterfaceHandler : public QObject { public: - ProcessInterfaceHandler(QtcProcessPrivate *caller, ProcessInterface *process); + ProcessInterfaceHandler(GeneralProcessBlockingImpl *caller, ProcessInterface *process); // Called from caller's thread exclusively. - bool waitForSignal(int msecs, ProcessSignalType newSignal); + bool waitForSignal(ProcessSignalType newSignal, int msecs); void moveToCallerThread(); private: @@ -555,11 +607,44 @@ private: void handleDone(const ProcessResultData &data); void appendSignal(ProcessInterfaceSignal *newSignal); - QtcProcessPrivate *m_caller = nullptr; + GeneralProcessBlockingImpl *m_caller = nullptr; QMutex m_mutex; QWaitCondition m_waitCondition; }; +class GeneralProcessBlockingImpl : public ProcessBlockingInterface +{ +public: + GeneralProcessBlockingImpl(QtcProcessPrivate *parent); + + void flush() { flushSignals(takeAllSignals()); } + bool flushFor(ProcessSignalType signalType) { + return flushSignals(takeSignalsFor(signalType), &signalType); + } + + bool shouldFlush() const { QMutexLocker locker(&m_mutex); return !m_signals.isEmpty(); } + // Called from ProcessInterfaceHandler thread exclusively. + void appendSignal(ProcessInterfaceSignal *launcherSignal); + +private: + // Called from caller's thread exclusively + bool waitForSignal(ProcessSignalType newSignal, int msecs) final; + + QList takeAllSignals(); + QList takeSignalsFor(ProcessSignalType signalType); + bool flushSignals(const QList &signalList, + ProcessSignalType *signalType = nullptr); + + void handleStartedSignal(const StartedSignal *launcherSignal); + void handleReadyReadSignal(const ReadyReadSignal *launcherSignal); + void handleDoneSignal(const DoneSignal *launcherSignal); + + QtcProcessPrivate *m_caller = nullptr; + std::unique_ptr m_processHandler; + mutable QMutex m_mutex; + QList m_signals; +}; + class QtcProcessPrivate : public QObject { public: @@ -591,11 +676,18 @@ public: void setProcessInterface(ProcessInterface *process) { m_process.reset(process); - m_processHandler.reset(new ProcessInterfaceHandler(this, process)); + m_process->setParent(this); + connect(m_process.get(), &ProcessInterface::started, + this, &QtcProcessPrivate::handleStarted); + connect(m_process.get(), &ProcessInterface::readyRead, + this, &QtcProcessPrivate::handleReadyRead); + connect(m_process.get(), &ProcessInterface::done, + this, &QtcProcessPrivate::handleDone); - // In order to move the process into another thread together with handle - m_process->setParent(m_processHandler.get()); - m_processHandler->setParent(this); + m_blockingInterface.reset(process->processBlockingInterface()); + if (!m_blockingInterface) + m_blockingInterface.reset(new GeneralProcessBlockingImpl(this)); + m_blockingInterface->setParent(this); } CommandLine fullCommandLine() const @@ -624,14 +716,11 @@ public: } QtcProcess *q; - std::unique_ptr m_processHandler; + std::unique_ptr m_blockingInterface; std::unique_ptr m_process; ProcessSetupData m_setup; void slotTimeout(); - void handleStartedSignal(const StartedSignal *launcherSignal); - void handleReadyReadSignal(const ReadyReadSignal *launcherSignal); - void handleDoneSignal(const DoneSignal *launcherSignal); void handleStarted(qint64 processId, qint64 applicationMainThreadId); void handleReadyRead(const QByteArray &outputData, const QByteArray &errorData); void handleDone(const ProcessResultData &data); @@ -647,31 +736,11 @@ public: ProcessResult interpretExitCode(int exitCode); - // === ProcessInterfaceHandler related === - // Called from caller's thread exclusively - bool waitForSignal(int msecs, ProcessSignalType newSignal); - void flush() { flushSignals(takeAllSignals()); } - bool flushFor(ProcessSignalType signalType) { - return flushSignals(takeSignalsFor(signalType), &signalType); - } - - QList takeAllSignals(); - QList takeSignalsFor(ProcessSignalType signalType); - bool flushSignals(const QList &signalList, - ProcessSignalType *signalType = nullptr); - - bool shouldFlush() const { QMutexLocker locker(&m_mutex); return !m_signals.isEmpty(); } + bool waitForSignal(ProcessSignalType signalType, int msecs); Qt::ConnectionType connectionType() const; void sendControlSignal(ControlSignal controlSignal); - // Called from ProcessInterfaceHandler thread exclusively. - void appendSignal(ProcessInterfaceSignal *launcherSignal); - mutable QMutex m_mutex; - QList m_signals; QTimer m_killTimer; - - // ======================================= - QProcess::ProcessState m_state = QProcess::NotRunning; qint64 m_processId = 0; qint64 m_applicationMainThreadId = 0; @@ -692,10 +761,11 @@ public: Guard m_guard; }; -ProcessInterfaceHandler::ProcessInterfaceHandler(QtcProcessPrivate *caller, +ProcessInterfaceHandler::ProcessInterfaceHandler(GeneralProcessBlockingImpl *caller, ProcessInterface *process) : m_caller(caller) { + process->disconnect(); connect(process, &ProcessInterface::started, this, &ProcessInterfaceHandler::handleStarted); connect(process, &ProcessInterface::readyRead, @@ -705,7 +775,7 @@ ProcessInterfaceHandler::ProcessInterfaceHandler(QtcProcessPrivate *caller, } // Called from caller's thread exclusively. -bool ProcessInterfaceHandler::waitForSignal(int msecs, ProcessSignalType newSignal) +bool ProcessInterfaceHandler::waitForSignal(ProcessSignalType newSignal, int msecs) { QDeadlineTimer deadline(msecs); while (true) { @@ -769,17 +839,20 @@ void ProcessInterfaceHandler::appendSignal(ProcessInterfaceSignal *newSignal) } m_waitCondition.wakeOne(); // call in callers thread - QMetaObject::invokeMethod(m_caller, &QtcProcessPrivate::flush); + QMetaObject::invokeMethod(m_caller, &GeneralProcessBlockingImpl::flush); } -// Called from caller's thread exclusively -bool QtcProcessPrivate::waitForSignal(int msecs, ProcessSignalType newSignal) +GeneralProcessBlockingImpl::GeneralProcessBlockingImpl(QtcProcessPrivate *parent) + : m_caller(parent) + , m_processHandler(new ProcessInterfaceHandler(this, parent->m_process.get())) { - const QDeadlineTimer timeout(msecs); - const QDeadlineTimer currentKillTimeout(m_killTimer.remainingTime()); - const bool needsSplit = m_killTimer.isActive() ? timeout > currentKillTimeout : false; - const QDeadlineTimer mainTimeout = needsSplit ? currentKillTimeout : timeout; + // In order to move the process interface into another thread together with handle + parent->m_process.get()->setParent(m_processHandler.get()); + m_processHandler->setParent(this); +} +bool GeneralProcessBlockingImpl::waitForSignal(ProcessSignalType newSignal, int msecs) +{ m_processHandler->setParent(nullptr); QThread thread; @@ -789,12 +862,7 @@ bool QtcProcessPrivate::waitForSignal(int msecs, ProcessSignalType newSignal) // the caller here is blocked, so all signals should be buffered and we are going // to flush them from inside waitForSignal(). m_processHandler->moveToThread(&thread); - bool result = m_processHandler->waitForSignal(mainTimeout.remainingTime(), newSignal); - if (!result && needsSplit) { - m_killTimer.stop(); - sendControlSignal(ControlSignal::Kill); - result = m_processHandler->waitForSignal(timeout.remainingTime(), newSignal); - } + const bool result = m_processHandler->waitForSignal(newSignal, msecs); m_processHandler->moveToCallerThread(); m_processHandler->setParent(this); thread.quit(); @@ -803,14 +871,14 @@ bool QtcProcessPrivate::waitForSignal(int msecs, ProcessSignalType newSignal) } // Called from caller's thread exclusively -QList QtcProcessPrivate::takeAllSignals() +QList GeneralProcessBlockingImpl::takeAllSignals() { QMutexLocker locker(&m_mutex); return std::exchange(m_signals, {}); } // Called from caller's thread exclusively -QList QtcProcessPrivate::takeSignalsFor(ProcessSignalType signalType) +QList GeneralProcessBlockingImpl::takeSignalsFor(ProcessSignalType signalType) { // If we are flushing for ReadyRead or Done - flush all. if (signalType != ProcessSignalType::Started) @@ -840,7 +908,7 @@ QList QtcProcessPrivate::takeSignalsFor(ProcessSignalT } // Called from caller's thread exclusively -bool QtcProcessPrivate::flushSignals(const QList &signalList, +bool GeneralProcessBlockingImpl::flushSignals(const QList &signalList, ProcessSignalType *signalType) { bool signalMatched = false; @@ -866,14 +934,50 @@ bool QtcProcessPrivate::flushSignals(const QList &sign return signalMatched; } -// Called from caller's thread exclusively +void GeneralProcessBlockingImpl::handleStartedSignal(const StartedSignal *aSignal) +{ + m_caller->handleStarted(aSignal->processId(), aSignal->applicationMainThreadId()); +} + +void GeneralProcessBlockingImpl::handleReadyReadSignal(const ReadyReadSignal *aSignal) +{ + m_caller->handleReadyRead(aSignal->stdOut(), aSignal->stdErr()); +} + +void GeneralProcessBlockingImpl::handleDoneSignal(const DoneSignal *aSignal) +{ + m_caller->handleDone(aSignal->resultData()); +} + +// Called from ProcessInterfaceHandler thread exclusively. +void GeneralProcessBlockingImpl::appendSignal(ProcessInterfaceSignal *newSignal) +{ + QMutexLocker locker(&m_mutex); + m_signals.append(newSignal); +} + +bool QtcProcessPrivate::waitForSignal(ProcessSignalType newSignal, int msecs) +{ + const QDeadlineTimer timeout(msecs); + const QDeadlineTimer currentKillTimeout(m_killTimer.remainingTime()); + const bool needsSplit = m_killTimer.isActive() ? timeout > currentKillTimeout : false; + const QDeadlineTimer mainTimeout = needsSplit ? currentKillTimeout : timeout; + + bool result = m_blockingInterface->waitForSignal(newSignal, mainTimeout.remainingTime()); + if (!result && needsSplit) { + m_killTimer.stop(); + sendControlSignal(ControlSignal::Kill); + result = m_blockingInterface->waitForSignal(newSignal, timeout.remainingTime()); + } + return result; +} + Qt::ConnectionType QtcProcessPrivate::connectionType() const { return (m_process->thread() == thread()) ? Qt::DirectConnection : Qt::BlockingQueuedConnection; } -// Called from caller's thread exclusively void QtcProcessPrivate::sendControlSignal(ControlSignal controlSignal) { QTC_ASSERT(QThread::currentThread() == thread(), return); @@ -885,13 +989,6 @@ void QtcProcessPrivate::sendControlSignal(ControlSignal controlSignal) }, connectionType()); } -// Called from ProcessInterfaceHandler thread exclusively. -void QtcProcessPrivate::appendSignal(ProcessInterfaceSignal *newSignal) -{ - QMutexLocker locker(&m_mutex); - m_signals.append(newSignal); -} - void QtcProcessPrivate::clearForRun() { m_hangTimerCount = 0; @@ -1444,8 +1541,8 @@ bool QtcProcess::waitForStarted(int msecs) return true; if (d->m_state == QProcess::NotRunning) return false; - return s_waitForStarted.measureAndRun(&QtcProcessPrivate::waitForSignal, d, msecs, - ProcessSignalType::Started); + return s_waitForStarted.measureAndRun(&QtcProcessPrivate::waitForSignal, d, + ProcessSignalType::Started, msecs); } bool QtcProcess::waitForReadyRead(int msecs) @@ -1453,7 +1550,7 @@ bool QtcProcess::waitForReadyRead(int msecs) QTC_ASSERT(d->m_process, return false); if (d->m_state == QProcess::NotRunning) return false; - return d->waitForSignal(msecs, ProcessSignalType::ReadyRead); + return d->waitForSignal(ProcessSignalType::ReadyRead, msecs); } bool QtcProcess::waitForFinished(int msecs) @@ -1461,7 +1558,7 @@ bool QtcProcess::waitForFinished(int msecs) QTC_ASSERT(d->m_process, return false); if (d->m_state == QProcess::NotRunning) return false; - return d->waitForSignal(msecs, ProcessSignalType::Done); + return d->waitForSignal(ProcessSignalType::Done, msecs); } QByteArray QtcProcess::readAllStandardOutput() @@ -1511,9 +1608,9 @@ void QtcProcess::close() d->m_process->disconnect(); d->m_process.release()->deleteLater(); } - if (d->m_processHandler) { - d->m_processHandler->disconnect(); - d->m_processHandler.release()->deleteLater(); + if (d->m_blockingInterface) { + d->m_blockingInterface->disconnect(); + d->m_blockingInterface.release()->deleteLater(); } d->clearForRun(); } @@ -1854,22 +1951,6 @@ void QtcProcessPrivate::slotTimeout() } } -void QtcProcessPrivate::handleStartedSignal(const StartedSignal *aSignal) -{ - handleStarted(aSignal->processId(), aSignal->applicationMainThreadId()); -} - -void QtcProcessPrivate::handleReadyReadSignal(const ReadyReadSignal *aSignal) -{ - handleReadyRead(aSignal->stdOut(), aSignal->stdErr()); -} - -void QtcProcessPrivate::handleDoneSignal(const DoneSignal *aSignal) -{ - m_killTimer.stop(); - handleDone(aSignal->resultData()); -} - void QtcProcessPrivate::handleStarted(qint64 processId, qint64 applicationMainThreadId) { QTC_CHECK(m_state == QProcess::Starting); @@ -1908,6 +1989,7 @@ void QtcProcessPrivate::handleReadyRead(const QByteArray &outputData, const QByt void QtcProcessPrivate::handleDone(const ProcessResultData &data) { + m_killTimer.stop(); m_resultData = data; switch (m_state) { diff --git a/src/libs/utils/terminalprocess_p.h b/src/libs/utils/terminalprocess_p.h index f92d00f8448..32be83f0206 100644 --- a/src/libs/utils/terminalprocess_p.h +++ b/src/libs/utils/terminalprocess_p.h @@ -50,12 +50,6 @@ private: qint64 write(const QByteArray &) final { QTC_CHECK(false); return -1; } void sendControlSignal(ControlSignal controlSignal) final; - // intentionally no-op without an assert - bool waitForStarted(int) final { return false; } - bool waitForReadyRead(int) final { QTC_CHECK(false); return false; } - // intentionally no-op without an assert - bool waitForFinished(int) final { return false; } - // OK, however, impl looks a bit different (!= NotRunning vs == Running). // Most probably changing it into (== Running) should be OK. bool isRunning() const; diff --git a/src/plugins/docker/dockerdevice.cpp b/src/plugins/docker/dockerdevice.cpp index 7c450a7b90f..ba24dd7bea0 100644 --- a/src/plugins/docker/dockerdevice.cpp +++ b/src/plugins/docker/dockerdevice.cpp @@ -168,10 +168,6 @@ private: qint64 write(const QByteArray &data) override; void sendControlSignal(ControlSignal controlSignal) override; - bool waitForStarted(int msecs) override; - bool waitForReadyRead(int msecs) override; - bool waitForFinished(int msecs) override; - private: CommandLine fullLocalCommandLine(bool interactive); @@ -288,27 +284,6 @@ void DockerProcessImpl::sendControlSignal(ControlSignal controlSignal) {"kill", {QString("-%1").arg(signal), QString("%2").arg(m_remotePID)}}); } -bool DockerProcessImpl::waitForStarted(int msecs) -{ - Q_UNUSED(msecs) - QTC_CHECK(false); - return false; -} - -bool DockerProcessImpl::waitForReadyRead(int msecs) -{ - Q_UNUSED(msecs) - QTC_CHECK(false); - return false; -} - -bool DockerProcessImpl::waitForFinished(int msecs) -{ - Q_UNUSED(msecs) - QTC_CHECK(false); - return false; -} - IDeviceWidget *DockerDevice::createWidget() { return new DockerDeviceWidget(sharedFromThis()); diff --git a/src/plugins/remotelinux/linuxdevice.cpp b/src/plugins/remotelinux/linuxdevice.cpp index 55be3fe0575..9f68025c688 100644 --- a/src/plugins/remotelinux/linuxdevice.cpp +++ b/src/plugins/remotelinux/linuxdevice.cpp @@ -497,27 +497,6 @@ qint64 SshProcessInterface::write(const QByteArray &data) return d->m_process.writeRaw(data); } -bool SshProcessInterface::waitForStarted(int msecs) -{ - Q_UNUSED(msecs) - QTC_CHECK(false); - return false; -} - -bool SshProcessInterface::waitForReadyRead(int msecs) -{ - Q_UNUSED(msecs) - QTC_CHECK(false); - return false; -} - -bool SshProcessInterface::waitForFinished(int msecs) -{ - Q_UNUSED(msecs) - QTC_CHECK(false); - return false; -} - LinuxProcessInterface::LinuxProcessInterface(const LinuxDevice *linuxDevice) : SshProcessInterface(linuxDevice) { diff --git a/src/plugins/remotelinux/sshprocessinterface.h b/src/plugins/remotelinux/sshprocessinterface.h index e60009ded2a..871c90d3ed6 100644 --- a/src/plugins/remotelinux/sshprocessinterface.h +++ b/src/plugins/remotelinux/sshprocessinterface.h @@ -60,10 +60,6 @@ private: qint64 write(const QByteArray &data) final; void sendControlSignal(Utils::ControlSignal controlSignal) override = 0; - bool waitForStarted(int msecs) final; - bool waitForReadyRead(int msecs) final; - bool waitForFinished(int msecs) final; - friend class SshProcessInterfacePrivate; SshProcessInterfacePrivate *d = nullptr; }; From 7bd703d123166061a5ee2543b35da4ef177755fa Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Fri, 10 Jun 2022 13:45:29 +0200 Subject: [PATCH 18/94] Increase ctest timeout for tst_qtcprocess Default is 5 seconds, which is by far not enough. Change-Id: I4a5851de3ec2268bd68b6a386efa8dfa181e0af3 Reviewed-by: Reviewed-by: Jarek Kobus --- tests/auto/utils/qtcprocess/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/auto/utils/qtcprocess/CMakeLists.txt b/tests/auto/utils/qtcprocess/CMakeLists.txt index 51720bbeb5b..c03eee4945b 100644 --- a/tests/auto/utils/qtcprocess/CMakeLists.txt +++ b/tests/auto/utils/qtcprocess/CMakeLists.txt @@ -4,6 +4,7 @@ file(RELATIVE_PATH RELATIVE_TEST_PATH "${PROJECT_BINARY_DIR}" "${CMAKE_CURRENT_B file(RELATIVE_PATH TEST_RELATIVE_LIBEXEC_PATH "/${RELATIVE_TEST_PATH}" "/${IDE_LIBEXEC_PATH}") add_qtc_test(tst_qtcprocess + TIMEOUT 30 DEFINES "TEST_RELATIVE_LIBEXEC_PATH=\"${TEST_RELATIVE_LIBEXEC_PATH}\"" "PROCESS_TESTAPP=\"${CMAKE_CURRENT_BINARY_DIR}/processtestapp\"" DEPENDS Utils app_version From a370c154d09e1a5d744cffa434c742de7eee6121 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Tue, 14 Jun 2022 09:03:23 +0200 Subject: [PATCH 19/94] QmlProjectManager: Fix crash when building with Qt5 Change-Id: Id5af5b6dfe4613f2a0669febee4622944854a999 Reviewed-by: Alessandro Portale --- src/plugins/qmlprojectmanager/qdslandingpage.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/plugins/qmlprojectmanager/qdslandingpage.cpp b/src/plugins/qmlprojectmanager/qdslandingpage.cpp index 6ca001ae7fc..13b469a18e7 100644 --- a/src/plugins/qmlprojectmanager/qdslandingpage.cpp +++ b/src/plugins/qmlprojectmanager/qdslandingpage.cpp @@ -103,12 +103,14 @@ QWidget *QdsLandingPage::widget() void QdsLandingPage::show() { - m_widget->rootObject()->setProperty(PROPERTY_QDSINSTALLED, m_qdsInstalled); - m_widget->rootObject()->setProperty(PROPERTY_PROJECTFILEEXISTS, m_projectFileExists); - m_widget->rootObject()->setProperty(PROPERTY_QTVERSION, m_qtVersion); - m_widget->rootObject()->setProperty(PROPERTY_QDSVERSION, m_qdsVersion); - m_widget->rootObject()->setProperty(PROPERTY_CMAKES, m_cmakeResources); - m_widget->rootObject()->setProperty(PROPERTY_REMEMBER, Qt::Unchecked); + if (m_widget->rootObject()) { + m_widget->rootObject()->setProperty(PROPERTY_QDSINSTALLED, m_qdsInstalled); + m_widget->rootObject()->setProperty(PROPERTY_PROJECTFILEEXISTS, m_projectFileExists); + m_widget->rootObject()->setProperty(PROPERTY_QTVERSION, m_qtVersion); + m_widget->rootObject()->setProperty(PROPERTY_QDSVERSION, m_qdsVersion); + m_widget->rootObject()->setProperty(PROPERTY_CMAKES, m_cmakeResources); + m_widget->rootObject()->setProperty(PROPERTY_REMEMBER, Qt::Unchecked); + } m_widget->show(); } From 6c4d5ef3c7a74ff18d29c624c56b44bea6cfdc88 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Mon, 13 Jun 2022 09:38:01 +0200 Subject: [PATCH 20/94] Modeling: Fix crash while reset model Fixes: QTCREATORBUG-27226 Change-Id: I1333379a99ff5ebd08b121f2f014c6971a192699 Reviewed-by: David Schulz Reviewed-by: hjk --- .../qmt/diagram_controller/diagramcontroller.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/libs/modelinglib/qmt/diagram_controller/diagramcontroller.cpp b/src/libs/modelinglib/qmt/diagram_controller/diagramcontroller.cpp index f7d7e702e5b..72eef3ef742 100644 --- a/src/libs/modelinglib/qmt/diagram_controller/diagramcontroller.cpp +++ b/src/libs/modelinglib/qmt/diagram_controller/diagramcontroller.cpp @@ -557,9 +557,11 @@ void DiagramController::onBeginResetModel() void DiagramController::onEndResetModel() { updateAllDiagramsList(); - foreach (MDiagram *diagram, m_allDiagrams) { + for (MDiagram *diagram : qAsConst(m_allDiagrams)) { + const QList elements = diagram->diagramElements(); // remove all elements which are not longer part of the model - foreach (DElement *element, diagram->diagramElements()) { + for (int i = elements.size() - 1; i >= 0; --i) { + DElement *element = elements.at(i); if (element->modelUid().isValid()) { MElement *modelElement = m_modelController->findElement(element->modelUid()); if (!modelElement) @@ -567,7 +569,7 @@ void DiagramController::onEndResetModel() } } // update all remaining elements from model - foreach (DElement *element, diagram->diagramElements()) + for (DElement *element : diagram->diagramElements()) updateElementFromModel(element, diagram, false); } emit endResetAllDiagrams(); From 4e69aece65aaad4ee7ca8c8f84cc109a9529feec Mon Sep 17 00:00:00 2001 From: hjk Date: Fri, 10 Jun 2022 18:13:28 +0200 Subject: [PATCH 21/94] RemoteLinux: Hack in a way do make the MakeInstallStep work with docker A proper solution would be a proper step handling the copy from the build container to the device. Instead, rely on the (unchecked) mounting of build directory from the host file system. Task-number: QTCREATORBUG-27325 Change-Id: I1a364460c08f205dbc341fa0dc941cf1e3c950ac Reviewed-by: Christian Stenger --- src/plugins/remotelinux/makeinstallstep.cpp | 33 ++++++++++++++++----- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/src/plugins/remotelinux/makeinstallstep.cpp b/src/plugins/remotelinux/makeinstallstep.cpp index d676a26f46d..f5f60b95bfc 100644 --- a/src/plugins/remotelinux/makeinstallstep.cpp +++ b/src/plugins/remotelinux/makeinstallstep.cpp @@ -31,6 +31,8 @@ #include #include #include +#include +#include #include #include #include @@ -67,6 +69,18 @@ MakeInstallStep::MakeInstallStep(BuildStepList *parent, Id id) : MakeStep(parent jobCountAspect()->setVisible(false); disabledForSubdirsAspect()->setVisible(false); + // FIXME: Hack, Part#1: If the build device is not local, start with a temp dir + // inside the build dir. On Docker that's typically shared with the host. + const IDevice::ConstPtr device = BuildDeviceKitAspect::device(target()->kit()); + const bool hack = device && device->type() != ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE; + FilePath rootPath; + if (hack) { + rootPath = buildDirectory().pathAppended(".tmp-root"); + } else { + QTemporaryDir tmpDir; + rootPath = FilePath::fromString(tmpDir.path()); + } + const auto makeAspect = addAspect(parent->target(), ExecutableAspect::BuildDevice); makeAspect->setId(MakeAspectId); @@ -82,6 +96,7 @@ MakeInstallStep::MakeInstallStep(BuildStepList *parent, Id id) : MakeStep(parent installRootAspect->setDisplayStyle(StringAspect::PathChooserDisplay); installRootAspect->setExpectedKind(PathChooser::Directory); installRootAspect->setLabelText(tr("Install root:")); + installRootAspect->setFilePath(rootPath); connect(installRootAspect, &StringAspect::changed, this, &MakeInstallStep::updateArgsFromAspect); @@ -110,17 +125,14 @@ MakeInstallStep::MakeInstallStep(BuildStepList *parent, Id id) : MakeStep(parent updateArgsFromAspect(); updateFromCustomCommandLineAspect(); }; + connect(customCommandLineAspect, &StringAspect::checkedChanged, this, updateCommand); connect(customCommandLineAspect, &StringAspect::changed, this, &MakeInstallStep::updateFromCustomCommandLineAspect); connect(target(), &Target::buildSystemUpdated, this, updateCommand); - QTemporaryDir tmpDir; - installRootAspect->setFilePath(FilePath::fromString(tmpDir.path())); - - const MakeInstallCommand cmd = - buildSystem()->makeInstallCommand(FilePath::fromString(tmpDir.path())); + const MakeInstallCommand cmd = buildSystem()->makeInstallCommand(rootPath); QTC_ASSERT(!cmd.command.isEmpty(), return); makeAspect->setExecutable(cmd.command.executable()); } @@ -194,6 +206,7 @@ bool MakeInstallStep::init() void MakeInstallStep::finish(bool success) { if (success) { + const bool hack = makeCommand().needsDevice(); const FilePath rootDir = installRoot().onDevice(makeCommand()); m_deploymentData = DeploymentData(); @@ -204,7 +217,7 @@ void MakeInstallStep::finish(bool success) const auto appFileNames = transform>(buildSystem()->applicationTargets(), [](const BuildTargetInfo &appTarget) { return appTarget.targetFilePath.fileName(); }); - auto handleFile = [this, &appFileNames, startPos](const FilePath &filePath) { + auto handleFile = [this, &appFileNames, startPos, hack](const FilePath &filePath) { const DeployableFile::Type type = appFileNames.contains(filePath.fileName()) ? DeployableFile::TypeExecutable : DeployableFile::TypeNormal; @@ -212,7 +225,13 @@ void MakeInstallStep::finish(bool success) // FIXME: This is conceptually the wrong place, but currently "downstream" like // the rsync step doesn't handle full remote paths here. targetDir = FilePath::fromString(targetDir).path(); - m_deploymentData.addFile(filePath, targetDir, type); + + // FIXME: Hack, Part#2: If the build was indeed not local, drop the remoteness. + // As we rely on shared build directory, this "maps" to the host. + if (hack) + m_deploymentData.addFile(FilePath::fromString(filePath.path()), targetDir, type); + else + m_deploymentData.addFile(filePath, targetDir, type); return true; }; rootDir.iterateDirectory(handleFile, From fd90cf0a827931a08e80279ced8748ba6b3864d6 Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Mon, 13 Jun 2022 17:10:03 +0200 Subject: [PATCH 22/94] Fix debugging on iOS The RunControl nowadays asks DeviceManager::deviceForPath(runnable.command.executable) to get the device, instead of passing that through the runnable. Since the runnable's command executable is set via IDevice::filePath(pathOnDevice), where "pathOnDevice" by default is from the executableAspect, IDevice::filePath should actually return a "global" path in the form of "device:///". Since we do not want "device:...." paths for the desktop, return the simple path in that case only instead. Fixes: QTCREATORBUG-27709 Change-Id: I75f9406cf3254980e1fee203275b0e72202b7b6d Reviewed-by: Jarek Kobus Reviewed-by: hjk --- .../devicesupport/desktopdevice.cpp | 6 ++++++ .../projectexplorer/devicesupport/desktopdevice.h | 1 + .../projectexplorer/devicesupport/idevice.cpp | 15 +++++++++++++-- src/plugins/remotelinux/linuxdevice.cpp | 14 -------------- src/plugins/remotelinux/linuxdevice.h | 1 - 5 files changed, 20 insertions(+), 17 deletions(-) diff --git a/src/plugins/projectexplorer/devicesupport/desktopdevice.cpp b/src/plugins/projectexplorer/devicesupport/desktopdevice.cpp index 1ffbdba5f71..64e9556995d 100644 --- a/src/plugins/projectexplorer/devicesupport/desktopdevice.cpp +++ b/src/plugins/projectexplorer/devicesupport/desktopdevice.cpp @@ -179,6 +179,12 @@ bool DesktopDevice::setPermissions(const FilePath &filePath, QFile::Permissions return filePath.setPermissions(permissions); } +FilePath DesktopDevice::mapToGlobalPath(const Utils::FilePath &pathOnDevice) const +{ + QTC_CHECK(!pathOnDevice.needsDevice()); + return pathOnDevice; +} + Environment DesktopDevice::systemEnvironment() const { return Environment::systemEnvironment(); diff --git a/src/plugins/projectexplorer/devicesupport/desktopdevice.h b/src/plugins/projectexplorer/devicesupport/desktopdevice.h index 391bf53997f..37dc326a989 100644 --- a/src/plugins/projectexplorer/devicesupport/desktopdevice.h +++ b/src/plugins/projectexplorer/devicesupport/desktopdevice.h @@ -79,6 +79,7 @@ public: qint64 fileSize(const Utils::FilePath &filePath) const override; QFile::Permissions permissions(const Utils::FilePath &filePath) const override; bool setPermissions(const Utils::FilePath &filePath, QFile::Permissions) const override; + Utils::FilePath mapToGlobalPath(const Utils::FilePath &pathOnDevice) const override; protected: DesktopDevice(); diff --git a/src/plugins/projectexplorer/devicesupport/idevice.cpp b/src/plugins/projectexplorer/devicesupport/idevice.cpp index 69344b44a2c..f7ca5633bb7 100644 --- a/src/plugins/projectexplorer/devicesupport/idevice.cpp +++ b/src/plugins/projectexplorer/devicesupport/idevice.cpp @@ -212,7 +212,17 @@ bool IDevice::isAnyUnixDevice() const FilePath IDevice::mapToGlobalPath(const FilePath &pathOnDevice) const { - return pathOnDevice; + if (pathOnDevice.needsDevice()) { + // Already correct form, only sanity check it's ours... + QTC_CHECK(handlesFile(pathOnDevice)); + return pathOnDevice; + } + // match DeviceManager::deviceForPath + FilePath result; + result.setPath(pathOnDevice.path()); + result.setScheme("device"); + result.setHost(id().toString()); + return result; } QString IDevice::mapToDevicePath(const FilePath &globalPath) const @@ -227,7 +237,8 @@ FilePath IDevice::filePath(const QString &pathOnDevice) const bool IDevice::handlesFile(const FilePath &filePath) const { - Q_UNUSED(filePath); + if (filePath.scheme() == "device" && filePath.host() == id().toString()) + return true; return false; } diff --git a/src/plugins/remotelinux/linuxdevice.cpp b/src/plugins/remotelinux/linuxdevice.cpp index 9f68025c688..edc6a624562 100644 --- a/src/plugins/remotelinux/linuxdevice.cpp +++ b/src/plugins/remotelinux/linuxdevice.cpp @@ -1104,20 +1104,6 @@ QString LinuxDevice::userAtHost() const return sshParameters().userAtHost(); } -FilePath LinuxDevice::mapToGlobalPath(const FilePath &pathOnDevice) const -{ - if (pathOnDevice.needsDevice()) { - // Already correct form, only sanity check it's ours... - QTC_CHECK(handlesFile(pathOnDevice)); - return pathOnDevice; - } - FilePath result; - result.setScheme("device"); - result.setHost(id().toString()); - result.setPath(pathOnDevice.path()); - return result; -} - bool LinuxDevice::handlesFile(const FilePath &filePath) const { if (filePath.scheme() == "device" && filePath.host() == id().toString()) diff --git a/src/plugins/remotelinux/linuxdevice.h b/src/plugins/remotelinux/linuxdevice.h index 1b286ac1080..2e7000a09dd 100644 --- a/src/plugins/remotelinux/linuxdevice.h +++ b/src/plugins/remotelinux/linuxdevice.h @@ -56,7 +56,6 @@ public: ProjectExplorer::DeviceEnvironmentFetcher::Ptr environmentFetcher() const override; QString userAtHost() const; - Utils::FilePath mapToGlobalPath(const Utils::FilePath &pathOnDevice) const override; bool handlesFile(const Utils::FilePath &filePath) const override; bool isExecutableFile(const Utils::FilePath &filePath) const override; From 91b8433cbd3a2485f99776dbaf65c2ee0f2cae22 Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 14 Jun 2022 15:12:35 +0200 Subject: [PATCH 23/94] ProjectExplorer: Remove an explicit mimetype from FileInfo use Change-Id: I96e6cfcb5c8f42487d693e1a55448b3441d796ba Reviewed-by: Eike Ziller --- src/plugins/projectexplorer/simpleprojectwizard.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/projectexplorer/simpleprojectwizard.cpp b/src/plugins/projectexplorer/simpleprojectwizard.cpp index 6d7b2e2884f..0b8a20a29ff 100644 --- a/src/plugins/projectexplorer/simpleprojectwizard.cpp +++ b/src/plugins/projectexplorer/simpleprojectwizard.cpp @@ -224,7 +224,7 @@ GeneratedFiles generateQmakeFiles(const SimpleProjectWizardDialog *wizard, for (const FilePath &fileName : wizard->selectedFiles()) { QString source = dir.relativeFilePath(fileName.toString()); - MimeType mimeType = Utils::mimeTypeForFile(fileName.toFileInfo()); + MimeType mimeType = Utils::mimeTypeForFile(fileName); if (mimeType.matchesName("text/x-chdr") || mimeType.matchesName("text/x-c++hdr")) proHeaders += " $$PWD/" + source + " \\\n"; else From dcbeb354f414fcc6da6f05bfe2077627f92c1446 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Tue, 14 Jun 2022 13:05:31 +0200 Subject: [PATCH 24/94] AutoTest: Only display function name if we have one Should normally not happen, but may happen if we face sanitizer issues. Change-Id: I5e99fb99f241e24f507f94bce9009c2212188691 Reviewed-by: David Schulz --- src/plugins/autotest/qtest/qttestresult.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/plugins/autotest/qtest/qttestresult.cpp b/src/plugins/autotest/qtest/qttestresult.cpp index aa16f601963..eee2697ff71 100644 --- a/src/plugins/autotest/qtest/qttestresult.cpp +++ b/src/plugins/autotest/qtest/qttestresult.cpp @@ -52,7 +52,9 @@ const QString QtTestResult::outputString(bool selected) const case ResultType::UnexpectedPass: case ResultType::BlacklistedFail: case ResultType::BlacklistedPass: - output = className + "::" + m_function; + output = className; + if (!m_function.isEmpty()) + output.append("::" + m_function); if (!m_dataTag.isEmpty()) output.append(QString(" (%1)").arg(m_dataTag)); if (selected && !desc.isEmpty()) { @@ -60,7 +62,9 @@ const QString QtTestResult::outputString(bool selected) const } break; case ResultType::Benchmark: - output = className + "::" + m_function; + output = className; + if (!m_function.isEmpty()) + output.append("::" + m_function); if (!m_dataTag.isEmpty()) output.append(QString(" (%1)").arg(m_dataTag)); if (!desc.isEmpty()) { From b28f90711491c329cf7e439f193aaf4d53e9f922 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Fri, 10 Jun 2022 10:18:34 +0200 Subject: [PATCH 25/94] AutoTest: Use QtcProcess for test runner Change-Id: I29b15a08a260aaf8d2c4071d5ea71d49902d8ef6 Reviewed-by: David Schulz --- .../autotest/boost/boosttestconfiguration.cpp | 2 +- .../autotest/boost/boosttestconfiguration.h | 2 +- .../autotest/boost/boosttestoutputreader.cpp | 8 ++-- .../autotest/boost/boosttestoutputreader.h | 4 +- .../autotest/catch/catchconfiguration.cpp | 3 +- .../autotest/catch/catchconfiguration.h | 2 +- .../autotest/catch/catchoutputreader.cpp | 3 +- .../autotest/catch/catchoutputreader.h | 2 +- .../autotest/ctest/ctestconfiguration.cpp | 2 +- .../autotest/ctest/ctestconfiguration.h | 2 +- .../autotest/ctest/ctestoutputreader.cpp | 2 +- .../autotest/ctest/ctestoutputreader.h | 4 +- .../autotest/gtest/gtestconfiguration.cpp | 2 +- .../autotest/gtest/gtestconfiguration.h | 2 +- .../autotest/gtest/gtestoutputreader.cpp | 10 +++-- .../autotest/gtest/gtestoutputreader.h | 2 +- .../autotest/qtest/qttestconfiguration.cpp | 2 +- .../autotest/qtest/qttestconfiguration.h | 2 +- .../autotest/qtest/qttestoutputreader.cpp | 2 +- .../autotest/qtest/qttestoutputreader.h | 2 +- .../autotest/quick/quicktestconfiguration.cpp | 2 +- .../autotest/quick/quicktestconfiguration.h | 2 +- src/plugins/autotest/testconfiguration.h | 6 +-- src/plugins/autotest/testoutputreader.cpp | 20 ++++----- src/plugins/autotest/testoutputreader.h | 7 ++-- src/plugins/autotest/testrunconfiguration.h | 2 +- src/plugins/autotest/testrunner.cpp | 41 +++++++++++-------- src/plugins/autotest/testrunner.h | 6 ++- 28 files changed, 79 insertions(+), 67 deletions(-) diff --git a/src/plugins/autotest/boost/boosttestconfiguration.cpp b/src/plugins/autotest/boost/boosttestconfiguration.cpp index 5e65962a52e..556228bd653 100644 --- a/src/plugins/autotest/boost/boosttestconfiguration.cpp +++ b/src/plugins/autotest/boost/boosttestconfiguration.cpp @@ -39,7 +39,7 @@ namespace Autotest { namespace Internal { TestOutputReader *BoostTestConfiguration::outputReader(const QFutureInterface &fi, - QProcess *app) const + Utils::QtcProcess *app) const { auto settings = static_cast(framework()->testSettings()); return new BoostTestOutputReader(fi, app, buildDirectory(), projectFile(), diff --git a/src/plugins/autotest/boost/boosttestconfiguration.h b/src/plugins/autotest/boost/boosttestconfiguration.h index 2259eca5137..d3d4b851df4 100644 --- a/src/plugins/autotest/boost/boosttestconfiguration.h +++ b/src/plugins/autotest/boost/boosttestconfiguration.h @@ -36,7 +36,7 @@ public: explicit BoostTestConfiguration(ITestFramework *framework) : DebuggableTestConfiguration(framework) {} TestOutputReader *outputReader(const QFutureInterface &fi, - QProcess *app) const override; + Utils::QtcProcess *app) const override; QStringList argumentsForTestRunner(QStringList *omitted = nullptr) const override; Utils::Environment filteredEnvironment(const Utils::Environment &original) const override; }; diff --git a/src/plugins/autotest/boost/boosttestoutputreader.cpp b/src/plugins/autotest/boost/boosttestoutputreader.cpp index 5036a683ff3..a9668fc8e80 100644 --- a/src/plugins/autotest/boost/boosttestoutputreader.cpp +++ b/src/plugins/autotest/boost/boosttestoutputreader.cpp @@ -29,6 +29,7 @@ #include "boosttesttreeitem.h" #include +#include #include #include @@ -41,7 +42,7 @@ namespace Internal { static Q_LOGGING_CATEGORY(orLog, "qtc.autotest.boost.outputreader", QtWarningMsg) BoostTestOutputReader::BoostTestOutputReader(const QFutureInterface &futureInterface, - QProcess *testApplication, + Utils::QtcProcess *testApplication, const Utils::FilePath &buildDirectory, const Utils::FilePath &projectFile, LogLevel log, ReportLevel report) @@ -51,7 +52,7 @@ BoostTestOutputReader::BoostTestOutputReader(const QFutureInterface::of(&QProcess::finished), + connect(m_testApplication, &Utils::QtcProcess::finished, this, &BoostTestOutputReader::onFinished); } } @@ -405,7 +406,8 @@ TestResultPtr BoostTestOutputReader::createDefaultResult() const return TestResultPtr(result); } -void BoostTestOutputReader::onFinished(int exitCode, QProcess::ExitStatus /*exitState*/) { +void BoostTestOutputReader::onFinished() { + int exitCode = m_testApplication->exitCode(); if (m_reportLevel == ReportLevel::No && m_testCaseCount != -1) { int reportedFailsAndSkips = m_summary[ResultType::Fail] + m_summary[ResultType::Skip]; m_summary.insert(ResultType::Pass, m_testCaseCount - reportedFailsAndSkips); diff --git a/src/plugins/autotest/boost/boosttestoutputreader.h b/src/plugins/autotest/boost/boosttestoutputreader.h index 56527fa6271..b5cab378a7c 100644 --- a/src/plugins/autotest/boost/boosttestoutputreader.h +++ b/src/plugins/autotest/boost/boosttestoutputreader.h @@ -39,7 +39,7 @@ class BoostTestOutputReader : public TestOutputReader Q_OBJECT public: BoostTestOutputReader(const QFutureInterface &futureInterface, - QProcess *testApplication, const Utils::FilePath &buildDirectory, + Utils::QtcProcess *testApplication, const Utils::FilePath &buildDirectory, const Utils::FilePath &projectFile, LogLevel log, ReportLevel report); protected: void processOutputLine(const QByteArray &outputLine) override; @@ -47,7 +47,7 @@ protected: TestResultPtr createDefaultResult() const override; private: - void onFinished(int exitCode, QProcess::ExitStatus /*exitState*/); + void onFinished(); void sendCompleteInformation(); void handleMessageMatch(const QRegularExpressionMatch &match); void reportNoOutputFinish(const QString &description, ResultType type); diff --git a/src/plugins/autotest/catch/catchconfiguration.cpp b/src/plugins/autotest/catch/catchconfiguration.cpp index bb1353ff4a9..4a3436d476b 100644 --- a/src/plugins/autotest/catch/catchconfiguration.cpp +++ b/src/plugins/autotest/catch/catchconfiguration.cpp @@ -35,7 +35,8 @@ namespace Autotest { namespace Internal { -TestOutputReader *CatchConfiguration::outputReader(const QFutureInterface &fi, QProcess *app) const +TestOutputReader *CatchConfiguration::outputReader(const QFutureInterface &fi, + Utils::QtcProcess *app) const { return new CatchOutputReader(fi, app, buildDirectory(), projectFile()); } diff --git a/src/plugins/autotest/catch/catchconfiguration.h b/src/plugins/autotest/catch/catchconfiguration.h index 2a198558098..ef3549514b5 100644 --- a/src/plugins/autotest/catch/catchconfiguration.h +++ b/src/plugins/autotest/catch/catchconfiguration.h @@ -34,7 +34,7 @@ class CatchConfiguration : public DebuggableTestConfiguration public: CatchConfiguration(ITestFramework *framework) : DebuggableTestConfiguration(framework) {} TestOutputReader *outputReader(const QFutureInterface &fi, - QProcess *app) const override; + Utils::QtcProcess *app) const override; QStringList argumentsForTestRunner(QStringList *omitted = nullptr) const override; Utils::Environment filteredEnvironment(const Utils::Environment &original) const override; }; diff --git a/src/plugins/autotest/catch/catchoutputreader.cpp b/src/plugins/autotest/catch/catchoutputreader.cpp index f7ae4d3bc8f..f788aea017c 100644 --- a/src/plugins/autotest/catch/catchoutputreader.cpp +++ b/src/plugins/autotest/catch/catchoutputreader.cpp @@ -49,7 +49,8 @@ namespace CatchXml { } CatchOutputReader::CatchOutputReader(const QFutureInterface &futureInterface, - QProcess *testApplication, const Utils::FilePath &buildDirectory, + Utils::QtcProcess *testApplication, + const Utils::FilePath &buildDirectory, const Utils::FilePath &projectFile) : TestOutputReader (futureInterface, testApplication, buildDirectory) , m_projectFile(projectFile) diff --git a/src/plugins/autotest/catch/catchoutputreader.h b/src/plugins/autotest/catch/catchoutputreader.h index 70158309617..86c3acbb034 100644 --- a/src/plugins/autotest/catch/catchoutputreader.h +++ b/src/plugins/autotest/catch/catchoutputreader.h @@ -39,7 +39,7 @@ class CatchOutputReader : public TestOutputReader public: CatchOutputReader(const QFutureInterface &futureInterface, - QProcess *testApplication, const Utils::FilePath &buildDirectory, + Utils::QtcProcess *testApplication, const Utils::FilePath &buildDirectory, const Utils::FilePath &projectFile); protected: diff --git a/src/plugins/autotest/ctest/ctestconfiguration.cpp b/src/plugins/autotest/ctest/ctestconfiguration.cpp index de2a94061e1..2a1d18389fb 100644 --- a/src/plugins/autotest/ctest/ctestconfiguration.cpp +++ b/src/plugins/autotest/ctest/ctestconfiguration.cpp @@ -36,7 +36,7 @@ CTestConfiguration::CTestConfiguration(ITestBase *testBase) } TestOutputReader *CTestConfiguration::outputReader(const QFutureInterface &fi, - QProcess *app) const + Utils::QtcProcess *app) const { return new CTestOutputReader(fi, app, workingDirectory()); } diff --git a/src/plugins/autotest/ctest/ctestconfiguration.h b/src/plugins/autotest/ctest/ctestconfiguration.h index 77f7904ab31..3c62c7ea843 100644 --- a/src/plugins/autotest/ctest/ctestconfiguration.h +++ b/src/plugins/autotest/ctest/ctestconfiguration.h @@ -36,7 +36,7 @@ public: explicit CTestConfiguration(ITestBase *testBase); TestOutputReader *outputReader(const QFutureInterface &fi, - QProcess *app) const final; + Utils::QtcProcess *app) const final; }; } // namespace Internal diff --git a/src/plugins/autotest/ctest/ctestoutputreader.cpp b/src/plugins/autotest/ctest/ctestoutputreader.cpp index 93315c0bea6..e9bd1f465d3 100644 --- a/src/plugins/autotest/ctest/ctestoutputreader.cpp +++ b/src/plugins/autotest/ctest/ctestoutputreader.cpp @@ -71,7 +71,7 @@ private: }; CTestOutputReader::CTestOutputReader(const QFutureInterface &futureInterface, - QProcess *testApplication, + Utils::QtcProcess *testApplication, const Utils::FilePath &buildDirectory) : TestOutputReader(futureInterface, testApplication, buildDirectory) { diff --git a/src/plugins/autotest/ctest/ctestoutputreader.h b/src/plugins/autotest/ctest/ctestoutputreader.h index bbec3f70c77..205325fe1f7 100644 --- a/src/plugins/autotest/ctest/ctestoutputreader.h +++ b/src/plugins/autotest/ctest/ctestoutputreader.h @@ -28,6 +28,8 @@ #include +namespace Utils { class QtcProcess; } + namespace Autotest { namespace Internal { @@ -36,7 +38,7 @@ class CTestOutputReader final : public Autotest::TestOutputReader Q_DECLARE_TR_FUNCTIONS(Autotest::Internal::CTestOutputReader) public: CTestOutputReader(const QFutureInterface &futureInterface, - QProcess *testApplication, const Utils::FilePath &buildDirectory); + Utils::QtcProcess *testApplication, const Utils::FilePath &buildDirectory); protected: void processOutputLine(const QByteArray &outputLineWithNewLine) final; diff --git a/src/plugins/autotest/gtest/gtestconfiguration.cpp b/src/plugins/autotest/gtest/gtestconfiguration.cpp index ff60f32171c..025040f54c8 100644 --- a/src/plugins/autotest/gtest/gtestconfiguration.cpp +++ b/src/plugins/autotest/gtest/gtestconfiguration.cpp @@ -38,7 +38,7 @@ namespace Autotest { namespace Internal { TestOutputReader *GTestConfiguration::outputReader(const QFutureInterface &fi, - QProcess *app) const + Utils::QtcProcess *app) const { return new GTestOutputReader(fi, app, buildDirectory(), projectFile()); } diff --git a/src/plugins/autotest/gtest/gtestconfiguration.h b/src/plugins/autotest/gtest/gtestconfiguration.h index 822ad99fd1b..3844869a4b9 100644 --- a/src/plugins/autotest/gtest/gtestconfiguration.h +++ b/src/plugins/autotest/gtest/gtestconfiguration.h @@ -37,7 +37,7 @@ public: : DebuggableTestConfiguration(framework) {} TestOutputReader *outputReader(const QFutureInterface &fi, - QProcess *app) const override; + Utils::QtcProcess *app) const override; QStringList argumentsForTestRunner(QStringList *omitted = nullptr) const override; Utils::Environment filteredEnvironment(const Utils::Environment &original) const override; }; diff --git a/src/plugins/autotest/gtest/gtestoutputreader.cpp b/src/plugins/autotest/gtest/gtestoutputreader.cpp index 997e7d2ddc2..0c9f0b87334 100644 --- a/src/plugins/autotest/gtest/gtestoutputreader.cpp +++ b/src/plugins/autotest/gtest/gtestoutputreader.cpp @@ -28,6 +28,7 @@ #include "../testtreemodel.h" #include "../testtreeitem.h" #include +#include #include #include @@ -37,18 +38,19 @@ namespace Autotest { namespace Internal { GTestOutputReader::GTestOutputReader(const QFutureInterface &futureInterface, - QProcess *testApplication, + Utils::QtcProcess *testApplication, const Utils::FilePath &buildDirectory, const Utils::FilePath &projectFile) : TestOutputReader(futureInterface, testApplication, buildDirectory) , m_projectFile(projectFile) { if (m_testApplication) { - connect(m_testApplication, QOverload::of(&QProcess::finished), - this, [this] (int exitCode, QProcess::ExitStatus /*exitStatus*/) { + connect(m_testApplication, &Utils::QtcProcess::finished, + this, [this]() { + int exitCode = m_testApplication->exitCode(); if (exitCode == 1 && !m_description.isEmpty()) { createAndReportResult(tr("Running tests failed.\n %1\nExecutable: %2") - .arg(m_description).arg(id()), ResultType::MessageFatal); + .arg(m_description).arg(id()), ResultType::MessageFatal); } // on Windows abort() will result in normal termination, but exit code will be set to 3 if (Utils::HostOsInfo::isWindowsHost() && exitCode == 3) diff --git a/src/plugins/autotest/gtest/gtestoutputreader.h b/src/plugins/autotest/gtest/gtestoutputreader.h index 05688a4fa2b..f6d499dbed5 100644 --- a/src/plugins/autotest/gtest/gtestoutputreader.h +++ b/src/plugins/autotest/gtest/gtestoutputreader.h @@ -38,7 +38,7 @@ class GTestOutputReader : public TestOutputReader public: GTestOutputReader(const QFutureInterface &futureInterface, - QProcess *testApplication, const Utils::FilePath &buildDirectory, + Utils::QtcProcess *testApplication, const Utils::FilePath &buildDirectory, const Utils::FilePath &projectFile); protected: void processOutputLine(const QByteArray &outputLine) override; diff --git a/src/plugins/autotest/qtest/qttestconfiguration.cpp b/src/plugins/autotest/qtest/qttestconfiguration.cpp index 7f613702137..4ca1326ba52 100644 --- a/src/plugins/autotest/qtest/qttestconfiguration.cpp +++ b/src/plugins/autotest/qtest/qttestconfiguration.cpp @@ -38,7 +38,7 @@ namespace Autotest { namespace Internal { TestOutputReader *QtTestConfiguration::outputReader(const QFutureInterface &fi, - QProcess *app) const + Utils::QtcProcess *app) const { auto qtSettings = static_cast(framework()->testSettings()); const QtTestOutputReader::OutputMode mode = qtSettings && qtSettings->useXMLOutput.value() diff --git a/src/plugins/autotest/qtest/qttestconfiguration.h b/src/plugins/autotest/qtest/qttestconfiguration.h index 8196665679c..83ac6d79a53 100644 --- a/src/plugins/autotest/qtest/qttestconfiguration.h +++ b/src/plugins/autotest/qtest/qttestconfiguration.h @@ -36,7 +36,7 @@ public: explicit QtTestConfiguration(ITestFramework *framework) : DebuggableTestConfiguration(framework) {} TestOutputReader *outputReader(const QFutureInterface &fi, - QProcess *app) const override; + Utils::QtcProcess *app) const override; QStringList argumentsForTestRunner(QStringList *omitted = nullptr) const override; Utils::Environment filteredEnvironment(const Utils::Environment &original) const override; }; diff --git a/src/plugins/autotest/qtest/qttestoutputreader.cpp b/src/plugins/autotest/qtest/qttestoutputreader.cpp index a6be21019d9..fc762bbe0a4 100644 --- a/src/plugins/autotest/qtest/qttestoutputreader.cpp +++ b/src/plugins/autotest/qtest/qttestoutputreader.cpp @@ -126,7 +126,7 @@ static QString constructBenchmarkInformation(const QString &metric, double value } QtTestOutputReader::QtTestOutputReader(const QFutureInterface &futureInterface, - QProcess *testApplication, + Utils::QtcProcess *testApplication, const Utils::FilePath &buildDirectory, const Utils::FilePath &projectFile, OutputMode mode, TestType type) diff --git a/src/plugins/autotest/qtest/qttestoutputreader.h b/src/plugins/autotest/qtest/qttestoutputreader.h index eff84dd4642..6ceabd508b5 100644 --- a/src/plugins/autotest/qtest/qttestoutputreader.h +++ b/src/plugins/autotest/qtest/qttestoutputreader.h @@ -48,7 +48,7 @@ public: }; QtTestOutputReader(const QFutureInterface &futureInterface, - QProcess *testApplication, const Utils::FilePath &buildDirectory, + Utils::QtcProcess *testApplication, const Utils::FilePath &buildDirectory, const Utils::FilePath &projectFile, OutputMode mode, TestType type); protected: void processOutputLine(const QByteArray &outputLine) override; diff --git a/src/plugins/autotest/quick/quicktestconfiguration.cpp b/src/plugins/autotest/quick/quicktestconfiguration.cpp index 8ede65e66bc..9cb1abb680e 100644 --- a/src/plugins/autotest/quick/quicktestconfiguration.cpp +++ b/src/plugins/autotest/quick/quicktestconfiguration.cpp @@ -44,7 +44,7 @@ QuickTestConfiguration::QuickTestConfiguration(ITestFramework *framework) } TestOutputReader *QuickTestConfiguration::outputReader(const QFutureInterface &fi, - QProcess *app) const + Utils::QtcProcess *app) const { auto qtSettings = static_cast(framework()->testSettings()); const QtTestOutputReader::OutputMode mode = qtSettings && qtSettings->useXMLOutput.value() diff --git a/src/plugins/autotest/quick/quicktestconfiguration.h b/src/plugins/autotest/quick/quicktestconfiguration.h index 88f94c96df9..ca74633a912 100644 --- a/src/plugins/autotest/quick/quicktestconfiguration.h +++ b/src/plugins/autotest/quick/quicktestconfiguration.h @@ -35,7 +35,7 @@ class QuickTestConfiguration : public DebuggableTestConfiguration public: explicit QuickTestConfiguration(ITestFramework *framework); TestOutputReader *outputReader(const QFutureInterface &fi, - QProcess *app) const override; + Utils::QtcProcess *app) const override; QStringList argumentsForTestRunner(QStringList *omitted = nullptr) const override; Utils::Environment filteredEnvironment(const Utils::Environment &original) const override; }; diff --git a/src/plugins/autotest/testconfiguration.h b/src/plugins/autotest/testconfiguration.h index a1a4240f3dd..e338280a954 100644 --- a/src/plugins/autotest/testconfiguration.h +++ b/src/plugins/autotest/testconfiguration.h @@ -35,9 +35,7 @@ #include #include -QT_BEGIN_NAMESPACE -class QProcess; -QT_END_NAMESPACE +namespace Utils { class QtcProcess; } namespace Autotest { namespace Internal { @@ -66,7 +64,7 @@ public: Utils::FilePath executableFilePath() const; virtual TestOutputReader *outputReader(const QFutureInterface &fi, - QProcess *app) const = 0; + Utils::QtcProcess *app) const = 0; virtual Utils::Environment filteredEnvironment(const Utils::Environment &original) const; ITestBase *testBase() const { return m_testBase; } diff --git a/src/plugins/autotest/testoutputreader.cpp b/src/plugins/autotest/testoutputreader.cpp index f2ad3bff054..fcd0ace2300 100644 --- a/src/plugins/autotest/testoutputreader.cpp +++ b/src/plugins/autotest/testoutputreader.cpp @@ -30,6 +30,7 @@ #include "testtreeitem.h" #include +#include #include #include @@ -46,11 +47,12 @@ Utils::FilePath TestOutputReader::constructSourceFilePath(const Utils::FilePath } TestOutputReader::TestOutputReader(const QFutureInterface &futureInterface, - QProcess *testApplication, const Utils::FilePath &buildDirectory) + Utils::QtcProcess *testApplication, + const Utils::FilePath &buildDirectory) : m_futureInterface(futureInterface) , m_testApplication(testApplication) , m_buildDir(buildDirectory) - , m_id(testApplication ? testApplication->program() : QString()) + , m_id(testApplication ? testApplication->commandLine().executable().toUserOutput() : QString()) { auto chopLineBreak = [](QByteArray line) { if (line.endsWith('\n')) @@ -61,17 +63,11 @@ TestOutputReader::TestOutputReader(const QFutureInterface &future }; if (m_testApplication) { - connect(m_testApplication, &QProcess::readyReadStandardOutput, - this, [chopLineBreak, this] () { - m_testApplication->setReadChannel(QProcess::StandardOutput); - while (m_testApplication->canReadLine()) - processStdOutput(chopLineBreak(m_testApplication->readLine())); + m_testApplication->setStdOutLineCallback([this, &chopLineBreak](const QString &line) { + processStdOutput(chopLineBreak(line.toUtf8())); }); - connect(m_testApplication, &QProcess::readyReadStandardError, - this, [chopLineBreak, this] () { - m_testApplication->setReadChannel(QProcess::StandardError); - while (m_testApplication->canReadLine()) - processStdError(chopLineBreak(m_testApplication->readLine())); + m_testApplication->setStdErrLineCallback([this, &chopLineBreak](const QString &line) { + processStdError(chopLineBreak(line.toUtf8())); }); } } diff --git a/src/plugins/autotest/testoutputreader.h b/src/plugins/autotest/testoutputreader.h index b3d7cc3476d..4f5d75b471c 100644 --- a/src/plugins/autotest/testoutputreader.h +++ b/src/plugins/autotest/testoutputreader.h @@ -29,9 +29,10 @@ #include #include -#include #include +namespace Utils { class QtcProcess; } + namespace Autotest { class TestOutputReader : public QObject @@ -39,7 +40,7 @@ class TestOutputReader : public QObject Q_OBJECT public: TestOutputReader(const QFutureInterface &futureInterface, - QProcess *testApplication, const Utils::FilePath &buildDirectory); + Utils::QtcProcess *testApplication, const Utils::FilePath &buildDirectory); virtual ~TestOutputReader(); void processStdOutput(const QByteArray &outputLine); virtual void processStdError(const QByteArray &outputLine); @@ -67,7 +68,7 @@ protected: void reportResult(const TestResultPtr &result); QFutureInterface m_futureInterface; - QProcess *m_testApplication; // not owned + Utils::QtcProcess *m_testApplication; // not owned Utils::FilePath m_buildDir; QString m_id; QHash m_summary; diff --git a/src/plugins/autotest/testrunconfiguration.h b/src/plugins/autotest/testrunconfiguration.h index 451add1fa2b..ccb6282059b 100644 --- a/src/plugins/autotest/testrunconfiguration.h +++ b/src/plugins/autotest/testrunconfiguration.h @@ -66,7 +66,7 @@ public: ProjectExplorer::Runnable r; QTC_ASSERT(m_testConfig, return r); r.command.setExecutable(m_testConfig->executableFilePath()); - r.command.setArguments(m_testConfig->argumentsForTestRunner().join(' ')); + r.command.addArgs(m_testConfig->argumentsForTestRunner().join(' '), Utils::CommandLine::Raw); r.workingDirectory = m_testConfig->workingDirectory(); r.environment = m_testConfig->environment(); return r; diff --git a/src/plugins/autotest/testrunner.cpp b/src/plugins/autotest/testrunner.cpp index aa930eb595e..942730ba9d8 100644 --- a/src/plugins/autotest/testrunner.cpp +++ b/src/plugins/autotest/testrunner.cpp @@ -90,6 +90,8 @@ TestRunner::TestRunner() { s_instance = this; + m_cancelTimer.setSingleShot(true); + connect(&m_cancelTimer, &QTimer::timeout, this, [this]() { cancelCurrent(Timeout); }); connect(&m_futureWatcher, &QFutureWatcher::resultReadyAt, this, [this](int index) { emit testResultReady(m_futureWatcher.resultAt(index)); }); connect(&m_futureWatcher, &QFutureWatcher::finished, @@ -131,16 +133,17 @@ void TestRunner::runTest(TestRunMode mode, const ITestTreeItem *item) } } -static QString processInformation(const QProcess *proc) +static QString processInformation(const QtcProcess *proc) { QTC_ASSERT(proc, return QString()); - QString information("\nCommand line: " + proc->program() + ' ' + proc->arguments().join(' ')); + const Utils::CommandLine command = proc->commandLine(); + QString information("\nCommand line: " + command.executable().toUserOutput() + ' ' + command.arguments()); QStringList important = { "PATH" }; if (Utils::HostOsInfo::isLinuxHost()) important.append("LD_LIBRARY_PATH"); else if (Utils::HostOsInfo::isMacHost()) important.append({ "DYLD_LIBRARY_PATH", "DYLD_FRAMEWORK_PATH" }); - const QProcessEnvironment &environment = proc->processEnvironment(); + const Utils::Environment &environment = proc->environment(); for (const QString &var : important) information.append('\n' + var + ": " + environment.value(var)); return information; @@ -204,34 +207,35 @@ bool TestRunner::currentConfigValid() void TestRunner::setUpProcess() { QTC_ASSERT(m_currentConfig, return); - m_currentProcess = new QProcess; - m_currentProcess->setReadChannel(QProcess::StandardOutput); + m_currentProcess = new QtcProcess; if (m_currentConfig->testBase()->type() == ITestBase::Framework) { TestConfiguration *current = static_cast(m_currentConfig); - m_currentProcess->setProgram(current->executableFilePath().toString()); + m_currentProcess->setCommand({current->executableFilePath(), {}}); } else { TestToolConfiguration *current = static_cast(m_currentConfig); - m_currentProcess->setProgram(current->commandLine().executable().toString()); + m_currentProcess->setCommand({current->commandLine().executable(), {}}); } } void TestRunner::setUpProcessEnv() { + Utils::CommandLine command = m_currentProcess->commandLine(); if (m_currentConfig->testBase()->type() == ITestBase::Framework) { TestConfiguration *current = static_cast(m_currentConfig); QStringList omitted; - m_currentProcess->setArguments(current->argumentsForTestRunner(&omitted)); + command.addArgs(current->argumentsForTestRunner(&omitted).join(' '), Utils::CommandLine::Raw); if (!omitted.isEmpty()) { const QString &details = constructOmittedDetailsString(omitted); reportResult(ResultType::MessageWarn, details.arg(current->displayName())); } } else { TestToolConfiguration *current = static_cast(m_currentConfig); - m_currentProcess->setArguments(current->commandLine().splitArguments()); + command.setArguments(current->commandLine().arguments()); } + m_currentProcess->setCommand(command); - m_currentProcess->setWorkingDirectory(m_currentConfig->workingDirectory().toString()); + m_currentProcess->setWorkingDirectory(m_currentConfig->workingDirectory()); const Utils::Environment &original = m_currentConfig->environment(); Utils::Environment environment = m_currentConfig->filteredEnvironment(original); const Utils::EnvironmentItems removedVariables = Utils::filtered( @@ -243,7 +247,7 @@ void TestRunner::setUpProcessEnv() .arg(m_currentConfig->displayName()); reportResult(ResultType::MessageWarn, details); } - m_currentProcess->setProcessEnvironment(environment.toProcessEnvironment()); + m_currentProcess->setEnvironment(environment); } void TestRunner::scheduleNext() @@ -272,15 +276,16 @@ void TestRunner::scheduleNext() setUpProcessEnv(); - connect(m_currentProcess, QOverload::of(&QProcess::finished), + connect(m_currentProcess, &Utils::QtcProcess::finished, this, &TestRunner::onProcessFinished); const int timeout = AutotestPlugin::settings()->timeout; - QTimer::singleShot(timeout, m_currentProcess, [this]() { cancelCurrent(Timeout); }); + m_cancelTimer.setInterval(timeout); + m_cancelTimer.start(); - qCInfo(runnerLog) << "Command:" << m_currentProcess->program(); - qCInfo(runnerLog) << "Arguments:" << m_currentProcess->arguments(); + qCInfo(runnerLog) << "Command:" << m_currentProcess->commandLine().executable(); + qCInfo(runnerLog) << "Arguments:" << m_currentProcess->commandLine().arguments(); qCInfo(runnerLog) << "Working directory:" << m_currentProcess->workingDirectory(); - qCDebug(runnerLog) << "Environment:" << m_currentProcess->environment(); + qCDebug(runnerLog) << "Environment:" << m_currentProcess->environment().toStringList(); m_currentProcess->start(); if (!m_currentProcess->waitForStarted()) { @@ -355,7 +360,8 @@ void TestRunner::onProcessFinished() void TestRunner::resetInternalPointers() { delete m_currentOutputReader; - delete m_currentProcess; + if (m_currentProcess) + m_currentProcess->deleteLater(); delete m_currentConfig; m_currentOutputReader = nullptr; m_currentProcess = nullptr; @@ -812,6 +818,7 @@ void TestRunner::onBuildQueueFinished(bool success) void TestRunner::onFinished() { + m_cancelTimer.stop(); // if we've been canceled and we still have test configurations queued just throw them away qDeleteAll(m_selectedTests); m_selectedTests.clear(); diff --git a/src/plugins/autotest/testrunner.h b/src/plugins/autotest/testrunner.h index a95a78ab9d5..961312b6410 100644 --- a/src/plugins/autotest/testrunner.h +++ b/src/plugins/autotest/testrunner.h @@ -32,16 +32,17 @@ #include #include #include +#include QT_BEGIN_NAMESPACE class QCheckBox; class QComboBox; class QDialogButtonBox; class QLabel; -class QProcess; QT_END_NAMESPACE namespace ProjectExplorer { class Project; } +namespace Utils { class QtcProcess; } namespace Autotest { @@ -105,7 +106,7 @@ private: bool m_executingTests = false; bool m_canceled = false; ITestConfiguration *m_currentConfig = nullptr; - QProcess *m_currentProcess = nullptr; + Utils::QtcProcess *m_currentProcess = nullptr; TestOutputReader *m_currentOutputReader = nullptr; TestRunMode m_runMode = TestRunMode::None; @@ -116,6 +117,7 @@ private: QMetaObject::Connection m_finishDebugConnect; // temporarily used for handling of switching the current target QMetaObject::Connection m_targetConnect; + QTimer m_cancelTimer; bool m_skipTargetsCheck = false; }; From 734035194b374f469ccbe655a81a2dcc2faa09ff Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Tue, 14 Jun 2022 12:34:15 +0200 Subject: [PATCH 26/94] PE: Move ResourceFileNode to ProjectExplorer Avoids additional dependencies later on. No functional change. Change-Id: Idc21ed856f4f31d68d55742b5796243227b254dc Reviewed-by: hjk --- src/plugins/projectexplorer/projectnodes.cpp | 24 +++++++++++++++++++ src/plugins/projectexplorer/projectnodes.h | 14 +++++++++++ .../qmlpreviewfileontargetfinder.cpp | 4 +--- src/plugins/qtsupport/baseqtversion.cpp | 2 +- src/plugins/resourceeditor/resourcenode.cpp | 24 ------------------- src/plugins/resourceeditor/resourcenode.h | 14 ----------- 6 files changed, 40 insertions(+), 42 deletions(-) diff --git a/src/plugins/projectexplorer/projectnodes.cpp b/src/plugins/projectexplorer/projectnodes.cpp index c4b33d74140..61dfff43d05 100644 --- a/src/plugins/projectexplorer/projectnodes.cpp +++ b/src/plugins/projectexplorer/projectnodes.cpp @@ -1094,4 +1094,28 @@ QIcon DirectoryIcon::icon() const return icon; } +ResourceFileNode::ResourceFileNode(const FilePath &filePath, const QString &qrcPath, const QString &displayName) + : FileNode(filePath, FileNode::fileTypeForFileName(filePath)) + , m_qrcPath(qrcPath) + , m_displayName(displayName) +{ +} + +QString ResourceFileNode::displayName() const +{ + return m_displayName; +} + +QString ResourceFileNode::qrcPath() const +{ + return m_qrcPath; +} + +bool ResourceFileNode::supportsAction(ProjectAction action, const Node *node) const +{ + if (action == HidePathActions) + return false; + return parentFolderNode()->supportsAction(action, node); +} + } // namespace ProjectExplorer diff --git a/src/plugins/projectexplorer/projectnodes.h b/src/plugins/projectexplorer/projectnodes.h index c5cd68a4c53..9e2e4e9474d 100644 --- a/src/plugins/projectexplorer/projectnodes.h +++ b/src/plugins/projectexplorer/projectnodes.h @@ -464,6 +464,20 @@ private: Project *m_project; }; +class PROJECTEXPLORER_EXPORT ResourceFileNode : public ProjectExplorer::FileNode +{ +public: + ResourceFileNode(const Utils::FilePath &filePath, const QString &qrcPath, const QString &displayName); + + QString displayName() const override; + QString qrcPath() const; + bool supportsAction(ProjectExplorer::ProjectAction action, const Node *node) const override; + +private: + QString m_qrcPath; + QString m_displayName; +}; + } // namespace ProjectExplorer Q_DECLARE_METATYPE(ProjectExplorer::Node *) diff --git a/src/plugins/qmlpreview/qmlpreviewfileontargetfinder.cpp b/src/plugins/qmlpreview/qmlpreviewfileontargetfinder.cpp index aebce83d5a9..f4c6e438072 100644 --- a/src/plugins/qmlpreview/qmlpreviewfileontargetfinder.cpp +++ b/src/plugins/qmlpreview/qmlpreviewfileontargetfinder.cpp @@ -33,8 +33,6 @@ #include #include -#include - #include namespace QmlPreview { @@ -52,7 +50,7 @@ ProjectExplorer::Target *QmlPreviewFileOnTargetFinder::target() const QString resourceNodePath(const ProjectExplorer::Node *node) { - if (auto resourceNode = dynamic_cast(node)) + if (auto resourceNode = dynamic_cast(node)) return ":" + resourceNode->qrcPath(); return QString(); } diff --git a/src/plugins/qtsupport/baseqtversion.cpp b/src/plugins/qtsupport/baseqtversion.cpp index 62b2927b022..c2460fd1290 100644 --- a/src/plugins/qtsupport/baseqtversion.cpp +++ b/src/plugins/qtsupport/baseqtversion.cpp @@ -1693,7 +1693,7 @@ void QtVersion::populateQmlFileFinder(FileInProjectFinder *finder, const Target if (startupProject) { if (ProjectNode *rootNode = startupProject->rootProjectNode()) { rootNode->forEachNode([&](FileNode *node) { - if (auto resourceNode = dynamic_cast(node)) + if (auto resourceNode = dynamic_cast(node)) finder->addMappedPath(node->filePath(), ":" + resourceNode->qrcPath()); }); } else { diff --git a/src/plugins/resourceeditor/resourcenode.cpp b/src/plugins/resourceeditor/resourcenode.cpp index 30070e7ec71..bc9274fa895 100644 --- a/src/plugins/resourceeditor/resourcenode.cpp +++ b/src/plugins/resourceeditor/resourcenode.cpp @@ -637,28 +637,4 @@ ResourceTopLevelNode *ResourceFolderNode::resourceNode() const return m_topLevelNode; } -ResourceFileNode::ResourceFileNode(const FilePath &filePath, const QString &qrcPath, const QString &displayName) - : FileNode(filePath, FileNode::fileTypeForFileName(filePath)) - , m_qrcPath(qrcPath) - , m_displayName(displayName) -{ -} - -QString ResourceFileNode::displayName() const -{ - return m_displayName; -} - -QString ResourceFileNode::qrcPath() const -{ - return m_qrcPath; -} - -bool ResourceFileNode::supportsAction(ProjectAction action, const Node *node) const -{ - if (action == HidePathActions) - return false; - return parentFolderNode()->supportsAction(action, node); -} - } // ResourceEditor diff --git a/src/plugins/resourceeditor/resourcenode.h b/src/plugins/resourceeditor/resourcenode.h index 03ae8039f0c..bb974cb2af5 100644 --- a/src/plugins/resourceeditor/resourcenode.h +++ b/src/plugins/resourceeditor/resourcenode.h @@ -91,18 +91,4 @@ private: QString m_lang; }; -class RESOURCE_EXPORT ResourceFileNode : public ProjectExplorer::FileNode -{ -public: - ResourceFileNode(const Utils::FilePath &filePath, const QString &qrcPath, const QString &displayName); - - QString displayName() const override; - QString qrcPath() const; - bool supportsAction(ProjectExplorer::ProjectAction action, const Node *node) const override; - -private: - QString m_qrcPath; - QString m_displayName; -}; - } // namespace ResourceEditor From bf8bf1adc0784f8deb43c7299458b45c27d6082c Mon Sep 17 00:00:00 2001 From: hjk Date: Fri, 10 Jun 2022 13:26:46 +0200 Subject: [PATCH 27/94] Utils: Also use device name when trying to disambiguate path displays With two /tmp/foo.cpp from different devices there is no directly visible difference in the Open Documents. Adding the device path for remote cases introduces a difference. For local files there is no visible difference. Change-Id: I6f1632d6f51ff24573831af3161492989c5c0bec Reviewed-by: Eike Ziller --- src/libs/utils/filepath.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libs/utils/filepath.cpp b/src/libs/utils/filepath.cpp index 1d469ec2ef4..14436bdc1d1 100644 --- a/src/libs/utils/filepath.cpp +++ b/src/libs/utils/filepath.cpp @@ -527,10 +527,11 @@ QString FilePath::fileNameWithPathComponents(int pathComponents) const ; } - // If there are no more slashes before the found one, return the entire string if (i > 0 && m_data.lastIndexOf(slash, i) != -1) return m_data.mid(component); - return m_data; + + // If there are no more slashes before the found one, return the entire string + return displayName(); } /// \returns the base name of the file without the path. From 79e467a8b87c24a242e7cc96a20315af4fdd0eaa Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 14 Jun 2022 15:48:57 +0200 Subject: [PATCH 28/94] CppEditor: Remove one use of mimetype via QFileInfo Plus some cosmetical changes I could not resist. Change-Id: Id2634d3876437a5dfe7ddb4aaa53db396f37e02a Reviewed-by: Christian Kandeler --- src/plugins/cppeditor/cppeditordocument.cpp | 37 +++++++++------------ 1 file changed, 15 insertions(+), 22 deletions(-) diff --git a/src/plugins/cppeditor/cppeditordocument.cpp b/src/plugins/cppeditor/cppeditordocument.cpp index e203bd3cdb9..e7621e823ee 100644 --- a/src/plugins/cppeditor/cppeditordocument.cpp +++ b/src/plugins/cppeditor/cppeditordocument.cpp @@ -26,16 +26,13 @@ #include "cppeditordocument.h" #include "baseeditordocumentparser.h" -#include "builtineditordocumentprocessor.h" #include "cppcodeformatter.h" -#include "cppcodemodelsettings.h" #include "cppeditorconstants.h" #include "cppeditorplugin.h" #include "cppmodelmanager.h" #include "cppeditorconstants.h" #include "cppeditorplugin.h" #include "cpphighlighter.h" -#include "cppqtstyleindenter.h" #include "cppquickfixassistant.h" #include @@ -58,20 +55,17 @@ const char NO_PROJECT_CONFIGURATION[] = "NoProject"; -namespace { - -CppEditor::CppModelManager *mm() -{ - return CppEditor::CppModelManager::instance(); -} - -} // anonymous namespace - using namespace TextEditor; +using namespace Utils; namespace CppEditor { namespace Internal { +static CppEditor::CppModelManager *mm() +{ + return CppEditor::CppModelManager::instance(); +} + enum { processDocumentIntervalInMs = 150 }; class CppEditorDocumentHandleImpl : public CppEditorDocumentHandle @@ -245,14 +239,13 @@ void CppEditorDocument::reparseWithPreferredParseContext(const QString &parseCon scheduleProcessDocument(); } -void CppEditorDocument::onFilePathChanged(const Utils::FilePath &oldPath, - const Utils::FilePath &newPath) +void CppEditorDocument::onFilePathChanged(const FilePath &oldPath, const FilePath &newPath) { Q_UNUSED(oldPath) if (!newPath.isEmpty()) { indenter()->setFileName(newPath); - setMimeType(Utils::mimeTypeForFile(newPath.toFileInfo()).name()); + setMimeType(mimeTypeForFile(newPath).name()); connect(this, &Core::IDocument::contentsChanged, this, &CppEditorDocument::scheduleProcessDocument, @@ -363,13 +356,13 @@ void CppEditorDocument::releaseResources() void CppEditorDocument::showHideInfoBarAboutMultipleParseContexts(bool show) { - const Utils::Id id = Constants::MULTIPLE_PARSE_CONTEXTS_AVAILABLE; + const Id id = Constants::MULTIPLE_PARSE_CONTEXTS_AVAILABLE; if (show) { - Utils::InfoBarEntry info(id, - tr("Note: Multiple parse contexts are available for this file. " - "Choose the preferred one from the editor toolbar."), - Utils::InfoBarEntry::GlobalSuppression::Enabled); + InfoBarEntry info(id, + tr("Note: Multiple parse contexts are available for this file. " + "Choose the preferred one from the editor toolbar."), + InfoBarEntry::GlobalSuppression::Enabled); info.removeCancelButton(); if (infoBar()->canInfoBeAdded(id)) infoBar()->addInfo(info); @@ -444,9 +437,9 @@ TextEditor::TabSettings CppEditorDocument::tabSettings() const return indenter()->tabSettings().value_or(TextEditor::TextDocument::tabSettings()); } -bool CppEditorDocument::save(QString *errorString, const Utils::FilePath &filePath, bool autoSave) +bool CppEditorDocument::save(QString *errorString, const FilePath &filePath, bool autoSave) { - Utils::ExecuteOnDestruction resetSettingsOnScopeExit; + ExecuteOnDestruction resetSettingsOnScopeExit; if (indenter()->formatOnSave() && !autoSave) { auto *layout = qobject_cast(document()->documentLayout()); From 33f78fa27db7366b0e90a3fafaf0586c887567bd Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Tue, 14 Jun 2022 15:47:24 +0200 Subject: [PATCH 29/94] QmakeProjectManager: Also consider the "Forms" virtual folder ... for the "Hide Sources and Headers" setting. A .ui file usually corresponds to a source (and possibly a header) file, and the user very likely wants the option applied to it as well. Fixes: QTCREATORBUG-27482 Change-Id: I8652d8a9e7686239bcaef8f90d070c794fd5f993 Reviewed-by: hjk --- src/plugins/qmakeprojectmanager/qmakenodetreebuilder.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/plugins/qmakeprojectmanager/qmakenodetreebuilder.cpp b/src/plugins/qmakeprojectmanager/qmakenodetreebuilder.cpp index 8ae6a7cf1e5..10fc625d562 100644 --- a/src/plugins/qmakeprojectmanager/qmakenodetreebuilder.cpp +++ b/src/plugins/qmakeprojectmanager/qmakenodetreebuilder.cpp @@ -179,7 +179,8 @@ static void createTree(QmakeBuildSystem *buildSystem, vfolder->setIcon(fileTypes.at(i).icon); vfolder->setDisplayName(fileTypes.at(i).typeName); vfolder->setAddFileFilter(fileTypes.at(i).addFileFilter); - vfolder->setIsSourcesOrHeaders(type == FileType::Source || type == FileType::Header); + vfolder->setIsSourcesOrHeaders(type == FileType::Source || type == FileType::Header + || type == FileType::Form); if (type == FileType::Resource) { for (const auto &file : newFilePaths) { From 525ea8a1ec7b0d046cb27aa08d564f3bc7605c44 Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 14 Jun 2022 16:37:25 +0200 Subject: [PATCH 30/94] ProjectExplorer: Remove last use of mimeType via QFileInfo Change-Id: I7097a1198fd99540bd945ea203bc2033fbcfef6c Reviewed-by: Alessandro Portale --- src/plugins/projectexplorer/jsonwizard/jsonkitspage.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/plugins/projectexplorer/jsonwizard/jsonkitspage.cpp b/src/plugins/projectexplorer/jsonwizard/jsonkitspage.cpp index f0d3433d23f..d4a9f07c929 100644 --- a/src/plugins/projectexplorer/jsonwizard/jsonkitspage.cpp +++ b/src/plugins/projectexplorer/jsonwizard/jsonkitspage.cpp @@ -112,10 +112,8 @@ void JsonKitsPage::setupProjectFiles(const JsonWizard::GeneratorFiles &files) { for (const JsonWizard::GeneratorFile &f : files) { if (f.file.attributes() & GeneratedFile::OpenProjectAttribute) { - const QFileInfo fi(f.file.path()); - const QString path = fi.absoluteFilePath(); - Project *project = ProjectManager::openProject(Utils::mimeTypeForFile(fi), - Utils::FilePath::fromString(path)); + Project *project = ProjectManager::openProject(Utils::mimeTypeForFile(f.file.filePath()), + f.file.filePath().absolutePath()); if (project) { if (setupProject(project)) project->saveSettings(); From 2bf46d9e7f16fb404502a8580a93fc9d647750f2 Mon Sep 17 00:00:00 2001 From: Alexander Akulich Date: Fri, 10 Jun 2022 13:26:54 +0300 Subject: [PATCH 31/94] TextEditor: Add an option to hide file line ending combobox Change-Id: Iae8160f7cd567fc6d42116837fc367fa6dffdc4b Reviewed-by: Reviewed-by: David Schulz --- src/plugins/texteditor/displaysettings.cpp | 4 ++++ src/plugins/texteditor/displaysettings.h | 1 + src/plugins/texteditor/displaysettingspage.cpp | 2 ++ src/plugins/texteditor/displaysettingspage.ui | 9 ++++++++- src/plugins/texteditor/texteditor.cpp | 14 ++++++++++---- 5 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/plugins/texteditor/displaysettings.cpp b/src/plugins/texteditor/displaysettings.cpp index c5e41fb4991..f092150a0e6 100644 --- a/src/plugins/texteditor/displaysettings.cpp +++ b/src/plugins/texteditor/displaysettings.cpp @@ -47,6 +47,7 @@ static const char autoFoldFirstCommentKey[] = "AutoFoldFirstComment"; static const char centerCursorOnScrollKey[] = "CenterCursorOnScroll"; static const char openLinksInNextSplitKey[] = "OpenLinksInNextSplitKey"; static const char displayFileEncodingKey[] = "DisplayFileEncoding"; +static const char displayFileLineEndingKey[] = "DisplayFileLineEnding"; static const char scrollBarHighlightsKey[] = "ScrollBarHighlights"; static const char animateNavigationWithinFileKey[] = "AnimateNavigationWithinFile"; static const char animateWithinFileTimeMaxKey[] = "AnimateWithinFileTimeMax"; @@ -76,6 +77,7 @@ void DisplaySettings::toSettings(const QString &category, QSettings *s) const s->setValue(QLatin1String(centerCursorOnScrollKey), m_centerCursorOnScroll); s->setValue(QLatin1String(openLinksInNextSplitKey), m_openLinksInNextSplit); s->setValue(QLatin1String(displayFileEncodingKey), m_displayFileEncoding); + s->setValue(QLatin1String(displayFileLineEndingKey), m_displayFileLineEnding); s->setValue(QLatin1String(scrollBarHighlightsKey), m_scrollBarHighlights); s->setValue(QLatin1String(animateNavigationWithinFileKey), m_animateNavigationWithinFile); s->setValue(QLatin1String(displayAnnotationsKey), m_displayAnnotations); @@ -105,6 +107,7 @@ void DisplaySettings::fromSettings(const QString &category, const QSettings *s) m_centerCursorOnScroll = s->value(group + QLatin1String(centerCursorOnScrollKey), m_centerCursorOnScroll).toBool(); m_openLinksInNextSplit = s->value(group + QLatin1String(openLinksInNextSplitKey), m_openLinksInNextSplit).toBool(); m_displayFileEncoding = s->value(group + QLatin1String(displayFileEncodingKey), m_displayFileEncoding).toBool(); + m_displayFileLineEnding = s->value(group + QLatin1String(displayFileLineEndingKey), m_displayFileLineEnding).toBool(); m_scrollBarHighlights = s->value(group + QLatin1String(scrollBarHighlightsKey), m_scrollBarHighlights).toBool(); m_animateNavigationWithinFile = s->value(group + QLatin1String(animateNavigationWithinFileKey), m_animateNavigationWithinFile).toBool(); m_animateWithinFileTimeMax = s->value(group + QLatin1String(animateWithinFileTimeMaxKey), m_animateWithinFileTimeMax).toInt(); @@ -131,6 +134,7 @@ bool DisplaySettings::equals(const DisplaySettings &ds) const && m_openLinksInNextSplit == ds.m_openLinksInNextSplit && m_forceOpenLinksInNextSplit == ds.m_forceOpenLinksInNextSplit && m_displayFileEncoding == ds.m_displayFileEncoding + && m_displayFileLineEnding == ds.m_displayFileLineEnding && m_scrollBarHighlights == ds.m_scrollBarHighlights && m_animateNavigationWithinFile == ds.m_animateNavigationWithinFile && m_animateWithinFileTimeMax == ds.m_animateWithinFileTimeMax diff --git a/src/plugins/texteditor/displaysettings.h b/src/plugins/texteditor/displaysettings.h index ae87f76dfbd..97b716a8fc7 100644 --- a/src/plugins/texteditor/displaysettings.h +++ b/src/plugins/texteditor/displaysettings.h @@ -69,6 +69,7 @@ public: bool m_openLinksInNextSplit = false; bool m_forceOpenLinksInNextSplit = false; bool m_displayFileEncoding = false; + bool m_displayFileLineEnding = true; bool m_scrollBarHighlights = true; bool m_animateNavigationWithinFile = false; int m_animateWithinFileTimeMax = 333; // read only setting diff --git a/src/plugins/texteditor/displaysettingspage.cpp b/src/plugins/texteditor/displaysettingspage.cpp index fa551504211..f972e1735a8 100644 --- a/src/plugins/texteditor/displaysettingspage.cpp +++ b/src/plugins/texteditor/displaysettingspage.cpp @@ -102,6 +102,7 @@ void DisplaySettingsWidget::settingsFromUI(DisplaySettings &displaySettings, displaySettings.m_centerCursorOnScroll = m_ui.centerOnScroll->isChecked(); displaySettings.m_openLinksInNextSplit = m_ui.openLinksInNextSplit->isChecked(); displaySettings.m_displayFileEncoding = m_ui.displayFileEncoding->isChecked(); + displaySettings.m_displayFileLineEnding = m_ui.displayFileLineEnding->isChecked(); displaySettings.m_scrollBarHighlights = m_ui.scrollBarHighlights->isChecked(); displaySettings.m_animateNavigationWithinFile = m_ui.animateNavigationWithinFile->isChecked(); displaySettings.m_displayAnnotations = m_ui.displayAnnotations->isChecked(); @@ -135,6 +136,7 @@ void DisplaySettingsWidget::settingsToUI() m_ui.centerOnScroll->setChecked(displaySettings.m_centerCursorOnScroll); m_ui.openLinksInNextSplit->setChecked(displaySettings.m_openLinksInNextSplit); m_ui.displayFileEncoding->setChecked(displaySettings.m_displayFileEncoding); + m_ui.displayFileLineEnding->setChecked(displaySettings.m_displayFileLineEnding); m_ui.scrollBarHighlights->setChecked(displaySettings.m_scrollBarHighlights); m_ui.animateNavigationWithinFile->setChecked(displaySettings.m_animateNavigationWithinFile); m_ui.displayAnnotations->setChecked(displaySettings.m_displayAnnotations); diff --git a/src/plugins/texteditor/displaysettingspage.ui b/src/plugins/texteditor/displaysettingspage.ui index c7d49ac0692..29dea5649a3 100644 --- a/src/plugins/texteditor/displaysettingspage.ui +++ b/src/plugins/texteditor/displaysettingspage.ui @@ -97,6 +97,13 @@ + + + + Display file line ending + + + @@ -170,7 +177,7 @@ - + Animate navigation within file diff --git a/src/plugins/texteditor/texteditor.cpp b/src/plugins/texteditor/texteditor.cpp index eb33c6de6a3..22c23387d3a 100644 --- a/src/plugins/texteditor/texteditor.cpp +++ b/src/plugins/texteditor/texteditor.cpp @@ -640,6 +640,7 @@ public: void slotSelectionChanged(); void _q_animateUpdate(const QTextCursor &cursor, QPointF lastPos, QRectF rect); void updateCodeFoldingVisible(); + void updateFileLineEndingVisible(); void reconfigure(); void updateSyntaxInfoBar(const Highlighter::Definitions &definitions, const QString &fileName); @@ -952,10 +953,9 @@ TextEditorWidgetPrivate::TextEditorWidgetPrivate(TextEditorWidget *parent) m_fileLineEnding->addItems(ExtraEncodingSettings::lineTerminationModeNames()); m_fileLineEnding->setContentsMargins(spacing, 0, spacing, 0); m_fileLineEndingAction = m_toolBar->addWidget(m_fileLineEnding); - m_fileLineEndingAction->setVisible(!q->isReadOnly()); - connect(q, &TextEditorWidget::readOnlyChanged, this, [this] { - m_fileLineEndingAction->setVisible(!q->isReadOnly()); - }); + updateFileLineEndingVisible(); + connect(q, &TextEditorWidget::readOnlyChanged, + this, &TextEditorWidgetPrivate::updateFileLineEndingVisible); m_fileEncodingLabel = new FixedSizeClickLabel; m_fileEncodingLabel->setContentsMargins(spacing, 0, spacing, 0); @@ -3225,6 +3225,11 @@ void TextEditorWidgetPrivate::updateCodeFoldingVisible() } } +void TextEditorWidgetPrivate::updateFileLineEndingVisible() +{ + m_fileLineEndingAction->setVisible(m_displaySettings.m_displayFileLineEnding && !q->isReadOnly()); +} + void TextEditorWidgetPrivate::reconfigure() { m_document->setMimeType(Utils::mimeTypeForFile(m_document->filePath()).name()); @@ -7211,6 +7216,7 @@ void TextEditorWidget::setDisplaySettings(const DisplaySettings &ds) } d->updateCodeFoldingVisible(); + d->updateFileLineEndingVisible(); d->updateHighlights(); d->setupScrollBar(); viewport()->update(); From 601cb1689361ff3f6dc5adf8cbe9360f22dea636 Mon Sep 17 00:00:00 2001 From: David Schulz Date: Tue, 14 Jun 2022 10:47:05 +0200 Subject: [PATCH 32/94] Debugger: set the inferior executable when attaching to a run control The inferior is used to verify that the bitness of the selected debugger matches the inferior bitness on windows. Change-Id: Ide7703a1ecc63a7d69101df779ce7f2660fecdbc Reviewed-by: hjk --- src/plugins/debugger/debuggerplugin.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp index 3accce69ebb..5de92dd4831 100644 --- a/src/plugins/debugger/debuggerplugin.cpp +++ b/src/plugins/debugger/debuggerplugin.cpp @@ -1753,6 +1753,7 @@ void DebuggerPlugin::attachExternalApplication(RunControl *rc) runControl->setTarget(rc->target()); runControl->setDisplayName(tr("Process %1").arg(pid.pid())); auto debugger = new DebuggerRunTool(runControl); + debugger->setInferiorExecutable(rc->targetFilePath()); debugger->setAttachPid(pid); debugger->setStartMode(AttachToLocalProcess); debugger->setCloseMode(DetachAtClose); From 3341fa827f9fee6812b15bcb8eefb41211358958 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Tue, 14 Jun 2022 11:34:02 +0200 Subject: [PATCH 33/94] Debugger: Fix handling breakpoints of same file names ...while qml debugging. Fixes: QTCREATORBUG-24803 Change-Id: Ieedeb13236f8129a1f6d445de5218462c8d0676a Reviewed-by: hjk --- src/plugins/debugger/qml/qmlengine.cpp | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/plugins/debugger/qml/qmlengine.cpp b/src/plugins/debugger/qml/qmlengine.cpp index 1b6a64c6a5c..ef6a753b23f 100644 --- a/src/plugins/debugger/qml/qmlengine.cpp +++ b/src/plugins/debugger/qml/qmlengine.cpp @@ -47,6 +47,9 @@ #include #include +#include +#include + #include #include #include @@ -1384,6 +1387,17 @@ void QmlEnginePrivate::scripts(int types, const QList ids, bool includeSour runCommand(cmd); } +static QString targetFile(const FilePath &original) +{ + auto projectTree = ProjectExplorer::ProjectTree::instance(); + auto node = projectTree->nodeForFile(original); + + if (auto resourceNode = dynamic_cast(node)) + return QLatin1String("qrc:") + resourceNode->qrcPath(); + + return original.fileName(); +} + void QmlEnginePrivate::setBreakpoint(const QString type, const QString target, bool enabled, int line, int column, const QString condition, int ignoreCount) @@ -1413,7 +1427,7 @@ void QmlEnginePrivate::setBreakpoint(const QString type, const QString target, cmd.arg(ENABLED, enabled); if (type == SCRIPTREGEXP) - cmd.arg(TARGET, Utils::FilePath::fromString(target).fileName()); + cmd.arg(TARGET, targetFile(FilePath::fromString(target))); else cmd.arg(TARGET, target); @@ -1841,6 +1855,12 @@ void QmlEnginePrivate::messageReceived(const QByteArray &data) QList v8Breakpoints; const QVariantList v8BreakpointIdList = breakData.value("breakpoints").toList(); + // skip debug break if no breakpoint - likely stopped in another file with same naming + if (v8BreakpointIdList.isEmpty()) { + inferiorStop = false; + continueDebugging(Continue); + } + for (const QVariant &breakpointId : v8BreakpointIdList) { const QString responseId = QString::number(breakpointId.toInt()); Breakpoint bp = engine->breakHandler()->findBreakpointByResponseId(responseId); From 02bfd03c226a15d2ed90ca43580df7e099e310a6 Mon Sep 17 00:00:00 2001 From: David Schulz Date: Thu, 9 Jun 2022 15:21:35 +0200 Subject: [PATCH 34/94] Python: simplify detect python for document path Change-Id: I49b943e8b89db32c11b12ee66c0ad3add9a695af Reviewed-by: Christian Stenger --- src/plugins/python/pythonutils.cpp | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/src/plugins/python/pythonutils.cpp b/src/plugins/python/pythonutils.cpp index ae4fd3a1f77..fdecc5e37ce 100644 --- a/src/plugins/python/pythonutils.cpp +++ b/src/plugins/python/pythonutils.cpp @@ -47,8 +47,6 @@ namespace Internal { FilePath detectPython(const FilePath &documentPath) { - FilePath python; - PythonProject *project = documentPath.isEmpty() ? nullptr : qobject_cast( @@ -60,23 +58,21 @@ FilePath detectPython(const FilePath &documentPath) if (auto target = project->activeTarget()) { if (auto runConfig = target->activeRunConfiguration()) { if (auto interpreter = runConfig->aspect()) - python = interpreter->currentInterpreter().command; + return interpreter->currentInterpreter().command; } } } // check whether this file is inside a python virtual environment - QList venvInterpreters = PythonSettings::detectPythonVenvs(documentPath); - if (!python.exists() && !venvInterpreters.isEmpty()) - python = venvInterpreters.first().command; + const QList venvInterpreters = PythonSettings::detectPythonVenvs(documentPath); + if (!venvInterpreters.isEmpty()) + return venvInterpreters.first().command; - if (!python.exists()) - python = PythonSettings::defaultInterpreter().command; + auto defaultInterpreter = PythonSettings::defaultInterpreter().command; + if (defaultInterpreter.exists()) + return defaultInterpreter; - if (!python.exists() && !PythonSettings::interpreters().isEmpty()) - python = PythonSettings::interpreters().constFirst().command; - - return python; + return PythonSettings::interpreters().value(0).command; } static QStringList replImportArgs(const FilePath &pythonFile, ReplType type) From 2b428d5de09659220b7b94d793fdce401ed9d2bf Mon Sep 17 00:00:00 2001 From: David Schulz Date: Thu, 9 Jun 2022 15:29:11 +0200 Subject: [PATCH 35/94] Python: prefer python from path when detecting python for document Change-Id: I794a741fa7257833f0b4efbc25dfae43b8748427 Reviewed-by: Christian Stenger --- src/plugins/python/pythonutils.cpp | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/plugins/python/pythonutils.cpp b/src/plugins/python/pythonutils.cpp index fdecc5e37ce..08c8750c21f 100644 --- a/src/plugins/python/pythonutils.cpp +++ b/src/plugins/python/pythonutils.cpp @@ -47,18 +47,20 @@ namespace Internal { FilePath detectPython(const FilePath &documentPath) { - PythonProject *project = documentPath.isEmpty() - ? nullptr - : qobject_cast( - SessionManager::projectForFile(documentPath)); + Project *project = documentPath.isEmpty() ? nullptr + : SessionManager::projectForFile(documentPath); if (!project) - project = qobject_cast(SessionManager::startupProject()); + project = SessionManager::startupProject(); + + Environment env = Environment::systemEnvironment(); if (project) { if (auto target = project->activeTarget()) { if (auto runConfig = target->activeRunConfiguration()) { if (auto interpreter = runConfig->aspect()) return interpreter->currentInterpreter().command; + if (auto environmentAspect = runConfig->aspect()) + env = environmentAspect->environment(); } } } @@ -72,6 +74,14 @@ FilePath detectPython(const FilePath &documentPath) if (defaultInterpreter.exists()) return defaultInterpreter; + const FilePath python3FromPath = env.searchInPath("python3"); + if (python3FromPath.exists()) + return python3FromPath; + + const FilePath pythonFromPath = env.searchInPath("python"); + if (pythonFromPath.exists()) + return pythonFromPath; + return PythonSettings::interpreters().value(0).command; } From 9b08363d82184b01a4e685cdb1c2d0ca636f6154 Mon Sep 17 00:00:00 2001 From: David Schulz Date: Mon, 13 Jun 2022 10:15:35 +0200 Subject: [PATCH 36/94] Coco: update annotation color on font settings change Change-Id: I7812fccb047d696701d477ae85697facdb1c0361 Reviewed-by: Christian Stenger --- src/plugins/coco/cocolanguageclient.cpp | 30 +++++++++++++++---- .../languageclient/diagnosticmanager.cpp | 8 +++++ .../languageclient/diagnosticmanager.h | 2 ++ 3 files changed, 34 insertions(+), 6 deletions(-) diff --git a/src/plugins/coco/cocolanguageclient.cpp b/src/plugins/coco/cocolanguageclient.cpp index e360b6952f6..4006a14550c 100644 --- a/src/plugins/coco/cocolanguageclient.cpp +++ b/src/plugins/coco/cocolanguageclient.cpp @@ -154,15 +154,11 @@ class CocoTextMark : public TextEditor::TextMark public: CocoTextMark(const FilePath &fileName, const CocoDiagnostic &diag, const Id &clientId) : TextEditor::TextMark(fileName, diag.range().start().line() + 1, clientId) + , m_severity(diag.cocoSeverity()) { setLineAnnotation(diag.message()); setToolTip(diag.message()); - if (optional severity = diag.cocoSeverity()) { - - const TextEditor::TextStyle style = styleForSeverity(*severity); - m_annotationColor = - TextEditor::TextEditorSettings::fontSettings().formatFor(style).foreground(); - } + updateAnnotationColor(); } QColor annotationColor() const override @@ -171,6 +167,16 @@ public: : TextEditor::TextMark::annotationColor(); } + void updateAnnotationColor() + { + if (m_severity) { + const TextEditor::TextStyle style = styleForSeverity(*m_severity); + m_annotationColor = + TextEditor::TextEditorSettings::fontSettings().formatFor(style).foreground(); + } + } + + optional m_severity; QColor m_annotationColor; }; @@ -180,10 +186,22 @@ public: CocoDiagnosticManager(Client *client) : DiagnosticManager(client) { + connect(TextEditor::TextEditorSettings::instance(), + &TextEditor::TextEditorSettings::fontSettingsChanged, + this, + &CocoDiagnosticManager::fontSettingsChanged); setExtraSelectionsId("CocoExtraSelections"); } private: + void fontSettingsChanged(const TextEditor::FontSettings &fontSettings) + { + forAllMarks([](TextEditor::TextMark *mark){ + static_cast(mark)->updateAnnotationColor(); + mark->updateMarker(); + }); + } + TextEditor::TextMark *createTextMark(const FilePath &filePath, const Diagnostic &diagnostic, bool /*isProjectFile*/) const override diff --git a/src/plugins/languageclient/diagnosticmanager.cpp b/src/plugins/languageclient/diagnosticmanager.cpp index 4ebb7f6c304..e81bda7bd8a 100644 --- a/src/plugins/languageclient/diagnosticmanager.cpp +++ b/src/plugins/languageclient/diagnosticmanager.cpp @@ -176,6 +176,14 @@ void DiagnosticManager::setExtraSelectionsId(const Utils::Id &extraSelectionsId) m_extraSelectionsId = extraSelectionsId; } +void DiagnosticManager::forAllMarks(std::function func) +{ + for (const Marks &marks : qAsConst(m_marks)) { + for (TextEditor::TextMark *mark : marks.marks) + func(mark); + } +} + void DiagnosticManager::clearDiagnostics() { for (const DocumentUri &uri : m_diagnostics.keys()) diff --git a/src/plugins/languageclient/diagnosticmanager.h b/src/plugins/languageclient/diagnosticmanager.h index aa229b91c00..282a5c3d065 100644 --- a/src/plugins/languageclient/diagnosticmanager.h +++ b/src/plugins/languageclient/diagnosticmanager.h @@ -85,6 +85,8 @@ protected: void setExtraSelectionsId(const Utils::Id &extraSelectionsId); + void forAllMarks(std::function func); + private: struct VersionedDiagnostics { From a9245bf1869fd3f68a399ac60abd67ac156b4e8d Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 14 Jun 2022 17:10:17 +0200 Subject: [PATCH 37/94] LanguageClient: Use more FilePath Change-Id: Ia4ffec1fd2c6bd8dc2cce40efa49e3b4a4634f15 Reviewed-by: Reviewed-by: David Schulz --- src/plugins/languageclient/client.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/plugins/languageclient/client.cpp b/src/plugins/languageclient/client.cpp index 0186921b88a..303436a7ff4 100644 --- a/src/plugins/languageclient/client.cpp +++ b/src/plugins/languageclient/client.cpp @@ -896,8 +896,7 @@ void Client::setShadowDocument(const Utils::FilePath &filePath, const QString &c return; const auto uri = DocumentUri::fromFilePath(filePath); if (isNew) { - const QString mimeType = mimeTypeForFile( - filePath.toString(), MimeMatchMode::MatchExtension).name(); + const QString mimeType = mimeTypeForFile(filePath, MimeMatchMode::MatchExtension).name(); d->sendOpenNotification(filePath, mimeType, content, 0); } From 386c462a72a51d8e5ca1bd8bd47de1b1c6eacd12 Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 14 Jun 2022 17:08:36 +0200 Subject: [PATCH 38/94] Designer: Use more FilePath Change-Id: I9571c25c6c3dd430ccd3f7233a4f7290c9ba508b Reviewed-by: Jarek Kobus Reviewed-by: --- src/plugins/designer/formeditorplugin.cpp | 33 +++++++++++------------ 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/src/plugins/designer/formeditorplugin.cpp b/src/plugins/designer/formeditorplugin.cpp index ebe2f7cad38..6643a78e734 100644 --- a/src/plugins/designer/formeditorplugin.cpp +++ b/src/plugins/designer/formeditorplugin.cpp @@ -27,7 +27,6 @@ #include "formeditorfactory.h" #include "formeditorw.h" #include "formtemplatewizardpage.h" -#include "formwindoweditor.h" #ifdef CPP_ENABLED # include "cpp/formclasswizard.h" @@ -58,6 +57,7 @@ using namespace Core; using namespace Designer::Constants; +using namespace Utils; namespace Designer { namespace Internal { @@ -141,24 +141,24 @@ void FormEditorPlugin::extensionsInitialized() //////////////////////////////////////////////////// // Find out current existing editor file -static QString currentFile() +static FilePath currentFile() { if (const IDocument *document = EditorManager::currentDocument()) { - const QString fileName = document->filePath().toString(); - if (!fileName.isEmpty() && QFileInfo(fileName).isFile()) - return fileName; + const FilePath filePath = document->filePath(); + if (!filePath.isEmpty() && filePath.isFile()) + return filePath; } - return QString(); + return {}; } // Switch between form ('ui') and source file ('cpp'): // Find corresponding 'other' file, simply assuming it is in the same directory. -static QString otherFile() +static FilePath otherFile() { // Determine mime type of current file. - const QString current = currentFile(); + const FilePath current = currentFile(); if (current.isEmpty()) - return QString(); + return {}; const Utils::MimeType currentMimeType = Utils::mimeTypeForFile(current); // Determine potential suffixes of candidate files // 'ui' -> 'cpp', 'cpp/h' -> 'ui'. @@ -169,22 +169,21 @@ static QString otherFile() || currentMimeType.matchesName(CppEditor::Constants::CPP_HEADER_MIMETYPE)) { candidateSuffixes += Utils::mimeTypeForName(FORM_MIMETYPE).suffixes(); } else { - return QString(); + return {}; } // Try to find existing file with desired suffix - const QFileInfo currentFI(current); - const QString currentBaseName = currentFI.path() + '/' + currentFI.baseName() + '.'; + const FilePath currentBaseName = current.parentDir().pathAppended(current.baseName() + '.'); for (const QString &candidateSuffix : qAsConst(candidateSuffixes)) { - const QFileInfo fi(currentBaseName + candidateSuffix); - if (fi.isFile()) - return fi.absoluteFilePath(); + const FilePath filePath = currentBaseName.stringAppended(candidateSuffix); + if (filePath.isFile()) + return filePath.absoluteFilePath(); } - return QString(); + return {}; } void FormEditorPlugin::switchSourceForm() { - const auto fileToOpen = Utils::FilePath::fromString(otherFile()); + const FilePath fileToOpen = otherFile(); if (!fileToOpen.isEmpty()) EditorManager::openEditor(fileToOpen); } From 7f7768cdd10ec34f1f209d8bd5154d60c53ea6c9 Mon Sep 17 00:00:00 2001 From: hjk Date: Thu, 9 Jun 2022 11:36:41 +0200 Subject: [PATCH 39/94] Debugger: Add simple dumper for QSettingsKey Change-Id: Ieaa702051066e7dcf7f0bd44d869e5a231c19112 Reviewed-by: Reviewed-by: Christian Stenger --- share/qtcreator/debugger/qttypes.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/share/qtcreator/debugger/qttypes.py b/share/qtcreator/debugger/qttypes.py index 0cacac30c25..fee0e12049a 100644 --- a/share/qtcreator/debugger/qttypes.py +++ b/share/qtcreator/debugger/qttypes.py @@ -1740,6 +1740,11 @@ def qdump__QString(d, value): d.putArrayData(data, size, d.createType('@QChar')) +def qdump__QSettingsKey(d, value): + qdump__QString(d, value) + d.putBetterType(value.type) + + def qdump__QStaticStringData(d, value): size = value.type[0] (ref, size, alloc, pad, offset, data) = value.split('iii@p%ss' % (2 * size)) From 04a23c38f0d751cd4b1757d775434e8c40eae006 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Mon, 13 Jun 2022 14:21:23 +0200 Subject: [PATCH 40/94] ProjectExplorer: Pop up task window on first error ... rather than only at the end of the build process. Fixes: QTCREATORBUG-27702 Change-Id: I114ef2898f26904e29d96b2cf65dcae4ee9a6121 Reviewed-by: Qt CI Bot Reviewed-by: Reviewed-by: hjk --- src/plugins/projectexplorer/buildmanager.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/plugins/projectexplorer/buildmanager.cpp b/src/plugins/projectexplorer/buildmanager.cpp index 7116792d77c..41e27da1f23 100644 --- a/src/plugins/projectexplorer/buildmanager.cpp +++ b/src/plugins/projectexplorer/buildmanager.cpp @@ -228,6 +228,7 @@ public: QStringList m_stepNames; int m_progress = 0; int m_maxProgress = 0; + bool m_poppedUpTaskWindow = false; bool m_running = false; bool m_isDeploying = false; // is set to true while canceling, so that nextBuildStep knows that the BuildStep finished because of canceling @@ -489,6 +490,10 @@ void BuildManager::updateTaskCount() { const int errors = getErrorTaskCount(); ProgressManager::setApplicationLabel(errors > 0 ? QString::number(errors) : QString()); + if (errors > 0 && !d->m_poppedUpTaskWindow) { + showTaskWindow(); + d->m_poppedUpTaskWindow = true; + } } void BuildManager::finish() @@ -516,6 +521,7 @@ void BuildManager::clearBuildQueue() d->m_buildQueue.clear(); d->m_enabledState.clear(); d->m_running = false; + d->m_poppedUpTaskWindow = false; d->m_isDeploying = false; d->m_previousBuildStepProject = nullptr; d->m_currentBuildStep = nullptr; @@ -752,6 +758,7 @@ void BuildManager::nextStep() d->m_currentBuildStep->run(); } else { d->m_running = false; + d->m_poppedUpTaskWindow = false; d->m_isDeploying = false; d->m_previousBuildStepProject = nullptr; d->m_progressFutureInterface->reportFinished(); From 56e838da70c55a881fabda25e34e4aede1dfe9c8 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Tue, 14 Jun 2022 11:48:25 +0200 Subject: [PATCH 41/94] CMakeProjectManager: Check for generic ninja error message ... in the output parser. This improves the user experience for the edge case that the failing tool did not emit a (known) error message, and does not hurt otherwise. Fixes: QTCREATORBUG-27606 Change-Id: I74cd327b1daff80ea2f46620e9d169a3db73578e Reviewed-by: Cristian Adam Reviewed-by: Qt CI Bot Reviewed-by: --- src/plugins/cmakeprojectmanager/cmakeparser.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/plugins/cmakeprojectmanager/cmakeparser.cpp b/src/plugins/cmakeprojectmanager/cmakeparser.cpp index 3da9a18b49a..addde5fd239 100644 --- a/src/plugins/cmakeprojectmanager/cmakeparser.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeparser.cpp @@ -64,6 +64,13 @@ void CMakeParser::setSourceDirectory(const QString &sourceDir) OutputLineParser::Result CMakeParser::handleLine(const QString &line, OutputFormat type) { + if (line.startsWith("ninja: build stopped")) { + m_lastTask = BuildSystemTask(Task::Error, line); + m_lines = 1; + flush(); + return Status::Done; + } + if (type != StdErrFormat) return Status::NotHandled; From 71b914b82865adeb562aa48d5d1011498627d94c Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Mon, 13 Jun 2022 16:52:52 +0200 Subject: [PATCH 42/94] ClangCodeModel: Do not dump compile_commands.json into project dir We can't know if it's safe to put there; e.g. we might overwrite an existing one. Fixes: QTCREATORBUG-27573 Change-Id: I928408996759aaccb84332fcf95cf43d7f3bf083 Reviewed-by: Qt CI Bot Reviewed-by: Reviewed-by: Christian Stenger --- src/plugins/clangcodemodel/clangcodemodelplugin.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/plugins/clangcodemodel/clangcodemodelplugin.cpp b/src/plugins/clangcodemodel/clangcodemodelplugin.cpp index 3b26d7b82c7..675ee4e0e93 100644 --- a/src/plugins/clangcodemodel/clangcodemodelplugin.cpp +++ b/src/plugins/clangcodemodel/clangcodemodelplugin.cpp @@ -34,8 +34,6 @@ # include "test/clangfixittest.h" #endif -#include - #include #include #include @@ -45,6 +43,7 @@ #include #include +#include #include #include #include @@ -53,6 +52,9 @@ #include +#include +#include + using namespace Utils; namespace ClangCodeModel { @@ -69,10 +71,13 @@ void ClangCodeModelPlugin::generateCompilationDB() const auto projectInfo = CppModelManager::instance()->projectInfo(target->project()); if (!projectInfo) return; + FilePath baseDir = projectInfo->buildRoot(); + if (baseDir == target->project()->projectDirectory()) + baseDir = TemporaryDirectory::masterDirectoryFilePath(); QFuture task = Utils::runAsync(&Internal::generateCompilationDB, projectInfo, - projectInfo->buildRoot(), CompilationDbPurpose::Project, + baseDir, CompilationDbPurpose::Project, warningsConfigForProject(target->project()), globalClangOptions(), FilePath()); From 9ecc7b356b8c6ef362483b423b5a21119a7440d5 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Tue, 14 Jun 2022 13:44:56 +0200 Subject: [PATCH 43/94] QtSupport: Make sure Qt 6 matches a Qt 5 version requirement ... of a wizard. For example, the QtQuick application wizard specifies "Qt.5.6" as a required feature, which has the implicit semantics of "Qt 5.6 or higher". On the C++ side, a QtVersion adds its exact version x.y plus all lower ones down to x.0, in an attempt to somehow implement versioning semantics using tags. This means that versions 6.0 and higher did not fulfill the 5.6 requirement anymore, which was very likely not the intention. We therefore extend the mechanism to major version x-1, though in the future we should probably come up with a less absurd approach. Fixes: QTCREATORBUG-27612 Change-Id: I41d60809a02f0caddba7e702c91c01e86ecbd4ac Reviewed-by: Qt CI Bot Reviewed-by: Reviewed-by: Eike Ziller --- src/plugins/qtsupport/baseqtversion.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/plugins/qtsupport/baseqtversion.cpp b/src/plugins/qtsupport/baseqtversion.cpp index c2460fd1290..ea74600c520 100644 --- a/src/plugins/qtsupport/baseqtversion.cpp +++ b/src/plugins/qtsupport/baseqtversion.cpp @@ -157,6 +157,10 @@ static QSet versionedIds(const QByteArray &prefix, int major, int minor) result.insert(Id::fromName(featureDotMajor + '.' + minorStr)); } + // FIXME: Terrible hack. Get rid of using version numbers as tags! + if (major > 5) + result.unite(versionedIds(prefix, major - 1, 15)); + return result; } From 5304042d2b21899426902ae8a059ba6fc359bbff Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 14 Jun 2022 16:28:46 +0200 Subject: [PATCH 44/94] QmlProjectMananger: Remove a use of mimeType via QFileInfo And a bit cosmetics. Change-Id: I3e64b661d86cadad22422c2bffad0ed1262283b4 Reviewed-by: Eike Ziller Reviewed-by: Qt CI Bot Reviewed-by: --- src/plugins/qmlprojectmanager/qmlmainfileaspect.cpp | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/plugins/qmlprojectmanager/qmlmainfileaspect.cpp b/src/plugins/qmlprojectmanager/qmlmainfileaspect.cpp index d16f79ed64f..404b43bb772 100644 --- a/src/plugins/qmlprojectmanager/qmlmainfileaspect.cpp +++ b/src/plugins/qmlprojectmanager/qmlmainfileaspect.cpp @@ -27,7 +27,6 @@ #include "qmlproject.h" #include "qmlprojectmanagerconstants.h" -#include "qmlprojectrunconfiguration.h" #include @@ -75,7 +74,7 @@ QmlMainFileAspect::~QmlMainFileAspect() delete m_fileListCombo; } -void QmlMainFileAspect::addToLayout(Utils::LayoutBuilder &builder) +void QmlMainFileAspect::addToLayout(LayoutBuilder &builder) { QTC_ASSERT(!m_fileListCombo, delete m_fileListCombo); m_fileListCombo = new QComboBox; @@ -238,7 +237,7 @@ bool QmlMainFileAspect::isQmlFilePresent() bool qmlFileFound = false; if (mainScriptSource() == FileInEditor) { IDocument *document = EditorManager::currentDocument(); - Utils::MimeType mainScriptMimeType = Utils::mimeTypeForFile(mainScript()); + const MimeType mainScriptMimeType = mimeTypeForFile(mainScript()); if (document) { m_currentFileFilename = document->filePath().toString(); if (mainScriptMimeType.matchesName(ProjectExplorer::Constants::QML_MIMETYPE) @@ -251,11 +250,9 @@ bool QmlMainFileAspect::isQmlFilePresent() // find a qml file with lowercase filename. This is slow, but only done // in initialization/other border cases. const auto files = m_target->project()->files(Project::SourceFiles); - for (const Utils::FilePath &filename : files) { - const QFileInfo fi = filename.toFileInfo(); - - if (!filename.isEmpty() && fi.baseName().at(0).isLower()) { - Utils::MimeType type = Utils::mimeTypeForFile(fi); + for (const FilePath &filename : files) { + if (!filename.isEmpty() && filename.baseName().at(0).isLower()) { + const MimeType type = mimeTypeForFile(filename); if (type.matchesName(ProjectExplorer::Constants::QML_MIMETYPE) || type.matchesName(ProjectExplorer::Constants::QMLUI_MIMETYPE)) { m_currentFileFilename = filename.toString(); From a29944c68ec68a0eaae4fac5fdddf43e81d3946b Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 14 Jun 2022 15:31:28 +0200 Subject: [PATCH 45/94] Core: Remove another use of mimetype from FileInfo Change-Id: I9f0b789f60c78de059bf10c36aab2d6a60da9f3e Reviewed-by: Eike Ziller Reviewed-by: --- src/plugins/coreplugin/dialogs/filepropertiesdialog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/coreplugin/dialogs/filepropertiesdialog.cpp b/src/plugins/coreplugin/dialogs/filepropertiesdialog.cpp index 18e13f35311..5236511adc0 100644 --- a/src/plugins/coreplugin/dialogs/filepropertiesdialog.cpp +++ b/src/plugins/coreplugin/dialogs/filepropertiesdialog.cpp @@ -152,7 +152,7 @@ void FilePropertiesDialog::refresh() m_ui->name->setText(fileInfo.fileName()); m_ui->path->setText(QDir::toNativeSeparators(fileInfo.canonicalPath())); - const Utils::MimeType mimeType = Utils::mimeTypeForFile(fileInfo); + const Utils::MimeType mimeType = Utils::mimeTypeForFile(m_filePath); m_ui->mimeType->setText(mimeType.name()); const EditorTypeList factories = IEditorFactory::preferredEditorTypes(m_filePath); From 56a3afef3cddf03fc495d576aff4f7d1dbd426ad Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 14 Jun 2022 16:39:52 +0200 Subject: [PATCH 46/94] Utils: Remove mimeTypeForFile(const QFileInfo &fileInfo, ...) Use the FilePath based overload instead. Change-Id: I048bcbf891f10683428c73130db882253c169333 Reviewed-by: Eike Ziller Reviewed-by: --- src/libs/utils/mimetypes2/mimeutils.cpp | 6 ------ src/libs/utils/mimeutils.h | 6 ------ 2 files changed, 12 deletions(-) diff --git a/src/libs/utils/mimetypes2/mimeutils.cpp b/src/libs/utils/mimetypes2/mimeutils.cpp index ffa2488df19..676398bb140 100644 --- a/src/libs/utils/mimetypes2/mimeutils.cpp +++ b/src/libs/utils/mimetypes2/mimeutils.cpp @@ -60,12 +60,6 @@ MimeType mimeTypeForFile(const QString &fileName, MimeMatchMode mode) return mdb.mimeTypeForFile(fileName, MimeDatabase::MatchMode(mode)); } -MimeType mimeTypeForFile(const QFileInfo &fileInfo, MimeMatchMode mode) -{ - MimeDatabase mdb; - return mdb.mimeTypeForFile(fileInfo, MimeDatabase::MatchMode(mode)); -} - MimeType mimeTypeForFile(const FilePath &filePath, MimeMatchMode mode) { MimeDatabase mdb; diff --git a/src/libs/utils/mimeutils.h b/src/libs/utils/mimeutils.h index e334258c732..7b3071ff609 100644 --- a/src/libs/utils/mimeutils.h +++ b/src/libs/utils/mimeutils.h @@ -44,10 +44,6 @@ #include #include -QT_BEGIN_NAMESPACE -class QFileInfo; -QT_END_NAMESPACE - namespace Utils { class FilePath; @@ -59,8 +55,6 @@ enum class MimeMatchMode { MatchDefault = 0x0, MatchExtension = 0x1, MatchConten QTCREATOR_UTILS_EXPORT MimeType mimeTypeForFile(const QString &fileName, MimeMatchMode mode = MimeMatchMode::MatchDefault); -QTCREATOR_UTILS_EXPORT MimeType mimeTypeForFile(const QFileInfo &fileInfo, - MimeMatchMode mode = MimeMatchMode::MatchDefault); QTCREATOR_UTILS_EXPORT MimeType mimeTypeForFile(const FilePath &filePath, MimeMatchMode mode = MimeMatchMode::MatchDefault); QTCREATOR_UTILS_EXPORT QList mimeTypesForFileName(const QString &fileName); From 44764bc54efcee882686ff353ae7da6f78f1fe31 Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 14 Jun 2022 17:06:19 +0200 Subject: [PATCH 47/94] ProjectExplorer: Replace a non-FilePath based mimetype use Change-Id: Icac2f3b2b79f725151a6947a0a6f544f51b31fd7 Reviewed-by: Reviewed-by: Alessandro Portale --- .../jsonwizard/jsonwizardgeneratorfactory.cpp | 4 ++-- .../jsonwizard/jsonwizardscannergenerator.cpp | 8 +++----- .../projectexplorer/projectfilewizardextension.cpp | 2 +- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/plugins/projectexplorer/jsonwizard/jsonwizardgeneratorfactory.cpp b/src/plugins/projectexplorer/jsonwizard/jsonwizardgeneratorfactory.cpp index 38a92e93707..624583f6dcb 100644 --- a/src/plugins/projectexplorer/jsonwizard/jsonwizardgeneratorfactory.cpp +++ b/src/plugins/projectexplorer/jsonwizard/jsonwizardgeneratorfactory.cpp @@ -86,7 +86,7 @@ bool JsonWizardGenerator::formatFile(const JsonWizard *wizard, GeneratedFile *fi if (file->isBinary() || file->contents().isEmpty()) return true; // nothing to do - Id languageId = TextEditorSettings::languageId(Utils::mimeTypeForFile(file->path()).name()); + Id languageId = TextEditorSettings::languageId(Utils::mimeTypeForFile(file->filePath()).name()); if (!languageId.isValid()) return true; // don't modify files like *.ui, *.pro @@ -99,7 +99,7 @@ bool JsonWizardGenerator::formatFile(const JsonWizard *wizard, GeneratedFile *fi Indenter *indenter = nullptr; if (factory) { indenter = factory->createIndenter(&doc); - indenter->setFileName(Utils::FilePath::fromString(file->path())); + indenter->setFileName(file->filePath()); } if (!indenter) indenter = new TextIndenter(&doc); diff --git a/src/plugins/projectexplorer/jsonwizard/jsonwizardscannergenerator.cpp b/src/plugins/projectexplorer/jsonwizard/jsonwizardscannergenerator.cpp index 7912d5decfd..528110e8799 100644 --- a/src/plugins/projectexplorer/jsonwizard/jsonwizardscannergenerator.cpp +++ b/src/plugins/projectexplorer/jsonwizard/jsonwizardscannergenerator.cpp @@ -25,15 +25,12 @@ #include "jsonwizardscannergenerator.h" -#include "../projectexplorer.h" #include "../projectmanager.h" -#include "jsonwizard.h" -#include "jsonwizardfactory.h" #include #include -#include +#include #include #include #include @@ -104,7 +101,8 @@ Core::GeneratedFiles JsonWizardScannerGenerator::fileList(Utils::MacroExpander * for (auto it = result.begin(); it != result.end(); ++it) { const QString relPath = project.relativeFilePath(it->path()); it->setBinary(binaryPattern.match(relPath).hasMatch()); - bool found = ProjectManager::canOpenProjectForMimeType(Utils::mimeTypeForFile(relPath)); + bool found = ProjectManager::canOpenProjectForMimeType(Utils::mimeTypeForFile( + Utils::FilePath::fromString(relPath))); if (found) { it->setAttributes(it->attributes() | Core::GeneratedFile::OpenProjectAttribute); minDepth = std::min(minDepth, getDepth(it->path())); diff --git a/src/plugins/projectexplorer/projectfilewizardextension.cpp b/src/plugins/projectexplorer/projectfilewizardextension.cpp index fc3fb6ec5f8..f0ba9a95710 100644 --- a/src/plugins/projectexplorer/projectfilewizardextension.cpp +++ b/src/plugins/projectexplorer/projectfilewizardextension.cpp @@ -244,7 +244,7 @@ void ProjectFileWizardExtension::applyCodeStyle(GeneratedFile *file) const if (file->isBinary() || file->contents().isEmpty()) return; // nothing to do - Id languageId = TextEditorSettings::languageId(Utils::mimeTypeForFile(file->path()).name()); + Id languageId = TextEditorSettings::languageId(Utils::mimeTypeForFile(file->filePath()).name()); if (!languageId.isValid()) return; // don't modify files like *.ui *.pro From a7d8698bf212fb7751069941c44719eb613dc40c Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Wed, 15 Jun 2022 12:46:17 +0200 Subject: [PATCH 48/94] Fix generating .user files when creating projects Amends 525ea8a1ec7b0d046cb27aa08d564f3bc7605c44 Change-Id: I04b2e55b986278b93ae88dd3163e63cafefdd546 Reviewed-by: hjk --- src/plugins/projectexplorer/jsonwizard/jsonkitspage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/projectexplorer/jsonwizard/jsonkitspage.cpp b/src/plugins/projectexplorer/jsonwizard/jsonkitspage.cpp index d4a9f07c929..5ddb908baef 100644 --- a/src/plugins/projectexplorer/jsonwizard/jsonkitspage.cpp +++ b/src/plugins/projectexplorer/jsonwizard/jsonkitspage.cpp @@ -113,7 +113,7 @@ void JsonKitsPage::setupProjectFiles(const JsonWizard::GeneratorFiles &files) for (const JsonWizard::GeneratorFile &f : files) { if (f.file.attributes() & GeneratedFile::OpenProjectAttribute) { Project *project = ProjectManager::openProject(Utils::mimeTypeForFile(f.file.filePath()), - f.file.filePath().absolutePath()); + f.file.filePath().absoluteFilePath()); if (project) { if (setupProject(project)) project->saveSettings(); From d80a713b894355f26048a54554ac125124f30e27 Mon Sep 17 00:00:00 2001 From: David Schulz Date: Tue, 14 Jun 2022 09:53:26 +0200 Subject: [PATCH 49/94] LanguageClient: move relevant snippets to the front If a snippet starts with the current prefix move it to the front of the proposed completions. Fixes: QTCREATORBUG-27566 Change-Id: I568d34e4da596a8cf4f08eb88eb1ee865edbed70 Reviewed-by: Christian Kandeler --- .../languageclientcompletionassist.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/plugins/languageclient/languageclientcompletionassist.cpp b/src/plugins/languageclient/languageclientcompletionassist.cpp index e9e8ad64533..e10729987ce 100644 --- a/src/plugins/languageclient/languageclientcompletionassist.cpp +++ b/src/plugins/languageclient/languageclientcompletionassist.cpp @@ -233,7 +233,7 @@ public: // GenericProposalModel interface bool containsDuplicates() const override { return false; } bool isSortable(const QString &/*prefix*/) const override; - void sort(const QString &/*prefix*/) override; + void sort(const QString &prefix) override; bool supportsPrefixExpansion() const override { return false; } QList items() const { return m_currentItems; } @@ -247,19 +247,21 @@ bool LanguageClientCompletionModel::isSortable(const QString &) const }); } -void LanguageClientCompletionModel::sort(const QString &/*prefix*/) +void LanguageClientCompletionModel::sort(const QString &prefix) { std::sort(m_currentItems.begin(), m_currentItems.end(), - [] (AssistProposalItemInterface *a, AssistProposalItemInterface *b){ + [&prefix] (AssistProposalItemInterface *a, AssistProposalItemInterface *b){ const auto lca = dynamic_cast(a); const auto lcb = dynamic_cast(b); if (!lca && !lcb) return a->text() < b->text(); if (lca && lcb) return *lca < *lcb; - if (lca && !lcb) - return true; - return false; + if (prefix.isEmpty()) + return lca && !lcb; + if (!lca) + return a->text().toLower().startsWith(prefix.toLower()); + return !b->text().toLower().startsWith(prefix.toLower()); }); } From a750961f4d652b08c6777a5acf5dafbcd093449a Mon Sep 17 00:00:00 2001 From: David Schulz Date: Wed, 15 Jun 2022 13:20:05 +0200 Subject: [PATCH 50/94] Python: make sure working dir is on python device Task-number: QTCREATORBUG-27536 Change-Id: If9c8f88f2a871ec71b200020689a4ae9df1e8a6a Reviewed-by: hjk --- src/plugins/python/pythonrunconfiguration.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/plugins/python/pythonrunconfiguration.cpp b/src/plugins/python/pythonrunconfiguration.cpp index fc8a367da45..a04d2b723a7 100644 --- a/src/plugins/python/pythonrunconfiguration.cpp +++ b/src/plugins/python/pythonrunconfiguration.cpp @@ -198,6 +198,10 @@ PythonRunConfiguration::PythonRunConfiguration(Target *target, Id id) connect(target, &Target::buildSystemUpdated, this, &RunConfiguration::update); connect(target, &Target::buildSystemUpdated, this, &PythonRunConfiguration::updateExtraCompilers); currentInterpreterChanged(); + + setRunnableModifier([](Runnable &r) { + r.workingDirectory = r.workingDirectory.onDevice(r.command.executable()); + }); } PythonRunConfiguration::~PythonRunConfiguration() From a91043d8badc67bfa06faf94f1611af3a9fc807b Mon Sep 17 00:00:00 2001 From: David Schulz Date: Wed, 15 Jun 2022 11:47:05 +0200 Subject: [PATCH 51/94] Docker: assert on starting process in non device working dir Change-Id: I7dd1040c77b3a7f7378b5567b7b5568af5f57848 Reviewed-by: hjk --- src/plugins/docker/dockerdevice.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/docker/dockerdevice.cpp b/src/plugins/docker/dockerdevice.cpp index ba24dd7bea0..ca6d87e36fb 100644 --- a/src/plugins/docker/dockerdevice.cpp +++ b/src/plugins/docker/dockerdevice.cpp @@ -187,6 +187,7 @@ CommandLine DockerProcessImpl::fullLocalCommandLine(bool interactive) QStringList args; if (!m_setup.m_workingDirectory.isEmpty()) { + QTC_CHECK(DeviceManager::deviceForPath(m_setup.m_workingDirectory) == m_device); args.append({"cd", m_setup.m_workingDirectory.path()}); args.append("&&"); } From 3b7029fbdc8d947c700145752f990ddd8d37e42a Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Fri, 10 Jun 2022 10:17:20 +0200 Subject: [PATCH 52/94] AutoTest: Fix handling of test cases with comma Fixes: QTCREATORBUG-27705 Change-Id: I6e22df4e401dc52e8d8599cc8b4de16200093b03 Reviewed-by: David Schulz --- src/plugins/autotest/catch/catchconfiguration.cpp | 2 +- src/plugins/autotest/catch/catchtreeitem.cpp | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/plugins/autotest/catch/catchconfiguration.cpp b/src/plugins/autotest/catch/catchconfiguration.cpp index 4a3436d476b..7d374413a51 100644 --- a/src/plugins/autotest/catch/catchconfiguration.cpp +++ b/src/plugins/autotest/catch/catchconfiguration.cpp @@ -98,7 +98,7 @@ QStringList CatchConfiguration::argumentsForTestRunner(QStringList *omitted) con { QStringList arguments; if (testCaseCount()) - arguments << "\"" + testCases().join("\",\"") + "\""; + arguments << "\"" + testCases().join("\", \"") + "\""; arguments << "--reporter" << "xml"; if (AutotestPlugin::settings()->processArgs) { diff --git a/src/plugins/autotest/catch/catchtreeitem.cpp b/src/plugins/autotest/catch/catchtreeitem.cpp index 0108811008c..462f03dba84 100644 --- a/src/plugins/autotest/catch/catchtreeitem.cpp +++ b/src/plugins/autotest/catch/catchtreeitem.cpp @@ -37,7 +37,9 @@ namespace Internal { QString CatchTreeItem::testCasesString() const { - return m_state & CatchTreeItem::Parameterized ? QString(name() + " -*") : name(); + QString testcase = m_state & CatchTreeItem::Parameterized ? QString(name() + " -*") : name(); + // mask comma if it is part of the test case name + return testcase.replace(',', "\\,"); } static QString nonRootDisplayName(const CatchTreeItem *it) From 924806e10b34aa07e6da2ba11fac3d0c23e794c8 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Fri, 10 Jun 2022 10:46:35 +0200 Subject: [PATCH 53/94] AutoTest: Fix catch2 parsing when using prefixed commands If Catch2 is used with CATCH_CONFIG_PREFIX_ALL the relevant macros get a prefix. This patch enhances the respective parser to be able to handle these appropriate. This does not really take into account whether the define is set or not, so the parse results will only be correct if the project can be built. Fixes: QTCREATORBUG-27704 Change-Id: I935de752ac6106524c45c027af3e0f43673c4578 Reviewed-by: David Schulz --- .../autotest/catch/catchcodeparser.cpp | 24 ++++++++++--------- .../autotest/catch/catchtestparser.cpp | 6 +++-- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/src/plugins/autotest/catch/catchcodeparser.cpp b/src/plugins/autotest/catch/catchcodeparser.cpp index c1368c1aa72..350b34f5dc6 100644 --- a/src/plugins/autotest/catch/catchcodeparser.cpp +++ b/src/plugins/autotest/catch/catchcodeparser.cpp @@ -90,22 +90,24 @@ void CatchCodeParser::handleIdentifier() QTC_ASSERT(m_currentIndex < m_tokens.size(), return); const Token &token = m_tokens.at(m_currentIndex); const QByteArray &identifier = m_source.mid(int(token.bytesBegin()), int(token.bytes())); - if (identifier == "TEST_CASE") { + const QByteArray unprefixed = identifier.startsWith("CATCH_") ? identifier.mid(6) : identifier; + + if (unprefixed == "TEST_CASE") { handleTestCase(false); - } else if (identifier == "SCENARIO") { + } else if (unprefixed == "SCENARIO") { handleTestCase(true); - } else if (identifier == "TEMPLATE_TEST_CASE" || identifier == "TEMPLATE_PRODUCT_TEST_CASE" - || identifier == "TEMPLATE_LIST_TEST_CASE" || identifier == "TEMPLATE_TEST_CASE_SIG" - || identifier == "TEMPLATE_PRODUCT_TEST_CASE_SIG") { + } else if (unprefixed == "TEMPLATE_TEST_CASE" || unprefixed == "TEMPLATE_PRODUCT_TEST_CASE" + || unprefixed == "TEMPLATE_LIST_TEST_CASE" || unprefixed == "TEMPLATE_TEST_CASE_SIG" + || unprefixed == "TEMPLATE_PRODUCT_TEST_CASE_SIG") { handleParameterizedTestCase(false); - } else if (identifier == "TEST_CASE_METHOD") { + } else if (unprefixed == "TEST_CASE_METHOD") { handleFixtureOrRegisteredTestCase(true); - } else if (identifier == "TEMPLATE_TEST_CASE_METHOD_SIG" - || identifier == "TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG" - || identifier == "TEMPLATE_TEST_CASE_METHOD" - || identifier == "TEMPLATE_LIST_TEST_CASE_METHOD") { + } else if (unprefixed == "TEMPLATE_TEST_CASE_METHOD_SIG" + || unprefixed == "TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG" + || unprefixed == "TEMPLATE_TEST_CASE_METHOD" + || unprefixed == "TEMPLATE_LIST_TEST_CASE_METHOD") { handleParameterizedTestCase(true); - } else if (identifier == "METHOD_AS_TEST_CASE" || identifier == "REGISTER_TEST_CASE") { + } else if (unprefixed == "METHOD_AS_TEST_CASE" || unprefixed == "REGISTER_TEST_CASE") { handleFixtureOrRegisteredTestCase(false); } } diff --git a/src/plugins/autotest/catch/catchtestparser.cpp b/src/plugins/autotest/catch/catchtestparser.cpp index da6f6ca423a..c878da135e3 100644 --- a/src/plugins/autotest/catch/catchtestparser.cpp +++ b/src/plugins/autotest/catch/catchtestparser.cpp @@ -57,10 +57,11 @@ static bool isCatchTestCaseMacro(const QString ¯oName) static bool isCatchMacro(const QString ¯oName) { + QString unprefixed = macroName.startsWith("CATCH_") ? macroName.mid(6) : macroName; const QStringList validSectionMacros = { QStringLiteral("SECTION"), QStringLiteral("WHEN") }; - return isCatchTestCaseMacro(macroName) || validSectionMacros.contains(macroName); + return isCatchTestCaseMacro(unprefixed) || validSectionMacros.contains(unprefixed); } static bool includesCatchHeader(const CPlusPlus::Document::Ptr &doc, @@ -123,7 +124,8 @@ bool CatchTestParser::processDocument(QFutureInterface &futu const QByteArray &fileContent = getFileContent(fileName); if (!hasCatchNames(doc)) { - const QRegularExpression regex("\\b(SCENARIO|(TEMPLATE_(PRODUCT_)?)?TEST_CASE(_METHOD)?|" + const QRegularExpression regex("\\b(CATCH_)?" + "(SCENARIO|(TEMPLATE_(PRODUCT_)?)?TEST_CASE(_METHOD)?|" "TEMPLATE_TEST_CASE(_METHOD)?_SIG|" "TEMPLATE_PRODUCT_TEST_CASE(_METHOD)?_SIG|" "TEMPLATE_LIST_TEST_CASE_METHOD|METHOD_AS_TEST_CASE|" From 17ff9317cdc3de1773b62e46c1ec9b6958fa1035 Mon Sep 17 00:00:00 2001 From: Alessandro Portale Date: Wed, 15 Jun 2022 19:08:21 +0200 Subject: [PATCH 54/94] Debugger: Ensure termination of lldb.exe LLDB 12.0.8, which is included in NDK 23.1, hesitates to termiate when being told to. Setting UseCtrlCStub to true helps with that. Fixes: QTCREATORBUG-27723 Change-Id: If14f196cc18f0c6943b59702aca117101b66d02c Reviewed-by: Cristian Adam Reviewed-by: --- src/plugins/debugger/lldb/lldbengine.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/debugger/lldb/lldbengine.cpp b/src/plugins/debugger/lldb/lldbengine.cpp index 2168280abe3..5d7ed986588 100644 --- a/src/plugins/debugger/lldb/lldbengine.cpp +++ b/src/plugins/debugger/lldb/lldbengine.cpp @@ -83,6 +83,7 @@ static int ¤tToken() LldbEngine::LldbEngine() { + m_lldbProc.setUseCtrlCStub(true); m_lldbProc.setProcessMode(ProcessMode::Writer); setObjectName("LldbEngine"); From 87645d7355c5314b814881f179d33e610f0ba08d Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Thu, 16 Jun 2022 07:52:50 +0200 Subject: [PATCH 55/94] Fix Qt Quick Application wizard for Qt >= 6.2 Wrong variable used in the template's CMakeLists.txt resulted in errors when configuring. Amends db2cc2ba2745dfdc268698582610eb11e3bbb91b Fixes: QTCREATORBUG-27725 Change-Id: Id644ba83e118de1f12f4cdb4caa6368bd418419d Reviewed-by: Cristian Adam --- .../wizards/projects/qtquickapplication/CMakeLists.6.x.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/share/qtcreator/templates/wizards/projects/qtquickapplication/CMakeLists.6.x.txt b/share/qtcreator/templates/wizards/projects/qtquickapplication/CMakeLists.6.x.txt index a59656b3733..03f9091f768 100644 --- a/share/qtcreator/templates/wizards/projects/qtquickapplication/CMakeLists.6.x.txt +++ b/share/qtcreator/templates/wizards/projects/qtquickapplication/CMakeLists.6.x.txt @@ -28,4 +28,4 @@ set_target_properties(%{TargetName} PROPERTIES target_link_libraries(%{TargetName} PRIVATE Qt6::Quick) -install(TARGETS %{ProjectName} BUNDLE DESTINATION .) +install(TARGETS %{TargetName} BUNDLE DESTINATION .) From cc4c12b2810415505f8d267a389b8bcbae74f9dd Mon Sep 17 00:00:00 2001 From: hjk Date: Wed, 15 Jun 2022 14:53:02 +0200 Subject: [PATCH 56/94] CMake: Drop some unneeded includes Change-Id: I212d518e47529ff0cacdd968c1d09a7f0970c8d4 Reviewed-by: Cristian Adam --- src/plugins/cmakeprojectmanager/builddirparameters.cpp | 4 ---- src/plugins/cmakeprojectmanager/builddirparameters.h | 8 +------- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/src/plugins/cmakeprojectmanager/builddirparameters.cpp b/src/plugins/cmakeprojectmanager/builddirparameters.cpp index 57007fd635a..5595182db69 100644 --- a/src/plugins/cmakeprojectmanager/builddirparameters.cpp +++ b/src/plugins/cmakeprojectmanager/builddirparameters.cpp @@ -28,7 +28,6 @@ #include "cmakebuildconfiguration.h" #include "cmakebuildsystem.h" #include "cmakekitinformation.h" -#include "cmakeprojectconstants.h" #include "cmakeprojectplugin.h" #include "cmakespecificsettings.h" #include "cmaketoolmanager.h" @@ -109,8 +108,5 @@ CMakeTool *BuildDirParameters::cmakeTool() const return CMakeToolManager::findById(cmakeToolId); } -BuildDirParameters::BuildDirParameters(const BuildDirParameters &) = default; -BuildDirParameters &BuildDirParameters::operator=(const BuildDirParameters &) = default; - } // namespace Internal } // namespace CMakeProjectManager diff --git a/src/plugins/cmakeprojectmanager/builddirparameters.h b/src/plugins/cmakeprojectmanager/builddirparameters.h index 64666d3c65a..354a18678fe 100644 --- a/src/plugins/cmakeprojectmanager/builddirparameters.h +++ b/src/plugins/cmakeprojectmanager/builddirparameters.h @@ -25,14 +25,10 @@ #pragma once -#include "cmakeconfigitem.h" #include "cmaketool.h" #include -#include -#include - -#include +#include namespace CMakeProjectManager { namespace Internal { @@ -44,8 +40,6 @@ class BuildDirParameters public: BuildDirParameters(); explicit BuildDirParameters(CMakeBuildSystem *buildSystem); - BuildDirParameters(const BuildDirParameters &other); - BuildDirParameters &operator=(const BuildDirParameters &other); bool isValid() const; CMakeTool *cmakeTool() const; From f81afa455609a06482b5cd95ec80f7271ee476ac Mon Sep 17 00:00:00 2001 From: David Schulz Date: Mon, 13 Jun 2022 09:04:09 +0200 Subject: [PATCH 57/94] TextEditor: adjust default coco colors and controls Change-Id: I6fa4d5a65067d58e07be974e6ccc349030a03a53 Reviewed-by: Alessandro Portale Reviewed-by: Christian Stenger --- src/plugins/texteditor/texteditorsettings.cpp | 31 +++++++++++++------ 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/src/plugins/texteditor/texteditorsettings.cpp b/src/plugins/texteditor/texteditorsettings.cpp index 630fbd440a9..ed840b1d428 100644 --- a/src/plugins/texteditor/texteditorsettings.cpp +++ b/src/plugins/texteditor/texteditorsettings.cpp @@ -373,46 +373,57 @@ FormatDescriptions TextEditorSettingsPrivate::initialFormats() tr("Names of static fields or member functions."), FormatDescription::ShowAllControls); + const auto cocoControls = FormatDescription::ShowControls( + FormatDescription::ShowAllAbsoluteControls | FormatDescription::ShowRelativeControls); formatDescr.emplace_back(C_COCO_CODE_ADDED, tr("Code Coverage Added Code"), tr("New code that was not checked for tests."), - FormatDescription::ShowAllControls); + cocoControls); formatDescr.emplace_back(C_COCO_PARTIALLY_COVERED, tr("Partially Covered Code"), tr("Partial branch/condition coverage."), - FormatDescription::ShowAllControls); + Qt::darkYellow, + cocoControls); formatDescr.emplace_back(C_COCO_NOT_COVERED, tr("Uncovered Code"), tr("Not covered at all."), - FormatDescription::ShowAllControls); + Qt::red, + cocoControls); formatDescr.emplace_back(C_COCO_FULLY_COVERED, tr("Fully Covered Code"), tr("Fully covered code."), - FormatDescription::ShowAllControls); + Qt::green, + cocoControls); formatDescr.emplace_back(C_COCO_MANUALLY_VALIDATED, tr("Manually Validated Code"), tr("User added validation."), - FormatDescription::ShowAllControls); + Qt::blue, + cocoControls); formatDescr.emplace_back(C_COCO_DEAD_CODE, tr("Code Coverage Dead Code"), tr("Unreachable code."), - FormatDescription::ShowAllControls); + Qt::magenta, + cocoControls); formatDescr.emplace_back(C_COCO_EXECUTION_COUNT_TOO_LOW, tr("Code Coverage Execution Count Too Low"), tr("Minimum count not reached."), - FormatDescription::ShowAllControls); + Qt::red, + cocoControls); formatDescr.emplace_back(C_COCO_NOT_COVERED_INFO, tr("Implicitly Not Covered Code"), tr("PLACEHOLDER"), - FormatDescription::ShowAllControls); + Qt::red, + cocoControls); formatDescr.emplace_back(C_COCO_COVERED_INFO, tr("Implicitly Covered Code"), tr("PLACEHOLDER"), - FormatDescription::ShowAllControls); + Qt::green, + cocoControls); formatDescr.emplace_back(C_COCO_MANUALLY_VALIDATED_INFO, tr("Implicit Manual Coverage Validation"), tr("PLACEHOLDER"), - FormatDescription::ShowAllControls); + Qt::blue, + cocoControls); return formatDescr; } From 43a927880976b090d0ee32acb1f0156dc2f58d98 Mon Sep 17 00:00:00 2001 From: hjk Date: Wed, 15 Jun 2022 18:18:23 +0200 Subject: [PATCH 58/94] Valgrind: Act on pressing Stop Fixes: QTCREATORBUG-27714 Change-Id: I82b49df8e4ac70e095abbac31fe5fc06d0140e17 Reviewed-by: Reviewed-by: Christian Stenger --- src/plugins/valgrind/valgrindrunner.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/valgrind/valgrindrunner.cpp b/src/plugins/valgrind/valgrindrunner.cpp index ec817b1f61b..b03b5180fff 100644 --- a/src/plugins/valgrind/valgrindrunner.cpp +++ b/src/plugins/valgrind/valgrindrunner.cpp @@ -316,7 +316,7 @@ QString ValgrindRunner::errorString() const void ValgrindRunner::stop() { - d->m_valgrindProcess.close(); + d->m_valgrindProcess.stopProcess(); } XmlProtocol::ThreadedParser *ValgrindRunner::parser() const From c96571ca745329c758d30d27685e194e32252b21 Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Wed, 15 Jun 2022 15:26:52 +0200 Subject: [PATCH 59/94] Update qlitehtml The new head contains a fix for pageUp/Down keys issue. Task-number: QTBUG-100837 Change-Id: Ifa925f4270fb9106b60dead94cdbf61c5cb38351 Reviewed-by: Qt CI Bot Reviewed-by: Reviewed-by: Eike Ziller --- src/libs/qlitehtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/qlitehtml b/src/libs/qlitehtml index 6bfa7a2beaf..076f57c9436 160000 --- a/src/libs/qlitehtml +++ b/src/libs/qlitehtml @@ -1 +1 @@ -Subproject commit 6bfa7a2beafa897406d99e1d082b05754117a9a3 +Subproject commit 076f57c9436b55921a6477bc81660c5564c117a9 From 1c587f136ae62e74e72f8f834b554bf227f55cfc Mon Sep 17 00:00:00 2001 From: hjk Date: Thu, 16 Jun 2022 08:44:51 +0200 Subject: [PATCH 60/94] Valgrind: Use stop() instead of stopProcess() Change-Id: I9efd3dcec1e894e64fc2684ae2fad5606c90b68f Reviewed-by: Jarek Kobus --- src/plugins/valgrind/valgrindrunner.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/valgrind/valgrindrunner.cpp b/src/plugins/valgrind/valgrindrunner.cpp index b03b5180fff..5a1f64c15ee 100644 --- a/src/plugins/valgrind/valgrindrunner.cpp +++ b/src/plugins/valgrind/valgrindrunner.cpp @@ -316,7 +316,7 @@ QString ValgrindRunner::errorString() const void ValgrindRunner::stop() { - d->m_valgrindProcess.stopProcess(); + d->m_valgrindProcess.stop(); } XmlProtocol::ThreadedParser *ValgrindRunner::parser() const From 48a43511c726c98820c39f6e1edfcc6ab7fc06cf Mon Sep 17 00:00:00 2001 From: David Schulz Date: Thu, 16 Jun 2022 09:29:22 +0200 Subject: [PATCH 61/94] ProjectExplorer: fix environment is valid check Amends d76458a8b6a03ba3b5657c88221884c05c848467 Change-Id: I0a9d4d6c4489f2bfd3d61c3db3f1040fbc5cbdbc Reviewed-by: hjk --- src/plugins/projectexplorer/msvctoolchain.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/projectexplorer/msvctoolchain.cpp b/src/plugins/projectexplorer/msvctoolchain.cpp index d6eaa3bbaf7..9f456a8b06c 100644 --- a/src/plugins/projectexplorer/msvctoolchain.cpp +++ b/src/plugins/projectexplorer/msvctoolchain.cpp @@ -1145,7 +1145,7 @@ ToolChain::BuiltInHeaderPathsRunner MsvcToolChain::createBuiltInHeaderPathsRunne void MsvcToolChain::addToEnvironment(Utils::Environment &env) const { // We cache the full environment (incoming + modifications by setup script). - if (m_resultEnvironment.isValid() || env != m_lastEnvironment) { + if (!m_resultEnvironment.isValid() || env != m_lastEnvironment) { qCDebug(Log) << "addToEnvironment: " << displayName(); m_lastEnvironment = env; m_resultEnvironment = readEnvironmentSetting(env); From 53cd1f1ea222bb5abff4c7447f686b7225bc5431 Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Wed, 25 May 2022 19:54:26 +0200 Subject: [PATCH 62/94] Move the options to the edit menu This is more consistent with many other tools. Visual Studio is one of the few tools that have the options under tools. and allows to hide tools in the context of Qt Design Studio. Renaming options to preferences. Change-Id: I4bb554f00005eb415a203faa8bf7340d047b5a84 Reviewed-by: Reviewed-by: hjk Reviewed-by: Alessandro Portale --- src/plugins/coreplugin/coreconstants.h | 2 +- src/plugins/coreplugin/mainwindow.cpp | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/plugins/coreplugin/coreconstants.h b/src/plugins/coreplugin/coreconstants.h index 96234c16c33..77ada82f061 100644 --- a/src/plugins/coreplugin/coreconstants.h +++ b/src/plugins/coreplugin/coreconstants.h @@ -188,7 +188,7 @@ const char G_VIEW_PANES[] = "QtCreator.Group.View.Panes"; // Tools menu groups const char G_TOOLS_DEBUG[] = "QtCreator.Group.Tools.Debug"; -const char G_TOOLS_OPTIONS[] = "QtCreator.Group.Tools.Options"; +const char G_EDIT_PREFERENCES[] = "QtCreator.Group.Edit.Preferences"; // Window menu groups const char G_WINDOW_SIZE[] = "QtCreator.Group.Window.Size"; diff --git a/src/plugins/coreplugin/mainwindow.cpp b/src/plugins/coreplugin/mainwindow.cpp index 1fa6d4be141..4bd44b5dddc 100644 --- a/src/plugins/coreplugin/mainwindow.cpp +++ b/src/plugins/coreplugin/mainwindow.cpp @@ -717,14 +717,14 @@ void MainWindow::registerDefaultActions() connect(m_loggerAction, &QAction::triggered, this, [] { LoggingViewer::showLoggingView(); }); // Options Action - mtools->appendGroup(Constants::G_TOOLS_OPTIONS); - mtools->addSeparator(Constants::G_TOOLS_OPTIONS); + medit->appendGroup(Constants::G_EDIT_PREFERENCES); + medit->addSeparator(Constants::G_EDIT_PREFERENCES); - m_optionsAction = new QAction(tr("&Options..."), this); + m_optionsAction = new QAction(tr("&Preferences..."), this); m_optionsAction->setMenuRole(QAction::PreferencesRole); cmd = ActionManager::registerAction(m_optionsAction, Constants::OPTIONS); cmd->setDefaultKeySequence(QKeySequence::Preferences); - mtools->addAction(cmd, Constants::G_TOOLS_OPTIONS); + medit->addAction(cmd, Constants::G_EDIT_PREFERENCES); connect(m_optionsAction, &QAction::triggered, this, [] { ICore::showOptionsDialog(Id()); }); mwindow->addSeparator(Constants::G_WINDOW_LIST); From 2dc343970bb45f2f2af68409a15335d8edf424a2 Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Thu, 16 Jun 2022 10:14:11 +0200 Subject: [PATCH 63/94] Update change log for 8.0 Change-Id: Ieff8d123ef1cb0596dc604256a284b8ba74fece8 Reviewed-by: Eike Ziller --- dist/changes-8.0.0.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/dist/changes-8.0.0.md b/dist/changes-8.0.0.md index 339a4af41c8..a95b8efc8da 100644 --- a/dist/changes-8.0.0.md +++ b/dist/changes-8.0.0.md @@ -10,17 +10,26 @@ the public Git repository. For example: git clone git://code.qt.io/qt-creator/qt-creator.git git log --cherry-pick --pretty=oneline origin/7.0..v8.0.0 +Help +---- + +* Added support for mouse forward and backward buttons (QTCREATORBUG-25168) + Editing ------- * Added shortcut for adding next search match to multi-selection * Added warning when editing generated file (QTCREATORBUG-27173) +* Added option for hiding line ending information * Fixed updating of annotations (QTCREATORBUG-26812) * Fixed that whitespace was not selected on double-click (QTCREATORBUG-24607) +* Fixed `Rewrap Paragraph` when indenting with tabs (QTCREATORBUG-27602) ### C++ * Removed `libclang` based code model +* Fixed that `Generate Setter and Getter` generated non-static methods for + static pointer types (QTCREATORBUG-27547) * Clangd * Increased minimum `Clangd` version to 14 * Improved performance of `compile_commands.json` creation @@ -64,6 +73,8 @@ Editing * Fixed semantic highlighting after server reset * Fixed that semantic update was delayed by `Document update threshold` even after saving +* Fixed that tooltips could appear while Qt Creator is not in the foreground +* Fixed synchronization of outline view (QTCREATORBUG-27595) ### Image Viewer @@ -73,11 +84,14 @@ Projects -------- * Added locator filter for starting run configurations +* Added `BuildSystem:Name` variable for default build directory + (QTCREATORBUG-26147) ### CMake * Added `Profile` build configuration type that is `RelWithDebInfo` with `QML debugging and profiling` +* Added `install` command to wizard generated projects * Turned `QML debugging and profiling` option on by default for `Debug` configurations * Removed hardcoded `QT_QML_DEBUG` from wizard created project files @@ -129,6 +143,11 @@ Platforms * Added auto-detection for MSVC ARM toolchain and debugger * Fixed ABI detection on ARM Windows +### macOS + +* Fixed import of existing builds of CMake projects that were done on the + command line (QTCREATORBUG-27591) + ### Android * Added option to connect physical device over WiFi @@ -160,6 +179,7 @@ Aaron Barany Adam Treat Alesandro Portale Alessandro Portale +Alexander Akulich Alexander Drozdov Alexandru Croitor Andre Hartmann @@ -176,6 +196,7 @@ David Schulz Dmitry Shachnev Eike Ziller Erik Verbruggen +Evgeny Shtanov Fawzi Mohamed Henning Gruendl Ihor Ivlev From ebfbc5516630b181a00a79530a216f90d9912c91 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Wed, 15 Jun 2022 15:50:44 +0200 Subject: [PATCH 64/94] RemoteLinux: Remove CheckForFreeDiskSpaceStep This step was of very little use out of the box, as it required the user to pass sensible values for e.g. the required disk space. Making it smart enough would require non-trivial effort for very little gain, in particular as the concept hardly makes any sense at all in conjunction with deployment via rsync. Fixes: QTCREATORBUG-27081 Change-Id: I586fceb59947334eba19b10fcc94ecedc661908f Reviewed-by: Jarek Kobus Reviewed-by: Qt CI Bot Reviewed-by: --- .../boot2qt/qdbdeployconfigurationfactory.cpp | 1 - src/plugins/boot2qt/qdbplugin.cpp | 3 - src/plugins/projectexplorer/buildsteplist.cpp | 5 + src/plugins/qnx/qnxplugin.cpp | 3 - src/plugins/remotelinux/CMakeLists.txt | 1 - .../remotelinux/checkforfreediskspacestep.cpp | 153 ------------------ .../remotelinux/checkforfreediskspacestep.h | 45 ------ src/plugins/remotelinux/remotelinux.qbs | 2 - .../remotelinux/remotelinux_constants.h | 1 - .../remotelinuxdeployconfiguration.cpp | 1 - src/plugins/remotelinux/remotelinuxplugin.cpp | 2 - 11 files changed, 5 insertions(+), 212 deletions(-) delete mode 100644 src/plugins/remotelinux/checkforfreediskspacestep.cpp delete mode 100644 src/plugins/remotelinux/checkforfreediskspacestep.h diff --git a/src/plugins/boot2qt/qdbdeployconfigurationfactory.cpp b/src/plugins/boot2qt/qdbdeployconfigurationfactory.cpp index a8b86a87ffd..535658f0f17 100644 --- a/src/plugins/boot2qt/qdbdeployconfigurationfactory.cpp +++ b/src/plugins/boot2qt/qdbdeployconfigurationfactory.cpp @@ -52,7 +52,6 @@ QdbDeployConfigurationFactory::QdbDeployConfigurationFactory() return prj->deploymentKnowledge() == DeploymentKnowledge::Bad && prj->hasMakeInstallEquivalent(); }); - addInitialStep(RemoteLinux::Constants::CheckForFreeDiskSpaceId); addInitialStep(Qdb::Constants::QdbStopApplicationStepId); addInitialStep(RemoteLinux::Constants::DirectUploadStepId); } diff --git a/src/plugins/boot2qt/qdbplugin.cpp b/src/plugins/boot2qt/qdbplugin.cpp index 1382954c807..711cdb50099 100644 --- a/src/plugins/boot2qt/qdbplugin.cpp +++ b/src/plugins/boot2qt/qdbplugin.cpp @@ -45,7 +45,6 @@ #include -#include #include #include #include @@ -177,8 +176,6 @@ public: QdbStopApplicationStepFactory m_stopApplicationStepFactory; QdbMakeDefaultAppStepFactory m_makeDefaultAppStepFactory; - QdbDeployStepFactory - m_checkForFreeDiskSpaceStepFactory{RemoteLinux::Constants::CheckForFreeDiskSpaceId}; QdbDeployStepFactory m_directUploadStepFactory{RemoteLinux::Constants::DirectUploadStepId}; QdbDeployStepFactory diff --git a/src/plugins/projectexplorer/buildsteplist.cpp b/src/plugins/projectexplorer/buildsteplist.cpp index de9f7611717..d77dd327ba7 100644 --- a/src/plugins/projectexplorer/buildsteplist.cpp +++ b/src/plugins/projectexplorer/buildsteplist.cpp @@ -131,6 +131,11 @@ bool BuildStepList::fromMap(const QVariantMap &map) } bool handled = false; Utils::Id stepId = idFromMap(bsData); + + // pre-8.0 compat + if (stepId == "RemoteLinux.CheckForFreeDiskSpaceStep") + continue; + for (BuildStepFactory *factory : factories) { if (factory->stepId() == stepId) { if (factory->canHandle(this)) { diff --git a/src/plugins/qnx/qnxplugin.cpp b/src/plugins/qnx/qnxplugin.cpp index b939efeae77..f5cf7991ec6 100644 --- a/src/plugins/qnx/qnxplugin.cpp +++ b/src/plugins/qnx/qnxplugin.cpp @@ -54,7 +54,6 @@ #include #include -#include #include #include #include @@ -105,7 +104,6 @@ public: && prj->hasMakeInstallEquivalent(); }); addInitialStep(DeviceCheckBuildStep::stepId()); - addInitialStep(RemoteLinux::Constants::CheckForFreeDiskSpaceId); addInitialStep(QnxUploadStep::stepId()); } }; @@ -123,7 +121,6 @@ public: QnxDeviceFactory deviceFactory; QnxDeployConfigurationFactory deployConfigFactory; GenericQnxDeployStepFactory directUploadDeployFactory; - GenericQnxDeployStepFactory checkForFreeDiskSpaceDeployFactory; GenericQnxDeployStepFactory makeInstallDeployFactory; GenericQnxDeployStepFactory checkBuildDeployFactory; QnxRunConfigurationFactory runConfigFactory; diff --git a/src/plugins/remotelinux/CMakeLists.txt b/src/plugins/remotelinux/CMakeLists.txt index 2de46781890..a13af8cd47b 100644 --- a/src/plugins/remotelinux/CMakeLists.txt +++ b/src/plugins/remotelinux/CMakeLists.txt @@ -4,7 +4,6 @@ add_qtc_plugin(RemoteLinux SOURCES abstractremotelinuxdeployservice.cpp abstractremotelinuxdeployservice.h abstractremotelinuxdeploystep.cpp abstractremotelinuxdeploystep.h - checkforfreediskspacestep.cpp checkforfreediskspacestep.h customcommanddeploystep.cpp customcommanddeploystep.h deploymenttimeinfo.cpp deploymenttimeinfo.h genericdirectuploadservice.cpp genericdirectuploadservice.h diff --git a/src/plugins/remotelinux/checkforfreediskspacestep.cpp b/src/plugins/remotelinux/checkforfreediskspacestep.cpp deleted file mode 100644 index 3c2cb42c27b..00000000000 --- a/src/plugins/remotelinux/checkforfreediskspacestep.cpp +++ /dev/null @@ -1,153 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#include "checkforfreediskspacestep.h" - -#include "abstractremotelinuxdeployservice.h" - -#include - -#include -#include - -#include - -#include - -using namespace ProjectExplorer; -using namespace Utils; - -namespace RemoteLinux { - -class CheckForFreeDiskSpaceService : public AbstractRemoteLinuxDeployService -{ - Q_DECLARE_TR_FUNCTIONS(RemoteLinux::CheckForFreeDiskSpaceService) - -public: - CheckForFreeDiskSpaceService() {} - - void setPathToCheck(const QString &path); - void setRequiredSpaceInBytes(quint64 sizeInBytes); - -private: - bool isDeploymentNecessary() const override { return true; } - - CheckResult isDeploymentPossible() const override; - - void doDeploy() final; - void stopDeployment() final {} - - QString m_pathToCheck; - quint64 m_requiredSpaceInBytes = 0; -}; - -void CheckForFreeDiskSpaceService::setPathToCheck(const QString &path) -{ - m_pathToCheck = path; -} - -void CheckForFreeDiskSpaceService::setRequiredSpaceInBytes(quint64 sizeInBytes) -{ - m_requiredSpaceInBytes = sizeInBytes; -} - -void CheckForFreeDiskSpaceService::doDeploy() -{ - auto cleanup = qScopeGuard([this] { setFinished(); }); - const FilePath path = deviceConfiguration()->filePath(m_pathToCheck); - const qint64 freeSpace = path.bytesAvailable(); - if (freeSpace < 0) { - emit errorMessage(tr("Cannot get info about free disk space for \"%1\"") - .arg(path.displayName())); - handleDeploymentDone(); - return; - } - - const qint64 mb = 1024 * 1024; - const qint64 freeSpaceMB = freeSpace / mb; - const qint64 requiredSpaceMB = m_requiredSpaceInBytes / mb; - - if (freeSpaceMB < requiredSpaceMB) { - emit errorMessage(tr("The remote file system has only %n megabytes of free space, " - "but %1 megabytes are required.", nullptr, freeSpaceMB) - .arg(requiredSpaceMB)); - handleDeploymentDone(); - return; - } - - emit progressMessage(tr("The remote file system has %n megabytes of free space, going ahead.", - nullptr, freeSpaceMB)); - handleDeploymentDone(); -} - -CheckResult CheckForFreeDiskSpaceService::isDeploymentPossible() const -{ - if (!m_pathToCheck.startsWith('/')) { - return CheckResult::failure( - tr("Cannot check for free disk space: \"%1\" is not an absolute path.") - .arg(m_pathToCheck)); - } - - return AbstractRemoteLinuxDeployService::isDeploymentPossible(); -} - -CheckForFreeDiskSpaceStep::CheckForFreeDiskSpaceStep - (BuildStepList *bsl, Id id) - : AbstractRemoteLinuxDeployStep(bsl, id) -{ - auto service = createDeployService(); - - auto pathToCheckAspect = addAspect(); - pathToCheckAspect->setSettingsKey("RemoteLinux.CheckForFreeDiskSpaceStep.PathToCheck"); - pathToCheckAspect->setDisplayStyle(StringAspect::LineEditDisplay); - pathToCheckAspect->setValue("/"); - pathToCheckAspect->setLabelText(tr("Remote path to check for free space:")); - - auto requiredSpaceAspect = addAspect(); - requiredSpaceAspect->setSettingsKey("RemoteLinux.CheckForFreeDiskSpaceStep.RequiredSpace"); - requiredSpaceAspect->setLabel(tr("Required disk space:")); - requiredSpaceAspect->setDisplayScaleFactor(1024*1024); - requiredSpaceAspect->setValue(5*1024*1024); - requiredSpaceAspect->setSuffix(tr("MB")); - requiredSpaceAspect->setRange(1, std::numeric_limits::max()); - - setInternalInitializer([service, pathToCheckAspect, requiredSpaceAspect] { - service->setPathToCheck(pathToCheckAspect->value()); - service->setRequiredSpaceInBytes(requiredSpaceAspect->value()); - return CheckResult::success(); - }); -} - -Id CheckForFreeDiskSpaceStep::stepId() -{ - return "RemoteLinux.CheckForFreeDiskSpaceStep"; -} - -QString CheckForFreeDiskSpaceStep::displayName() -{ - return tr("Check for free disk space"); -} - -} // namespace RemoteLinux diff --git a/src/plugins/remotelinux/checkforfreediskspacestep.h b/src/plugins/remotelinux/checkforfreediskspacestep.h deleted file mode 100644 index e1ff4c3765e..00000000000 --- a/src/plugins/remotelinux/checkforfreediskspacestep.h +++ /dev/null @@ -1,45 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#pragma once - -#include "remotelinux_export.h" - -#include "abstractremotelinuxdeploystep.h" - -namespace RemoteLinux { - -class REMOTELINUX_EXPORT CheckForFreeDiskSpaceStep : public AbstractRemoteLinuxDeployStep -{ - Q_OBJECT - -public: - CheckForFreeDiskSpaceStep(ProjectExplorer::BuildStepList *bsl, Utils::Id id); - - static Utils::Id stepId(); - static QString displayName(); -}; - -} // namespace RemoteLinux diff --git a/src/plugins/remotelinux/remotelinux.qbs b/src/plugins/remotelinux/remotelinux.qbs index 859c8f249d7..8aaf6fbcc2e 100644 --- a/src/plugins/remotelinux/remotelinux.qbs +++ b/src/plugins/remotelinux/remotelinux.qbs @@ -19,8 +19,6 @@ Project { "abstractremotelinuxdeploystep.h", "deploymenttimeinfo.cpp", "deploymenttimeinfo.h", - "checkforfreediskspacestep.cpp", - "checkforfreediskspacestep.h", "customcommanddeploystep.cpp", "customcommanddeploystep.h", "genericdirectuploadservice.cpp", diff --git a/src/plugins/remotelinux/remotelinux_constants.h b/src/plugins/remotelinux/remotelinux_constants.h index da6eac43d40..909d327e5d3 100644 --- a/src/plugins/remotelinux/remotelinux_constants.h +++ b/src/plugins/remotelinux/remotelinux_constants.h @@ -32,7 +32,6 @@ const char GenericLinuxOsType[] = "GenericLinuxOsType"; const char DeployToGenericLinux[] = "DeployToGenericLinux"; -const char CheckForFreeDiskSpaceId[] = "RemoteLinux.CheckForFreeDiskSpaceStep"; const char DirectUploadStepId[] = "RemoteLinux.DirectUploadStep"; const char MakeInstallStepId[] = "RemoteLinux.MakeInstall"; const char TarPackageCreationStepId[] = "MaemoTarPackageCreationStep"; diff --git a/src/plugins/remotelinux/remotelinuxdeployconfiguration.cpp b/src/plugins/remotelinux/remotelinuxdeployconfiguration.cpp index db5ecfc5280..37a44298017 100644 --- a/src/plugins/remotelinux/remotelinuxdeployconfiguration.cpp +++ b/src/plugins/remotelinux/remotelinuxdeployconfiguration.cpp @@ -63,7 +63,6 @@ RemoteLinuxDeployConfigurationFactory::RemoteLinuxDeployConfigurationFactory() }); addInitialStep(Constants::MakeInstallStepId, needsMakeInstall); - addInitialStep(Constants::CheckForFreeDiskSpaceId); addInitialStep(Constants::KillAppStepId); addInitialStep(Constants::RsyncDeployStepId, [](Target *target) { auto device = DeviceKitAspect::device(target->kit()); diff --git a/src/plugins/remotelinux/remotelinuxplugin.cpp b/src/plugins/remotelinux/remotelinuxplugin.cpp index 1f072a38a50..5e4cbd1c266 100644 --- a/src/plugins/remotelinux/remotelinuxplugin.cpp +++ b/src/plugins/remotelinux/remotelinuxplugin.cpp @@ -25,7 +25,6 @@ #include "remotelinuxplugin.h" -#include "checkforfreediskspacestep.h" #include "customcommanddeploystep.h" #include "genericdirectuploadstep.h" #include "killappstep.h" @@ -79,7 +78,6 @@ public: GenericDeployStepFactory genericDirectUploadStepFactory; GenericDeployStepFactory rsyncDeployStepFactory; CustomCommandDeployStepFactory customCommandDeployStepFactory; - GenericDeployStepFactory checkForFreeDiskSpaceStepFactory; GenericDeployStepFactory killAppStepFactory; GenericDeployStepFactory makeInstallStepFactory; From 07dfd7c0b30e4a7b795b1bedf811c905f92934a2 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Tue, 14 Jun 2022 09:57:32 +0200 Subject: [PATCH 65/94] Wizards: Bump QtQuick import version in file wizards Use 2.15 as default, plus a little heuristic to use the same version as other files in the project. Fixes: QTCREATORBUG-27614 Change-Id: Ic84db5da97a9f35a2ad0e57fd47b75fb32a0b7f8 Reviewed-by: Qt CI Bot Reviewed-by: Reviewed-by: Alessandro Portale --- .../wizards/autotest/files/tst_qml.tmpl | 2 +- .../wizards/files/qtquick2/file.qml.tpl | 2 +- .../wizards/files/qtquick2/wizard.json | 7 +++-- src/plugins/coreplugin/corejsextensions.cpp | 31 +++++++++++++++++++ src/plugins/coreplugin/corejsextensions.h | 3 ++ 5 files changed, 41 insertions(+), 4 deletions(-) diff --git a/share/qtcreator/templates/wizards/autotest/files/tst_qml.tmpl b/share/qtcreator/templates/wizards/autotest/files/tst_qml.tmpl index 5d3da10b700..e87c3dee134 100644 --- a/share/qtcreator/templates/wizards/autotest/files/tst_qml.tmpl +++ b/share/qtcreator/templates/wizards/autotest/files/tst_qml.tmpl @@ -1,4 +1,4 @@ -import QtQuick 2.0 +import QtQuick 2.15 import QtTest 1.0 TestCase { diff --git a/share/qtcreator/templates/wizards/files/qtquick2/file.qml.tpl b/share/qtcreator/templates/wizards/files/qtquick2/file.qml.tpl index 9c36e13c5bf..53df26f056d 100644 --- a/share/qtcreator/templates/wizards/files/qtquick2/file.qml.tpl +++ b/share/qtcreator/templates/wizards/files/qtquick2/file.qml.tpl @@ -1,4 +1,4 @@ -import QtQuick 2.0 +import QtQuick %{QtQuickVersion} Item { diff --git a/share/qtcreator/templates/wizards/files/qtquick2/wizard.json b/share/qtcreator/templates/wizards/files/qtquick2/wizard.json index 0fa070cf934..bcb8ca994fe 100644 --- a/share/qtcreator/templates/wizards/files/qtquick2/wizard.json +++ b/share/qtcreator/templates/wizards/files/qtquick2/wizard.json @@ -3,13 +3,16 @@ "supportedProjectTypes": [ ], "id": "Q.Qml.2", "category": "R.Qt", - "trDescription": "Creates a QML file with boilerplate code, starting with \"import QtQuick 2.0\".", + "trDescription": "Creates a QML file with boilerplate code, starting with \"import QtQuick\".", "trDisplayName": "QML File (Qt Quick 2)", "trDisplayCategory": "Qt", "iconText": "qml", "enabled": "%{JS: value('Plugins').indexOf('QmlJSEditor') >= 0}", - "options": { "key": "DefaultSuffix", "value": "%{JS: Util.preferredSuffix('text/x-qml')}" }, + "options": [ + {"key": "DefaultSuffix", "value": "%{JS: Util.preferredSuffix('text/x-qml')}"}, + {"key": "QtQuickVersion", "value": "%{JS: Util.qtQuickVersion(value('TargetPath'))}"} + ], "pages" : [ diff --git a/src/plugins/coreplugin/corejsextensions.cpp b/src/plugins/coreplugin/corejsextensions.cpp index b73534b25b5..a88de1020c4 100644 --- a/src/plugins/coreplugin/corejsextensions.cpp +++ b/src/plugins/coreplugin/corejsextensions.cpp @@ -32,8 +32,10 @@ #include #include +#include #include #include +#include namespace Core { namespace Internal { @@ -165,5 +167,34 @@ QString UtilsJsExtension::asciify(const QString &input) const return result; } +QString UtilsJsExtension::qtQuickVersion(const QString &filePath) const +{ + QDirIterator dirIt(Utils::FilePath::fromString(filePath).parentDir().path(), {"*.qml"}, + QDir::Files, QDirIterator::Subdirectories); + while (dirIt.hasNext()) { + Utils::FileReader reader; + if (!reader.fetch(Utils::FilePath::fromString(dirIt.next()))) + continue; + const QString data = QString::fromUtf8(reader.data()); + static const QString importString("import QtQuick"); + const int importIndex = data.indexOf(importString); + if (importIndex == -1) + continue; + const int versionIndex = importIndex + importString.length(); + const int newLineIndex = data.indexOf('\n', versionIndex); + if (newLineIndex == -1) + continue; + const QString versionString = data.mid(versionIndex, + newLineIndex - versionIndex).simplified(); + if (versionString.isEmpty()) + return {}; + const auto version = QVersionNumber::fromString(versionString); + if (version.isNull()) + return {}; + return version.toString(); + } + return QLatin1String("2.15"); +} + } // namespace Internal } // namespace Core diff --git a/src/plugins/coreplugin/corejsextensions.h b/src/plugins/coreplugin/corejsextensions.h index bbdc8762512..8a668cbd161 100644 --- a/src/plugins/coreplugin/corejsextensions.h +++ b/src/plugins/coreplugin/corejsextensions.h @@ -76,6 +76,9 @@ public: // Generate a ascii-only string: Q_INVOKABLE QString asciify(const QString &input) const; + + // Heuristic to find out which QtQuick import version to use for the given file. + Q_INVOKABLE QString qtQuickVersion(const QString &filePath) const; }; } // namespace Internal From bfad59ade006fd704439c229bbb37ffc560cd243 Mon Sep 17 00:00:00 2001 From: hjk Date: Thu, 16 Jun 2022 08:53:43 +0200 Subject: [PATCH 66/94] Debugger: Use QtcProcess::stop instead of stopProcess Less synchronous in cases where it is not needed. Change-Id: Ia07e6d293c7f5e6dfb81b06c0ffb6d5d651b88b3 Reviewed-by: Jarek Kobus Reviewed-by: David Schulz --- src/plugins/debugger/cdb/cdbengine.cpp | 4 ++-- src/plugins/debugger/debuggersourcepathmappingwidget.cpp | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/plugins/debugger/cdb/cdbengine.cpp b/src/plugins/debugger/cdb/cdbengine.cpp index 99f9b14e7fd..33ef864dd12 100644 --- a/src/plugins/debugger/cdb/cdbengine.cpp +++ b/src/plugins/debugger/cdb/cdbengine.cpp @@ -265,7 +265,7 @@ void CdbEngine::init() } // update source path maps from debugger start params mergeStartParametersSourcePathMap(); - QTC_ASSERT(m_process.state() != QProcess::Running, m_process.stopProcess()); + QTC_ASSERT(m_process.state() != QProcess::Running, m_process.stop()); } CdbEngine::~CdbEngine() = default; @@ -691,7 +691,7 @@ void CdbEngine::shutdownEngine() } } else { // Remote process. No can do, currently - m_process.stopProcess(); + m_process.stop(); } } diff --git a/src/plugins/debugger/debuggersourcepathmappingwidget.cpp b/src/plugins/debugger/debuggersourcepathmappingwidget.cpp index c34b01d7c4f..b5985ac214a 100644 --- a/src/plugins/debugger/debuggersourcepathmappingwidget.cpp +++ b/src/plugins/debugger/debuggersourcepathmappingwidget.cpp @@ -453,7 +453,6 @@ static QString findQtInstallPath(const FilePath &qmakePath) return QString(); } if (!proc.waitForFinished()) { - proc.stopProcess(); qWarning("%s: Timeout running '%s'.", Q_FUNC_INFO, qPrintable(qmakePath.toString())); return QString(); } From 152b14207ce264222557665c568907931e9277d8 Mon Sep 17 00:00:00 2001 From: hjk Date: Thu, 16 Jun 2022 10:17:33 +0200 Subject: [PATCH 67/94] Replace QtcProcess::stopProcess() by stop() plus waitForFinished ... or nothing, if the process object is destroyed immediately. Change-Id: I6a1e1928bc49fc20a1c0e0ee9b8f4f723276bbca Reviewed-by: Jarek Kobus --- src/libs/utils/shellcommand.cpp | 5 ++++- src/plugins/android/androidqmlpreviewworker.cpp | 3 ++- src/plugins/android/androidsdkmanager.cpp | 12 ++++++++---- src/plugins/clangtools/clangtoolrunner.cpp | 3 ++- src/plugins/coreplugin/patchtool.cpp | 3 ++- src/plugins/git/gerrit/gerritmodel.cpp | 3 ++- src/plugins/git/gerrit/gerritplugin.cpp | 3 ++- src/plugins/gitlab/queryrunner.cpp | 3 ++- .../languageclient/languageclientinterface.cpp | 4 +--- src/plugins/perforce/perforcechecker.cpp | 3 ++- src/plugins/perforce/perforceplugin.cpp | 3 ++- src/plugins/projectexplorer/runcontrol.cpp | 3 ++- src/plugins/python/pipsupport.cpp | 3 ++- src/plugins/qmldesigner/generateresource.cpp | 3 --- src/plugins/qnx/qnxutils.cpp | 4 +--- src/plugins/qtsupport/baseqtversion.cpp | 1 - src/plugins/vcsbase/vcsbasesubmiteditor.cpp | 1 - 17 files changed, 34 insertions(+), 26 deletions(-) diff --git a/src/libs/utils/shellcommand.cpp b/src/libs/utils/shellcommand.cpp index 00f655a1ef6..6f8a49de019 100644 --- a/src/libs/utils/shellcommand.cpp +++ b/src/libs/utils/shellcommand.cpp @@ -368,7 +368,10 @@ void ShellCommand::runFullySynchronous(QtcProcess &process, const FilePath &work void ShellCommand::runSynchronous(QtcProcess &process, const FilePath &workingDirectory) { - connect(this, &ShellCommand::terminate, &process, &QtcProcess::stopProcess); + connect(this, &ShellCommand::terminate, &process, [&process] { + process.stop(); + process.waitForFinished(); + }); process.setEnvironment(processEnvironment()); if (d->m_codec) process.setCodec(d->m_codec); diff --git a/src/plugins/android/androidqmlpreviewworker.cpp b/src/plugins/android/androidqmlpreviewworker.cpp index 103e7b2e5c3..6c78c562d11 100644 --- a/src/plugins/android/androidqmlpreviewworker.cpp +++ b/src/plugins/android/androidqmlpreviewworker.cpp @@ -363,7 +363,8 @@ FilePath AndroidQmlPreviewWorker::createQmlrcFile(const FilePath &workFolder, QByteArray stdOut; QByteArray stdErr; if (!rccProcess.readDataFromProcess(30, &stdOut, &stdErr, true)) { - rccProcess.stopProcess(); + rccProcess.stop(); + rccProcess.waitForFinished(); appendMessage(tr("A timeout occurred running \"%1\""). arg(rccProcess.commandLine().toUserOutput()), StdErrFormat); qrcPath.removeFile(); diff --git a/src/plugins/android/androidsdkmanager.cpp b/src/plugins/android/androidsdkmanager.cpp index d238e60ef38..628f245c349 100644 --- a/src/plugins/android/androidsdkmanager.cpp +++ b/src/plugins/android/androidsdkmanager.cpp @@ -166,8 +166,10 @@ static void sdkManagerCommand(const AndroidConfig &config, const QStringList &ar proc.setTimeoutS(timeout); proc.setStdOutCallback([offset, progressQuota, &proc, &assertionFound, &fi](const QString &out) { int progressPercent = parseProgress(out, assertionFound); - if (assertionFound) - proc.stopProcess(); + if (assertionFound) { + proc.stop(); + proc.waitForFinished(); + } if (progressPercent != -1) fi.setProgressValue(offset + qRound((progressPercent / 100.0) * progressQuota)); }); @@ -175,8 +177,10 @@ static void sdkManagerCommand(const AndroidConfig &config, const QStringList &ar output.stdError = err; }); if (interruptible) { - QObject::connect(&sdkManager, &AndroidSdkManager::cancelActiveOperations, - &proc, &QtcProcess::stopProcess); + QObject::connect(&sdkManager, &AndroidSdkManager::cancelActiveOperations, &proc, [&proc] { + proc.stop(); + proc.waitForFinished(); + }); } proc.setCommand({config.sdkManagerToolPath(), newArgs}); proc.runBlocking(EventLoopMode::On); diff --git a/src/plugins/clangtools/clangtoolrunner.cpp b/src/plugins/clangtools/clangtoolrunner.cpp index c970028709b..ab5ef389899 100644 --- a/src/plugins/clangtools/clangtoolrunner.cpp +++ b/src/plugins/clangtools/clangtoolrunner.cpp @@ -71,7 +71,8 @@ ClangToolRunner::~ClangToolRunner() m_process->kill(); m_process->waitForFinished(100); } else { - m_process->stopProcess(); + m_process->stop(); + m_process->waitForFinished(); } } diff --git a/src/plugins/coreplugin/patchtool.cpp b/src/plugins/coreplugin/patchtool.cpp index f49185ea0ef..d26fcba6c08 100644 --- a/src/plugins/coreplugin/patchtool.cpp +++ b/src/plugins/coreplugin/patchtool.cpp @@ -112,7 +112,8 @@ static bool runPatchHelper(const QByteArray &input, const FilePath &workingDirec QByteArray stdOut; QByteArray stdErr; if (!patchProcess.readDataFromProcess(30, &stdOut, &stdErr, true)) { - patchProcess.stopProcess(); + patchProcess.stop(); + patchProcess.waitForFinished(); MessageManager::writeFlashing( QApplication::translate("Core::PatchTool", "A timeout occurred running \"%1\"") .arg(patch.toUserOutput())); diff --git a/src/plugins/git/gerrit/gerritmodel.cpp b/src/plugins/git/gerrit/gerritmodel.cpp index 8f1f990cbb9..9c835c98a5b 100644 --- a/src/plugins/git/gerrit/gerritmodel.cpp +++ b/src/plugins/git/gerrit/gerritmodel.cpp @@ -335,7 +335,8 @@ void QueryContext::errorTermination(const QString &msg) void QueryContext::terminate() { - m_process.stopProcess(); + m_process.stop(); + m_process.waitForFinished(); } void QueryContext::processDone() diff --git a/src/plugins/git/gerrit/gerritplugin.cpp b/src/plugins/git/gerrit/gerritplugin.cpp index f13c8b8c2a2..b68aa56c7be 100644 --- a/src/plugins/git/gerrit/gerritplugin.cpp +++ b/src/plugins/git/gerrit/gerritplugin.cpp @@ -259,7 +259,8 @@ void FetchContext::checkout() void FetchContext::terminate() { - m_process.stopProcess(); + m_process.stop(); + m_process.waitForFinished(); } diff --git a/src/plugins/gitlab/queryrunner.cpp b/src/plugins/gitlab/queryrunner.cpp index 0e54a99a092..fe46db842e0 100644 --- a/src/plugins/gitlab/queryrunner.cpp +++ b/src/plugins/gitlab/queryrunner.cpp @@ -137,7 +137,8 @@ void QueryRunner::start() void QueryRunner::terminate() { - m_process.stopProcess(); + m_process.stop(); + m_process.waitForFinished(); } void QueryRunner::errorTermination(const QString &msg) diff --git a/src/plugins/languageclient/languageclientinterface.cpp b/src/plugins/languageclient/languageclientinterface.cpp index 49d0699a665..5b7431cda00 100644 --- a/src/plugins/languageclient/languageclientinterface.cpp +++ b/src/plugins/languageclient/languageclientinterface.cpp @@ -105,15 +105,13 @@ StdIOClientInterface::StdIOClientInterface() StdIOClientInterface::~StdIOClientInterface() { - if (m_process) - m_process->stopProcess(); delete m_process; } void StdIOClientInterface::startImpl() { if (m_process) { - QTC_ASSERT(!m_process->isRunning(), m_process->stopProcess() ); + QTC_CHECK(!m_process->isRunning()); delete m_process; } m_process = new Utils::QtcProcess; diff --git a/src/plugins/perforce/perforcechecker.cpp b/src/plugins/perforce/perforcechecker.cpp index 2e53d1e538e..3dc7f73d504 100644 --- a/src/plugins/perforce/perforcechecker.cpp +++ b/src/plugins/perforce/perforcechecker.cpp @@ -107,7 +107,8 @@ void PerforceChecker::slotTimeOut() if (!isRunning()) return; m_timedOut = true; - m_process.stopProcess(); + m_process.stop(); + m_process.waitForFinished(); emitFailed(tr("\"%1\" timed out after %2 ms.").arg(m_binary.toUserOutput()).arg(m_timeOutMS)); } diff --git a/src/plugins/perforce/perforceplugin.cpp b/src/plugins/perforce/perforceplugin.cpp index b415b219674..4c7039d2606 100644 --- a/src/plugins/perforce/perforceplugin.cpp +++ b/src/plugins/perforce/perforceplugin.cpp @@ -1329,7 +1329,8 @@ PerforceResponse PerforcePluginPrivate::fullySynchronousProcess(const FilePath & QByteArray stdErr; const int timeOutS = (flags & LongTimeOut) ? m_settings.longTimeOutS() : m_settings.timeOutS.value(); if (!process.readDataFromProcess(timeOutS, &stdOut, &stdErr, true)) { - process.stopProcess(); + process.stop(); + process.waitForFinished(); response.error = true; response.message = msgTimeout(timeOutS); return response; diff --git a/src/plugins/projectexplorer/runcontrol.cpp b/src/plugins/projectexplorer/runcontrol.cpp index bd7714546a8..53bcd28d101 100644 --- a/src/plugins/projectexplorer/runcontrol.cpp +++ b/src/plugins/projectexplorer/runcontrol.cpp @@ -1336,7 +1336,8 @@ void SimpleTargetRunnerPrivate::stop() if (m_isLocal) { if (!isRunning()) return; - m_process.stopProcess(); + m_process.stop(); + m_process.waitForFinished(); QTimer::singleShot(100, this, [this] { forwardDone(); }); } else { if (m_stopRequested) diff --git a/src/plugins/python/pipsupport.cpp b/src/plugins/python/pipsupport.cpp index c354ebb4e14..44ee82727c0 100644 --- a/src/plugins/python/pipsupport.cpp +++ b/src/plugins/python/pipsupport.cpp @@ -95,7 +95,8 @@ void PipInstallTask::run() void PipInstallTask::cancel() { - m_process.stopProcess(); + m_process.stop(); + m_process.waitForFinished(); Core::MessageManager::writeFlashing( tr("The %1 installation was canceled by %2.") .arg(m_package.displayName, m_killTimer.isActive() ? tr("user") : tr("time out"))); diff --git a/src/plugins/qmldesigner/generateresource.cpp b/src/plugins/qmldesigner/generateresource.cpp index 7210a144717..b85370f60f9 100644 --- a/src/plugins/qmldesigner/generateresource.cpp +++ b/src/plugins/qmldesigner/generateresource.cpp @@ -255,7 +255,6 @@ void GenerateResource::generateMenuEntry() QByteArray stdOut; QByteArray stdErr; if (!rccProcess.readDataFromProcess(30, &stdOut, &stdErr, true)) { - rccProcess.stopProcess(); Core::MessageManager::writeDisrupting( QCoreApplication::translate("QmlDesigner::GenerateResource", "A timeout occurred running \"%1\"") @@ -415,7 +414,6 @@ void GenerateResource::generateMenuEntry() QByteArray stdOut; QByteArray stdErr; if (!rccProcess.readDataFromProcess(30, &stdOut, &stdErr, true)) { - rccProcess.stopProcess(); Core::MessageManager::writeDisrupting( QCoreApplication::translate("QmlDesigner::GenerateResource", "A timeout occurred running \"%1\"") @@ -545,7 +543,6 @@ void GenerateResource::generateMenuEntry() QByteArray stdOut; QByteArray stdErr; if (!rccProcess.readDataFromProcess(30, &stdOut, &stdErr, true)) { - rccProcess.stopProcess(); Core::MessageManager::writeDisrupting( QCoreApplication::translate("QmlDesigner::GenerateResource", "A timeout occurred running \"%1\"") diff --git a/src/plugins/qnx/qnxutils.cpp b/src/plugins/qnx/qnxutils.cpp index 6639f772059..e46b5cec8e0 100644 --- a/src/plugins/qnx/qnxutils.cpp +++ b/src/plugins/qnx/qnxutils.cpp @@ -118,10 +118,8 @@ EnvironmentItems QnxUtils::qnxEnvironmentFromEnvFile(const FilePath &filePath) QApplication::setOverrideCursor(Qt::BusyCursor); bool waitResult = process.waitForFinished(10000); QApplication::restoreOverrideCursor(); - if (!waitResult) { - process.stopProcess(); + if (!waitResult) return items; - } if (process.result() != ProcessResult::FinishedWithSuccess) return items; diff --git a/src/plugins/qtsupport/baseqtversion.cpp b/src/plugins/qtsupport/baseqtversion.cpp index ea74600c520..4298c74590e 100644 --- a/src/plugins/qtsupport/baseqtversion.cpp +++ b/src/plugins/qtsupport/baseqtversion.cpp @@ -1809,7 +1809,6 @@ static QByteArray runQmakeQuery(const FilePath &binary, const Environment &env, return {}; } if (!process.waitForFinished(timeOutMS)) { - process.stopProcess(); *error = QCoreApplication::translate("QtVersion", "Timeout running \"%1\" (%2 ms).") .arg(binary.displayName()).arg(timeOutMS); return {}; diff --git a/src/plugins/vcsbase/vcsbasesubmiteditor.cpp b/src/plugins/vcsbase/vcsbasesubmiteditor.cpp index b405bf40b1d..ae8d877452a 100644 --- a/src/plugins/vcsbase/vcsbasesubmiteditor.cpp +++ b/src/plugins/vcsbase/vcsbasesubmiteditor.cpp @@ -669,7 +669,6 @@ bool VcsBaseSubmitEditor::runSubmitMessageCheckScript(const QString &checkScript QByteArray stdOutData; QByteArray stdErrData; if (!checkProcess.readDataFromProcess(30, &stdOutData, &stdErrData, false)) { - checkProcess.stopProcess(); *errorMessage = tr("The check script \"%1\" timed out."). arg(QDir::toNativeSeparators(checkScript)); return false; From 3ef8635261f8a64773edd54d1d91a1ea51c577da Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Thu, 16 Jun 2022 10:59:43 +0200 Subject: [PATCH 68/94] Add Coco detail to change log Change-Id: I2b829b38136a86cf4596f3d152fc082ee7de8272 Reviewed-by: David Schulz --- dist/changes-8.0.0.md | 1 + 1 file changed, 1 insertion(+) diff --git a/dist/changes-8.0.0.md b/dist/changes-8.0.0.md index a95b8efc8da..87bf811f3df 100644 --- a/dist/changes-8.0.0.md +++ b/dist/changes-8.0.0.md @@ -110,6 +110,7 @@ Analyzer ### Coco * Added experimental `Coco` integration +* Added visualization of code coverage in code editor ### CppCheck From b7a71af4c17b46b5962e122f241d5e2b9f4aa4e7 Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Thu, 16 Jun 2022 10:34:22 +0200 Subject: [PATCH 69/94] Replace QtcProcess::stopProcess() by stop() Amends 219339987aaf67fe97c5ffa418879b747545b137 Change-Id: I31709910a5f0a4f4ec5bcbafa422f693b3c2049e Reviewed-by: hjk --- src/plugins/android/androidqmlpreviewworker.cpp | 8 ++++---- src/plugins/debugger/terminal.cpp | 6 ++++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/plugins/android/androidqmlpreviewworker.cpp b/src/plugins/android/androidqmlpreviewworker.cpp index 6c78c562d11..b739c1de768 100644 --- a/src/plugins/android/androidqmlpreviewworker.cpp +++ b/src/plugins/android/androidqmlpreviewworker.cpp @@ -127,7 +127,7 @@ bool AndroidQmlPreviewWorker::isPreviewRunning(int lastKnownPid) const void AndroidQmlPreviewWorker::startPidWatcher() { - m_pidFutureWatcher.setFuture(Utils::runAsync([this]() { + m_pidFutureWatcher.setFuture(runAsync([this]() { // wait for started const int sleepTimeMs = 2000; QDeadlineTimer deadline(20000); @@ -157,7 +157,7 @@ void AndroidQmlPreviewWorker::startLogcat() QString args = QString("logcat --pid=%1").arg(m_viewerPid); if (!m_logcatStartTimeStamp.isEmpty()) args += QString(" -T '%1'").arg(m_logcatStartTimeStamp); - Utils::CommandLine cmd(AndroidConfigurations::currentConfig().adbToolPath()); + CommandLine cmd(AndroidConfigurations::currentConfig().adbToolPath()); cmd.setArguments(args); m_logcatProcess.setCommand(cmd); m_logcatProcess.setUseCtrlCStub(true); @@ -190,7 +190,7 @@ AndroidQmlPreviewWorker::AndroidQmlPreviewWorker(ProjectExplorer::RunControl *ru connect(this, &AndroidQmlPreviewWorker::previewPidChanged, this, &AndroidQmlPreviewWorker::startLogcat); - connect(this, &RunWorker::stopped, &m_logcatProcess, &Utils::QtcProcess::stopProcess); + connect(this, &RunWorker::stopped, &m_logcatProcess, &QtcProcess::stop); m_logcatProcess.setStdOutCallback([this](const QString &stdOut) { filterLogcatAndAppendMessage(stdOut); }); @@ -314,7 +314,7 @@ bool AndroidQmlPreviewWorker::preparePreviewArtefacts() } } else { const FilePaths allFiles = m_rc->project()->files(m_rc->project()->SourceFiles); - const FilePaths filesToExport = Utils::filtered(allFiles,[](const FilePath &path) { + const FilePaths filesToExport = filtered(allFiles, [](const FilePath &path) { return path.suffix() == "qmlproject"; }); diff --git a/src/plugins/debugger/terminal.cpp b/src/plugins/debugger/terminal.cpp index 55d6fd265e9..f2dd9b0b1de 100644 --- a/src/plugins/debugger/terminal.cpp +++ b/src/plugins/debugger/terminal.cpp @@ -213,8 +213,10 @@ void TerminalRunner::start() void TerminalRunner::stop() { - if (m_stubProc) - m_stubProc->stopProcess(); + if (m_stubProc && m_stubProc->isRunning()) { + m_stubProc->stop(); + m_stubProc->waitForFinished(); + } reportStopped(); } From 53896ed2952f10234ebb2aeeaa2ddb1cbce25e6d Mon Sep 17 00:00:00 2001 From: hjk Date: Thu, 16 Jun 2022 10:56:26 +0200 Subject: [PATCH 70/94] Utils: Dissolve QtcProcess::stopProcess Change-Id: Ife07f34ffc69cd30984276464bd89738c2a71311 Reviewed-by: Jarek Kobus --- src/libs/utils/qtcprocess.cpp | 14 ++------------ src/libs/utils/qtcprocess.h | 1 - 2 files changed, 2 insertions(+), 13 deletions(-) diff --git a/src/libs/utils/qtcprocess.cpp b/src/libs/utils/qtcprocess.cpp index 6aeb7cac897..fdf013a5665 100644 --- a/src/libs/utils/qtcprocess.cpp +++ b/src/libs/utils/qtcprocess.cpp @@ -1285,17 +1285,6 @@ void QtcProcess::setRemoteProcessHooks(const DeviceProcessHooks &hooks) s_deviceHooks = hooks; } -void QtcProcess::stopProcess() -{ - if (state() == QProcess::NotRunning) - return; - terminate(); - if (waitForFinished(300)) - return; - kill(); - waitForFinished(300); -} - static bool askToKill(const QString &command) { #ifdef QT_GUI_LIB @@ -1940,7 +1929,8 @@ void QtcProcessPrivate::slotTimeout() || askToKill(m_setup.m_commandLine.executable().toString()); m_waitingForUser = false; if (terminate) { - q->stopProcess(); + q->stop(); + q->waitForFinished(); m_result = ProcessResult::Hang; } else { m_hangTimerCount = 0; diff --git a/src/libs/utils/qtcprocess.h b/src/libs/utils/qtcprocess.h index 15cc4693c3c..1c793451838 100644 --- a/src/libs/utils/qtcprocess.h +++ b/src/libs/utils/qtcprocess.h @@ -175,7 +175,6 @@ public: void setStdErrCallback(const std::function &callback); void setStdErrLineCallback(const std::function &callback); - void stopProcess(); bool readDataFromProcess(int timeoutS, QByteArray *stdOut, QByteArray *stdErr, bool showTimeOutMessageBox); From af8f6dc039a96c05f4906300d63239d13f14f374 Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Tue, 31 May 2022 18:03:05 +0200 Subject: [PATCH 71/94] LinuxDeviceTester: Test if required commands are available Change-Id: Iaad3ec8667c4134ead86ca9e3239e810554b8f43 Reviewed-by: Christian Stenger Reviewed-by: Reviewed-by: hjk --- src/plugins/remotelinux/linuxdevicetester.cpp | 99 ++++++++++++++++++- src/plugins/remotelinux/linuxdevicetester.h | 4 + 2 files changed, 101 insertions(+), 2 deletions(-) diff --git a/src/plugins/remotelinux/linuxdevicetester.cpp b/src/plugins/remotelinux/linuxdevicetester.cpp index 869ac90b3e8..796b9c87d4e 100644 --- a/src/plugins/remotelinux/linuxdevicetester.cpp +++ b/src/plugins/remotelinux/linuxdevicetester.cpp @@ -42,7 +42,13 @@ namespace RemoteLinux { namespace Internal { namespace { -enum State { Inactive, TestingEcho, TestingUname, TestingPorts, TestingSftp, TestingRsync }; +enum State { Inactive, + TestingEcho, + TestingUname, + TestingPorts, + TestingSftp, + TestingRsync, + TestingCommands }; } // anonymous namespace @@ -56,8 +62,43 @@ public: FileTransfer fileTransfer; State state = Inactive; bool sftpWorks = false; + int currentCommandIndex = 0; + bool commandFailed = false; + QtcProcess commandsProcess; }; +const QStringList s_commandsToTest = {"base64", + "cat", + "chmod", + "cp", + "cut", + "dd", + "df", + "echo", + "eval", + "exit", + "kill", + "ls", + "mkdir", + "mkfifo", + "mktemp", + "mv", + "printf", + "read", + "readlink", + "rm", + "sed", + "sh", + "shift", + "stat", + "tail", + "test", + "trap", + "touch", + "which"}; +// other possible commands (checked for qnx): +// "awk", "grep", "netstat", "print", "pidin", "sleep", "uname" + } // namespace Internal using namespace Internal; @@ -75,6 +116,8 @@ GenericLinuxDeviceTester::GenericLinuxDeviceTester(QObject *parent) this, &GenericLinuxDeviceTester::handlePortsGathererDone); connect(&d->fileTransfer, &FileTransfer::done, this, &GenericLinuxDeviceTester::handleFileTransferDone); + connect(&d->commandsProcess, &QtcProcess::done, + this, &GenericLinuxDeviceTester::handleCommandDone); } GenericLinuxDeviceTester::~GenericLinuxDeviceTester() = default; @@ -106,6 +149,9 @@ void GenericLinuxDeviceTester::stopTest() case TestingRsync: d->fileTransfer.stop(); break; + case TestingCommands: + d->commandsProcess.close(); + break; case Inactive: break; } @@ -254,10 +300,59 @@ void GenericLinuxDeviceTester::handleFileTransferDone(const ProcessResultData &r } } d->device->setExtraData(Constants::SupportsRSync, succeeded); - setFinished(d->sftpWorks || succeeded ? TestSuccess : TestFailure); + if (d->sftpWorks || succeeded) + testCommands(); + else + setFinished(TestFailure); } } +void GenericLinuxDeviceTester::testCommands() +{ + d->state = TestingCommands; + emit progressMessage(tr("Checking if required commands are available...")); + + d->currentCommandIndex = 0; + d->commandFailed = false; + testNextCommand(); +} + +void GenericLinuxDeviceTester::testNextCommand() +{ + d->commandsProcess.close(); + if (s_commandsToTest.size() == d->currentCommandIndex) { + setFinished(d->commandFailed ? TestFailure : TestSuccess); + return; + } + + const QString commandName = s_commandsToTest[d->currentCommandIndex]; + emit progressMessage(tr("%1...").arg(commandName)); + CommandLine command{d->device->filePath("/bin/sh"), {"-c"}}; + command.addArgs(QLatin1String("\"command -v %1\"").arg(commandName), CommandLine::Raw); + d->commandsProcess.setCommand(command); + d->commandsProcess.start(); +} + +void GenericLinuxDeviceTester::handleCommandDone() +{ + QTC_ASSERT(d->state == TestingCommands, return); + + const QString command = s_commandsToTest[d->currentCommandIndex]; + if (d->commandsProcess.result() == ProcessResult::FinishedWithSuccess) { + emit progressMessage(tr("%1 found.").arg(command)); + } else { + d->commandFailed = true; + const QString message = d->commandsProcess.result() == ProcessResult::StartFailed + ? tr("An error occurred while checking for %1.").arg(command) + + '\n' + d->commandsProcess.errorString() + : tr("%1 not found.").arg(command); + emit errorMessage(message); + } + + ++d->currentCommandIndex; + testNextCommand(); +} + void GenericLinuxDeviceTester::setFinished(TestResult result) { d->state = Inactive; diff --git a/src/plugins/remotelinux/linuxdevicetester.h b/src/plugins/remotelinux/linuxdevicetester.h index 890484a8705..67c392771a6 100644 --- a/src/plugins/remotelinux/linuxdevicetester.h +++ b/src/plugins/remotelinux/linuxdevicetester.h @@ -61,6 +61,10 @@ private: void testFileTransfer(ProjectExplorer::FileTransferMethod method); void handleFileTransferDone(const Utils::ProcessResultData &resultData); + void testCommands(); + void testNextCommand(); + void handleCommandDone(); + void setFinished(ProjectExplorer::DeviceTester::TestResult result); std::unique_ptr d; From 3efa0f3961f53adda53157915a82707048acd3a6 Mon Sep 17 00:00:00 2001 From: hjk Date: Wed, 1 Jun 2022 17:32:44 +0200 Subject: [PATCH 72/94] Combine more of local and remote paths in SimpleTarget runner Change-Id: Ic50d96b582b355807234618884ec45da09e398d4 Reviewed-by: Reviewed-by: David Schulz Reviewed-by: Jarek Kobus --- src/plugins/projectexplorer/runcontrol.cpp | 106 ++++++--------------- 1 file changed, 27 insertions(+), 79 deletions(-) diff --git a/src/plugins/projectexplorer/runcontrol.cpp b/src/plugins/projectexplorer/runcontrol.cpp index 53bcd28d101..b826b215698 100644 --- a/src/plugins/projectexplorer/runcontrol.cpp +++ b/src/plugins/projectexplorer/runcontrol.cpp @@ -1257,7 +1257,6 @@ public: SimpleTargetRunner *q = nullptr; - bool m_isLocal = true; bool m_runAsRoot = false; QtcProcess m_process; @@ -1266,10 +1265,6 @@ public: QTextCodec::ConverterState m_outputCodecState; QTextCodec::ConverterState m_errorCodecState; - // Keep track whether we need to emit a finished signal - bool m_processRunning = false; - - // Remote State m_state = Inactive; bool m_stopRequested = false; @@ -1333,7 +1328,9 @@ SimpleTargetRunnerPrivate::~SimpleTargetRunnerPrivate() void SimpleTargetRunnerPrivate::stop() { m_resultData.m_exitStatus = QProcess::CrashExit; - if (m_isLocal) { + + const bool isLocal = !m_command.executable().needsDevice(); + if (isLocal) { if (!isRunning()) return; m_process.stop(); @@ -1346,7 +1343,8 @@ void SimpleTargetRunnerPrivate::stop() q->appendMessage(tr("User requested stop. Shutting down..."), NormalMessageFormat); switch (m_state) { case Run: - m_process.terminate(); + m_process.stop(); + m_process.waitForFinished(); break; case Inactive: break; @@ -1370,48 +1368,9 @@ qint64 SimpleTargetRunnerPrivate::privateApplicationPID() const void SimpleTargetRunnerPrivate::handleDone() { m_resultData = m_process.resultData(); + QTC_ASSERT(m_state == Run, forwardDone(); return); - if (m_isLocal) { - if (m_resultData.m_error == QProcess::UnknownError) { - forwardDone(); - return; - } - // TODO: why below handlings are different? - if (m_process.usesTerminal()) { - q->appendMessage(m_process.errorString(), ErrorMessageFormat); - if (m_processRunning && m_process.processId() == 0) { - m_processRunning = false; - m_resultData.m_exitCode = -1; // FIXME: Why? - } - } else { - QString errorString; - switch (m_resultData.m_error) { - case QProcess::FailedToStart: - errorString = tr("Failed to start program. Path or permissions wrong?"); - break; - case QProcess::Crashed: - m_resultData.m_exitStatus = QProcess::CrashExit; - break; - default: - errorString = tr("Some error has occurred while running the program."); - } - if (!errorString.isEmpty()) - q->appendMessage(errorString, ErrorMessageFormat); - if (m_processRunning && !isRunning()) { - m_processRunning = false; - m_resultData.m_exitCode = -1; - } - } - - } else { - QTC_ASSERT(m_state == Run, forwardDone(); return); - if (m_resultData.m_error == QProcess::FailedToStart) { - m_resultData.m_exitStatus = QProcess::CrashExit; - } else if (m_resultData.m_exitStatus == QProcess::CrashExit) { - m_resultData.m_error = QProcess::Crashed; - } - m_state = Inactive; - } + m_state = Inactive; forwardDone(); } @@ -1433,19 +1392,18 @@ void SimpleTargetRunnerPrivate::handleStandardError() void SimpleTargetRunnerPrivate::start() { - m_isLocal = !m_command.executable().needsDevice(); + const bool isLocal = !m_command.executable().needsDevice(); m_resultData = {}; + QTC_ASSERT(m_state == Inactive, return); - if (m_isLocal) { + if (isLocal) { Environment env = m_environment; if (m_runAsRoot) RunControl::provideAskPassEntry(env); m_process.setEnvironment(env); - m_processRunning = true; - WinDebugInterface::startIfNeeded(); CommandLine cmdLine = m_command; @@ -1458,37 +1416,27 @@ void SimpleTargetRunnerPrivate::start() m_process.setRunAsRoot(m_runAsRoot); m_process.setCommand(cmdLine); - } else { - QTC_ASSERT(m_state == Inactive, return); - - const IDevice::ConstPtr device = DeviceManager::deviceForPath(m_command.executable()); - if (!device) { - m_resultData.m_errorString = tr("Cannot run: No device."); - m_resultData.m_error = QProcess::FailedToStart; - m_resultData.m_exitStatus = QProcess::CrashExit; - forwardDone(); - return; - } - - if (!device->isEmptyCommandAllowed() && m_command.isEmpty()) { - m_resultData.m_errorString = tr("Cannot run: No command given."); - m_resultData.m_error = QProcess::FailedToStart; - m_resultData.m_exitStatus = QProcess::CrashExit; - forwardDone(); - return; - } - - m_state = Run; - m_stopRequested = false; - - m_process.setCommand(m_command); - m_process.setEnvironment(m_environment); - m_process.setExtraData(m_extraData); } + const IDevice::ConstPtr device = DeviceManager::deviceForPath(m_command.executable()); + if (device && !device->isEmptyCommandAllowed() && m_command.isEmpty()) { + m_resultData.m_errorString = tr("Cannot run: No command given."); + m_resultData.m_error = QProcess::FailedToStart; + m_resultData.m_exitStatus = QProcess::CrashExit; + forwardDone(); + return; + } + + m_stopRequested = false; + + m_process.setCommand(m_command); + m_process.setEnvironment(m_environment); + m_process.setExtraData(m_extraData); + + m_state = Run; m_process.setWorkingDirectory(m_workingDirectory); - if (m_isLocal) + if (isLocal) m_outputCodec = QTextCodec::codecForLocale(); else m_outputCodec = QTextCodec::codecForName("utf8"); From 21e254baca1f732d91708d4946de3b071be9b2c6 Mon Sep 17 00:00:00 2001 From: David Schulz Date: Wed, 15 Jun 2022 13:49:38 +0200 Subject: [PATCH 73/94] ClangCodeModel: return absolute path to fallback client from path Change-Id: I9731aca47975e47756042fb8ed42c2f648e365ed Reviewed-by: Christian Kandeler --- src/plugins/cppeditor/cppcodemodelsettings.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/cppeditor/cppcodemodelsettings.cpp b/src/plugins/cppeditor/cppcodemodelsettings.cpp index aacf8ff5625..0c59d923c25 100644 --- a/src/plugins/cppeditor/cppcodemodelsettings.cpp +++ b/src/plugins/cppeditor/cppcodemodelsettings.cpp @@ -87,7 +87,7 @@ static FilePath fallbackClangdFilePath() { if (g_defaultClangdFilePath.exists()) return g_defaultClangdFilePath; - return "clangd"; + return Environment::systemEnvironment().searchInPath("clangd"); } void CppCodeModelSettings::fromSettings(QSettings *s) From 677a8fe34a0afeafd83988d1353a7ebb9093f62a Mon Sep 17 00:00:00 2001 From: David Schulz Date: Thu, 16 Jun 2022 12:31:42 +0200 Subject: [PATCH 74/94] Coco: remove unused parameter Change-Id: If4af2b10df1260d6f3806a5f1f6f1a442609f8d5 Reviewed-by: hjk --- src/plugins/coco/cocolanguageclient.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/coco/cocolanguageclient.cpp b/src/plugins/coco/cocolanguageclient.cpp index 4006a14550c..45cb39e9f74 100644 --- a/src/plugins/coco/cocolanguageclient.cpp +++ b/src/plugins/coco/cocolanguageclient.cpp @@ -194,7 +194,7 @@ public: } private: - void fontSettingsChanged(const TextEditor::FontSettings &fontSettings) + void fontSettingsChanged() { forAllMarks([](TextEditor::TextMark *mark){ static_cast(mark)->updateAnnotationColor(); From 706dc654b996f7fa35fddbed40e6b555cc3cb1b4 Mon Sep 17 00:00:00 2001 From: Artem Sokolovskii Date: Thu, 16 Jun 2022 10:39:21 +0200 Subject: [PATCH 75/94] CppQuickFixes: Add function getDeclaration for AddLocalDeclaration Change-Id: Ie2d5c5de6b871a855b95efe7c633b28d6ed5c512 Reviewed-by: Christian Kandeler --- src/plugins/cppeditor/cppquickfixes.cpp | 37 ++++++++++++++++--------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/src/plugins/cppeditor/cppquickfixes.cpp b/src/plugins/cppeditor/cppquickfixes.cpp index b63d8f115f9..50170e82767 100644 --- a/src/plugins/cppeditor/cppquickfixes.cpp +++ b/src/plugins/cppeditor/cppquickfixes.cpp @@ -1614,6 +1614,23 @@ public: } void perform() override + { + CppRefactoringChanges refactoring(snapshot()); + CppRefactoringFilePtr currentFile = refactoring.file(filePath()); + QString declaration = getDeclaration(); + + if (!declaration.isEmpty()) { + ChangeSet changes; + changes.replace(currentFile->startOf(binaryAST), + currentFile->endOf(simpleNameAST), + declaration); + currentFile->setChangeSet(changes); + currentFile->apply(); + } + } + +private: + QString getDeclaration() { CppRefactoringChanges refactoring(snapshot()); CppRefactoringFilePtr currentFile = refactoring.file(filePath()); @@ -1622,9 +1639,9 @@ public: typeOfExpression.init(semanticInfo().doc, snapshot(), context().bindings()); Scope *scope = currentFile->scopeAt(binaryAST->firstToken()); const QList result = - typeOfExpression(currentFile->textOf(binaryAST->right_expression).toUtf8(), - scope, - TypeOfExpression::Preprocess); + typeOfExpression(currentFile->textOf(binaryAST->right_expression).toUtf8(), + scope, + TypeOfExpression::Preprocess); if (!result.isEmpty()) { SubstitutionEnvironment env; @@ -1640,19 +1657,13 @@ public: FullySpecifiedType tn = rewriteType(result.first().type(), &env, control); Overview oo = CppCodeStyleSettings::currentProjectCodeStyleOverview(); - QString ty = oo.prettyType(tn, simpleNameAST->name); - if (!ty.isEmpty()) { - ChangeSet changes; - changes.replace(currentFile->startOf(binaryAST), - currentFile->endOf(simpleNameAST), - ty); - currentFile->setChangeSet(changes); - currentFile->apply(); - } + QString declaration = oo.prettyType(tn, simpleNameAST->name); + return declaration; } + + return {}; } -private: const BinaryExpressionAST *binaryAST; const SimpleNameAST *simpleNameAST; }; From 189fe7fab37591e1cc43a322d019e7e980c5dedb Mon Sep 17 00:00:00 2001 From: hjk Date: Thu, 16 Jun 2022 10:34:01 +0200 Subject: [PATCH 76/94] ClangTools: Simplify process rampdown This is now taken care of in the desctuctor of QtcProcess itself. Change-Id: I51e65344e6d2cae4498e292e4ad6a586c68b0539 Reviewed-by: Jarek Kobus Reviewed-by: David Schulz --- src/plugins/clangtools/clangtoolrunner.cpp | 44 +++++++--------------- src/plugins/clangtools/clangtoolrunner.h | 8 +--- 2 files changed, 15 insertions(+), 37 deletions(-) diff --git a/src/plugins/clangtools/clangtoolrunner.cpp b/src/plugins/clangtools/clangtoolrunner.cpp index ab5ef389899..c602203a24d 100644 --- a/src/plugins/clangtools/clangtoolrunner.cpp +++ b/src/plugins/clangtools/clangtoolrunner.cpp @@ -25,8 +25,6 @@ #include "clangtoolrunner.h" -#include "clangtoolsconstants.h" - #include #include #include @@ -60,33 +58,17 @@ static QString finishedWithBadExitCode(const QString &name, int exitCode) } ClangToolRunner::ClangToolRunner(QObject *parent) - : QObject(parent), m_process(new QtcProcess) + : QObject(parent) {} -ClangToolRunner::~ClangToolRunner() -{ - if (m_process->state() != QProcess::NotRunning) { - // asking politly to terminate costs ~300 ms on windows so skip the courtasy and direct kill the process - if (HostOsInfo::isWindowsHost()) { - m_process->kill(); - m_process->waitForFinished(100); - } else { - m_process->stop(); - m_process->waitForFinished(); - } - } - - m_process->deleteLater(); -} - void ClangToolRunner::init(const FilePath &outputDirPath, const Environment &environment) { m_outputDirPath = outputDirPath; QTC_CHECK(!m_outputDirPath.isEmpty()); - m_process->setEnvironment(environment); - m_process->setWorkingDirectory(m_outputDirPath); // Current clang-cl puts log file into working dir. - connect(m_process, &QtcProcess::done, this, &ClangToolRunner::onProcessDone); + m_process.setEnvironment(environment); + m_process.setWorkingDirectory(m_outputDirPath); // Current clang-cl puts log file into working dir. + connect(&m_process, &QtcProcess::done, this, &ClangToolRunner::onProcessDone); } QStringList ClangToolRunner::mainToolArguments() const @@ -140,20 +122,20 @@ bool ClangToolRunner::run(const QString &fileToAnalyze, const QStringList &compi m_commandLine = {m_executable, m_argsCreator(compilerOptions)}; qCDebug(LOG).noquote() << "Starting" << m_commandLine.toUserOutput(); - m_process->setCommand(m_commandLine); - m_process->start(); + m_process.setCommand(m_commandLine); + m_process.start(); return true; } void ClangToolRunner::onProcessDone() { - if (m_process->result() == ProcessResult::StartFailed) { + if (m_process.result() == ProcessResult::StartFailed) { emit finishedWithFailure(generalProcessError(m_name), commandlineAndOutput()); - } else if (m_process->result() == ProcessResult::FinishedWithSuccess) { - qCDebug(LOG).noquote() << "Output:\n" << m_process->stdOut(); + } else if (m_process.result() == ProcessResult::FinishedWithSuccess) { + qCDebug(LOG).noquote() << "Output:\n" << m_process.stdOut(); emit finishedWithSuccess(m_fileToAnalyze); - } else if (m_process->result() == ProcessResult::FinishedWithError) { - emit finishedWithFailure(finishedWithBadExitCode(m_name, m_process->exitCode()), + } else if (m_process.result() == ProcessResult::FinishedWithError) { + emit finishedWithFailure(finishedWithBadExitCode(m_name, m_process.exitCode()), commandlineAndOutput()); } else { // == QProcess::CrashExit emit finishedWithFailure(finishedDueToCrash(m_name), commandlineAndOutput()); @@ -166,8 +148,8 @@ QString ClangToolRunner::commandlineAndOutput() const "Process Error: %2\n" "Output:\n%3") .arg(m_commandLine.toUserOutput()) - .arg(m_process->error()) - .arg(m_process->stdOut()); + .arg(m_process.error()) + .arg(m_process.stdOut()); } } // namespace Internal diff --git a/src/plugins/clangtools/clangtoolrunner.h b/src/plugins/clangtools/clangtoolrunner.h index 988aa56f48d..6df1213642b 100644 --- a/src/plugins/clangtools/clangtoolrunner.h +++ b/src/plugins/clangtools/clangtoolrunner.h @@ -28,13 +28,10 @@ #include "clangtoolslogfilereader.h" #include - -#include +#include #include -namespace Utils { class QtcProcess; } - namespace ClangTools { namespace Internal { @@ -46,7 +43,6 @@ class ClangToolRunner : public QObject public: ClangToolRunner(QObject *parent = nullptr); - ~ClangToolRunner() override; void init(const Utils::FilePath &outputDirPath, const Utils::Environment &environment); void setName(const QString &name) { m_name = name; } @@ -83,7 +79,7 @@ private: private: Utils::FilePath m_outputDirPath; - Utils::QtcProcess *m_process = nullptr; + Utils::QtcProcess m_process; QString m_name; Utils::FilePath m_executable; From 5d8f13bfd4e7d82291db930f22f9315efe28a120 Mon Sep 17 00:00:00 2001 From: Artem Sokolovskii Date: Wed, 15 Jun 2022 13:16:05 +0200 Subject: [PATCH 77/94] CppQuickFixes: Add "auto" as local declaration incase cxx11 Add local declaration function add "auto " incase cxx11 features are enabled. Fixes: QTCREATORBUG-26004 Change-Id: I10da77e8baa52740b1c4df5a21d78ac5f0d1c5d6 Reviewed-by: Christian Kandeler --- src/plugins/cppeditor/cppquickfix_test.cpp | 10 ++++++++++ src/plugins/cppeditor/cppquickfixes.cpp | 7 +++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/plugins/cppeditor/cppquickfix_test.cpp b/src/plugins/cppeditor/cppquickfix_test.cpp index 206a88ff740..6471134ec47 100644 --- a/src/plugins/cppeditor/cppquickfix_test.cpp +++ b/src/plugins/cppeditor/cppquickfix_test.cpp @@ -1745,6 +1745,16 @@ void QuickfixTest::testGeneric_data() << CppQuickFixFactoryPtr(new EscapeStringLiteral) << _(R"(const char *str = @"\xc3\xa0""f23\xd0\xb1g\xd0\xb1""1";)") << _(R"(const char *str = "àf23бgб1";)"); + QTest::newRow("AddLocalDeclaration_QTCREATORBUG-26004") + << CppQuickFixFactoryPtr(new AddLocalDeclaration) + << _("void func() {\n" + " QStringList list;\n" + " @it = list.cbegin();\n" + "}\n") + << _("void func() {\n" + " QStringList list;\n" + " auto it = list.cbegin();\n" + "}\n"); } void QuickfixTest::testGeneric() diff --git a/src/plugins/cppeditor/cppquickfixes.cpp b/src/plugins/cppeditor/cppquickfixes.cpp index 50170e82767..42f90edf7c6 100644 --- a/src/plugins/cppeditor/cppquickfixes.cpp +++ b/src/plugins/cppeditor/cppquickfixes.cpp @@ -1634,6 +1634,10 @@ private: { CppRefactoringChanges refactoring(snapshot()); CppRefactoringFilePtr currentFile = refactoring.file(filePath()); + Overview oo = CppCodeStyleSettings::currentProjectCodeStyleOverview(); + + if (currentFile->cppDocument()->languageFeatures().cxx11Enabled) + return "auto " + oo.prettyName(simpleNameAST->name); TypeOfExpression typeOfExpression; typeOfExpression.init(semanticInfo().doc, snapshot(), context().bindings()); @@ -1656,7 +1660,6 @@ private: Control *control = context().bindings()->control().data(); FullySpecifiedType tn = rewriteType(result.first().type(), &env, control); - Overview oo = CppCodeStyleSettings::currentProjectCodeStyleOverview(); QString declaration = oo.prettyType(tn, simpleNameAST->name); return declaration; } @@ -3864,7 +3867,7 @@ void GetterSetterRefactoringHelper::performGeneration(ExistingGetterSetterData d FullySpecifiedType memberVariableType = data.declarationSymbol->type(); memberVariableType.setConst(false); - const bool isMemberVariableStatic = data.declarationSymbol->isStatic(); + const bool isMemberVariableStatic = memberVariableType.isStatic(); memberVariableType.setStatic(false); Overview overview = CppCodeStyleSettings::currentProjectCodeStyleOverview(); overview.showTemplateParameters = false; From 1558a81ac11c77bad7443e882ef12792384847c1 Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Thu, 16 Jun 2022 13:58:43 +0200 Subject: [PATCH 78/94] MesonProcess: Connect to done() signal Instead of connecting to errorOccurred() and finished() signals. Change-Id: I94b5b55795110ea4bdc90fd5da88585bd28f1b32 Reviewed-by: hjk --- .../project/mesonprocess.cpp | 81 +++++-------------- .../project/mesonprocess.h | 5 +- 2 files changed, 20 insertions(+), 66 deletions(-) diff --git a/src/plugins/mesonprojectmanager/project/mesonprocess.cpp b/src/plugins/mesonprojectmanager/project/mesonprocess.cpp index e457a9c379b..f8561ecbee7 100644 --- a/src/plugins/mesonprojectmanager/project/mesonprocess.cpp +++ b/src/plugins/mesonprojectmanager/project/mesonprocess.cpp @@ -52,7 +52,7 @@ MesonProcess::MesonProcess() } bool MesonProcess::run(const Command &command, - const Utils::Environment env, + const Environment &env, const QString &projectName, bool captureStdo) { @@ -97,58 +97,25 @@ void MesonProcess::setProgressValue(int p) m_future.setProgressValue(p); } -void MesonProcess::handleProcessFinished(int code, QProcess::ExitStatus status) +void MesonProcess::handleProcessDone() { + if (m_process->result() != ProcessResult::FinishedWithSuccess) { + ProjectExplorer::TaskHub::addTask(ProjectExplorer::BuildSystemTask{ + ProjectExplorer::Task::TaskType::Error, m_process->exitMessage()}); + } m_cancelTimer.stop(); m_stdo = m_process->readAllStandardOutput(); m_stderr = m_process->readAllStandardError(); - if (status == QProcess::NormalExit) { + if (m_process->exitStatus() == QProcess::NormalExit) { m_future.setProgressValue(1); m_future.reportFinished(); } else { m_future.reportCanceled(); m_future.reportFinished(); } - const QString elapsedTime = Utils::formatElapsedTime(m_elapsed.elapsed()); + const QString elapsedTime = formatElapsedTime(m_elapsed.elapsed()); Core::MessageManager::writeSilently(elapsedTime); - emit finished(code, status); -} - -void MesonProcess::handleProcessError(QProcess::ProcessError error) -{ - QString message; - QString commandStr = m_currentCommand.toUserOutput(); - switch (error) { - case QProcess::FailedToStart: - message = tr("The process failed to start.") - + tr("Either the " - "invoked program \"%1\" is missing, or you may have insufficient " - "permissions to invoke the program.") - .arg(m_currentCommand.executable().toUserOutput()); - break; - case QProcess::Crashed: - message = tr("The process was ended forcefully."); - break; - case QProcess::Timedout: - message = tr("Process timed out."); - break; - case QProcess::WriteError: - message = tr("An error occurred when attempting to write " - "to the process. For example, the process may not be running, " - "or it may have closed its input channel."); - break; - case QProcess::ReadError: - message = tr("An error occurred when attempting to read from " - "the process. For example, the process may not be running."); - break; - case QProcess::UnknownError: - message = tr("An unknown error in the process occurred."); - break; - } - ProjectExplorer::TaskHub::addTask( - ProjectExplorer::BuildSystemTask{ProjectExplorer::Task::TaskType::Error, - QString("%1\n%2").arg(message).arg(commandStr)}); - handleProcessFinished(-1, QProcess::CrashExit); + emit finished(m_process->exitCode(), m_process->exitStatus()); } void MesonProcess::checkForCancelled() @@ -161,26 +128,16 @@ void MesonProcess::checkForCancelled() } void MesonProcess::setupProcess(const Command &command, - const Utils::Environment env, + const Environment env, bool captureStdo) { - if (m_process) - disconnect(m_process.get()); - m_process = std::make_unique(); - connect(m_process.get(), &QtcProcess::finished, this, [this] { - handleProcessFinished(m_process->exitCode(), m_process->exitStatus()); - }); - connect(m_process.get(), &QtcProcess::errorOccurred, this, &MesonProcess::handleProcessError); + m_process.reset(new QtcProcess); + connect(m_process.get(), &QtcProcess::done, this, &MesonProcess::handleProcessDone); if (!captureStdo) { - connect(m_process.get(), - &QtcProcess::readyReadStandardOutput, - this, - &MesonProcess::processStandardOutput); - - connect(m_process.get(), - &QtcProcess::readyReadStandardError, - this, - &MesonProcess::processStandardError); + connect(m_process.get(), &QtcProcess::readyReadStandardOutput, + this, &MesonProcess::processStandardOutput); + connect(m_process.get(), &QtcProcess::readyReadStandardError, + this, &MesonProcess::processStandardError); } m_process->setWorkingDirectory(command.workDir()); @@ -213,17 +170,15 @@ bool MesonProcess::sanityCheck(const Command &command) const void MesonProcess::processStandardOutput() { - QTC_ASSERT(m_process, return ); - auto data = m_process->readAllStandardOutput(); + const auto data = m_process->readAllStandardOutput(); Core::MessageManager::writeSilently(QString::fromLocal8Bit(data)); emit readyReadStandardOutput(data); } void MesonProcess::processStandardError() { - QTC_ASSERT(m_process, return ); - Core::MessageManager::writeSilently(QString::fromLocal8Bit(m_process->readAllStandardError())); } + } // namespace Internal } // namespace MesonProjectManager diff --git a/src/plugins/mesonprojectmanager/project/mesonprocess.h b/src/plugins/mesonprojectmanager/project/mesonprocess.h index f4c191af933..d1ee043781c 100644 --- a/src/plugins/mesonprojectmanager/project/mesonprocess.h +++ b/src/plugins/mesonprojectmanager/project/mesonprocess.h @@ -47,7 +47,7 @@ class MesonProcess final : public QObject public: MesonProcess(); bool run(const Command &command, - const Utils::Environment env, + const Utils::Environment &env, const QString &projectName, bool captureStdo = false); @@ -66,8 +66,7 @@ signals: void readyReadStandardOutput(const QByteArray &data); private: - void handleProcessFinished(int code, QProcess::ExitStatus status); - void handleProcessError(QProcess::ProcessError error); + void handleProcessDone(); void checkForCancelled(); void setupProcess(const Command &command, const Utils::Environment env, bool captureStdo); From 01d3b6971984e7cd66ec3cf2269174f344030b7d Mon Sep 17 00:00:00 2001 From: Cristian Adam Date: Thu, 16 Jun 2022 12:07:41 +0200 Subject: [PATCH 79/94] cdb: Use CtrlCStub for cdb.exe This makes sure that any processes started by the debugged project in cdb are also closed when the debugger should be stopped. It happened to me in the past that while debugging Qt Creator in Qt Creator and closing the debugging session tens of uic.exe were left as zombies. And for some reason they started consuming CPU time. taskkill /f /im uic.exe was the needed command to handle the situation. Change-Id: I498381e793405854f7c02e9fec6b6e4718c75c25 Reviewed-by: hjk Reviewed-by: --- src/plugins/debugger/cdb/cdbengine.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/debugger/cdb/cdbengine.cpp b/src/plugins/debugger/cdb/cdbengine.cpp index 33ef864dd12..6a959beba4e 100644 --- a/src/plugins/debugger/cdb/cdbengine.cpp +++ b/src/plugins/debugger/cdb/cdbengine.cpp @@ -185,6 +185,7 @@ CdbEngine::CdbEngine() : m_extensionCommandPrefix("!" QT_CREATOR_CDB_EXT ".") { m_process.setProcessMode(ProcessMode::Writer); + m_process.setUseCtrlCStub(true); setObjectName("CdbEngine"); setDebuggerName("CDB"); From 25b1c59f744716d0f206663485ca582bfcd20d42 Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Thu, 16 Jun 2022 15:01:14 +0200 Subject: [PATCH 80/94] ValgrindRunner: Connect to done() signal Instead of connecting to errorOccurred() and finished() signals. Change-Id: I8eda3a01d73c87bd2673b40723e563ec3ce3a01c Reviewed-by: hjk --- src/plugins/valgrind/valgrindrunner.cpp | 55 +++++++------------------ src/plugins/valgrind/valgrindrunner.h | 4 -- 2 files changed, 15 insertions(+), 44 deletions(-) diff --git a/src/plugins/valgrind/valgrindrunner.cpp b/src/plugins/valgrind/valgrindrunner.cpp index 5a1f64c15ee..b547edc802a 100644 --- a/src/plugins/valgrind/valgrindrunner.cpp +++ b/src/plugins/valgrind/valgrindrunner.cpp @@ -50,6 +50,7 @@ public: bool run(); void processStarted(); + void processDone(); void localProcessStarted(); void remoteProcessStarted(); void findPidProcessDone(); @@ -65,7 +66,6 @@ public: QHostAddress localServerAddress; QProcess::ProcessChannelMode channelMode = QProcess::SeparateChannels; - bool m_finished = false; QTcpServer xmlServer; XmlProtocol::ThreadedParser parser; @@ -116,12 +116,10 @@ bool ValgrindRunner::Private::run() // consider appending our options last so they override any interfering user-supplied options // -q as suggested by valgrind manual - connect(&m_valgrindProcess, &QtcProcess::finished, - q, &ValgrindRunner::processFinished); connect(&m_valgrindProcess, &QtcProcess::started, this, &ValgrindRunner::Private::processStarted); - connect(&m_valgrindProcess, &QtcProcess::errorOccurred, - q, &ValgrindRunner::processError); + connect(&m_valgrindProcess, &QtcProcess::done, + this, &ValgrindRunner::Private::processDone); connect(&m_valgrindProcess, &QtcProcess::readyReadStandardOutput, q, [this] { q->processOutputReceived(QString::fromUtf8(m_valgrindProcess.readAllStandardOutput()), @@ -145,7 +143,6 @@ bool ValgrindRunner::Private::run() m_valgrindProcess.setWorkingDirectory(m_debuggee.workingDirectory); m_valgrindProcess.setEnvironment(m_debuggee.environment); m_valgrindProcess.start(); - return true; } @@ -157,6 +154,17 @@ void ValgrindRunner::Private::processStarted() remoteProcessStarted(); } +void ValgrindRunner::Private::processDone() +{ + emit q->extraProcessFinished(); + + if (m_valgrindProcess.result() != ProcessResult::FinishedWithSuccess) + emit q->processErrorReceived(m_valgrindProcess.errorString(), m_valgrindProcess.error()); + + // make sure we don't wait for the connection anymore + emit q->finished(); +} + void ValgrindRunner::Private::localProcessStarted() { qint64 pid = m_valgrindProcess.processId(); @@ -268,7 +276,7 @@ void ValgrindRunner::setUseTerminal(bool on) void ValgrindRunner::waitForFinished() const { - if (d->m_finished) + if (d->m_valgrindProcess.state() == QProcess::NotRunning) return; QEventLoop loop; @@ -281,39 +289,6 @@ bool ValgrindRunner::start() return d->run(); } -void ValgrindRunner::processError(QProcess::ProcessError e) -{ - if (d->m_finished) - return; - - d->m_finished = true; - - // make sure we don't wait for the connection anymore - emit processErrorReceived(errorString(), e); - emit finished(); -} - -void ValgrindRunner::processFinished() -{ - emit extraProcessFinished(); - - if (d->m_finished) - return; - - d->m_finished = true; - - // make sure we don't wait for the connection anymore - emit finished(); - - if (d->m_valgrindProcess.exitCode() != 0 || d->m_valgrindProcess.exitStatus() == QProcess::CrashExit) - emit processErrorReceived(errorString(), d->m_valgrindProcess.error()); -} - -QString ValgrindRunner::errorString() const -{ - return d->m_valgrindProcess.errorString(); -} - void ValgrindRunner::stop() { d->m_valgrindProcess.stop(); diff --git a/src/plugins/valgrind/valgrindrunner.h b/src/plugins/valgrind/valgrindrunner.h index 7ba28b1392c..3350792b51f 100644 --- a/src/plugins/valgrind/valgrindrunner.h +++ b/src/plugins/valgrind/valgrindrunner.h @@ -57,8 +57,6 @@ public: void waitForFinished() const; - QString errorString() const; - bool start(); void stop(); @@ -75,8 +73,6 @@ signals: private: bool startServers(); - void processError(QProcess::ProcessError); - void processFinished(); void xmlSocketConnected(); void logSocketConnected(); From 5ee880ce5e6998170823e6fc9afb6b6c36c6170a Mon Sep 17 00:00:00 2001 From: hjk Date: Thu, 16 Jun 2022 15:13:07 +0200 Subject: [PATCH 81/94] Utils: Add a few convenience functions to work with process output Change-Id: I45acea77ccfdc15b1be9693c1658890865383c16 Reviewed-by: Jarek Kobus --- src/libs/utils/qtcprocess.cpp | 42 ++++++++++++++++++++++++++++++----- src/libs/utils/qtcprocess.h | 12 +++++++--- 2 files changed, 45 insertions(+), 9 deletions(-) diff --git a/src/libs/utils/qtcprocess.cpp b/src/libs/utils/qtcprocess.cpp index fdf013a5665..925038086f4 100644 --- a/src/libs/utils/qtcprocess.cpp +++ b/src/libs/utils/qtcprocess.cpp @@ -1361,7 +1361,7 @@ bool QtcProcess::readDataFromProcess(int timeoutS, QString QtcProcess::normalizeNewlines(const QString &text) { QString res = text; - const auto newEnd = std::unique(res.begin(), res.end(), [](const QChar &c1, const QChar &c2) { + const auto newEnd = std::unique(res.begin(), res.end(), [](const QChar c1, const QChar c2) { return c1 == '\r' && c2 == '\r'; // QTCREATORBUG-24556 }); res.chop(std::distance(newEnd, res.end())); @@ -1704,10 +1704,16 @@ QString QtcProcess::allOutput() const return !out.isEmpty() ? out : err; } +QByteArray QtcProcess::rawStdOut() const +{ + QTC_CHECK(d->m_stdOut.keepRawData); + return d->m_stdOut.rawData; +} + QString QtcProcess::stdOut() const { QTC_CHECK(d->m_stdOut.keepRawData); - return normalizeNewlines(d->m_codec->toUnicode(d->m_stdOut.rawData)); + return d->m_codec->toUnicode(d->m_stdOut.rawData); } QString QtcProcess::stdErr() const @@ -1717,13 +1723,37 @@ QString QtcProcess::stdErr() const // is not trivial. So weaken it a bit for now. //QTC_CHECK(d->m_stdErr.keepRawData); QTC_CHECK(d->m_stdErr.keepRawData || d->m_stdErr.rawData.isEmpty()); - return normalizeNewlines(d->m_codec->toUnicode(d->m_stdErr.rawData)); + return d->m_codec->toUnicode(d->m_stdErr.rawData); } -QByteArray QtcProcess::rawStdOut() const +QString QtcProcess::cleanedStdOut() const { - QTC_CHECK(d->m_stdOut.keepRawData); - return d->m_stdOut.rawData; + return normalizeNewlines(stdOut()); +} + +QString QtcProcess::cleanedStdErr() const +{ + return normalizeNewlines(stdErr()); +} + +static QStringList splitLines(const QString &text) +{ + QStringList result = text.split('\n'); + for (QString &line : result) { + if (line.endsWith('\r')) + line.chop(1); + } + return result; +} + +const QStringList QtcProcess::stdOutLines() const +{ + return splitLines(stdOut()); +} + +const QStringList QtcProcess::stdErrLines() const +{ + return splitLines(stdErr()); } QTCREATOR_UTILS_EXPORT QDebug operator<<(QDebug str, const QtcProcess &r) diff --git a/src/libs/utils/qtcprocess.h b/src/libs/utils/qtcprocess.h index 1c793451838..42c981a3431 100644 --- a/src/libs/utils/qtcprocess.h +++ b/src/libs/utils/qtcprocess.h @@ -184,11 +184,17 @@ public: QByteArray allRawOutput() const; QString allOutput() const; - QString stdOut() const; - QString stdErr() const; - QByteArray rawStdOut() const; + QString stdOut() const; // possibly with CR + QString stdErr() const; // possibly with CR + + QString cleanedStdOut() const; // with CR removed + QString cleanedStdErr() const; // with CR removed + + const QStringList stdOutLines() const; // split, CR removed + const QStringList stdErrLines() const; // split, CR removed + QString exitMessage() const; QString toStandaloneCommandLine() const; From aa117f9955df9c2c266a799df41be8988c892f27 Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Thu, 16 Jun 2022 15:27:39 +0200 Subject: [PATCH 82/94] QbsSession: Connect to done() signal Instead of connecting to errorOccurred() and finished() signals. Change-Id: I164338c17acf6ec0eff5c514d6919a27c3feaae8 Reviewed-by: Reviewed-by: Christian Kandeler --- src/plugins/qbsprojectmanager/qbssession.cpp | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/src/plugins/qbsprojectmanager/qbssession.cpp b/src/plugins/qbsprojectmanager/qbssession.cpp index 76bf4e14c00..bd2c3ecb496 100644 --- a/src/plugins/qbsprojectmanager/qbssession.cpp +++ b/src/plugins/qbsprojectmanager/qbssession.cpp @@ -182,23 +182,12 @@ void QbsSession::initialize() connect(d->qbsProcess, &QtcProcess::readyReadStandardError, this, [this] { qCDebug(qbsPmLog) << "[qbs stderr]: " << d->qbsProcess->readAllStandardError(); }); - connect(d->qbsProcess, &QtcProcess::errorOccurred, this, [this](QProcess::ProcessError e) { - d->eventLoop.exit(1); - switch (e) { - case QProcess::FailedToStart: + connect(d->qbsProcess, &QtcProcess::done, this, [this] { + if (d->qbsProcess->result() == ProcessResult::StartFailed) { + d->eventLoop.exit(1); setError(Error::QbsFailedToStart); - break; - case QProcess::WriteError: - case QProcess::ReadError: - setError(Error::ProtocolError); - break; - case QProcess::Crashed: - case QProcess::Timedout: - case QProcess::UnknownError: - break; + return; } - }); - connect(d->qbsProcess, &QtcProcess::finished, this, [this] { d->qbsProcess->deleteLater(); switch (d->state) { case State::Inactive: From af4a6b1a743f4ade995b3cad12fe7d556df7261b Mon Sep 17 00:00:00 2001 From: hjk Date: Thu, 16 Jun 2022 17:28:02 +0200 Subject: [PATCH 83/94] Debugger: Use ProcessResultData a bit more Instead of its individual items. Change-Id: Icd668a61de1c2de676e0a44769f1c1bb5375c523 Reviewed-by: Jarek Kobus --- src/plugins/debugger/cdb/cdbengine.cpp | 3 ++- src/plugins/debugger/debuggerengine.cpp | 15 ++++++++------- src/plugins/debugger/debuggerengine.h | 8 ++++---- src/plugins/debugger/gdb/gdbengine.cpp | 3 ++- src/plugins/debugger/lldb/lldbengine.cpp | 4 +++- 5 files changed, 19 insertions(+), 14 deletions(-) diff --git a/src/plugins/debugger/cdb/cdbengine.cpp b/src/plugins/debugger/cdb/cdbengine.cpp index 6a959beba4e..e3602fba712 100644 --- a/src/plugins/debugger/cdb/cdbengine.cpp +++ b/src/plugins/debugger/cdb/cdbengine.cpp @@ -65,6 +65,7 @@ #include #include #include +#include #include #include #include @@ -708,7 +709,7 @@ void CdbEngine::processFinished() elapsedLogTime(), qPrintable(stateName(state())), m_process.exitStatus(), m_process.exitCode()); - notifyDebuggerProcessFinished(m_process.exitCode(), m_process.exitStatus(), "CDB"); + notifyDebuggerProcessFinished(m_process.resultData(), "CDB"); } void CdbEngine::detachDebugger() diff --git a/src/plugins/debugger/debuggerengine.cpp b/src/plugins/debugger/debuggerengine.cpp index e95ee836eae..884debdff44 100644 --- a/src/plugins/debugger/debuggerengine.cpp +++ b/src/plugins/debugger/debuggerengine.cpp @@ -77,6 +77,7 @@ #include #include #include +#include #include #include #include @@ -1789,14 +1790,14 @@ void DebuggerEngine::showMessage(const QString &msg, int channel, int timeout) c } } -void DebuggerEngine::notifyDebuggerProcessFinished(int exitCode, - QProcess::ExitStatus exitStatus, const QString &backendName) +void DebuggerEngine::notifyDebuggerProcessFinished(const ProcessResultData &result, + const QString &backendName) { showMessage(QString("%1 PROCESS FINISHED, status %2, exit code %3 (0x%4)") .arg(backendName) - .arg(exitStatus) - .arg(exitCode) - .arg(QString::number(exitCode, 16))); + .arg(result.m_exitStatus) + .arg(result.m_exitCode) + .arg(QString::number(result.m_exitCode, 16))); switch (state()) { case DebuggerFinished: @@ -1816,9 +1817,9 @@ void DebuggerEngine::notifyDebuggerProcessFinished(int exitCode, default: { // Initiate shutdown sequence notifyInferiorIll(); - const QString msg = exitStatus == QProcess::CrashExit ? + const QString msg = result.m_exitStatus == QProcess::CrashExit ? tr("The %1 process terminated.") : - tr("The %2 process terminated unexpectedly (exit code %1).").arg(exitCode); + tr("The %2 process terminated unexpectedly (exit code %1).").arg(result.m_exitCode); AsynchronousMessageBox::critical(tr("Unexpected %1 Exit").arg(backendName), msg.arg(backendName)); break; diff --git a/src/plugins/debugger/debuggerengine.h b/src/plugins/debugger/debuggerengine.h index 4205384cd99..64d1933201d 100644 --- a/src/plugins/debugger/debuggerengine.h +++ b/src/plugins/debugger/debuggerengine.h @@ -27,18 +27,17 @@ #include "debugger_global.h" #include "debuggerconstants.h" -#include "debuggeritem.h" #include "debuggerprotocol.h" #include "breakhandler.h" +#include "projectexplorer/abi.h" #include "threadshandler.h" #include #include #include #include -#include -#include +#include QT_BEGIN_NAMESPACE class QDebug; @@ -50,6 +49,7 @@ namespace Core { class IOptionsPage; } namespace Utils { class MacroExpander; class Perspective; +class ProcessResultData; } // Utils namespace Debugger { @@ -509,7 +509,7 @@ public: protected: void setDebuggerName(const QString &name); - void notifyDebuggerProcessFinished(int exitCode, QProcess::ExitStatus exitStatus, + void notifyDebuggerProcessFinished(const Utils::ProcessResultData &resultData, const QString &backendName); virtual void setState(DebuggerState state, bool forced = false); diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index 229a1658a0b..bf62f52c829 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -61,6 +61,7 @@ #include #include #include +#include #include #include #include @@ -4095,7 +4096,7 @@ void GdbEngine::handleGdbDone() if (m_commandTimer.isActive()) m_commandTimer.stop(); - notifyDebuggerProcessFinished(m_gdbProc.exitCode(), m_gdbProc.exitStatus(), "GDB"); + notifyDebuggerProcessFinished(m_gdbProc.resultData(), "GDB"); } void GdbEngine::abortDebuggerProcess() diff --git a/src/plugins/debugger/lldb/lldbengine.cpp b/src/plugins/debugger/lldb/lldbengine.cpp index 5d7ed986588..f870ba78f40 100644 --- a/src/plugins/debugger/lldb/lldbengine.cpp +++ b/src/plugins/debugger/lldb/lldbengine.cpp @@ -35,6 +35,7 @@ #include #include +#include #include #include #include @@ -49,6 +50,7 @@ #include #include +#include #include #include @@ -832,7 +834,7 @@ QString LldbEngine::errorMessage(QProcess::ProcessError error) const void LldbEngine::handleLldbFinished() { - notifyDebuggerProcessFinished(m_lldbProc.exitCode(), m_lldbProc.exitStatus(), "LLDB"); + notifyDebuggerProcessFinished(m_lldbProc.resultData(), "LLDB"); } void LldbEngine::readLldbStandardError() From 3ab822739df615c81c5fc777fff28d92fc7ea5fe Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Thu, 16 Jun 2022 16:29:29 +0200 Subject: [PATCH 84/94] FetchContext: Connect to done() signal Instead of connecting to errorOccurred() and finished() signals. Change-Id: I16e0de8422be989bf56cc6c5b865966f97013731 Reviewed-by: Orgad Shaneh Reviewed-by: --- src/plugins/git/gerrit/gerritplugin.cpp | 51 +++++++++---------------- 1 file changed, 17 insertions(+), 34 deletions(-) diff --git a/src/plugins/git/gerrit/gerritplugin.cpp b/src/plugins/git/gerrit/gerritplugin.cpp index b68aa56c7be..a92543dff8f 100644 --- a/src/plugins/git/gerrit/gerritplugin.cpp +++ b/src/plugins/git/gerrit/gerritplugin.cpp @@ -107,8 +107,7 @@ private: ErrorState }; - void processError(QProcess::ProcessError); - void processFinished(); + void processDone(); void processReadyReadStandardError(); void processReadyReadStandardOutput(); @@ -141,8 +140,7 @@ FetchContext::FetchContext(const QSharedPointer &change, , m_server(server) , m_state(FetchState) { - connect(&m_process, &QtcProcess::errorOccurred, this, &FetchContext::processError); - connect(&m_process, &QtcProcess::finished, this, &FetchContext::processFinished); + connect(&m_process, &QtcProcess::done, this, &FetchContext::processDone); connect(&m_process, &QtcProcess::readyReadStandardError, this, &FetchContext::processReadyReadStandardError); connect(&m_process, &QtcProcess::readyReadStandardOutput, @@ -175,29 +173,26 @@ void FetchContext::start() m_process.start(); } -void FetchContext::processFinished() +void FetchContext::processDone() { - if (m_process.exitStatus() != QProcess::NormalExit) { - handleError(tr("%1 crashed.").arg(m_git.toUserOutput())); + if (m_process.result() != ProcessResult::FinishedWithSuccess) { + handleError(m_process.exitMessage()); return; } - if (m_process.exitCode()) { - handleError(tr("%1 returned %2.").arg(m_git.toUserOutput()).arg(m_process.exitCode())); + if (m_state != FetchState) return; - } - if (m_state == FetchState) { - m_progress.setProgressValue(m_progress.progressValue() + 1); - if (m_fetchMode == FetchDisplay) - show(); - else if (m_fetchMode == FetchCherryPick) - cherryPick(); - else if (m_fetchMode == FetchCheckout) - checkout(); - m_progress.reportFinished(); - m_state = DoneState; - deleteLater(); - } + m_progress.setProgressValue(m_progress.progressValue() + 1); + if (m_fetchMode == FetchDisplay) + show(); + else if (m_fetchMode == FetchCherryPick) + cherryPick(); + else if (m_fetchMode == FetchCheckout) + checkout(); + + m_progress.reportFinished(); + m_state = DoneState; + deleteLater(); } void FetchContext::processReadyReadStandardError() @@ -226,17 +221,6 @@ void FetchContext::handleError(const QString &e) deleteLater(); } -void FetchContext::processError(QProcess::ProcessError e) -{ - if (m_progress.isCanceled()) - return; - const QString msg = tr("Error running %1: %2").arg(m_git.toUserOutput(), m_process.errorString()); - if (e == QProcess::FailedToStart) - handleError(msg); - else - VcsBase::VcsOutputWindow::appendError(msg); -} - void FetchContext::show() { const QString title = QString::number(m_change->number) + '/' @@ -263,7 +247,6 @@ void FetchContext::terminate() m_process.waitForFinished(); } - GerritPlugin::GerritPlugin(QObject *parent) : QObject(parent) , m_parameters(new GerritParameters) From e052d759876900401aa72e8af026629bea32c161 Mon Sep 17 00:00:00 2001 From: David Schulz Date: Thu, 16 Jun 2022 13:38:24 +0200 Subject: [PATCH 85/94] Core: FilePathify WindowTitleHandler Change-Id: I905a193e70b199cbbd483e76e14c7f9fd2b179ef Reviewed-by: hjk --- .../editormanager/editormanager.cpp | 6 +++--- .../coreplugin/editormanager/editormanager.h | 2 +- src/plugins/projectexplorer/session.cpp | 21 +++++++++---------- src/plugins/vcsbase/vcsbaseplugin.cpp | 6 +++--- 4 files changed, 17 insertions(+), 18 deletions(-) diff --git a/src/plugins/coreplugin/editormanager/editormanager.cpp b/src/plugins/coreplugin/editormanager/editormanager.cpp index 34054025349..dbd4edd7fc3 100644 --- a/src/plugins/coreplugin/editormanager/editormanager.cpp +++ b/src/plugins/coreplugin/editormanager/editormanager.cpp @@ -2148,8 +2148,8 @@ void EditorManagerPrivate::updateWindowTitleForDocument(IDocument *document, QWi if (!documentName.isEmpty()) windowTitle.append(documentName); - const QString filePath = document ? document->filePath().absoluteFilePath().path() - : QString(); + const Utils::FilePath filePath = document ? document->filePath().absoluteFilePath() + : Utils::FilePath(); const QString windowTitleAddition = d->m_titleAdditionHandler ? d->m_titleAdditionHandler(filePath) : QString(); @@ -2181,7 +2181,7 @@ void EditorManagerPrivate::updateWindowTitleForDocument(IDocument *document, QWi windowTitle.append(dashSep); windowTitle.append(Core::Constants::IDE_DISPLAY_NAME); window->window()->setWindowTitle(windowTitle); - window->window()->setWindowFilePath(filePath); + window->window()->setWindowFilePath(filePath.path()); if (HostOsInfo::isMacHost()) { if (document) diff --git a/src/plugins/coreplugin/editormanager/editormanager.h b/src/plugins/coreplugin/editormanager/editormanager.h index 4b722c6dce9..dbfe5849514 100644 --- a/src/plugins/coreplugin/editormanager/editormanager.h +++ b/src/plugins/coreplugin/editormanager/editormanager.h @@ -71,7 +71,7 @@ class CORE_EXPORT EditorManager : public QObject Q_OBJECT public: - using WindowTitleHandler = std::function; + using WindowTitleHandler = std::function; static EditorManager *instance(); diff --git a/src/plugins/projectexplorer/session.cpp b/src/plugins/projectexplorer/session.cpp index 67f1616c322..d5b3539bac2 100644 --- a/src/plugins/projectexplorer/session.cpp +++ b/src/plugins/projectexplorer/session.cpp @@ -96,8 +96,8 @@ public: QStringList dependenciesOrder() const; void dependencies(const QString &proName, QStringList &result) const; - static QString windowTitleAddition(const QString &filePath); - static QString sessionTitle(const QString &filePath); + static QString windowTitleAddition(const FilePath &filePath); + static QString sessionTitle(const FilePath &filePath); bool hasProjects() const { return !m_projects.isEmpty(); } @@ -118,7 +118,7 @@ public: PersistentSettingsWriter *m_writer = nullptr; private: - static QString locationInProject(const QString &filePath); + static QString locationInProject(const FilePath &filePath); }; static SessionManager *m_instance = nullptr; @@ -598,7 +598,7 @@ void SessionManagerPrivate::dependencies(const QString &proName, QStringList &re result.append(proName); } -QString SessionManagerPrivate::sessionTitle(const QString &filePath) +QString SessionManagerPrivate::sessionTitle(const FilePath &filePath) { if (SessionManager::isDefaultSession(d->m_sessionName)) { if (filePath.isEmpty()) { @@ -616,18 +616,17 @@ QString SessionManagerPrivate::sessionTitle(const QString &filePath) return QString(); } -QString SessionManagerPrivate::locationInProject(const QString &filePath) { - const Project *project = SessionManager::projectForFile(Utils::FilePath::fromString(filePath)); +QString SessionManagerPrivate::locationInProject(const FilePath &filePath) { + const Project *project = SessionManager::projectForFile(filePath); if (!project) return QString(); - const Utils::FilePath file = Utils::FilePath::fromString(filePath); - const Utils::FilePath parentDir = file.parentDir(); + const FilePath parentDir = filePath.parentDir(); if (parentDir == project->projectDirectory()) return "@ " + project->displayName(); - if (file.isChildOf(project->projectDirectory())) { - const Utils::FilePath dirInProject = parentDir.relativeChildPath(project->projectDirectory()); + if (filePath.isChildOf(project->projectDirectory())) { + const FilePath dirInProject = parentDir.relativeChildPath(project->projectDirectory()); return "(" + dirInProject.toUserOutput() + " @ " + project->displayName() + ")"; } @@ -637,7 +636,7 @@ QString SessionManagerPrivate::locationInProject(const QString &filePath) { return "(" + parentDir.toUserOutput() + " @ " + project->displayName() + ")"; } -QString SessionManagerPrivate::windowTitleAddition(const QString &filePath) +QString SessionManagerPrivate::windowTitleAddition(const FilePath &filePath) { return filePath.isEmpty() ? QString() : locationInProject(filePath); } diff --git a/src/plugins/vcsbase/vcsbaseplugin.cpp b/src/plugins/vcsbase/vcsbaseplugin.cpp index b371c8b2f64..74edfd3dd34 100644 --- a/src/plugins/vcsbase/vcsbaseplugin.cpp +++ b/src/plugins/vcsbase/vcsbaseplugin.cpp @@ -199,7 +199,7 @@ public: explicit StateListener(QObject *parent); ~StateListener(); - static QString windowTitleVcsTopic(const QString &filePath); + static QString windowTitleVcsTopic(const FilePath &filePath); signals: void stateChanged(const VcsBase::Internal::State &s, IVersionControl *vc); @@ -230,11 +230,11 @@ StateListener::~StateListener() EditorManager::setWindowTitleVcsTopicHandler({}); } -QString StateListener::windowTitleVcsTopic(const QString &filePath) +QString StateListener::windowTitleVcsTopic(const FilePath &filePath) { FilePath searchPath; if (!filePath.isEmpty()) { - searchPath = FilePath::fromString(filePath).absolutePath(); + searchPath = filePath.absolutePath(); } else { // use single project's information if there is only one loaded. const QList projects = SessionManager::projects(); From b2af450cdbb02792d142f31d39ba79a3d570e5b6 Mon Sep 17 00:00:00 2001 From: Alessandro Portale Date: Thu, 16 Jun 2022 13:57:08 +0200 Subject: [PATCH 86/94] Debugger: (Re-)Fix start of Android lldb from NDK 23.x on Linux In order to help lldb locate libpython3.9.so, we need to point LD_LIBRARY_PATH to the right lib/ path inside the NDK. Amends: b54bf8ad867e0beddf0fcda6b4deacc3b6a0f7c8 Reason for amend: The "prepend" use-case of Environment::prependOrSet failed due to the undefined separator. Now, use Environment::prependOrSetLibrarySearchPath instead, since that handles the separator and knows the environment variable name. Fixes: QTCREATORBUG-27297 Change-Id: I770a6335a7a26c65d23c930f7d6f9795b3dc52b5 Reviewed-by: Marcus Tillmanns Reviewed-by: Reviewed-by: Alessandro Portale --- src/plugins/debugger/debuggeritem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/debugger/debuggeritem.cpp b/src/plugins/debugger/debuggeritem.cpp index c8f6bdcb7ae..a6659506468 100644 --- a/src/plugins/debugger/debuggeritem.cpp +++ b/src/plugins/debugger/debuggeritem.cpp @@ -294,7 +294,7 @@ bool DebuggerItem::addAndroidLldbPythonEnv(const Utils::FilePath &lldbCmd, Utils if (HostOsInfo::isAnyUnixHost()) { const FilePath pythonLibDir = pythonDir.pathAppended("lib"); if (pythonLibDir.exists()) - env.prependOrSet("LD_LIBRARY_PATH", pythonLibDir.toString()); + env.prependOrSetLibrarySearchPath(pythonLibDir); } return true; From fd68b1c58ea654b4f218f1a32093b09301ea0e89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Mu=C4=87ko?= Date: Wed, 15 Jun 2022 16:29:17 +0200 Subject: [PATCH 87/94] McuSupport: Update renesas flash tool path env variable Change-Id: Ib5375ef2d5ab049313ccfbeb0fd3763d3baa8004 Reviewed-by: Reviewed-by: Yasser Grimes Reviewed-by: hjk Reviewed-by: Alessandro Portale --- src/plugins/mcusupport/mcusupportsdk.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/mcusupport/mcusupportsdk.cpp b/src/plugins/mcusupport/mcusupportsdk.cpp index 9fb416cea6f..b5ef907d8fe 100644 --- a/src/plugins/mcusupport/mcusupportsdk.cpp +++ b/src/plugins/mcusupport/mcusupportsdk.cpp @@ -427,7 +427,7 @@ static McuPackagePtr createCypressProgrammerPackage(const SettingsHandler::Ptr & static McuPackagePtr createRenesasProgrammerPackage(const SettingsHandler::Ptr &settingsHandler) { - const char envVar[] = "RenesasFlashProgrammer_PATH"; + const char envVar[] = "RENESAS_FLASH_PROGRAMMER_PATH"; FilePath defaultPath; if (qEnvironmentVariableIsSet(envVar)) { From e3fd840f98195a4f47ee7c9b3a2f27230eb3b099 Mon Sep 17 00:00:00 2001 From: Marcus Tillmanns Date: Wed, 15 Jun 2022 10:55:51 +0200 Subject: [PATCH 88/94] iostool: Improve deployment speed using delta deploy The iostool did always deploy the whole bundle, without taking into account whether anything has actually changed. This meant that for big bundles anytime the user starts the application on his device, a full deployment was done. For a ~1GB bundle this would take around a minute on a recent Mac and iPhone 12. This fix uses a new function from the mobiledevice framework called AMDeviceSecureInstallApplicationBundle. This function takes a new parameter "ShadowPathKey" which points to a directory where the last deploy state is captured temporarily. Before deploying to the device, the function compares what is to be deployed against the last deploy state and only deploys the parts that actually changed. QtCreator provides a temporary folder for this. Due to this, the initial deployment still does a complete deployment as no state is available yet. All subsequent deployments take the captured state into account. For backwards compatibility, the old deployment method is left intact. Fixes: QTCREATORBUG-24371 Change-Id: I4df6aa79d41b34c326d78be7952d7eeb23774648 Reviewed-by: Eike Ziller Reviewed-by: Reviewed-by: Qt CI Bot --- src/plugins/ios/iostoolhandler.cpp | 7 +- src/tools/iostool/CMakeLists.txt | 1 + src/tools/iostool/cfutils.h | 55 ++++++ src/tools/iostool/iosdevicemanager.cpp | 229 ++++++++++++++++++------- src/tools/iostool/iosdevicemanager.h | 2 +- src/tools/iostool/iostool.cpp | 8 +- src/tools/iostool/iostool.h | 1 + src/tools/iostool/iostool.qbs | 1 + src/tools/iostool/mobiledevicelib.cpp | 25 ++- src/tools/iostool/mobiledevicelib.h | 9 + 10 files changed, 269 insertions(+), 69 deletions(-) create mode 100644 src/tools/iostool/cfutils.h diff --git a/src/plugins/ios/iostoolhandler.cpp b/src/plugins/ios/iostoolhandler.cpp index c64a2731420..a3ccf2e5866 100644 --- a/src/plugins/ios/iostoolhandler.cpp +++ b/src/plugins/ios/iostoolhandler.cpp @@ -38,6 +38,7 @@ #include #include #include +#include #include #include @@ -701,10 +702,14 @@ void IosDeviceToolHandlerPrivate::requestTransferApp(const QString &bundlePath, { m_bundlePath = bundlePath; m_deviceId = deviceId; + QString tmpDeltaPath = Utils::TemporaryDirectory::masterDirectoryFilePath().pathAppended("ios").toString(); QStringList args; args << QLatin1String("--id") << deviceId << QLatin1String("--bundle") << bundlePath << QLatin1String("--timeout") << QString::number(timeout) - << QLatin1String("--install"); + << QLatin1String("--install") + << QLatin1String("--delta-path") + << tmpDeltaPath; + start(IosToolHandler::iosDeviceToolPath(), args); } diff --git a/src/tools/iostool/CMakeLists.txt b/src/tools/iostool/CMakeLists.txt index e02bf7463d4..b7efdc1abda 100644 --- a/src/tools/iostool/CMakeLists.txt +++ b/src/tools/iostool/CMakeLists.txt @@ -18,6 +18,7 @@ add_qtc_executable(iostool main.cpp mobiledevicelib.cpp mobiledevicelib.h relayserver.cpp relayserver.h + cfutils.h ) if (TARGET iostool) diff --git a/src/tools/iostool/cfutils.h b/src/tools/iostool/cfutils.h new file mode 100644 index 00000000000..94e8452f0ce --- /dev/null +++ b/src/tools/iostool/cfutils.h @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include + +#include + +namespace Ios { + +template +struct CFRefDeleter +{ + using pointer = CFType; + void operator()(CFType ref) { CFRelease(ref); } +}; + +inline QString toQStringRelease(CFStringRef str) +{ + QString result = QString::fromCFString(str); + CFRelease(str); + return result; +} + +using CFString_t = std::unique_ptr>; +using CFUrl_t = std::unique_ptr>; +using CFPropertyList_t = std::unique_ptr>; +using CFBundle_t = std::unique_ptr>; +using CFDictionary_t = std::unique_ptr>; +using CFArray_t = std::unique_ptr>; + +} // namespace Ios diff --git a/src/tools/iostool/iosdevicemanager.cpp b/src/tools/iostool/iosdevicemanager.cpp index 2e6aa4ccf36..781420beeb0 100644 --- a/src/tools/iostool/iosdevicemanager.cpp +++ b/src/tools/iostool/iosdevicemanager.cpp @@ -25,19 +25,19 @@ #include "iosdevicemanager.h" +#include "cfutils.h" #include "mobiledevicelib.h" -#include #include #include #include #include +#include #include #include #include #include #include -#include #include #include #include @@ -54,6 +54,10 @@ static const bool debugAll = false; static const bool verbose = true; static const bool noWifi = true; +namespace { + Q_LOGGING_CATEGORY(loggingCategory, "qtc.iostool.iosdevicemanager", QtWarningMsg) +} + // ------- MobileDeviceLib interface -------- namespace { @@ -277,8 +281,12 @@ public: static IosDeviceManagerPrivate *instance(); explicit IosDeviceManagerPrivate (IosDeviceManager *q); bool watchDevices(); - void requestAppOp(const QString &bundlePath, const QStringList &extraArgs, - Ios::IosDeviceManager::AppOp appOp, const QString &deviceId, int timeout); + void requestAppOp(const QString &bundlePath, + const QStringList &extraArgs, + Ios::IosDeviceManager::AppOp appOp, + const QString &deviceId, + int timeout, + const QString &deltaPath); void requestDeviceInfo(const QString &deviceId, int timeout); QStringList errors(); void addError(QString errorMsg); @@ -321,13 +329,17 @@ public: QString bundlePath; QStringList extraArgs; Ios::IosDeviceManager::AppOp appOp; + QString deltaPath; - - AppOpSession(const QString &deviceId, const QString &bundlePath, - const QStringList &extraArgs, Ios::IosDeviceManager::AppOp appOp); + AppOpSession(const QString &deviceId, + const QString &bundlePath, + const QStringList &extraArgs, + Ios::IosDeviceManager::AppOp appOp, + const QString &deltaPath); void deviceCallbackReturned() override; bool installApp(); + bool installAppNew(); bool runApp(); int qmljsDebugPort() const override; am_res_t appTransferCallback(CFDictionaryRef dict) override; @@ -486,11 +498,13 @@ bool IosDeviceManagerPrivate::watchDevices() } void IosDeviceManagerPrivate::requestAppOp(const QString &bundlePath, - const QStringList &extraArgs, - IosDeviceManager::AppOp appOp, - const QString &deviceId, int timeout) + const QStringList &extraArgs, + IosDeviceManager::AppOp appOp, + const QString &deviceId, + int timeout, + const QString &deltaPath) { - AppOpSession *session = new AppOpSession(deviceId, bundlePath, extraArgs, appOp); + AppOpSession *session = new AppOpSession(deviceId, bundlePath, extraArgs, appOp, deltaPath); session->startDeviceLookup(timeout); } @@ -1205,10 +1219,17 @@ bool CommandSession::developerDiskImagePath(QString *path, QString *signaturePat return false; } -AppOpSession::AppOpSession(const QString &deviceId, const QString &bundlePath, - const QStringList &extraArgs, IosDeviceManager::AppOp appOp): - CommandSession(deviceId), bundlePath(bundlePath), extraArgs(extraArgs), appOp(appOp) -{ } +AppOpSession::AppOpSession(const QString &deviceId, + const QString &bundlePath, + const QStringList &extraArgs, + IosDeviceManager::AppOp appOp, + const QString &deltaPath) + : CommandSession(deviceId) + , bundlePath(bundlePath) + , extraArgs(extraArgs) + , appOp(appOp) + , deltaPath(deltaPath) +{} QString AppOpSession::commandName() { @@ -1218,70 +1239,143 @@ QString AppOpSession::commandName() bool AppOpSession::installApp() { bool success = false; - if (device != 0) { - CFURLRef bundleUrl = QUrl::fromLocalFile(bundlePath).toCFURL(); - CFStringRef key[1] = {CFSTR("PackageType")}; - CFStringRef value[1] = {CFSTR("Developer")}; - CFDictionaryRef options = CFDictionaryCreate(0, reinterpret_cast(&key[0]), - reinterpret_cast(&value[0]), 1, - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks); + if (device) { + if (!installAppNew()) { + addError(QString::fromLatin1( + "Failed to transfer and install application, trying old way ...")); - MobileDeviceLib &mLib = MobileDeviceLib::instance(); - // Transfer bundle with secure API AMDeviceTransferApplication. - if (int error = mLib.deviceSecureTransferApplicationPath(0, device, bundleUrl, options, - &appSecureTransferSessionCallback,0)) { - addError(QString::fromLatin1("TransferAppSession(%1,%2) failed, AMDeviceTransferApplication returned %3 (0x%4)") - .arg(bundlePath, deviceId).arg(mobileDeviceErrorString(error)).arg(error)); - success = false; - } else { - // App is transferred. Try installing. - if (connectDevice()) { - // Secure install app api requires device to be connected. - if (am_res_t error = mLib.deviceSecureInstallApplication(0, device, bundleUrl, options, - &appSecureTransferSessionCallback,0)) { - const QString errorString = mobileDeviceErrorString(error); - if (!errorString.isEmpty()) { - addError(errorString - + QStringLiteral(" (0x") - + QString::number(error, 16) - + QStringLiteral(")")); + const CFUrl_t bundleUrl(QUrl::fromLocalFile(bundlePath).toCFURL()); + MobileDeviceLib &mLib = MobileDeviceLib::instance(); + + CFStringRef key[1] = {CFSTR("PackageType")}; + CFStringRef value[1] = {CFSTR("Developer")}; + const CFDictionary_t options( + CFDictionaryCreate(0, + reinterpret_cast(&key[0]), + reinterpret_cast(&value[0]), + 1, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks)); + + // Transfer bundle with secure API AMDeviceTransferApplication. + if (int error + = mLib.deviceSecureTransferApplicationPath(0, + device, + bundleUrl.get(), + options.get(), + &appSecureTransferSessionCallback, + 0)) { + addError(QString::fromLatin1("TransferAppSession(%1,%2) failed, " + "AMDeviceTransferApplication returned %3 (0x%4)") + .arg(bundlePath, deviceId) + .arg(mobileDeviceErrorString(error)) + .arg(error)); + success = false; + } else { + // App is transferred. Try installing. + if (connectDevice()) { + // Secure install app api requires device to be connected. + if (am_res_t error + = mLib.deviceSecureInstallApplication(0, + device, + bundleUrl.get(), + options.get(), + &appSecureTransferSessionCallback, + 0)) { + const QString errorString = mobileDeviceErrorString(error); + if (!errorString.isEmpty()) { + addError(errorString + QStringLiteral(" (0x") + + QString::number(error, 16) + QStringLiteral(")")); + } else { + addError(QString::fromLatin1("InstallAppSession(%1,%2) failed, " + "AMDeviceInstallApplication returned 0x%3") + .arg(bundlePath, deviceId) + .arg(QString::number(error, 16))); + } + success = false; } else { - addError(QString::fromLatin1("InstallAppSession(%1,%2) failed, " - "AMDeviceInstallApplication returned 0x%3") - .arg(bundlePath, deviceId).arg(QString::number(error, 16))); + // App is installed. + success = true; } - success = false; - } else { - // App is installed. - success = true; + disconnectDevice(); } - disconnectDevice(); } + } else { + success = true; } - if (debugAll) { - qDebug() << "AMDeviceSecureTransferApplication finished request with " << (success ? "Success" : "Failure"); - } - - CFRelease(options); - CFRelease(bundleUrl); + qCDebug(loggingCategory) << "AMDeviceSecureTransferApplication finished request with" + << (success ? "Success" : "Failure"); progressBase += 100; } - if (success) { sleep(5); // after installation the device needs a bit of quiet.... } - if (debugAll) { - qDebug() << "AMDeviceSecureInstallApplication finished request with " << (success ? "Success" : "Failure"); + qCDebug(loggingCategory) << "AMDeviceSecureInstallApplication finished request with" + << (success ? "Success" : "Failure"); + + IosDeviceManagerPrivate::instance()->didTransferApp(bundlePath, + deviceId, + (success ? IosDeviceManager::Success + : IosDeviceManager::Failure)); + return success; +} + +bool AppOpSession::installAppNew() +{ + const CFUrl_t bundleUrl(QUrl::fromLocalFile(bundlePath).toCFURL()); + MobileDeviceLib &mLib = MobileDeviceLib::instance(); + + CFBundle_t bundle(CFBundleCreate(kCFAllocatorDefault, bundleUrl.get())); + + if (!bundle) { + addError(QString::fromLatin1("Failed to create bundle")); + return false; } - IosDeviceManagerPrivate::instance()->didTransferApp(bundlePath, deviceId, - (success ? IosDeviceManager::Success : IosDeviceManager::Failure)); - return success; + const CFString_t bundleId(CFBundleGetIdentifier(bundle.get())); + if (!bundleId) { + addError(QString::fromLatin1("Failed to retrieve bundle id")); + return false; + } + + CFUrl_t dpath(QUrl::fromLocalFile(deltaPath).toCFURL()); + + CFStringRef keys[] = { + CFSTR("CFBundleIdentifier"), + CFSTR("CloseOnInvalidate"), + CFSTR("InvalidateOnDetach"), + CFSTR("IsUserInitiated"), + CFSTR("PackageType"), + CFSTR("PreferWifi"), + CFSTR("ShadowParentKey"), + }; + CFStringRef values[] = {bundleId.get(), + CFSTR("1"), + CFSTR("1"), + CFSTR("1"), + CFSTR("Developer"), + CFSTR("1"), + (CFStringRef)dpath.get()}; + + const CFDictionary_t options(CFDictionaryCreate(0, + reinterpret_cast(&keys[0]), + reinterpret_cast(&values[0]), + 7, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks)); + + if (int error = mLib.deviceSecureInstallApplicationBundle(0, + device, + bundleUrl.get(), + options.get(), + &appSecureTransferSessionCallback)) + return false; + + return true; } void AppOpSession::deviceCallbackReturned() @@ -1575,9 +1669,14 @@ bool IosDeviceManager::watchDevices() { return d->watchDevices(); } -void IosDeviceManager::requestAppOp(const QString &bundlePath, const QStringList &extraArgs, - AppOp appOp, const QString &deviceId, int timeout) { - d->requestAppOp(bundlePath, extraArgs, appOp, deviceId, timeout); +void IosDeviceManager::requestAppOp(const QString &bundlePath, + const QStringList &extraArgs, + AppOp appOp, + const QString &deviceId, + int timeout, + QString deltaPath) +{ + d->requestAppOp(bundlePath, extraArgs, appOp, deviceId, timeout, deltaPath); } void IosDeviceManager::requestDeviceInfo(const QString &deviceId, int timeout) diff --git a/src/tools/iostool/iosdevicemanager.h b/src/tools/iostool/iosdevicemanager.h index 7c521c789fd..2fb3bb1c3a3 100644 --- a/src/tools/iostool/iosdevicemanager.h +++ b/src/tools/iostool/iosdevicemanager.h @@ -62,7 +62,7 @@ public: static IosDeviceManager *instance(); bool watchDevices(); void requestAppOp(const QString &bundlePath, const QStringList &extraArgs, AppOp appOp, - const QString &deviceId, int timeout = 1000); + const QString &deviceId, int timeout = 1000, QString deltaPath = QString()); void requestDeviceInfo(const QString &deviceId, int timeout = 1000); int processGdbServer(ServiceConnRef conn); void stopGdbServer(ServiceConnRef conn, int phase); diff --git a/src/tools/iostool/iostool.cpp b/src/tools/iostool/iostool.cpp index e65cae852a4..2def3afa74a 100644 --- a/src/tools/iostool/iostool.cpp +++ b/src/tools/iostool/iostool.cpp @@ -82,6 +82,12 @@ void IosTool::run(const QStringList &args) printHelp = true; } bundlePath = args.value(iarg); + } else if (arg == QLatin1String("--delta-path")) { + if (++iarg == args.size()) { + writeMsg(QStringLiteral("missing path after ") + arg); + printHelp = true; + } + m_deltasPath = args.value(iarg); } else if (arg == QLatin1String("--install")) { appOp = IosDeviceManager::AppOp(appOp | IosDeviceManager::Install); } else if (arg == QLatin1String("--run")) { @@ -163,7 +169,7 @@ void IosTool::run(const QStringList &args) break; } maxProgress = 200; - manager->requestAppOp(bundlePath, extraArgs, appOp, deviceId, timeout); + manager->requestAppOp(bundlePath, extraArgs, appOp, deviceId, timeout, m_deltasPath); } if (opLeft == 0) doExit(0); diff --git a/src/tools/iostool/iostool.h b/src/tools/iostool/iostool.h index 6aa85216ca0..c71a30e6d8c 100644 --- a/src/tools/iostool/iostool.h +++ b/src/tools/iostool/iostool.h @@ -79,6 +79,7 @@ private: Ios::IosDeviceManager::AppOp appOp; QFile outFile; QString m_qmlPort; + QString m_deltasPath; QXmlStreamWriter out; GdbRelayServer *gdbServer; QmlRelayServer *qmlServer; diff --git a/src/tools/iostool/iostool.qbs b/src/tools/iostool/iostool.qbs index a39ace4dba1..bac9f43725f 100644 --- a/src/tools/iostool/iostool.qbs +++ b/src/tools/iostool/iostool.qbs @@ -11,6 +11,7 @@ QtcTool { Depends { name: "app_version_header" } files: [ + "cfutils.h" "Info.plist", "gdbrunner.cpp", "gdbrunner.h", diff --git a/src/tools/iostool/mobiledevicelib.cpp b/src/tools/iostool/mobiledevicelib.cpp index 025248262f1..ae1c70f4a86 100644 --- a/src/tools/iostool/mobiledevicelib.cpp +++ b/src/tools/iostool/mobiledevicelib.cpp @@ -89,7 +89,15 @@ bool MobileDeviceLib::load() m_AMDSetLogLevel = reinterpret_cast(lib.resolve("AMDSetLogLevel")); if (m_AMDSetLogLevel == 0) addError("MobileDeviceLib does not define AMDSetLogLevel"); - m_AMDeviceNotificationSubscribe = reinterpret_cast(lib.resolve("AMDeviceNotificationSubscribe")); + + m_AMDeviceSecureInstallApplicationBundle + = reinterpret_cast( + lib.resolve("AMDeviceSecureInstallApplicationBundle")); + if (m_AMDeviceSecureInstallApplicationBundle == 0) + addError("MobileDeviceLib does not define m_AMDeviceSecureInstallApplicationBundle"); + + m_AMDeviceNotificationSubscribe = reinterpret_cast( + lib.resolve("AMDeviceNotificationSubscribe")); if (m_AMDeviceNotificationSubscribe == 0) addError("MobileDeviceLib does not define AMDeviceNotificationSubscribe"); m_AMDeviceNotificationUnsubscribe = reinterpret_cast(lib.resolve("AMDeviceNotificationUnsubscribe")); @@ -358,6 +366,21 @@ int MobileDeviceLib::deviceSecureTransferApplicationPath(int zero, AMDeviceRef d return returnCode; } +int MobileDeviceLib::deviceSecureInstallApplicationBundle( + int zero, + AMDeviceRef device, + CFURLRef url, + CFDictionaryRef options, + AMDeviceSecureInstallApplicationCallback callback) +{ + int returnCode = -1; + + if (m_AMDeviceSecureInstallApplicationBundle) { + returnCode = m_AMDeviceSecureInstallApplicationBundle(device, url, options, callback, zero); + } + return returnCode; +} + int MobileDeviceLib::deviceSecureInstallApplication(int zero, AMDeviceRef device, CFURLRef url, CFDictionaryRef options, AMDeviceSecureInstallApplicationCallback callback, int arg) { int returnCode = -1; diff --git a/src/tools/iostool/mobiledevicelib.h b/src/tools/iostool/mobiledevicelib.h index 97735fdcb1a..68bca9d316d 100644 --- a/src/tools/iostool/mobiledevicelib.h +++ b/src/tools/iostool/mobiledevicelib.h @@ -101,6 +101,7 @@ typedef am_res_t (MDEV_API *USBMuxConnectByPortPtr)(unsigned int, int, ServiceSo // secure Api's typedef am_res_t (MDEV_API *AMDeviceSecureStartServicePtr)(AMDeviceRef, CFStringRef, unsigned int *, ServiceConnRef *); typedef int (MDEV_API *AMDeviceSecureTransferPathPtr)(int, AMDeviceRef, CFURLRef, CFDictionaryRef, AMDeviceSecureInstallApplicationCallback, int); +typedef int (MDEV_API *AMDeviceSecureInstallApplicationBundlePtr)(AMDeviceRef, CFURLRef, CFDictionaryRef, AMDeviceSecureInstallApplicationCallback, int zero); typedef int (MDEV_API *AMDeviceSecureInstallApplicationPtr)(int, AMDeviceRef, CFURLRef, CFDictionaryRef, AMDeviceSecureInstallApplicationCallback, int); typedef int (MDEV_API *AMDServiceConnectionGetSocketPtr)(ServiceConnRef); @@ -158,6 +159,13 @@ public: int deviceSecureTransferApplicationPath(int, AMDeviceRef, CFURLRef, CFDictionaryRef, AMDeviceSecureInstallApplicationCallback callback, int); + + int deviceSecureInstallApplicationBundle(int zero, + AMDeviceRef device, + CFURLRef url, + CFDictionaryRef options, + AMDeviceSecureInstallApplicationCallback callback); + int deviceSecureInstallApplication(int zero, AMDeviceRef device, CFURLRef url, CFDictionaryRef options, AMDeviceSecureInstallApplicationCallback callback, int arg); @@ -191,6 +199,7 @@ private: AMDeviceMountImagePtr m_AMDeviceMountImage; AMDeviceSecureStartServicePtr m_AMDeviceSecureStartService; AMDeviceSecureTransferPathPtr m_AMDeviceSecureTransferPath; + AMDeviceSecureInstallApplicationBundlePtr m_AMDeviceSecureInstallApplicationBundle; AMDeviceSecureInstallApplicationPtr m_AMDeviceSecureInstallApplication; AMDServiceConnectionGetSocketPtr m_AMDServiceConnectionGetSocket; AMDServiceConnectionSendPtr m_AMDServiceConnectionSend; From 35707f867493997531a641ba006e2f2ef94375ea Mon Sep 17 00:00:00 2001 From: Marcus Tillmanns Date: Thu, 16 Jun 2022 14:27:30 +0200 Subject: [PATCH 89/94] android: fix call TaskHub::addTask from wrong thread Fixes: QTCREATORBUG-27105 Change-Id: I3be5e09e66642f8405979f601eee0db7b6a530e8 Reviewed-by: hjk --- src/plugins/projectexplorer/taskhub.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/plugins/projectexplorer/taskhub.cpp b/src/plugins/projectexplorer/taskhub.cpp index ec402ad03bf..02d1f713e60 100644 --- a/src/plugins/projectexplorer/taskhub.cpp +++ b/src/plugins/projectexplorer/taskhub.cpp @@ -153,11 +153,18 @@ void TaskHub::addTask(Task::TaskType type, const QString &description, Utils::Id void TaskHub::addTask(Task task) { + if (QThread::currentThread() != qApp->thread()) { + QMetaObject::invokeMethod(qApp, [&task] { + TaskHub::addTask(task); + }); + + return; + } + QTC_ASSERT(m_registeredCategories.contains(task.category), return); QTC_ASSERT(!task.description().isEmpty(), return); QTC_ASSERT(!task.isNull(), return); QTC_ASSERT(task.m_mark.isNull(), return); - QTC_ASSERT(QThread::currentThread() == qApp->thread(), return); if (task.file.isEmpty() || task.line <= 0) task.line = -1; From addcfa6dc7f437ccbe098b9ad85fd9e1811a862e Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Wed, 15 Jun 2022 11:38:48 +0200 Subject: [PATCH 90/94] CMake build: Fix issues with sharing qmldesignercore files When adding the .ui files from qmldesignercore.cmake to tst_assetsImport and tst_merge in the qtquickdesigner repository, AUTOUIC for some reason gets the output location for the generated ui_*.h headers from: It puts them into qtquickdesigner/tests/qtcreator/src/plugins/qmldesigner/designercore/ instances/ instead of into the corresponding *_autogen directory. That leads to both tests wanting to generate the same file, and ninja complains with ninja: error: build.ninja:78635: multiple rules generate qtquickdesigner/..... Do not use AUTOUIC for these .ui files, but instead add them manually with qt_wrap_ui. Change-Id: I1d60fae95739335a87f8196ed2a686a0633165b2 Reviewed-by: Cristian Adam Reviewed-by: Qt CI Bot --- src/plugins/qmldesigner/qmldesignercore.cmake | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/plugins/qmldesigner/qmldesignercore.cmake b/src/plugins/qmldesigner/qmldesignercore.cmake index b904057da2b..46e30173a3b 100644 --- a/src/plugins/qmldesigner/qmldesignercore.cmake +++ b/src/plugins/qmldesigner/qmldesignercore.cmake @@ -49,6 +49,21 @@ function(extend_with_qmldesigner_core target_name) rewritertransaction.h ) + # autouic gets confused when adding the ui files to tests in the qtquickdesigner repo, + # so manually add them for UIC + set(UI_FILES + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/designercore/instances/puppetbuildprogressdialog.ui + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/designercore/instances/puppetdialog.ui + ) + qt_wrap_ui(UI_SOURCES ${UI_FILES}) + extend_qtc_target(${target_name} + INCLUDES ${CMAKE_CURRENT_BINARY_DIR} + SOURCES + ${UI_SOURCES} + ${UI_FILES} + ) + set_source_files_properties(${UI_FILES} PROPERTIES SKIP_AUTOUIC ON) + extend_qtc_target(${target_name} INCLUDES ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/designercore/exceptions @@ -204,12 +219,10 @@ function(extend_with_qmldesigner_core target_name) instances/nodeinstanceview.cpp instances/puppetbuildprogressdialog.cpp instances/puppetbuildprogressdialog.h - instances/puppetbuildprogressdialog.ui instances/puppetcreator.cpp instances/puppetcreator.h instances/puppetdialog.cpp instances/puppetdialog.h - instances/puppetdialog.ui instances/qprocessuniqueptr.h metainfo/itemlibraryinfo.cpp From 65e043961e7267fbe4b0d897ee9922801c53035e Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Wed, 15 Jun 2022 14:40:23 +0200 Subject: [PATCH 91/94] CMake: Fix missing path to ninja for ExternalProject_Add ExternalProject_Add runs CMake not during the CMake run of the toplevel project, but instead it runs CMake for the external project during the build step. And while ExternalProject passes the CMAKE_COMMAND on to the external project, it does not do so for the CMAKE_MAKE_PROGRAM. Make sure that the make program is also found when configuring the external project during the build step, by adding the path to ninja to the build environment, instead of just the CMake process. Fixes: QTCREATORBUG-27495 Change-Id: I672ec04881387a7411836ab94655176b7a5fb681 Reviewed-by: Qt CI Bot Reviewed-by: Reviewed-by: Cristian Adam --- src/plugins/cmakeprojectmanager/builddirparameters.cpp | 6 ------ .../cmakeprojectmanager/cmakebuildconfiguration.cpp | 9 +++++++++ .../cmakeprojectmanager/cmakebuildconfiguration.h | 2 ++ 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/plugins/cmakeprojectmanager/builddirparameters.cpp b/src/plugins/cmakeprojectmanager/builddirparameters.cpp index 5595182db69..939920e4b82 100644 --- a/src/plugins/cmakeprojectmanager/builddirparameters.cpp +++ b/src/plugins/cmakeprojectmanager/builddirparameters.cpp @@ -89,12 +89,6 @@ BuildDirParameters::BuildDirParameters(CMakeBuildSystem *buildSystem) if (Utils::HostOsInfo::isAnyUnixHost()) environment.set("ICECC", "no"); - CMakeSpecificSettings *settings = CMakeProjectPlugin::projectTypeSpecificSettings(); - if (!settings->ninjaPath.filePath().isEmpty()) { - const Utils::FilePath ninja = settings->ninjaPath.filePath(); - environment.appendOrSetPath(ninja.isFile() ? ninja.parentDir() : ninja); - } - cmakeToolId = CMakeKitAspect::cmakeToolId(k); } diff --git a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp index 66fa741c10b..80b0f67e2cb 100644 --- a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp +++ b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp @@ -1714,6 +1714,15 @@ FilePath CMakeBuildConfiguration::sourceDirectory() const return aspect()->filePath(); } +void CMakeBuildConfiguration::addToEnvironment(Utils::Environment &env) const +{ + CMakeSpecificSettings *settings = CMakeProjectPlugin::projectTypeSpecificSettings(); + if (!settings->ninjaPath.filePath().isEmpty()) { + const Utils::FilePath ninja = settings->ninjaPath.filePath(); + env.appendOrSetPath(ninja.isFile() ? ninja.parentDir() : ninja); + } +} + QString CMakeBuildSystem::cmakeBuildType() const { auto setBuildTypeFromConfig = [this](const CMakeConfig &config) { diff --git a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.h b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.h index bba266ca36a..7d279b1bba1 100644 --- a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.h +++ b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.h @@ -64,6 +64,8 @@ public: void setSourceDirectory(const Utils::FilePath& path); Utils::FilePath sourceDirectory() const; + void addToEnvironment(Utils::Environment &env) const override; + signals: void signingFlagsChanged(); From bd2a9944348a142ee8664d78ca8ac2a8ffb9541d Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Thu, 16 Jun 2022 14:26:23 +0200 Subject: [PATCH 92/94] UpdateInfo: Improve URL for "Qt blog" for new Qt releases Use the URL that shows all release blog posts, which increases chances for the user to find the right one without hassle. Change-Id: Ia34b4de031223dd8b856be3cf1596fe1db274e54 Reviewed-by: hjk --- src/plugins/updateinfo/updateinfoplugin.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/plugins/updateinfo/updateinfoplugin.cpp b/src/plugins/updateinfo/updateinfoplugin.cpp index c895d3c65a5..a0617df3a09 100644 --- a/src/plugins/updateinfo/updateinfoplugin.cpp +++ b/src/plugins/updateinfo/updateinfoplugin.cpp @@ -254,9 +254,9 @@ static void showQtUpdateInfo(const QtPackage &package, { Utils::InfoBarEntry info(InstallQtUpdates, UpdateInfoPlugin::tr( - "%1 is available. Check the Qt blog for details.") - .arg(package.displayName)); + "%1 is available. Check the Qt blog for details.") + .arg(package.displayName, + QString("href=\"https://www.qt.io/blog/tag/releases\""))); info.addCustomButton(UpdateInfoPlugin::tr("Start Package Manager"), [startPackageManager] { Core::ICore::infoBar()->removeInfo(InstallQtUpdates); startPackageManager(); From db451f77786b9027721b37700c95697f8971fbb0 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Fri, 17 Jun 2022 09:55:06 +0200 Subject: [PATCH 93/94] iostool: Fix qbs build Change-Id: I5a33a247152d779d89a5e607cd42ab7030ae528e Reviewed-by: Christian Stenger --- src/tools/iostool/iostool.qbs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/iostool/iostool.qbs b/src/tools/iostool/iostool.qbs index bac9f43725f..d45172e23f2 100644 --- a/src/tools/iostool/iostool.qbs +++ b/src/tools/iostool/iostool.qbs @@ -11,7 +11,7 @@ QtcTool { Depends { name: "app_version_header" } files: [ - "cfutils.h" + "cfutils.h", "Info.plist", "gdbrunner.cpp", "gdbrunner.h", From 1e70973c323af5194ed975144f884a4c3ecc394d Mon Sep 17 00:00:00 2001 From: Marcus Tillmanns Date: Thu, 16 Jun 2022 09:57:52 +0200 Subject: [PATCH 94/94] qml-debug-doc: Inform the user that breakpoints are only available in block mode Setting / triggering breakpoints is only possible if the target application was started with the "block" argument. Fixes: QTCREATORBUG-27515 Change-Id: Idafdaa87c38c8c452771897d4d845c4398d55fc4 Reviewed-by: hjk --- doc/qtcreator/src/debugger/qtquick-debugging.qdoc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/qtcreator/src/debugger/qtquick-debugging.qdoc b/doc/qtcreator/src/debugger/qtquick-debugging.qdoc index be900ea655c..0934b94e3d7 100644 --- a/doc/qtcreator/src/debugger/qtquick-debugging.qdoc +++ b/doc/qtcreator/src/debugger/qtquick-debugging.qdoc @@ -162,6 +162,8 @@ the application from running until the debug client connects to the server. This enables debugging from the start. + \note Setting breakpoints is only possible if the application is started with block mode. + \li Select \uicontrol Debug > \uicontrol {Start Debugging} > \uicontrol {Attach to QML Port}.