From 3c2296ae63071bb0d17ebeb9a4ea487342c96b28 Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Mon, 30 Sep 2024 16:26:04 +0200 Subject: [PATCH 01/76] Doc: Link from "Setting Breakpoints" to "Add breakpoints" Task-number: QTCREATORBUG-29692 Change-Id: Ied4fa2cd1e3dda78f62155dac61636a05b893300 Reviewed-by: Artem Sokolovskii --- doc/qtcreator/src/debugger/creator-debug-views.qdoc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/qtcreator/src/debugger/creator-debug-views.qdoc b/doc/qtcreator/src/debugger/creator-debug-views.qdoc index 8880b64218b..ad8d948c753 100644 --- a/doc/qtcreator/src/debugger/creator-debug-views.qdoc +++ b/doc/qtcreator/src/debugger/creator-debug-views.qdoc @@ -146,7 +146,8 @@ \generatelist studio-how-to-debug \else - \sa {Debug}{How To: Debug}, {Debugging}, {Debuggers}, {Debugger} + \sa {Add breakpoints}, {Debug}{How To: Debug}, {Debugging}, {Debuggers}, + {Debugger} \endif */ From 66ca4b69f0fb85fd22450e77f9544c66502d17c0 Mon Sep 17 00:00:00 2001 From: Alessandro Portale Date: Fri, 27 Sep 2024 15:46:44 +0200 Subject: [PATCH 02/76] Themes: Enable toolbar outlines/splitters having the same colors The current themes use distinguished colors for movable splitters, toolbar borders and toolbar separators. Dark themes do not draw any border between toolbar and pane content. The UI facelift defines the same color for the above mentioned splitters, borders and separators. That requires requires special handling in the styling code, since up till now, the border colors were calculated based on the theme colors (in order to blend better with an optionally recolored toolbar, see "- color" feature). For the new use-case, all colors need to come straight from the theme. Fixes: QTCREATORBUG-31682 Change-Id: I955dcc07d73b0cec0578e9d0665058eeb47653c0 Reviewed-by: hjk --- src/libs/utils/stylehelper.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/libs/utils/stylehelper.cpp b/src/libs/utils/stylehelper.cpp index 080bb8a3820..340f29d6f51 100644 --- a/src/libs/utils/stylehelper.cpp +++ b/src/libs/utils/stylehelper.cpp @@ -176,6 +176,10 @@ QColor StyleHelper::borderColor(bool lightColored) QColor StyleHelper::toolBarBorderColor() { + if (const QColor sepColor = creatorColor(Theme::FancyToolBarSeparatorColor); + sepColor == creatorColor(Theme::SplitterColor)) + return sepColor; // QTCREATORBUG-31682: Unify all separating line colors if two are the same + const QColor base = baseColor(); return QColor::fromHsv(base.hue(), base.saturation() , From 0ec78b422a3af32095d3f1d427b3b9a62411600f Mon Sep 17 00:00:00 2001 From: hjk Date: Fri, 4 Oct 2024 11:31:57 +0200 Subject: [PATCH 03/76] Git: Fix a warning about a dangling reference MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit .../src/plugins/git/gitclient.cpp:947:29: warning: possibly dangling reference to a temporary [-Wdangling-reference] 947 | const IVCF &modification = std::max(gitStates.value(line.at(0), IVCF::NoModification), | ^~~~~~~~~~~~ /data/dev/tqtc-qtc-super/qtcreator/src/plugins/git/gitclient.cpp:947:52: note: the temporary was destroyed at the end of the full expression ‘std::max(gitStates.QHash::value((& line)->QString::at(0), Core::IVersionControl::FileState::NoModification), gitStates.QHash::value((& line)->QString::at(1), Core::IVersionControl::FileState::NoModification))’ 947 | const IVCF &modification = std::max(gitStates.value(line.at(0), IVCF::NoModification), | ~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 948 | gitStates.value(line.at(1), IVCF::NoModification)); | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ IVCF (== IVersionControl::FileState) is an enum, no need to have that as reference to start with. Change-Id: If3bbcd07d803593fc00ce3a8b8d9bdb8e2d1cbeb Reviewed-by: André Hartmann --- src/plugins/git/gitclient.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp index 7739782c204..07ed22ebe52 100644 --- a/src/plugins/git/gitclient.cpp +++ b/src/plugins/git/gitclient.cpp @@ -944,7 +944,7 @@ void GitClient::updateModificationInfos() {'?', IVCF::UnmanagedState}, }; - const IVCF &modification = std::max(gitStates.value(line.at(0), IVCF::NoModification), + const IVCF modification = std::max(gitStates.value(line.at(0), IVCF::NoModification), gitStates.value(line.at(1), IVCF::NoModification)); if (modification != IVCF::NoModification) From 15d5f130f7056e1e45abf4877d56c2207a28dea9 Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Tue, 1 Oct 2024 14:31:05 +0200 Subject: [PATCH 04/76] ValgrindSettings: Introduce leakCheckOnFinishOptionString() Change-Id: I0ddfc583b84536cdcdb49971bd7755ebaf36962c Reviewed-by: hjk --- src/plugins/valgrind/memchecktool.cpp | 15 +-------------- src/plugins/valgrind/valgrindsettings.cpp | 11 +++++++++++ src/plugins/valgrind/valgrindsettings.h | 1 + 3 files changed, 13 insertions(+), 14 deletions(-) diff --git a/src/plugins/valgrind/memchecktool.cpp b/src/plugins/valgrind/memchecktool.cpp index ef50ea58849..b666bd2f7d4 100644 --- a/src/plugins/valgrind/memchecktool.cpp +++ b/src/plugins/valgrind/memchecktool.cpp @@ -185,20 +185,7 @@ void MemcheckToolRunner::addToolArguments(CommandLine &cmd) const if (m_settings.showReachable()) cmd << "--show-reachable=yes"; - QString leakCheckValue; - switch (m_settings.leakCheckOnFinish()) { - case ValgrindSettings::LeakCheckOnFinishNo: - leakCheckValue = "no"; - break; - case ValgrindSettings::LeakCheckOnFinishYes: - leakCheckValue = "full"; - break; - case ValgrindSettings::LeakCheckOnFinishSummaryOnly: - default: - leakCheckValue = "summary"; - break; - } - cmd << "--leak-check=" + leakCheckValue; + cmd << "--leak-check=" + m_settings.leakCheckOnFinishOptionString(); for (const FilePath &file : m_settings.suppressions()) cmd << QString("--suppressions=%1").arg(file.path()); diff --git a/src/plugins/valgrind/valgrindsettings.cpp b/src/plugins/valgrind/valgrindsettings.cpp index 0113f00c5a9..2291c9aa76a 100644 --- a/src/plugins/valgrind/valgrindsettings.cpp +++ b/src/plugins/valgrind/valgrindsettings.cpp @@ -397,6 +397,17 @@ ValgrindSettings::ValgrindSettings(bool global) readSettings(); } +QString ValgrindSettings::leakCheckOnFinishOptionString() const +{ + switch (leakCheckOnFinish()) { + case ValgrindSettings::LeakCheckOnFinishNo: return "no"; + case ValgrindSettings::LeakCheckOnFinishYes: return "full"; + case ValgrindSettings::LeakCheckOnFinishSummaryOnly: + default: return "summary"; + } + return {}; +} + ValgrindSettings &globalSettings() { static ValgrindSettings theSettings{true}; diff --git a/src/plugins/valgrind/valgrindsettings.h b/src/plugins/valgrind/valgrindsettings.h index 6f12c341a52..ef081e565d8 100644 --- a/src/plugins/valgrind/valgrindsettings.h +++ b/src/plugins/valgrind/valgrindsettings.h @@ -70,6 +70,7 @@ public: Utils::StringAspect memcheckArguments{this}; Utils::IntegerAspect numCallers{this}; Utils::SelectionAspect leakCheckOnFinish{this}; + QString leakCheckOnFinishOptionString() const; Utils::BoolAspect showReachable{this}; Utils::BoolAspect trackOrigins{this}; Utils::BoolAspect filterExternalIssues{this}; From 565b50755417149ea41809c2dde7f50c139a9b74 Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Wed, 2 Oct 2024 10:37:36 +0200 Subject: [PATCH 05/76] ValgrindProcess: Emit done() signal just once Change-Id: Ifb2ea389257e5e8b394d038c226a3104c7c4bb03 Reviewed-by: hjk --- src/plugins/valgrind/valgrindprocess.cpp | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/plugins/valgrind/valgrindprocess.cpp b/src/plugins/valgrind/valgrindprocess.cpp index 34bda25c5ab..4ef1862985f 100644 --- a/src/plugins/valgrind/valgrindprocess.cpp +++ b/src/plugins/valgrind/valgrindprocess.cpp @@ -95,12 +95,6 @@ public: connect(process, &Process::started, this, [this, process] { emit q->valgrindStarted(process->processId()); }); - connect(process, &Process::done, this, [this, process] { - const bool success = process->result() == ProcessResult::FinishedWithSuccess; - if (!success) - emit q->processErrorReceived(process->errorString(), process->error()); - emit q->done(toDoneResult(success)); - }); connect(process, &Process::readyReadStandardOutput, this, [this, process] { emit q->appendMessage(process->readAllStandardOutput(), StdOutFormat); }); @@ -185,6 +179,9 @@ Group ValgrindProcessPrivate::runRecipe() const const auto onProcessSetup = [this, storage](Process &process) { setupValgrindProcess(&process, storage->m_valgrindCommand); }; + const auto onProcessDone = [this, storage](const Process &process) { + emit q->processErrorReceived(process.errorString(), process.error()); + }; const auto isAddressValid = [this] { return !m_localServerAddress.isNull(); }; @@ -194,7 +191,7 @@ Group ValgrindProcessPrivate::runRecipe() const parser.setSocket(storage->m_xmlSocket.release()); }; - const auto onParserError = [this](const Parser &parser) { + const auto onParserDone = [this](const Parser &parser) { emit q->internalError(parser.errorString()); }; @@ -203,10 +200,10 @@ Group ValgrindProcessPrivate::runRecipe() const storage, xmlBarrier, If (isSetupValid) >> Then { - ProcessTask(onProcessSetup), + ProcessTask(onProcessSetup, onProcessDone, CallDoneIf::Error), If (isAddressValid) >> Then { waitForBarrierTask(xmlBarrier), - ParserTask(onParserSetup, onParserError, CallDoneIf::Error) + ParserTask(onParserSetup, onParserDone, CallDoneIf::Error) } } >> Else { errorItem From 80caa6cd62fa7c1cf4c2938108a1e9a811798be4 Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Wed, 2 Oct 2024 10:57:45 +0200 Subject: [PATCH 06/76] ValgrindProcess: Inline setupValgrindProcess Change-Id: I60a15a82dcfccc9fb32e69970e7f84feed3adbfd Reviewed-by: hjk --- src/plugins/valgrind/valgrindprocess.cpp | 65 +++++++++++------------- 1 file changed, 31 insertions(+), 34 deletions(-) diff --git a/src/plugins/valgrind/valgrindprocess.cpp b/src/plugins/valgrind/valgrindprocess.cpp index 4ef1862985f..afb8cc81ca9 100644 --- a/src/plugins/valgrind/valgrindprocess.cpp +++ b/src/plugins/valgrind/valgrindprocess.cpp @@ -70,39 +70,6 @@ public: }); } - void setupValgrindProcess(Process *process, const CommandLine &command) const { - CommandLine cmd = command; - cmd.addArgs(m_valgrindCommand.arguments(), CommandLine::Raw); - - // consider appending our options last so they override any interfering user-supplied - // options -q as suggested by valgrind manual - - if (cmd.executable().osType() == OsTypeMac) { - // May be slower to start but without it we get no filenames for symbols. - cmd.addArg("--dsymutil=yes"); - } - - cmd.addCommandLineAsArgs(m_debuggee.command); - - emit q->appendMessage(cmd.toUserOutput(), NormalMessageFormat); - - process->setCommand(cmd); - process->setWorkingDirectory(m_debuggee.workingDirectory); - process->setEnvironment(m_debuggee.environment); - process->setProcessChannelMode(m_channelMode); - process->setTerminalMode(m_useTerminal ? TerminalMode::Run : TerminalMode::Off); - - connect(process, &Process::started, this, [this, process] { - emit q->valgrindStarted(process->processId()); - }); - connect(process, &Process::readyReadStandardOutput, this, [this, process] { - emit q->appendMessage(process->readAllStandardOutput(), StdOutFormat); - }); - connect(process, &Process::readyReadStandardError, this, [this, process] { - emit q->appendMessage(process->readAllStandardError(), StdErrFormat); - }); - } - Group runRecipe() const; bool run(); @@ -177,7 +144,37 @@ Group ValgrindProcessPrivate::runRecipe() const }; const auto onProcessSetup = [this, storage](Process &process) { - setupValgrindProcess(&process, storage->m_valgrindCommand); + CommandLine cmd = storage->m_valgrindCommand; + cmd.addArgs(m_valgrindCommand.arguments(), CommandLine::Raw); + + // consider appending our options last so they override any interfering user-supplied + // options -q as suggested by valgrind manual + + if (cmd.executable().osType() == OsTypeMac) { + // May be slower to start but without it we get no filenames for symbols. + cmd.addArg("--dsymutil=yes"); + } + + cmd.addCommandLineAsArgs(m_debuggee.command); + + emit q->appendMessage(cmd.toUserOutput(), NormalMessageFormat); + + process.setCommand(cmd); + process.setWorkingDirectory(m_debuggee.workingDirectory); + process.setEnvironment(m_debuggee.environment); + process.setProcessChannelMode(m_channelMode); + process.setTerminalMode(m_useTerminal ? TerminalMode::Run : TerminalMode::Off); + + Process *processPtr = &process; + connect(processPtr, &Process::started, this, [this, processPtr] { + emit q->valgrindStarted(processPtr->processId()); + }); + connect(processPtr, &Process::readyReadStandardOutput, this, [this, processPtr] { + emit q->appendMessage(processPtr->readAllStandardOutput(), StdOutFormat); + }); + connect(processPtr, &Process::readyReadStandardError, this, [this, processPtr] { + emit q->appendMessage(processPtr->readAllStandardError(), StdErrFormat); + }); }; const auto onProcessDone = [this, storage](const Process &process) { emit q->processErrorReceived(process.errorString(), process.error()); From 83e471df985f04b69c4342ed97f4644f8f9e6837 Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Wed, 2 Oct 2024 15:59:04 +0200 Subject: [PATCH 07/76] Valgrind: Fix live data delivery for Memory Analyzer Before, the parser was started after the analyzed process has already finished. Start the parser now in parallel with the analyzed process. Change-Id: I13c133f8322767525ac50be3efc86eed80165164 Reviewed-by: hjk --- src/plugins/valgrind/valgrindprocess.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/valgrind/valgrindprocess.cpp b/src/plugins/valgrind/valgrindprocess.cpp index afb8cc81ca9..23c84f4b487 100644 --- a/src/plugins/valgrind/valgrindprocess.cpp +++ b/src/plugins/valgrind/valgrindprocess.cpp @@ -193,10 +193,10 @@ Group ValgrindProcessPrivate::runRecipe() const }; const Group root { - parallel, storage, xmlBarrier, If (isSetupValid) >> Then { + parallel, ProcessTask(onProcessSetup, onProcessDone, CallDoneIf::Error), If (isAddressValid) >> Then { waitForBarrierTask(xmlBarrier), From 5954f9ba1651b3f99e817cd4fce3e32286e901ce Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Fri, 4 Oct 2024 09:13:16 +0200 Subject: [PATCH 08/76] Valgrind: Devirtualize some methods There are no subclasses of DataModel and CallModel, so no need to have virtual methods. Change-Id: Ibce461bba2e80e491844aaaf1593efdcf03f3a9e Reviewed-by: hjk --- src/plugins/valgrind/callgrind/callgrindcallmodel.h | 8 ++++---- src/plugins/valgrind/callgrind/callgrinddatamodel.h | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/plugins/valgrind/callgrind/callgrindcallmodel.h b/src/plugins/valgrind/callgrind/callgrindcallmodel.h index 4b8e6f631e4..22db3ec1596 100644 --- a/src/plugins/valgrind/callgrind/callgrindcallmodel.h +++ b/src/plugins/valgrind/callgrind/callgrindcallmodel.h @@ -26,11 +26,11 @@ public: /// Only one cost event column will be shown, this decides which one it is. /// By default it is the first event in the @c ParseData, i.e. 0. - virtual int costEvent() const; - virtual void setCostEvent(int event); + int costEvent() const; + void setCostEvent(int event); - virtual void setParseData(const ParseData *data); - virtual const ParseData *parseData() const; + void setParseData(const ParseData *data); + const ParseData *parseData() const; void setCalls(const QList &calls, const Function *function); QList calls() const; diff --git a/src/plugins/valgrind/callgrind/callgrinddatamodel.h b/src/plugins/valgrind/callgrind/callgrinddatamodel.h index 136ea4a0d7f..a5233519fab 100644 --- a/src/plugins/valgrind/callgrind/callgrinddatamodel.h +++ b/src/plugins/valgrind/callgrind/callgrinddatamodel.h @@ -20,15 +20,15 @@ public: DataModel(); ~DataModel() override; - virtual void setParseData(const ParseData *data); - virtual const ParseData *parseData() const; + void setParseData(const ParseData *data); + const ParseData *parseData() const; void setVerboseToolTipsEnabled(bool enabled); bool verboseToolTipsEnabled() const; /// Only one cost event column will be shown, this decides which one it is. /// By default it is the first event in the @c ParseData, i.e. 0. - virtual int costEvent() const; + int costEvent() const; int rowCount(const QModelIndex &parent = QModelIndex()) const override; int columnCount(const QModelIndex &parent = QModelIndex()) const override; @@ -61,7 +61,7 @@ public: /// Only one cost event column will be shown, this decides which one it is. /// By default it is the first event in the @c ParseData, i.e. 0. - virtual void setCostEvent(int event); + void setCostEvent(int event); private: class Private; From b3cc723d298538c2b771b88b2a09b6fdbaeb35f8 Mon Sep 17 00:00:00 2001 From: Assam Boudjelthia Date: Fri, 4 Oct 2024 12:53:40 +0300 Subject: [PATCH 09/76] Android: move finished message from AndroidRunner to AndroidRunnerWorker Not calling setFinished() when the app is terminated by the user causes some issue and the app won't be able to restarted again from the run button and a new deployment is needed. So move the termination message to the worker where the "died" message is at. This amends 33022eec04a54c8ce87175d79738ea5c0abf7af0. Change-Id: Ieb02c4343d0f10d988372288715fe7fc2c85a643 Reviewed-by: Jarek Kobus --- src/plugins/android/androidrunner.cpp | 3 --- src/plugins/android/androidrunner.h | 1 - src/plugins/android/androidrunnerworker.cpp | 9 +++++---- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/plugins/android/androidrunner.cpp b/src/plugins/android/androidrunner.cpp index fa6dc5a415f..f5febfc275a 100644 --- a/src/plugins/android/androidrunner.cpp +++ b/src/plugins/android/androidrunner.cpp @@ -101,7 +101,6 @@ void AndroidRunner::start() runnerRecipe(glueStorage) }; m_taskTreeRunner.start(recipe); - m_packageName = AndroidManager::packageName(target); } void AndroidRunner::stop() @@ -110,8 +109,6 @@ void AndroidRunner::stop() return; emit canceled(); - appendMessage(Tr::tr("Android target \"%1\" terminated.").arg(m_packageName), - Utils::NormalMessageFormat); } void AndroidRunner::qmlServerPortReady(Port port) diff --git a/src/plugins/android/androidrunner.h b/src/plugins/android/androidrunner.h index 0a6d6a0fedf..7ec2babb7b0 100644 --- a/src/plugins/android/androidrunner.h +++ b/src/plugins/android/androidrunner.h @@ -46,7 +46,6 @@ private: Utils::ProcessHandle m_pid; QmlDebug::QmlOutputParser m_outputParser; Tasking::TaskTreeRunner m_taskTreeRunner; - QString m_packageName; }; } // namespace Android::Internal diff --git a/src/plugins/android/androidrunnerworker.cpp b/src/plugins/android/androidrunnerworker.cpp index abc56ea13a1..4033a86d2ce 100644 --- a/src/plugins/android/androidrunnerworker.cpp +++ b/src/plugins/android/androidrunnerworker.cpp @@ -581,10 +581,11 @@ static ExecutableItem postDoneRecipe(const Storage &storage) const auto onDone = [storage] { storage->m_processPID = -1; storage->m_processUser = -1; - if (!storage->m_glue->wasCancelled()) { - storage->m_glue->setFinished(Tr::tr("Android target \"%1\" died.") - .arg(storage->m_packageName)); - } + const QString package = storage->m_packageName; + const QString message = storage->m_glue->wasCancelled() + ? Tr::tr("Android target \"%1\" terminated.").arg(package) + : Tr::tr("Android target \"%1\" died.").arg(package); + storage->m_glue->setFinished(message); }; return Group { From 3158d8f38000d466dd89fea86622a7123b496ed5 Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Fri, 4 Oct 2024 10:08:48 +0200 Subject: [PATCH 10/76] Valgrind: Don't leak ParseData Use shared pointer for ParseData. Change-Id: Ief46feac2e7902405724b56b89c4acea5db411cd Reviewed-by: hjk --- .../valgrind/callgrind/callgrindcallmodel.cpp | 7 ++- .../valgrind/callgrind/callgrindcallmodel.h | 6 ++- .../valgrind/callgrind/callgrindcostitem.cpp | 11 ++-- .../valgrind/callgrind/callgrindcostitem.h | 2 +- .../valgrind/callgrind/callgrinddatamodel.cpp | 9 ++-- .../valgrind/callgrind/callgrinddatamodel.h | 7 +-- .../valgrind/callgrind/callgrindparsedata.cpp | 3 +- .../valgrind/callgrind/callgrindparsedata.h | 2 + .../valgrind/callgrind/callgrindparser.cpp | 24 +++------ .../valgrind/callgrind/callgrindparser.h | 4 +- .../callgrind/callgrindproxymodel.cpp | 2 +- src/plugins/valgrind/callgrindengine.cpp | 4 +- src/plugins/valgrind/callgrindengine.h | 2 +- src/plugins/valgrind/callgrindtool.cpp | 54 +++++++++---------- .../callgrind/callgrindparsertests.cpp | 25 +++++---- 15 files changed, 73 insertions(+), 89 deletions(-) diff --git a/src/plugins/valgrind/callgrind/callgrindcallmodel.cpp b/src/plugins/valgrind/callgrind/callgrindcallmodel.cpp index b341e29d5d1..c08256db2f1 100644 --- a/src/plugins/valgrind/callgrind/callgrindcallmodel.cpp +++ b/src/plugins/valgrind/callgrind/callgrindcallmodel.cpp @@ -5,7 +5,6 @@ #include "callgrindfunctioncall.h" #include "callgrindfunction.h" -#include "callgrindparsedata.h" #include "../valgrindtr.h" #include @@ -17,7 +16,7 @@ namespace Valgrind::Callgrind { class CallModel::Private { public: - const ParseData *m_data = nullptr; + ParseDataPtr m_data = nullptr; QList m_calls; int m_event = 0; const Function *m_function = nullptr; @@ -69,7 +68,7 @@ int CallModel::costEvent() const return d->m_event; } -void CallModel::setParseData(const ParseData *data) +void CallModel::setParseData(const ParseDataPtr &data) { if (d->m_data == data) return; @@ -80,7 +79,7 @@ void CallModel::setParseData(const ParseData *data) d->m_data = data; } -const ParseData *CallModel::parseData() const +ParseDataPtr CallModel::parseData() const { return d->m_data; } diff --git a/src/plugins/valgrind/callgrind/callgrindcallmodel.h b/src/plugins/valgrind/callgrind/callgrindcallmodel.h index 22db3ec1596..2bb0225ace7 100644 --- a/src/plugins/valgrind/callgrind/callgrindcallmodel.h +++ b/src/plugins/valgrind/callgrind/callgrindcallmodel.h @@ -5,6 +5,8 @@ #include "callgrindabstractmodel.h" +#include "callgrindparsedata.h" + #include namespace Valgrind::Callgrind { @@ -29,8 +31,8 @@ public: int costEvent() const; void setCostEvent(int event); - void setParseData(const ParseData *data); - const ParseData *parseData() const; + void setParseData(const ParseDataPtr &data); + ParseDataPtr parseData() const; void setCalls(const QList &calls, const Function *function); QList calls() const; diff --git a/src/plugins/valgrind/callgrind/callgrindcostitem.cpp b/src/plugins/valgrind/callgrind/callgrindcostitem.cpp index d6fa4f99013..8ae0b86190f 100644 --- a/src/plugins/valgrind/callgrind/callgrindcostitem.cpp +++ b/src/plugins/valgrind/callgrind/callgrindcostitem.cpp @@ -3,8 +3,8 @@ #include "callgrindcostitem.h" -#include "callgrindparsedata.h" #include "callgrindfunctioncall.h" +#include "callgrindparsedata.h" #include @@ -13,18 +13,18 @@ namespace Valgrind::Callgrind { class CostItem::Private { public: - Private(ParseData *data); + Private(const ParseData *data); ~Private(); QList m_positions; QList m_events; const FunctionCall *m_call = nullptr; - const ParseData *m_data = nullptr; + const ParseData *m_data; qint64 m_differingFileId = -1; }; -CostItem::Private::Private(ParseData *data) +CostItem::Private::Private(const ParseData *data) : m_positions(data->positions().size(), 0) , m_events(data->events().size(), 0) , m_data(data) @@ -36,9 +36,8 @@ CostItem::Private::~Private() delete m_call; } - //BEGIN CostItem -CostItem::CostItem(ParseData *data) +CostItem::CostItem(const ParseData *data) : d(new Private(data)) { } diff --git a/src/plugins/valgrind/callgrind/callgrindcostitem.h b/src/plugins/valgrind/callgrind/callgrindcostitem.h index 3cc54df1dab..6080d2fd52c 100644 --- a/src/plugins/valgrind/callgrind/callgrindcostitem.h +++ b/src/plugins/valgrind/callgrind/callgrindcostitem.h @@ -18,7 +18,7 @@ class CostItem public: /// @p data the file data this cost item was parsed in. /// required for decompression of string data like differing source file information - explicit CostItem(ParseData *data); + explicit CostItem(const ParseData *data); ~CostItem(); /** diff --git a/src/plugins/valgrind/callgrind/callgrinddatamodel.cpp b/src/plugins/valgrind/callgrind/callgrinddatamodel.cpp index a623a6a8c98..1122b2da28f 100644 --- a/src/plugins/valgrind/callgrind/callgrinddatamodel.cpp +++ b/src/plugins/valgrind/callgrind/callgrinddatamodel.cpp @@ -3,9 +3,8 @@ #include "callgrinddatamodel.h" -#include "callgrindparsedata.h" -#include "callgrindfunction.h" #include "callgrindcostitem.h" +#include "callgrindfunction.h" #include "../valgrindtr.h" #include @@ -21,7 +20,7 @@ class DataModel::Private public: void updateFunctions(); - const ParseData *m_data = nullptr; + ParseDataPtr m_data; int m_event = 0; bool m_verboseToolTips = true; bool m_cycleDetection = false; @@ -51,7 +50,7 @@ DataModel::~DataModel() delete d; } -void DataModel::setParseData(const ParseData *data) +void DataModel::setParseData(const ParseDataPtr &data) { if (d->m_data == data) return; @@ -73,7 +72,7 @@ bool DataModel::verboseToolTipsEnabled() const return d->m_verboseToolTips; } -const ParseData *DataModel::parseData() const +ParseDataPtr DataModel::parseData() const { return d->m_data; } diff --git a/src/plugins/valgrind/callgrind/callgrinddatamodel.h b/src/plugins/valgrind/callgrind/callgrinddatamodel.h index a5233519fab..176ed9a7394 100644 --- a/src/plugins/valgrind/callgrind/callgrinddatamodel.h +++ b/src/plugins/valgrind/callgrind/callgrinddatamodel.h @@ -5,12 +5,13 @@ #include "callgrindabstractmodel.h" +#include "callgrindparsedata.h" + #include namespace Valgrind::Callgrind { class Function; -class ParseData; class DataModel : public QAbstractItemModel { @@ -20,8 +21,8 @@ public: DataModel(); ~DataModel() override; - void setParseData(const ParseData *data); - const ParseData *parseData() const; + void setParseData(const ParseDataPtr &data); + ParseDataPtr parseData() const; void setVerboseToolTipsEnabled(bool enabled); bool verboseToolTipsEnabled() const; diff --git a/src/plugins/valgrind/callgrind/callgrindparsedata.cpp b/src/plugins/valgrind/callgrind/callgrindparsedata.cpp index d58450b9684..231e9dd32ea 100644 --- a/src/plugins/valgrind/callgrind/callgrindparsedata.cpp +++ b/src/plugins/valgrind/callgrind/callgrindparsedata.cpp @@ -116,8 +116,7 @@ void ParseData::Private::cycleDetection() ParseData::ParseData(const QString &fileName) : d(new Private(this, fileName)) -{ -} +{} ParseData::~ParseData() { diff --git a/src/plugins/valgrind/callgrind/callgrindparsedata.h b/src/plugins/valgrind/callgrind/callgrindparsedata.h index e6c7b0b8cb1..7f7e864ef47 100644 --- a/src/plugins/valgrind/callgrind/callgrindparsedata.h +++ b/src/plugins/valgrind/callgrind/callgrindparsedata.h @@ -109,4 +109,6 @@ private: Private *d; }; +using ParseDataPtr = std::shared_ptr; + } // namespace Valgrind::Callgrind diff --git a/src/plugins/valgrind/callgrind/callgrindparser.cpp b/src/plugins/valgrind/callgrind/callgrindparser.cpp index b2d4b166835..764b0104674 100644 --- a/src/plugins/valgrind/callgrind/callgrindparser.cpp +++ b/src/plugins/valgrind/callgrind/callgrindparser.cpp @@ -120,11 +120,6 @@ public: { } - ~Private() - { - delete data; - } - void parse(const FilePath &filePath); void parseHeader(QIODevice *device); @@ -145,7 +140,7 @@ public: int addressValuesCount = 0; int costValuesCount = 0; - ParseData *data = nullptr; + std::shared_ptr data; Function *currentFunction = nullptr; qint64 lastObject = -1; qint64 lastFile = -1; @@ -174,17 +169,12 @@ public: void Parser::Private::parse(const FilePath &filePath) { - // be sure to clean up existing data before re-allocating - // the callee might not have taken the parse data - delete data; - data = nullptr; - const QString path = filePath.path(); // FIXME: Works only accidentally for docker QFile file(path); if (!file.open(QIODevice::ReadOnly)) qWarning() << "Could not open file for parsing:" << filePath.toUserOutput(); - data = new ParseData(path); + data = std::make_shared(path); parseHeader(&file); while (!file.atEnd()) { const QByteArray line = file.readLine(); @@ -426,7 +416,7 @@ void Parser::Private::parseCostItem(const char *begin, const char *end) const char *current = begin; QTC_ASSERT(currentDifferingFile == -1 || currentDifferingFile != currentFunction->fileId(), return); - auto costItem = new CostItem(data); + auto costItem = new CostItem(data.get()); costItem->setDifferingFile(currentDifferingFile); FunctionCall *call = nullptr; if (isParsingFunctionCall) { @@ -530,7 +520,7 @@ void Parser::Private::parseSourceFile(const char *begin, const char *end) void Parser::Private::parseFunction(const char *begin, const char *end) { - currentFunction = new Function(data); + currentFunction = new Function(data.get()); currentFunction->setFile(lastFile); currentFunction->setObject(lastObject); @@ -634,11 +624,9 @@ Parser::~Parser() delete d; } -ParseData *Parser::takeData() +ParseDataPtr Parser::parserData() const { - ParseData *data = d->data; - d->data = nullptr; - return data; + return d->data; } } // namespace Valgrind::Callgrind diff --git a/src/plugins/valgrind/callgrind/callgrindparser.h b/src/plugins/valgrind/callgrind/callgrindparser.h index 6355a5859e8..f6211a9aae0 100644 --- a/src/plugins/valgrind/callgrind/callgrindparser.h +++ b/src/plugins/valgrind/callgrind/callgrindparser.h @@ -3,6 +3,8 @@ #pragma once +#include "callgrindparsedata.h" + #include namespace Utils { class FilePath; } @@ -30,7 +32,7 @@ public: // get and take ownership of the parsing results. If this function is not called the repository // will be destroyed when the parser is destroyed. Subsequent calls return null. - ParseData *takeData(); + ParseDataPtr parserData() const; void parse(const Utils::FilePath &filePath); signals: diff --git a/src/plugins/valgrind/callgrind/callgrindproxymodel.cpp b/src/plugins/valgrind/callgrind/callgrindproxymodel.cpp index d9bad9daefc..4dbbdf23d82 100644 --- a/src/plugins/valgrind/callgrind/callgrindproxymodel.cpp +++ b/src/plugins/valgrind/callgrind/callgrindproxymodel.cpp @@ -119,7 +119,7 @@ bool DataProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_ // check minimum inclusive costs DataModel *model = dataModel(); QTC_ASSERT(model, return false); // as always: this should never happen - const ParseData *data = model->parseData(); + const ParseDataPtr data = model->parseData(); QTC_ASSERT(data, return false); if (m_minimumInclusiveCostRatio != 0.0) { const quint64 totalCost = data->totalCost(0); diff --git a/src/plugins/valgrind/callgrindengine.cpp b/src/plugins/valgrind/callgrindengine.cpp index 8422bb01769..d0fa47853cb 100644 --- a/src/plugins/valgrind/callgrindengine.cpp +++ b/src/plugins/valgrind/callgrindengine.cpp @@ -117,9 +117,9 @@ void CallgrindToolRunner::setToggleCollectFunction(const QString &toggleCollectF m_argumentForToggleCollect = "--toggle-collect=" + toggleCollectFunction; } -Callgrind::ParseData *CallgrindToolRunner::takeParserData() +Callgrind::ParseDataPtr CallgrindToolRunner::parserData() const { - return m_parser.takeData(); + return m_parser.parserData(); } void CallgrindToolRunner::showStatusMessage(const QString &message) diff --git a/src/plugins/valgrind/callgrindengine.h b/src/plugins/valgrind/callgrindengine.h index c0e5ce2a8b6..f5720d2ba0c 100644 --- a/src/plugins/valgrind/callgrindengine.h +++ b/src/plugins/valgrind/callgrindengine.h @@ -23,7 +23,7 @@ public: void start() override; - Valgrind::Callgrind::ParseData *takeParserData(); + Callgrind::ParseDataPtr parserData() const; /// controller actions void dump() { run(Dump); } diff --git a/src/plugins/valgrind/callgrindtool.cpp b/src/plugins/valgrind/callgrindtool.cpp index 15b74a5c5f4..adbc052e070 100644 --- a/src/plugins/valgrind/callgrindtool.cpp +++ b/src/plugins/valgrind/callgrindtool.cpp @@ -95,10 +95,9 @@ public: void setupRunner(CallgrindToolRunner *runner); - void setParseData(ParseData *data); CostDelegate::CostFormat costFormat() const; - void doClear(bool clearParseData); + void doClear(); void updateEventCombo(); signals: @@ -136,10 +135,11 @@ public: void calleeFunctionSelected(const QModelIndex &index); void callerFunctionSelected(const QModelIndex &index); void visualisationFunctionSelected(const Function *function); - void showParserResults(const ParseData *data); + void showParserResults(const ParseDataPtr &data); void takeParserDataFromRunControl(CallgrindToolRunner *rc); - void takeParserData(ParseData *data); + void setParserData(const ParseDataPtr &data); + void doSetParseData(const ParseDataPtr &data); void engineFinished(); void editorOpened(IEditor *); @@ -385,7 +385,7 @@ CallgrindTool::CallgrindTool(QObject *parent) action->setToolTip(Tr::tr("Discard Data")); connect(action, &QAction::triggered, this, [this](bool) { clearTextMarks(); - doClear(true); + doClear(); }); // navigation @@ -494,10 +494,9 @@ CallgrindTool::~CallgrindTool() delete m_visualization; } -void CallgrindTool::doClear(bool clearParseData) +void CallgrindTool::doClear() { - if (clearParseData) // Crashed when done from destructor. - setParseData(nullptr); + doSetParseData({}); // clear filters if (m_filterProjectCosts) @@ -664,25 +663,20 @@ void CallgrindTool::visualisationFunctionSelected(const Function *function) selectFunction(function); } -void CallgrindTool::setParseData(ParseData *data) +void CallgrindTool::doSetParseData(const ParseDataPtr &data) { // we have new parse data, invalidate filters in the proxy model if (m_visualization) m_visualization->setFunction(nullptr); - // invalidate parse data in the data model - delete m_dataModel.parseData(); + // might happen if the user cancelled the profile run + // callgrind then sometimes produces empty callgrind.out.PID files + const ParseDataPtr newData = data && !data->events().isEmpty() ? data : ParseDataPtr(); - if (data && data->events().isEmpty()) { - // might happen if the user cancelled the profile run - // callgrind then sometimes produces empty callgrind.out.PID files - delete data; - data = nullptr; - } - m_lastFileName = data ? data->fileName() : QString(); - m_dataModel.setParseData(data); - m_calleesModel.setParseData(data); - m_callersModel.setParseData(data); + m_lastFileName = newData ? newData->fileName() : QString(); + m_dataModel.setParseData(newData); + m_calleesModel.setParseData(newData); + m_callersModel.setParseData(newData); if (m_eventCombo) updateEventCombo(); @@ -700,7 +694,7 @@ void CallgrindTool::updateEventCombo() m_eventCombo->clear(); - const ParseData *data = m_dataModel.parseData(); + const ParseDataPtr data = m_dataModel.parseData(); if (!data || data->events().isEmpty()) { m_eventCombo->hide(); return; @@ -749,7 +743,7 @@ void CallgrindTool::setupRunner(CallgrindToolRunner *toolRunner) m_dumpAction->setEnabled(true); m_loadExternalLogFile->setEnabled(false); clearTextMarks(); - doClear(true); + doClear(); } void CallgrindTool::updateRunActions() @@ -783,7 +777,7 @@ void CallgrindTool::engineFinished() m_dumpAction->setEnabled(false); m_loadExternalLogFile->setEnabled(true); - const ParseData *data = m_dataModel.parseData(); + const ParseDataPtr data = m_dataModel.parseData(); if (data) showParserResults(data); else @@ -792,7 +786,7 @@ void CallgrindTool::engineFinished() setBusyCursor(false); } -void CallgrindTool::showParserResults(const ParseData *data) +void CallgrindTool::showParserResults(const ParseDataPtr &data) { QString msg; if (data) { @@ -878,15 +872,15 @@ void CallgrindTool::loadExternalLogFile() Parser parser; parser.parse(filePath); - takeParserData(parser.takeData()); + setParserData(parser.parserData()); } void CallgrindTool::takeParserDataFromRunControl(CallgrindToolRunner *rc) { - takeParserData(rc->takeParserData()); + setParserData(rc->parserData()); } -void CallgrindTool::takeParserData(ParseData *data) +void CallgrindTool::setParserData(const ParseDataPtr &data) { showParserResults(data); @@ -895,9 +889,9 @@ void CallgrindTool::takeParserData(ParseData *data) // clear first clearTextMarks(); - doClear(true); + doClear(); + doSetParseData(data); - setParseData(data); const FilePath kcachegrindExecutable = globalSettings().kcachegrindExecutable(); const FilePath found = kcachegrindExecutable.searchInPath(); const bool kcachegrindExists = found.isExecutableFile(); diff --git a/tests/auto/valgrind/callgrind/callgrindparsertests.cpp b/tests/auto/valgrind/callgrind/callgrindparsertests.cpp index 803189e4a8a..76d5282fb66 100644 --- a/tests/auto/valgrind/callgrind/callgrindparsertests.cpp +++ b/tests/auto/valgrind/callgrind/callgrindparsertests.cpp @@ -80,17 +80,16 @@ void CallgrindParserTests::cleanup() { } -ParseData* parseDataFile(const QString &dataFile) +ParseDataPtr parseDataFile(const QString &dataFile) { Parser p; p.parse(Utils::FilePath::fromString(dataFile)); - - return p.takeData(); + return p.parserData(); } void CallgrindParserTests::testHeaderData() { - QScopedPointer data(parseDataFile(dataFile("simpleFunction.out"))); + const ParseDataPtr data(parseDataFile(dataFile("simpleFunction.out"))); QCOMPARE(data->command(), QLatin1String("ls")); QCOMPARE(data->creator(), QLatin1String("callgrind-3.6.0.SVN-Debian")); @@ -109,7 +108,7 @@ void CallgrindParserTests::testHeaderData() void CallgrindParserTests::testSimpleFunction() { - QScopedPointer data(parseDataFile(dataFile("simpleFunction.out"))); + const ParseDataPtr data(parseDataFile(dataFile("simpleFunction.out"))); QCOMPARE(data->functions().size(), 4); @@ -178,7 +177,7 @@ void CallgrindParserTests::testSimpleFunction() void CallgrindParserTests::testCallee() { - QScopedPointer data(parseDataFile(dataFile("calleeFunctions.out"))); + const ParseDataPtr data(parseDataFile(dataFile("calleeFunctions.out"))); QCOMPARE(data->functions().size(), 3); @@ -253,7 +252,7 @@ void CallgrindParserTests::testCallee() void CallgrindParserTests::testInlinedCalls() { - QScopedPointer data(parseDataFile(dataFile("inlinedFunctions.out"))); + const ParseDataPtr data(parseDataFile(dataFile("inlinedFunctions.out"))); QCOMPARE(data->functions().size(), 3); const Function *main = data->functions().first(); @@ -279,7 +278,7 @@ void CallgrindParserTests::testInlinedCalls() void CallgrindParserTests::testMultiCost() { - QScopedPointer data(parseDataFile(dataFile("multiCost.out"))); + const ParseDataPtr data(parseDataFile(dataFile("multiCost.out"))); QCOMPARE(data->functions().size(), 2); QCOMPARE(data->positions(), QStringList() << "line"); @@ -298,7 +297,7 @@ void CallgrindParserTests::testMultiCost() void CallgrindParserTests::testMultiPos() { - QScopedPointer data(parseDataFile(dataFile("multiPos.out"))); + const ParseDataPtr data(parseDataFile(dataFile("multiPos.out"))); QCOMPARE(data->functions().size(), 2); QCOMPARE(data->positions(), QStringList() << "line" << "memAddr"); @@ -316,7 +315,7 @@ void CallgrindParserTests::testMultiPos() void CallgrindParserTests::testMultiPosAndCost() { - QScopedPointer data(parseDataFile(dataFile("multiCostAndPos.out"))); + const ParseDataPtr data(parseDataFile(dataFile("multiCostAndPos.out"))); QCOMPARE(data->functions().size(), 2); QCOMPARE(data->positions(), QStringList() << "line" << "memAddr"); @@ -345,7 +344,7 @@ const Function *findFunction(const QString &needle, const QVector data(parseDataFile(dataFile("cycle.out"))); + const ParseDataPtr data(parseDataFile(dataFile("cycle.out"))); QCOMPARE(data->functions().size(), 4); const Function *main = data->functions().at(0); @@ -377,7 +376,7 @@ void CallgrindParserTests::testCycle() void CallgrindParserTests::testRecursiveCycle() { - QScopedPointer data(parseDataFile(dataFile("recursiveCycle.out"))); + const ParseDataPtr data(parseDataFile(dataFile("recursiveCycle.out"))); QCOMPARE(data->functions().size(), 5); const Function *main = findFunction(QLatin1String("main"), data->functions()); @@ -418,7 +417,7 @@ void CallgrindParserTests::testRecursiveCycle() void CallgrindParserTests::testRecursion() { - QScopedPointer data(parseDataFile(dataFile("recursion.out"))); + const ParseDataPtr data(parseDataFile(dataFile("recursion.out"))); QCOMPARE(data->functions().size(), 3); QCOMPARE(data->totalCost(0), quint64(35700972)); From 58d3fc18db6fac921150c42be68e46bda2d1a9e1 Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Fri, 4 Oct 2024 13:35:25 +0200 Subject: [PATCH 11/76] Valgrind: Dismantle Parser class Replace it with parseDataFile() function. Change-Id: I21ee1e5ffa2dba94501c7d8e258ac2c5478af633 Reviewed-by: hjk --- .../valgrind/callgrind/callgrindparser.cpp | 60 ++++++------------- .../valgrind/callgrind/callgrindparser.h | 22 +------ src/plugins/valgrind/callgrindengine.cpp | 15 +---- src/plugins/valgrind/callgrindengine.h | 5 +- src/plugins/valgrind/callgrindtool.cpp | 12 +--- .../callgrind/callgrindparsertests.cpp | 12 +--- 6 files changed, 28 insertions(+), 98 deletions(-) diff --git a/src/plugins/valgrind/callgrind/callgrindparser.cpp b/src/plugins/valgrind/callgrind/callgrindparser.cpp index 764b0104674..a9977f76cdc 100644 --- a/src/plugins/valgrind/callgrind/callgrindparser.cpp +++ b/src/plugins/valgrind/callgrind/callgrindparser.cpp @@ -110,17 +110,10 @@ static int parseNameShorthand(const char **current, const char *end) } -class Parser::Private +class ParserPrivate { - Parser *const q; public: - - explicit Private(Parser *qq) - : q(qq) - { - } - - void parse(const FilePath &filePath); + ParseDataPtr parse(const FilePath &filePath); void parseHeader(QIODevice *device); using NamePair = QPair; @@ -167,7 +160,7 @@ public: QSet recursiveFunctions; }; -void Parser::Private::parse(const FilePath &filePath) +ParseDataPtr ParserPrivate::parse(const FilePath &filePath) { const QString path = filePath.path(); // FIXME: Works only accidentally for docker QFile file(path); @@ -233,8 +226,7 @@ void Parser::Private::parse(const FilePath &filePath) // now accumulate callees for (Function *func : std::as_const(pendingFunctions)) func->finalize(); - - emit q->parserDataReady(); + return data; } inline QString getValue(const QByteArray &line, const int prefixLength) @@ -244,7 +236,7 @@ inline QString getValue(const QByteArray &line, const int prefixLength) return QString::fromLatin1(line.mid(prefixLength, line.length() - 1 - prefixLength).constData()); } -void Parser::Private::parseHeader(QIODevice *device) +void ParserPrivate::parseHeader(QIODevice *device) { QTC_ASSERT(device->isOpen(), return); QTC_ASSERT(device->isReadable(), return); @@ -301,7 +293,7 @@ void Parser::Private::parseHeader(QIODevice *device) } } -Parser::Private::NamePair Parser::Private::parseName(const char *begin, const char *end) +ParserPrivate::NamePair ParserPrivate::parseName(const char *begin, const char *end) { const char *current = begin; qint64 nameShorthand = -1; @@ -325,7 +317,7 @@ Parser::Private::NamePair Parser::Private::parseName(const char *begin, const ch * cfn means called function */ -void Parser::Private::dispatchLine(const QByteArray &line) +void ParserPrivate::dispatchLine(const QByteArray &line) { int lineEnding = line.endsWith("\r\n") ? 2 : 1; const char *const begin = line.constData(); @@ -408,7 +400,7 @@ void Parser::Private::dispatchLine(const QByteArray &line) } } -void Parser::Private::parseCostItem(const char *begin, const char *end) +void ParserPrivate::parseCostItem(const char *begin, const char *end) { QTC_ASSERT(currentFunction, return); @@ -504,7 +496,7 @@ void Parser::Private::parseCostItem(const char *begin, const char *end) currentFunction->addCostItem(costItem); } -void Parser::Private::parseSourceFile(const char *begin, const char *end) +void ParserPrivate::parseSourceFile(const char *begin, const char *end) { NamePair name = parseName(begin, end); @@ -518,7 +510,7 @@ void Parser::Private::parseSourceFile(const char *begin, const char *end) currentDifferingFile = -1; } -void Parser::Private::parseFunction(const char *begin, const char *end) +void ParserPrivate::parseFunction(const char *begin, const char *end) { currentFunction = new Function(data.get()); currentFunction->setFile(lastFile); @@ -534,7 +526,7 @@ void Parser::Private::parseFunction(const char *begin, const char *end) currentFunction->setName(name.first); } -void Parser::Private::parseDifferingSourceFile(const char *begin, const char *end) +void ParserPrivate::parseDifferingSourceFile(const char *begin, const char *end) { NamePair name = parseName(begin, end); @@ -550,7 +542,7 @@ void Parser::Private::parseDifferingSourceFile(const char *begin, const char *en currentDifferingFile = name.first; } -void Parser::Private::parseObjectFile(const char *begin, const char *end) +void ParserPrivate::parseObjectFile(const char *begin, const char *end) { NamePair name = parseName(begin, end); if (!name.second.isEmpty()) @@ -559,7 +551,7 @@ void Parser::Private::parseObjectFile(const char *begin, const char *end) lastObject = name.first; } -void Parser::Private::parseCalls(const char *begin, const char *end) +void ParserPrivate::parseCalls(const char *begin, const char *end) { const char *current = begin; bool ok; @@ -577,7 +569,7 @@ void Parser::Private::parseCalls(const char *begin, const char *end) isParsingFunctionCall = true; } -void Parser::Private::parseCalledFunction(const char *begin, const char *end) +void ParserPrivate::parseCalledFunction(const char *begin, const char *end) { NamePair name = parseName(begin, end); if (!name.second.isEmpty()) @@ -586,7 +578,7 @@ void Parser::Private::parseCalledFunction(const char *begin, const char *end) currentCallData.calledFunction = name.first; } -void Parser::Private::parseCalledSourceFile(const char *begin, const char *end) +void ParserPrivate::parseCalledSourceFile(const char *begin, const char *end) { NamePair name = parseName(begin, end); if (!name.second.isEmpty()) { @@ -598,7 +590,7 @@ void Parser::Private::parseCalledSourceFile(const char *begin, const char *end) currentCallData.calledFile = name.first; } -void Parser::Private::parseCalledObjectFile(const char *begin, const char *end) +void ParserPrivate::parseCalledObjectFile(const char *begin, const char *end) { NamePair name = parseName(begin, end); if (!name.second.isEmpty()) @@ -609,24 +601,10 @@ void Parser::Private::parseCalledObjectFile(const char *begin, const char *end) //BEGIN Parser -void Parser::parse(const Utils::FilePath &filePath) +ParseDataPtr parseDataFile(const Utils::FilePath &filePath) { - d->parse(filePath); -} - -Parser::Parser() - : d(new Private(this)) -{ -} - -Parser::~Parser() -{ - delete d; -} - -ParseDataPtr Parser::parserData() const -{ - return d->data; + ParserPrivate parser; + return parser.parse(filePath); } } // namespace Valgrind::Callgrind diff --git a/src/plugins/valgrind/callgrind/callgrindparser.h b/src/plugins/valgrind/callgrind/callgrindparser.h index f6211a9aae0..43058827047 100644 --- a/src/plugins/valgrind/callgrind/callgrindparser.h +++ b/src/plugins/valgrind/callgrind/callgrindparser.h @@ -11,8 +11,6 @@ namespace Utils { class FilePath; } namespace Valgrind::Callgrind { -class ParseData; - /** * Parser for Valgrind --tool=callgrind output * most of the format is documented at http://kcachegrind.sourceforge.net/html/CallgrindFormat.html @@ -22,25 +20,7 @@ class ParseData; * the rest is assumed to be zero." * */ -class Parser : public QObject -{ - Q_OBJECT -public: - Parser(); - ~Parser() override; - - // get and take ownership of the parsing results. If this function is not called the repository - // will be destroyed when the parser is destroyed. Subsequent calls return null. - ParseDataPtr parserData() const; - void parse(const Utils::FilePath &filePath); - -signals: - void parserDataReady(); - -private: - class Private; - Private *const d; -}; +ParseDataPtr parseDataFile(const Utils::FilePath &filePath); } // namespace Valgrind::Callgrind diff --git a/src/plugins/valgrind/callgrindengine.cpp b/src/plugins/valgrind/callgrindengine.cpp index d0fa47853cb..4d6c911df60 100644 --- a/src/plugins/valgrind/callgrindengine.cpp +++ b/src/plugins/valgrind/callgrindengine.cpp @@ -34,13 +34,7 @@ CallgrindToolRunner::CallgrindToolRunner(RunControl *runControl) connect(&m_runner, &ValgrindProcess::valgrindStarted, this, [this](qint64 pid) { m_pid = pid; }); - connect(&m_runner, &ValgrindProcess::done, this, [this] { - triggerParse(); - emit parserDataReady(this); - }); - connect(&m_parser, &Callgrind::Parser::parserDataReady, this, [this] { - emit parserDataReady(this); - }); + connect(&m_runner, &ValgrindProcess::done, this, &CallgrindToolRunner::triggerParse); m_valgrindRunnable = runControl->runnable(); @@ -117,11 +111,6 @@ void CallgrindToolRunner::setToggleCollectFunction(const QString &toggleCollectF m_argumentForToggleCollect = "--toggle-collect=" + toggleCollectFunction; } -Callgrind::ParseDataPtr CallgrindToolRunner::parserData() const -{ - return m_parser.parserData(); -} - void CallgrindToolRunner::showStatusMessage(const QString &message) { Debugger::showPermanentStatusMessage(message); @@ -253,7 +242,7 @@ void CallgrindToolRunner::triggerParse() if (!res) // failed to run callgrind return; showStatusMessage(Tr::tr("Parsing Profile Data...")); - m_parser.parse(m_hostOutputFile); + emit parserDataReady(parseDataFile(m_hostOutputFile)); }; // TODO: Store the handle and cancel on CallgrindToolRunner destructor? // TODO: Should d'tor of context object cancel the running task? diff --git a/src/plugins/valgrind/callgrindengine.h b/src/plugins/valgrind/callgrindengine.h index f5720d2ba0c..82db9bac378 100644 --- a/src/plugins/valgrind/callgrindengine.h +++ b/src/plugins/valgrind/callgrindengine.h @@ -23,8 +23,6 @@ public: void start() override; - Callgrind::ParseDataPtr parserData() const; - /// controller actions void dump() { run(Dump); } void reset() { run(ResetEventCounters); } @@ -52,7 +50,7 @@ protected: QString progressTitle() const override; signals: - void parserDataReady(CallgrindToolRunner *engine); + void parserDataReady(const Callgrind::ParseDataPtr &data); private: void showStatusMessage(const QString &message); @@ -83,7 +81,6 @@ private: Utils::FilePath m_valgrindOutputFile; // On the device that runs valgrind Utils::FilePath m_hostOutputFile; // On the device that runs creator - Callgrind::Parser m_parser; bool m_paused = false; QString m_argumentForToggleCollect; diff --git a/src/plugins/valgrind/callgrindtool.cpp b/src/plugins/valgrind/callgrindtool.cpp index adbc052e070..3d3c42832c9 100644 --- a/src/plugins/valgrind/callgrindtool.cpp +++ b/src/plugins/valgrind/callgrindtool.cpp @@ -137,7 +137,6 @@ public: void visualisationFunctionSelected(const Function *function); void showParserResults(const ParseDataPtr &data); - void takeParserDataFromRunControl(CallgrindToolRunner *rc); void setParserData(const ParseDataPtr &data); void doSetParseData(const ParseDataPtr &data); void engineFinished(); @@ -710,7 +709,7 @@ void CallgrindTool::setupRunner(CallgrindToolRunner *toolRunner) { RunControl *runControl = toolRunner->runControl(); - connect(toolRunner, &CallgrindToolRunner::parserDataReady, this, &CallgrindTool::takeParserDataFromRunControl); + connect(toolRunner, &CallgrindToolRunner::parserDataReady, this, &CallgrindTool::setParserData); connect(runControl, &RunControl::stopped, this, &CallgrindTool::engineFinished); connect(this, &CallgrindTool::dumpRequested, toolRunner, &CallgrindToolRunner::dump); @@ -870,14 +869,7 @@ void CallgrindTool::loadExternalLogFile() Debugger::showPermanentStatusMessage(Tr::tr("Parsing Profile Data...")); QCoreApplication::processEvents(); - Parser parser; - parser.parse(filePath); - setParserData(parser.parserData()); -} - -void CallgrindTool::takeParserDataFromRunControl(CallgrindToolRunner *rc) -{ - setParserData(rc->parserData()); + setParserData(parseDataFile(filePath)); } void CallgrindTool::setParserData(const ParseDataPtr &data) diff --git a/tests/auto/valgrind/callgrind/callgrindparsertests.cpp b/tests/auto/valgrind/callgrind/callgrindparsertests.cpp index 76d5282fb66..cc90f0b20ca 100644 --- a/tests/auto/valgrind/callgrind/callgrindparsertests.cpp +++ b/tests/auto/valgrind/callgrind/callgrindparsertests.cpp @@ -21,9 +21,10 @@ using namespace Valgrind::Callgrind; namespace { -static QString dataFile(const char *file) +static Utils::FilePath dataFile(const char *file) { - return QLatin1String(PARSERTESTS_DATA_DIR) + QLatin1String("/") + QLatin1String(file); + return Utils::FilePath::fromString( + QLatin1String(PARSERTESTS_DATA_DIR) + QLatin1String("/") + QLatin1String(file)); } void testCostItem(const CostItem *item, quint64 expectedPosition, quint64 expectedCost) @@ -80,13 +81,6 @@ void CallgrindParserTests::cleanup() { } -ParseDataPtr parseDataFile(const QString &dataFile) -{ - Parser p; - p.parse(Utils::FilePath::fromString(dataFile)); - return p.parserData(); -} - void CallgrindParserTests::testHeaderData() { const ParseDataPtr data(parseDataFile(dataFile("simpleFunction.out"))); From 2f0b7996d23d984e7f240a1becf4182c126328e3 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Fri, 4 Oct 2024 14:06:15 +0200 Subject: [PATCH 12/76] ProjectExplorer: Use the same name for all "none" entries ... in the kit aspects. Task-number: QTCREATORBUG-31574 Change-Id: If6a7238be7e3297cfa796a5901fe2d4be295d543 Reviewed-by: hjk --- src/plugins/projectexplorer/toolchainkitaspect.cpp | 2 +- src/plugins/projectexplorer/toolchainoptionspage.cpp | 2 +- src/plugins/qtsupport/qtoptionspage.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/plugins/projectexplorer/toolchainkitaspect.cpp b/src/plugins/projectexplorer/toolchainkitaspect.cpp index 178eaa000eb..631a1cbccdd 100644 --- a/src/plugins/projectexplorer/toolchainkitaspect.cpp +++ b/src/plugins/projectexplorer/toolchainkitaspect.cpp @@ -39,7 +39,7 @@ public: QModelIndex indexForBundleId(Id bundleId) const { if (!bundleId.isValid()) - return index(rowCount() - 1, 0); // The "no compiler" item always comes last + return index(rowCount() - 1, 0); // The "none" item always comes last const TreeItem *const item = findItemAtLevel<1>( [bundleId](TreeItem *item) { const auto tcItem = static_cast(item); diff --git a/src/plugins/projectexplorer/toolchainoptionspage.cpp b/src/plugins/projectexplorer/toolchainoptionspage.cpp index 4c3a29177bf..1d017f0efbd 100644 --- a/src/plugins/projectexplorer/toolchainoptionspage.cpp +++ b/src/plugins/projectexplorer/toolchainoptionspage.cpp @@ -51,7 +51,7 @@ QVariant ToolchainTreeItem::data(int column, int role) const switch (role) { case Qt::DisplayRole: if (column == 0) - return bundle ? bundle->displayName() : Tr::tr(""); + return bundle ? bundle->displayName() : Tr::tr("None"); return bundle->typeDisplayName(); case Qt::ToolTipRole: { if (!bundle) diff --git a/src/plugins/qtsupport/qtoptionspage.cpp b/src/plugins/qtsupport/qtoptionspage.cpp index 5ba6ff5c67a..95b8d19a9c7 100644 --- a/src/plugins/qtsupport/qtoptionspage.cpp +++ b/src/plugins/qtsupport/qtoptionspage.cpp @@ -166,7 +166,7 @@ QVariant QtVersionItem::data(int column, int role) const if (!version) { if (role == Qt::DisplayRole && column == 0) - return Tr::tr("No Qt"); + return Tr::tr("None"); if (role == IdRole) return -1; return TreeItem::data(column, role); From 87e0d5d46a697a9b737409a2d21438d88493e48b Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Fri, 4 Oct 2024 14:24:03 +0200 Subject: [PATCH 13/76] ProjectExplorer: Simplify some kit aspect models Change-Id: Ic494056102613f7a534b8da78540d4c951410cbe Reviewed-by: hjk --- src/plugins/debugger/debuggerkitaspect.cpp | 21 ++----------------- .../projectexplorer/toolchainkitaspect.cpp | 20 +----------------- src/plugins/qtsupport/qtkitaspect.cpp | 18 ++-------------- 3 files changed, 5 insertions(+), 54 deletions(-) diff --git a/src/plugins/debugger/debuggerkitaspect.cpp b/src/plugins/debugger/debuggerkitaspect.cpp index e70ab1430cd..5597e8fc204 100644 --- a/src/plugins/debugger/debuggerkitaspect.cpp +++ b/src/plugins/debugger/debuggerkitaspect.cpp @@ -43,18 +43,6 @@ public: , m_kit(kit) {} - QModelIndex indexForId(const QVariant &id) const - { - // The "None" item always comes last - const auto noneIndex = [this] { return index(rowCount() - 1, 0); }; - - if (id.isNull()) - return noneIndex(); - const TreeItem *const item = findItemAtLevel<1>( - [id](TreeItem *item) { return item->data(0, DebuggerTreeItem::IdRole) == id; }); - return item ? indexForItem(item) : noneIndex(); - } - void reset() { clear(); @@ -83,12 +71,6 @@ class DebuggerItemSortModel : public SortModel public: DebuggerItemSortModel(QObject *parent) : SortModel(parent) {} - QModelIndex indexForId(const QVariant &id) const - { - return mapFromSource( - static_cast(sourceModel())->indexForId(id)); - } - void reset() { static_cast(sourceModel())->reset(); } private: @@ -177,7 +159,8 @@ private: sortModel->reset(); sortModel->sort(0); const DebuggerItem * const item = DebuggerKitAspect::debugger(m_kit); - m_comboBox->setCurrentIndex(sortModel->indexForId(item ? item->id() : QVariant()).row()); + m_comboBox->setCurrentIndex( + m_comboBox->findData(item ? item->id() : QVariant(), DebuggerTreeItem::IdRole)); } QVariant currentId() const diff --git a/src/plugins/projectexplorer/toolchainkitaspect.cpp b/src/plugins/projectexplorer/toolchainkitaspect.cpp index 631a1cbccdd..aaac794c4d8 100644 --- a/src/plugins/projectexplorer/toolchainkitaspect.cpp +++ b/src/plugins/projectexplorer/toolchainkitaspect.cpp @@ -36,18 +36,6 @@ public: reset(); } - QModelIndex indexForBundleId(Id bundleId) const - { - if (!bundleId.isValid()) - return index(rowCount() - 1, 0); // The "none" item always comes last - const TreeItem *const item = findItemAtLevel<1>( - [bundleId](TreeItem *item) { - const auto tcItem = static_cast(item); - return tcItem->bundle && tcItem->bundle->bundleId() == bundleId; - }); - return item ? indexForItem(item) : QModelIndex(); - } - void reset() { clear(); @@ -77,12 +65,6 @@ class ToolchainSortModel : public SortModel public: ToolchainSortModel(QObject *parent) : SortModel(parent) {} - QModelIndex indexForBundleId(Id bundleId) const - { - return mapFromSource( - static_cast(sourceModel())->indexForBundleId(bundleId)); - } - void reset() { static_cast(sourceModel())->reset(); } private: @@ -222,7 +204,7 @@ private: int indexOf(QComboBox *cb, Id bundleId) { - return static_cast(cb->model())->indexForBundleId(bundleId).row(); + return cb->findData(bundleId.toSetting(), ToolchainTreeItem::BundleIdRole); } QWidget *m_mainWidget = nullptr; diff --git a/src/plugins/qtsupport/qtkitaspect.cpp b/src/plugins/qtsupport/qtkitaspect.cpp index 09bf54015a3..6910a87bbbe 100644 --- a/src/plugins/qtsupport/qtkitaspect.cpp +++ b/src/plugins/qtsupport/qtkitaspect.cpp @@ -39,15 +39,6 @@ public: , m_kit(kit) {} - QModelIndex indexForQtId(int id) const - { - if (id == -1) - return index(rowCount() - 1, 0); // The "No Qt" item always comes last - const TreeItem *const item = findItemAtLevel<1>( - [id](TreeItem *item) { return static_cast(item)->uniqueId() == id; }); - return item ? indexForItem(item) : QModelIndex(); - } - void reset() { clear(); @@ -71,12 +62,6 @@ class QtVersionSortModel : public SortModel public: QtVersionSortModel(QObject *parent) : SortModel(parent) {} - QModelIndex indexForId(int id) const - { - return mapFromSource( - static_cast(sourceModel())->indexForQtId(id)); - } - void reset() { static_cast(sourceModel())->reset(); } private: @@ -154,7 +139,8 @@ private: const auto sortModel = static_cast(m_combo->model()); sortModel->reset(); sortModel->sort(0); - m_combo->setCurrentIndex(sortModel->indexForId(QtKitAspect::qtVersionId(m_kit)).row()); + m_combo->setCurrentIndex( + m_combo->findData(QtKitAspect::qtVersionId(m_kit), QtVersionItem::IdRole)); } private: From b16567a659602dae67e9ae56244cc2fe64e4c1f7 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Fri, 4 Oct 2024 15:38:38 +0200 Subject: [PATCH 14/76] ProjectExplorer: Add KitAspect convenience .. for data to be displayed in a QComboBox. Make use of it for Qt versions, debuggers and CMake tools. Change-Id: I255f86c97fe30b43c1284842e7f9e5052d098946 Reviewed-by: hjk --- .../cmakeprojectmanager/cmakekitaspect.cpp | 71 ++++-------------- src/plugins/debugger/debuggerkitaspect.cpp | 67 ++++------------- src/plugins/projectexplorer/kitmanager.cpp | 45 ++++++++++++ src/plugins/projectexplorer/kitmanager.h | 45 +++++++++++- src/plugins/qtsupport/qtkitaspect.cpp | 72 ++++--------------- 5 files changed, 130 insertions(+), 170 deletions(-) diff --git a/src/plugins/cmakeprojectmanager/cmakekitaspect.cpp b/src/plugins/cmakeprojectmanager/cmakekitaspect.cpp index a827190d185..41c7580c352 100644 --- a/src/plugins/cmakeprojectmanager/cmakekitaspect.cpp +++ b/src/plugins/cmakeprojectmanager/cmakekitaspect.cpp @@ -187,72 +187,31 @@ class CMakeKitAspectImpl final : public KitAspect { public: CMakeKitAspectImpl(Kit *kit, const KitAspectFactory *factory) - : KitAspect(kit, factory), m_comboBox(createSubWidget()) + : KitAspect(kit, factory) { setManagingPage(Constants::Settings::TOOLS_ID); - m_comboBox->setSizePolicy(QSizePolicy::Ignored, m_comboBox->sizePolicy().verticalPolicy()); - m_comboBox->setToolTip(factory->description()); + const auto sortModel = new CMakeToolSortModel(this); sortModel->setSourceModel(new CMakeToolListModel(*kit, this)); - m_comboBox->setModel(sortModel); - - refresh(); - - connect(m_comboBox, &QComboBox::currentIndexChanged, - this, &CMakeKitAspectImpl::currentCMakeToolChanged); + auto getter = [](const Kit &k) { return CMakeKitAspect::cmakeToolId(&k).toSetting(); }; + auto setter = [](Kit &k, const QVariant &id) { + CMakeKitAspect::setCMakeTool(&k, Id::fromSetting(id)); + }; + auto resetModel = [](QAbstractItemModel &model) { + static_cast(model).reset(); + }; + setListAspectSpec( + {sortModel, + std::move(getter), + std::move(setter), + std::move(resetModel), + CMakeToolTreeItem::IdRole}); CMakeToolManager *cmakeMgr = CMakeToolManager::instance(); connect(cmakeMgr, &CMakeToolManager::cmakeAdded, this, &CMakeKitAspectImpl::refresh); connect(cmakeMgr, &CMakeToolManager::cmakeRemoved, this, &CMakeKitAspectImpl::refresh); connect(cmakeMgr, &CMakeToolManager::cmakeUpdated, this, &CMakeKitAspectImpl::refresh); } - - ~CMakeKitAspectImpl() override - { - delete m_comboBox; - } - -private: - // KitAspectWidget interface - void makeReadOnly() override { m_comboBox->setEnabled(false); } - - void addToInnerLayout(Layouting::Layout &builder) override - { - addMutableAction(m_comboBox); - builder.addItem(m_comboBox); - } - - void refresh() override - { - const GuardLocker locker(m_ignoreChanges); - - const auto sortModel = static_cast(m_comboBox->model()); - sortModel->reset(); - sortModel->sort(0); - m_comboBox->setCurrentIndex(indexOf(CMakeKitAspect::cmakeToolId(m_kit))); - } - - int indexOf(Id id) - { - for (int i = 0; i < m_comboBox->count(); ++i) { - if (id == Id::fromSetting(m_comboBox->itemData(i, CMakeToolTreeItem::IdRole))) - return i; - } - - return m_comboBox->count() - 1; - } - - void currentCMakeToolChanged(int index) - { - if (m_ignoreChanges.isLocked()) - return; - - const Id id = Id::fromSetting(m_comboBox->itemData(index, CMakeToolTreeItem::IdRole)); - CMakeKitAspect::setCMakeTool(m_kit, id); - } - - Guard m_ignoreChanges; - QComboBox *m_comboBox; }; CMakeKitAspectFactory::CMakeKitAspectFactory() diff --git a/src/plugins/debugger/debuggerkitaspect.cpp b/src/plugins/debugger/debuggerkitaspect.cpp index 5597e8fc204..dc21b046062 100644 --- a/src/plugins/debugger/debuggerkitaspect.cpp +++ b/src/plugins/debugger/debuggerkitaspect.cpp @@ -20,8 +20,6 @@ #include #include -#include - #include using namespace ProjectExplorer; @@ -117,59 +115,24 @@ public: { setManagingPage(ProjectExplorer::Constants::DEBUGGER_SETTINGS_PAGE_ID); - m_comboBox = createSubWidget(); - m_comboBox->setSizePolicy(QSizePolicy::Ignored, m_comboBox->sizePolicy().verticalPolicy()); - m_comboBox->setEnabled(true); const auto sortModel = new DebuggerItemSortModel(this); sortModel->setSourceModel(new DebuggerItemListModel(*workingCopy, this)); - m_comboBox->setModel(sortModel); - - refresh(); - m_comboBox->setToolTip(factory->description()); - connect(m_comboBox, &QComboBox::currentIndexChanged, this, [this] { - if (m_ignoreChanges.isLocked()) - return; - m_kit->setValue(DebuggerKitAspect::id(), currentId()); - }); - + auto getter = [](const Kit &k) { + if (const DebuggerItem * const item = DebuggerKitAspect::debugger(&k)) + return item->id(); + return QVariant(); + }; + auto setter = [](Kit &k, const QVariant &id) { k.setValue(DebuggerKitAspect::id(), id); }; + auto resetModel = [](QAbstractItemModel &model) { + static_cast(model).reset(); + }; + setListAspectSpec( + {sortModel, + std::move(getter), + std::move(setter), + std::move(resetModel), + DebuggerTreeItem::IdRole}); } - - ~DebuggerKitAspectImpl() override - { - delete m_comboBox; - } - -private: - void addToInnerLayout(Layouting::Layout &parent) override - { - addMutableAction(m_comboBox); - parent.addItem(m_comboBox); - } - - void makeReadOnly() override - { - KitAspect::makeReadOnly(); - m_comboBox->setEnabled(false); - } - - void refresh() override - { - const GuardLocker locker(m_ignoreChanges); - const auto sortModel = static_cast(m_comboBox->model()); - sortModel->reset(); - sortModel->sort(0); - const DebuggerItem * const item = DebuggerKitAspect::debugger(m_kit); - m_comboBox->setCurrentIndex( - m_comboBox->findData(item ? item->id() : QVariant(), DebuggerTreeItem::IdRole)); - } - - QVariant currentId() const - { - return m_comboBox->itemData(m_comboBox->currentIndex(), DebuggerTreeItem::IdRole); - } - - Guard m_ignoreChanges; - QComboBox *m_comboBox; }; } // namespace Internal diff --git a/src/plugins/projectexplorer/kitmanager.cpp b/src/plugins/projectexplorer/kitmanager.cpp index d6544c130c3..89680adeed5 100644 --- a/src/plugins/projectexplorer/kitmanager.cpp +++ b/src/plugins/projectexplorer/kitmanager.cpp @@ -29,7 +29,9 @@ #include +#include #include +#include #include #include #include @@ -767,6 +769,17 @@ KitAspect::~KitAspect() delete m_mutableAction; } +void KitAspect::refresh() +{ + if (!m_listAspectSpec) + return; + const GuardLocker locker(m_ignoreChanges); + m_listAspectSpec->resetModel(*m_listAspectSpec->model); + m_listAspectSpec->model->sort(0); + const QVariant itemId = m_listAspectSpec->getter(*kit()); + m_comboBox->setCurrentIndex(m_comboBox->findData(itemId, m_listAspectSpec->itemRole)); +} + void KitAspect::makeStickySubWidgetsReadOnly() { if (!m_kit->isSticky(m_factory->id())) @@ -778,6 +791,38 @@ void KitAspect::makeStickySubWidgetsReadOnly() makeReadOnly(); } +void KitAspect::makeReadOnly() +{ + if (m_comboBox) + m_comboBox->setEnabled(false); +} + +void KitAspect::addToInnerLayout(Layouting::Layout &parentItem) +{ + if (m_comboBox) { + addMutableAction(m_comboBox); + parentItem.addItem(m_comboBox); + } +} + +void KitAspect::setListAspectSpec(ListAspectSpec &&listAspectSpec) +{ + m_listAspectSpec = std::move(listAspectSpec); + + m_comboBox = createSubWidget(); + m_comboBox->setSizePolicy(QSizePolicy::Ignored, m_comboBox->sizePolicy().verticalPolicy()); + m_comboBox->setEnabled(true); + m_comboBox->setModel(m_listAspectSpec->model); + m_comboBox->setToolTip(factory()->description()); // FIXME: We want the tooltip for the current item + refresh(); + connect(m_comboBox, &QComboBox::currentIndexChanged, this, [this] { + if (m_ignoreChanges.isLocked()) + return; + m_listAspectSpec->setter( + *kit(), m_comboBox->itemData(m_comboBox->currentIndex(), m_listAspectSpec->itemRole)); + }); +} + void KitAspect::addToLayoutImpl(Layouting::Layout &layout) { auto label = createSubWidget(m_factory->displayName() + ':'); diff --git a/src/plugins/projectexplorer/kitmanager.h b/src/plugins/projectexplorer/kitmanager.h index e04b6755c83..2fae12fd836 100644 --- a/src/plugins/projectexplorer/kitmanager.h +++ b/src/plugins/projectexplorer/kitmanager.h @@ -10,6 +10,7 @@ #include #include +#include #include #include @@ -17,6 +18,11 @@ #include +QT_BEGIN_NAMESPACE +class QAbstractItemModel; +class QComboBox; +QT_END_NAMESPACE + namespace Utils { class Environment; class FilePath; @@ -108,7 +114,7 @@ public: KitAspect(Kit *kit, const KitAspectFactory *factory); ~KitAspect(); - virtual void refresh() = 0; + virtual void refresh(); void addToLayoutImpl(Layouting::Layout &layout) override; static QString msgManage(); @@ -122,15 +128,48 @@ public: void makeStickySubWidgetsReadOnly(); protected: - virtual void makeReadOnly() {} - virtual void addToInnerLayout(Layouting::Layout &parentItem) = 0; + virtual void makeReadOnly(); + virtual void addToInnerLayout(Layouting::Layout &parentItem); virtual Utils::Id settingsPageItemToPreselect() const { return {}; } + // Convenience for aspects that provide a list model from which one value can be chosen. + // It will be exposed via a QComboBox. + class ListAspectSpec + { + public: + using Getter = std::function; + using Setter = std::function; + using ResetModel = std::function; + + ListAspectSpec( + QAbstractItemModel *model, + Getter &&getter, + Setter &&setter, + ResetModel &&resetModel, + int itemRole) + : model(model) + , getter(std::move(getter)) + , setter(std::move(setter)) + , resetModel(std::move(resetModel)) + , itemRole(itemRole) + {} + + QAbstractItemModel *model; + Getter getter; + Setter setter; + ResetModel resetModel; + int itemRole; + }; + void setListAspectSpec(ListAspectSpec &&listAspectSpec); + Kit *m_kit; const KitAspectFactory *m_factory; QAction *m_mutableAction = nullptr; Utils::Id m_managingPageId; QPushButton *m_manageButton = nullptr; + QComboBox *m_comboBox = nullptr; + std::optional m_listAspectSpec; + Utils::Guard m_ignoreChanges; }; class PROJECTEXPLORER_EXPORT KitManager final : public QObject diff --git a/src/plugins/qtsupport/qtkitaspect.cpp b/src/plugins/qtsupport/qtkitaspect.cpp index 6910a87bbbe..344a88d3e77 100644 --- a/src/plugins/qtsupport/qtkitaspect.cpp +++ b/src/plugins/qtsupport/qtkitaspect.cpp @@ -23,8 +23,6 @@ #include #include -#include - using namespace ProjectExplorer; using namespace Utils; @@ -97,71 +95,27 @@ public: { setManagingPage(Constants::QTVERSION_SETTINGS_PAGE_ID); - m_combo = createSubWidget(); - m_combo->setSizePolicy(QSizePolicy::Ignored, m_combo->sizePolicy().verticalPolicy()); const auto sortModel = new QtVersionSortModel(this); sortModel->setSourceModel(new QtVersionListModel(*k, this)); - m_combo->setModel(sortModel); - - refresh(); - - // FIXME: We want the tooltip for the current item (also for toolchains etc). - m_combo->setToolTip(ki->description()); - - connect(m_combo, &QComboBox::currentIndexChanged, this, [this] { - if (!m_ignoreChanges.isLocked()) - currentWasChanged(m_combo->currentIndex()); - }); + auto getter = [](const Kit &k) { return QtKitAspect::qtVersionId(&k); }; + auto setter = [](Kit &k, const QVariant &versionId) { + QtKitAspect::setQtVersionId(&k, versionId.toInt()); + }; + auto resetModel = [](QAbstractItemModel &model) { + static_cast(model).reset(); + }; + setListAspectSpec( + {sortModel, + std::move(getter), + std::move(setter), + std::move(resetModel), + QtVersionItem::IdRole}); connect(KitManager::instance(), &KitManager::kitUpdated, this, [this](Kit *k) { if (k == kit()) refresh(); }); } - - ~QtKitAspectImpl() final - { - delete m_combo; - } - -private: - void makeReadOnly() final { m_combo->setEnabled(false); } - - void addToInnerLayout(Layouting::Layout &parent) override - { - addMutableAction(m_combo); - parent.addItem(m_combo); - } - - void refresh() final - { - const GuardLocker locker(m_ignoreChanges); - const auto sortModel = static_cast(m_combo->model()); - sortModel->reset(); - sortModel->sort(0); - m_combo->setCurrentIndex( - m_combo->findData(QtKitAspect::qtVersionId(m_kit), QtVersionItem::IdRole)); - } - -private: - static QString itemNameFor(const QtVersion *v) - { - QTC_ASSERT(v, return QString()); - QString name = v->displayName(); - if (!v->isValid()) - name = Tr::tr("%1 (invalid)").arg(v->displayName()); - return name; - } - - void currentWasChanged(int idx) - { - const QAbstractItemModel * const model = m_combo->model(); - const int versionId = model->data(model->index(idx, 0), QtVersionItem::IdRole).toInt(); - QtKitAspect::setQtVersionId(m_kit, versionId); - } - - Guard m_ignoreChanges; - QComboBox *m_combo; }; } // namespace Internal From 68371f55599957fcc90497038a2b4ca78b19f2ce Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Fri, 4 Oct 2024 17:00:12 +0200 Subject: [PATCH 15/76] ProjectExplorer: Show tooltip for current item in kit aspect comboboxes Change-Id: I756cf2ec7057fd5d6f287372b6c8b41b9d419666 Reviewed-by: hjk --- src/plugins/projectexplorer/kitmanager.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/plugins/projectexplorer/kitmanager.cpp b/src/plugins/projectexplorer/kitmanager.cpp index 89680adeed5..899acddae5e 100644 --- a/src/plugins/projectexplorer/kitmanager.cpp +++ b/src/plugins/projectexplorer/kitmanager.cpp @@ -813,11 +813,18 @@ void KitAspect::setListAspectSpec(ListAspectSpec &&listAspectSpec) m_comboBox->setSizePolicy(QSizePolicy::Ignored, m_comboBox->sizePolicy().verticalPolicy()); m_comboBox->setEnabled(true); m_comboBox->setModel(m_listAspectSpec->model); - m_comboBox->setToolTip(factory()->description()); // FIXME: We want the tooltip for the current item + refresh(); - connect(m_comboBox, &QComboBox::currentIndexChanged, this, [this] { + + const auto updateTooltip = [this] { + m_comboBox->setToolTip( + m_comboBox->itemData(m_comboBox->currentIndex(), Qt::ToolTipRole).toString()); + }; + updateTooltip(); + connect(m_comboBox, &QComboBox::currentIndexChanged, this, [this, updateTooltip] { if (m_ignoreChanges.isLocked()) return; + updateTooltip(); m_listAspectSpec->setter( *kit(), m_comboBox->itemData(m_comboBox->currentIndex(), m_listAspectSpec->itemRole)); }); From 1b47aaef2cb0343192ed0dbb740d2df507f8e722 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Fri, 4 Oct 2024 17:35:23 +0200 Subject: [PATCH 16/76] ProjectExplorer: Make KitAspect data members private Change-Id: Ib80f092e19a00bb0159eef13a8e4e4237a4aaed4 Reviewed-by: hjk --- .../cmakeprojectmanager/cmakekitaspect.cpp | 2 +- .../toolkitaspectwidget.cpp | 8 ++--- src/plugins/projectexplorer/kitaspects.cpp | 32 +++++++++---------- src/plugins/projectexplorer/kitmanager.h | 1 + .../projectexplorer/toolchainkitaspect.cpp | 6 ++-- src/plugins/python/pythonkitaspect.cpp | 4 +-- .../qmakeprojectmanager/qmakekitaspect.cpp | 4 +-- 7 files changed, 29 insertions(+), 28 deletions(-) diff --git a/src/plugins/cmakeprojectmanager/cmakekitaspect.cpp b/src/plugins/cmakeprojectmanager/cmakekitaspect.cpp index 41c7580c352..2b5edbe7224 100644 --- a/src/plugins/cmakeprojectmanager/cmakekitaspect.cpp +++ b/src/plugins/cmakeprojectmanager/cmakekitaspect.cpp @@ -393,7 +393,7 @@ private: void refresh() override { - CMakeTool *const tool = CMakeKitAspect::cmakeTool(m_kit); + CMakeTool *const tool = CMakeKitAspect::cmakeTool(kit()); if (tool != m_currentTool) m_currentTool = tool; diff --git a/src/plugins/mesonprojectmanager/toolkitaspectwidget.cpp b/src/plugins/mesonprojectmanager/toolkitaspectwidget.cpp index 7f28ebea5ab..bcf4bcf48f2 100644 --- a/src/plugins/mesonprojectmanager/toolkitaspectwidget.cpp +++ b/src/plugins/mesonprojectmanager/toolkitaspectwidget.cpp @@ -49,8 +49,8 @@ private: { const auto id = [this] { if (m_type == ToolType::Meson) - return MesonToolKitAspect::mesonToolId(m_kit); - return NinjaToolKitAspect::ninjaToolId(m_kit); + return MesonToolKitAspect::mesonToolId(kit()); + return NinjaToolKitAspect::ninjaToolId(kit()); }(); m_toolsComboBox->setCurrentIndex(indexOf(id)); } @@ -107,9 +107,9 @@ void MesonToolKitAspectImpl::setCurrentToolIndex(int index) return; const Id id = Id::fromSetting(m_toolsComboBox->itemData(index)); if (m_type == ToolType::Meson) - MesonToolKitAspect::setMesonTool(m_kit, id); + MesonToolKitAspect::setMesonTool(kit(), id); else - NinjaToolKitAspect::setNinjaTool(m_kit, id); + NinjaToolKitAspect::setNinjaTool(kit(), id); } int MesonToolKitAspectImpl::indexOf(const Id &id) diff --git a/src/plugins/projectexplorer/kitaspects.cpp b/src/plugins/projectexplorer/kitaspects.cpp index cef78fb2a25..0ca1a348281 100644 --- a/src/plugins/projectexplorer/kitaspects.cpp +++ b/src/plugins/projectexplorer/kitaspects.cpp @@ -71,13 +71,13 @@ private: void refresh() override { if (!m_ignoreChanges.isLocked()) - m_chooser->setFilePath(SysRootKitAspect::sysRoot(m_kit)); + m_chooser->setFilePath(SysRootKitAspect::sysRoot(kit())); } void pathWasChanged() { const GuardLocker locker(m_ignoreChanges); - SysRootKitAspect::setSysRoot(m_kit, m_chooser->filePath()); + SysRootKitAspect::setSysRoot(kit(), m_chooser->filePath()); } PathChooser *m_chooser; @@ -220,7 +220,7 @@ private: void refresh() override { - Id devType = DeviceTypeKitAspect::deviceTypeId(m_kit); + Id devType = DeviceTypeKitAspect::deviceTypeId(kit()); if (!devType.isValid()) m_comboBox->setCurrentIndex(-1); for (int i = 0; i < m_comboBox->count(); ++i) { @@ -234,7 +234,7 @@ private: void currentTypeChanged(int idx) { Id type = idx < 0 ? Id() : Id::fromSetting(m_comboBox->itemData(idx)); - DeviceTypeKitAspect::setDeviceTypeId(m_kit, type); + DeviceTypeKitAspect::setDeviceTypeId(kit(), type); } QComboBox *m_comboBox; @@ -368,12 +368,12 @@ private: void makeReadOnly() override { m_comboBox->setEnabled(false); } - Id settingsPageItemToPreselect() const override { return DeviceKitAspect::deviceId(m_kit); } + Id settingsPageItemToPreselect() const override { return DeviceKitAspect::deviceId(kit()); } void refresh() override { - m_model->setTypeFilter(DeviceTypeKitAspect::deviceTypeId(m_kit)); - m_comboBox->setCurrentIndex(m_model->indexOf(DeviceKitAspect::device(m_kit))); + m_model->setTypeFilter(DeviceTypeKitAspect::deviceTypeId(kit())); + m_comboBox->setCurrentIndex(m_model->indexOf(DeviceKitAspect::device(kit()))); } void modelAboutToReset() @@ -392,7 +392,7 @@ private: { if (m_ignoreChanges.isLocked()) return; - DeviceKitAspect::setDeviceId(m_kit, m_model->deviceId(m_comboBox->currentIndex())); + DeviceKitAspect::setDeviceId(kit(), m_model->deviceId(m_comboBox->currentIndex())); } Guard m_ignoreChanges; @@ -660,7 +660,7 @@ private: } m_model->setFilter(blackList); - m_comboBox->setCurrentIndex(m_model->indexOf(BuildDeviceKitAspect::device(m_kit))); + m_comboBox->setCurrentIndex(m_model->indexOf(BuildDeviceKitAspect::device(kit()))); } void modelAboutToReset() @@ -679,7 +679,7 @@ private: { if (m_ignoreChanges.isLocked()) return; - BuildDeviceKitAspect::setDeviceId(m_kit, m_model->deviceId(m_comboBox->currentIndex())); + BuildDeviceKitAspect::setDeviceId(kit(), m_model->deviceId(m_comboBox->currentIndex())); } Guard m_ignoreChanges; @@ -922,7 +922,7 @@ private: void editEnvironmentChanges() { - MacroExpander *expander = m_kit->macroExpander(); + MacroExpander *expander = kit()->macroExpander(); EnvironmentDialog::Polisher polisher = [expander](QWidget *w) { VariableChooser::addSupportForChildWidgets(w, expander); }; @@ -941,12 +941,12 @@ private: else if (enforcesMSVCEnglish(*changes)) m_vslangCheckbox->setChecked(true); } - EnvironmentKitAspect::setEnvironmentChanges(m_kit, *changes); + EnvironmentKitAspect::setEnvironmentChanges(kit(), *changes); } EnvironmentItems envWithoutMSVCEnglishEnforcement() const { - EnvironmentItems changes = EnvironmentKitAspect::environmentChanges(m_kit); + EnvironmentItems changes = EnvironmentKitAspect::environmentChanges(kit()); if (HostOsInfo::isWindowsHost()) changes.removeAll(forceMSVCEnglishItem()); @@ -961,15 +961,15 @@ private: m_vslangCheckbox->setToolTip(Tr::tr("Either switches MSVC to English or keeps the language and " "just forces UTF-8 output (may vary depending on the used MSVC " "compiler).")); - if (enforcesMSVCEnglish(EnvironmentKitAspect::environmentChanges(m_kit))) + if (enforcesMSVCEnglish(EnvironmentKitAspect::environmentChanges(kit()))) m_vslangCheckbox->setChecked(true); connect(m_vslangCheckbox, &QCheckBox::clicked, this, [this](bool checked) { - EnvironmentItems changes = EnvironmentKitAspect::environmentChanges(m_kit); + EnvironmentItems changes = EnvironmentKitAspect::environmentChanges(kit()); if (!checked && changes.indexOf(forceMSVCEnglishItem()) >= 0) changes.removeAll(forceMSVCEnglishItem()); if (checked && changes.indexOf(forceMSVCEnglishItem()) < 0) changes.append(forceMSVCEnglishItem()); - EnvironmentKitAspect::setEnvironmentChanges(m_kit, changes); + EnvironmentKitAspect::setEnvironmentChanges(kit(), changes); }); } diff --git a/src/plugins/projectexplorer/kitmanager.h b/src/plugins/projectexplorer/kitmanager.h index 2fae12fd836..a3aa5d8c669 100644 --- a/src/plugins/projectexplorer/kitmanager.h +++ b/src/plugins/projectexplorer/kitmanager.h @@ -162,6 +162,7 @@ protected: }; void setListAspectSpec(ListAspectSpec &&listAspectSpec); +private: Kit *m_kit; const KitAspectFactory *m_factory; QAction *m_mutableAction = nullptr; diff --git a/src/plugins/projectexplorer/toolchainkitaspect.cpp b/src/plugins/projectexplorer/toolchainkitaspect.cpp index aaac794c4d8..5cf7916094f 100644 --- a/src/plugins/projectexplorer/toolchainkitaspect.cpp +++ b/src/plugins/projectexplorer/toolchainkitaspect.cpp @@ -163,7 +163,7 @@ private: Id currentBundleId; for (const Id lang : lc) { - if (Toolchain * const currentTc = ToolchainKitAspect::toolchain(m_kit, lang)) { + if (Toolchain * const currentTc = ToolchainKitAspect::toolchain(kit(), lang)) { currentBundleId = currentTc->bundleId(); break; } @@ -196,9 +196,9 @@ private: return tc->language() == lang; }); if (tc) - ToolchainKitAspect::setToolchain(m_kit, tc); + ToolchainKitAspect::setToolchain(kit(), tc); else - ToolchainKitAspect::clearToolchain(m_kit, lang); + ToolchainKitAspect::clearToolchain(kit(), lang); } } diff --git a/src/plugins/python/pythonkitaspect.cpp b/src/plugins/python/pythonkitaspect.cpp index f4fd0a0f976..8bdc557d946 100644 --- a/src/plugins/python/pythonkitaspect.cpp +++ b/src/plugins/python/pythonkitaspect.cpp @@ -40,7 +40,7 @@ public: if (m_ignoreChanges.isLocked()) return; - PythonKitAspect::setPython(m_kit, m_comboBox->currentData().toString()); + PythonKitAspect::setPython(this->kit(), m_comboBox->currentData().toString()); }); connect(PythonSettings::instance(), &PythonSettings::interpretersChanged, @@ -62,7 +62,7 @@ public: for (const Interpreter &interpreter : PythonSettings::interpreters()) m_comboBox->addItem(interpreter.name, interpreter.id); - updateComboBox(PythonKitAspect::python(m_kit)); + updateComboBox(PythonKitAspect::python(kit())); emit changed(); // we need to emit changed here to update changes in the macro expander } diff --git a/src/plugins/qmakeprojectmanager/qmakekitaspect.cpp b/src/plugins/qmakeprojectmanager/qmakekitaspect.cpp index 896c0a35864..2f902e8f33f 100644 --- a/src/plugins/qmakeprojectmanager/qmakekitaspect.cpp +++ b/src/plugins/qmakeprojectmanager/qmakekitaspect.cpp @@ -50,13 +50,13 @@ private: void refresh() override { if (!m_ignoreChanges.isLocked()) - m_lineEdit->setText(QDir::toNativeSeparators(QmakeKitAspect::mkspec(m_kit))); + m_lineEdit->setText(QDir::toNativeSeparators(QmakeKitAspect::mkspec(kit()))); } void mkspecWasChanged(const QString &text) { const GuardLocker locker(m_ignoreChanges); - QmakeKitAspect::setMkspec(m_kit, text, QmakeKitAspect::MkspecSource::User); + QmakeKitAspect::setMkspec(kit(), text, QmakeKitAspect::MkspecSource::User); } QLineEdit *m_lineEdit = nullptr; From 293dd59c2b784c4661874964bdbb327a5d91f8a8 Mon Sep 17 00:00:00 2001 From: Andre Hartmann Date: Thu, 3 Oct 2024 12:50:49 +0200 Subject: [PATCH 17/76] Git: Add "show all branches" option to log window Seems most useful for file logs, but it can also help the keep the overview of several work branches. Change-Id: I7f794c6f7ed22351a5e0da5806fa3934cfa4bbff Reviewed-by: Orgad Shaneh --- src/plugins/git/gitclient.cpp | 5 +++++ src/plugins/git/gitsettings.cpp | 1 + src/plugins/git/gitsettings.h | 1 + 3 files changed, 7 insertions(+) diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp index 07ed22ebe52..ea60ac555a2 100644 --- a/src/plugins/git/gitclient.cpp +++ b/src/plugins/git/gitclient.cpp @@ -647,6 +647,11 @@ public: GitLogConfig(bool fileRelated, GitEditorWidget *editor) : GitBaseConfig(editor) { + QAction *allBranchesButton = + addToggleButton(QStringList{"--all"}, + Tr::tr("All"), + Tr::tr("Show log for all local branches.")); + mapSetting(allBranchesButton, &settings().allBranches); QAction *firstParentButton = addToggleButton({"-m", "--first-parent"}, Tr::tr("First Parent"), diff --git a/src/plugins/git/gitsettings.cpp b/src/plugins/git/gitsettings.cpp index daabb4dac1f..1021fbddb61 100644 --- a/src/plugins/git/gitsettings.cpp +++ b/src/plugins/git/gitsettings.cpp @@ -113,6 +113,7 @@ GitSettings::GitSettings() colorLog.setSettingsKey("ColorLog"); colorLog.setDefaultValue(true); + allBranches.setSettingsKey("AllBranches"); firstParent.setSettingsKey("FirstParent"); followRenames.setSettingsKey("FollowRenames"); diff --git a/src/plugins/git/gitsettings.h b/src/plugins/git/gitsettings.h index 97a2ab787fb..6844b8e2029 100644 --- a/src/plugins/git/gitsettings.h +++ b/src/plugins/git/gitsettings.h @@ -33,6 +33,7 @@ public: Utils::FilePathAspect repositoryBrowserCmd{this}; Utils::BoolAspect graphLog{this}; Utils::BoolAspect colorLog{this}; + Utils::BoolAspect allBranches{this}; Utils::BoolAspect firstParent{this}; Utils::BoolAspect followRenames{this}; Utils::IntegerAspect lastResetIndex{this}; From e26e58df99bfb81c615bce53d7921410aaa65930 Mon Sep 17 00:00:00 2001 From: Justyna Hudziak Date: Fri, 27 Sep 2024 14:54:24 +0200 Subject: [PATCH 18/76] Lua: Add support for permissions in FilePath class Change-Id: Ie7fde3f3efe79930ef89715ae43a520583016495 Reviewed-by: Marcus Tillmanns --- src/plugins/lua/bindings/qt.cpp | 18 ++++++++++++++++++ src/plugins/lua/bindings/utils.cpp | 10 +++++++++- src/plugins/lua/meta/qt.lua | 18 ++++++++++++++++++ src/plugins/lua/meta/utils.lua | 8 ++++++++ 4 files changed, 53 insertions(+), 1 deletion(-) diff --git a/src/plugins/lua/bindings/qt.cpp b/src/plugins/lua/bindings/qt.cpp index 733eac85a4d..fc929a84531 100644 --- a/src/plugins/lua/bindings/qt.cpp +++ b/src/plugins/lua/bindings/qt.cpp @@ -9,6 +9,7 @@ #include #include #include +#include namespace Lua::Internal { @@ -110,6 +111,23 @@ void setupQtModule() "NoSort", QDir::NoSort ) ); + + qt["QFileDevice"] = lua.create_table_with( + "Permission", lua.create_table_with( + "ReadOwner", QFileDevice::ReadOwner, + "ReadUser", QFileDevice::ReadUser, + "ReadGroup", QFileDevice::ReadGroup, + "ReadOther", QFileDevice::ReadOther, + "WriteOwner", QFileDevice::WriteOwner, + "WriteUser", QFileDevice::WriteUser, + "WriteGroup", QFileDevice::WriteGroup, + "WriteOther", QFileDevice::WriteOther, + "ExeOwner", QFileDevice::ExeOwner, + "ExeUser", QFileDevice::ExeUser, + "ExeGroup", QFileDevice::ExeGroup, + "ExeOther", QFileDevice::ExeOther + ) + ); // clang-format on return qt; diff --git a/src/plugins/lua/bindings/utils.cpp b/src/plugins/lua/bindings/utils.cpp index efd5a73a74c..be40b86c627 100644 --- a/src/plugins/lua/bindings/utils.cpp +++ b/src/plugins/lua/bindings/utils.cpp @@ -161,7 +161,15 @@ void setupUtilsModule() "resolvePath", sol::overload( [](const FilePath &p, const QString &path) { return p.resolvePath(path); }, - [](const FilePath &p, const FilePath &path) { return p.resolvePath(path); })); + [](const FilePath &p, const FilePath &path) { return p.resolvePath(path); }), + "permissions", + [](FilePath& p) { + return static_cast(p.permissions().toInt()); + }, + "setPermissions", + [](FilePath& p, QFileDevice::Permission permissions) { + p.setPermissions(static_cast(permissions)); + }); utils["FilePath"]["dirEntries_cb"] = utils["__dirEntries_cb__"]; utils["FilePath"]["dirEntries"] = wrap(utils["__dirEntries_cb__"]); diff --git a/src/plugins/lua/meta/qt.lua b/src/plugins/lua/meta/qt.lua index 6adaa261fc3..3588dcf6038 100644 --- a/src/plugins/lua/meta/qt.lua +++ b/src/plugins/lua/meta/qt.lua @@ -92,4 +92,22 @@ qt.QDirIterator = { } } +qt.QFileDevice = { + ---@enum Permission + Permission = { + ReadOwner = 0, + ReadUser = 0, + ReadGroup = 0, + ReadOther = 0, + WriteOwner = 0, + WriteUser = 0, + WriteGroup = 0, + WriteOther = 0, + ExeOwner = 0, + ExeUser = 0, + ExeGroup = 0, + ExeOther = 0, + } +} + return qt diff --git a/src/plugins/lua/meta/utils.lua b/src/plugins/lua/meta/utils.lua index adccb82525c..950561133ee 100644 --- a/src/plugins/lua/meta/utils.lua +++ b/src/plugins/lua/meta/utils.lua @@ -89,6 +89,14 @@ function utils.FilePath:completeSuffix() end ---@return boolean function utils.FilePath:isAbsolutePath() end +---Returns the complete OR-ed together combination of permissions for the file. +---@return Permission +function utils.FilePath:permissions() end + +---Sets permissions for the file. +---@param permissions Permission The complete OR-ed together combination of permissions for the file. +function utils.FilePath:setPermissions() end + ---@class CommandLine ---@field command FilePath The command to execute. ---@field arguments string[] The arguments to pass to the command. From 3de26e375259ebf241365245180538ebb9c643b0 Mon Sep 17 00:00:00 2001 From: Alessandro Portale Date: Fri, 4 Oct 2024 13:06:43 +0200 Subject: [PATCH 19/76] ExtensionManager: Color the status checkmark for loaded plugins green Fixes: QTCREATORBUG-31750 Change-Id: I806b71689f518a299366c3a65de0306078f89906 Reviewed-by: Marcus Tillmanns --- src/plugins/extensionmanager/extensionsbrowser.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/plugins/extensionmanager/extensionsbrowser.cpp b/src/plugins/extensionmanager/extensionsbrowser.cpp index 15ccea6b1ba..2d2d696210c 100644 --- a/src/plugins/extensionmanager/extensionsbrowser.cpp +++ b/src/plugins/extensionmanager/extensionsbrowser.cpp @@ -293,9 +293,12 @@ public: painter->drawText(effectiveR, itemNameTF.drawTextFlags, titleElided); } if (showState) { - static const QIcon checkmark = Icon({{":/extensionmanager/images/checkmark.png", - stateTF.themeColor}}, Icon::Tint).icon(); - checkmark.paint(painter, checkmarkR); + const FilePath checkmarkMask = ":/extensionmanager/images/checkmark.png"; + static const QIcon enabled = Icon({{checkmarkMask, Theme::Token_Accent_Muted}}, + Icon::Tint).icon(); + static const QIcon disabled = Icon({{checkmarkMask, stateTF.themeColor}}, + Icon::Tint).icon(); + (state == InstalledEnabled ? enabled : disabled).paint(painter, checkmarkR); painter->setPen(stateTF.color()); painter->setFont(stateTF.font()); painter->drawText(stateR, stateTF.drawTextFlags, stateString); From 36f1d6f66f4084415bc098e5aec5cd75d9c2bb33 Mon Sep 17 00:00:00 2001 From: Justyna Hudziak Date: Fri, 27 Sep 2024 14:54:24 +0200 Subject: [PATCH 20/76] Lua: Add supported platfroms list to Project class Change-Id: I35781b16ca9b7098418654c3bf57a72d2fbd3cf4 Reviewed-by: Marcus Tillmanns --- src/plugins/lua/bindings/project.cpp | 16 +++++++++++++++- src/plugins/lua/bindings/utils.cpp | 5 +++++ src/plugins/lua/meta/project.lua | 13 +++++++++++++ src/plugins/lua/meta/utils.lua | 3 +++ 4 files changed, 36 insertions(+), 1 deletion(-) diff --git a/src/plugins/lua/bindings/project.cpp b/src/plugins/lua/bindings/project.cpp index 8c8099c75fb..e104d5c4d66 100644 --- a/src/plugins/lua/bindings/project.cpp +++ b/src/plugins/lua/bindings/project.cpp @@ -28,11 +28,22 @@ void setupProjectModule() sol::table result = lua.create_table(); + result.new_usertype( + "Kit", + sol::no_constructor, + "supportedPlatforms", + [](Kit *kit) { + const auto set = kit->supportedPlatforms(); + return QList(set.constBegin(), set.constEnd()); + }); + result.new_usertype( "RunConfiguration", sol::no_constructor, "runnable", - sol::property(&RunConfiguration::runnable)); + sol::property(&RunConfiguration::runnable), + "kit", + sol::property(&RunConfiguration::kit)); result.new_usertype( "Project", @@ -99,6 +110,9 @@ void setupProjectModule() result["RunMode"] = lua.create_table_with( "Normal", Constants::NORMAL_RUN_MODE, "Debug", Constants::DEBUG_RUN_MODE); + result["Platforms"] = lua.create_table_with( + "Desktop", Utils::Id(Constants::DESKTOP_DEVICE_TYPE)); + return result; }); diff --git a/src/plugins/lua/bindings/utils.cpp b/src/plugins/lua/bindings/utils.cpp index be40b86c627..dcea1688070 100644 --- a/src/plugins/lua/bindings/utils.cpp +++ b/src/plugins/lua/bindings/utils.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -93,6 +94,10 @@ void setupUtilsModule() utils["pid"] = QCoreApplication::applicationPid(); + utils.new_usertype( + "Id", + sol::no_constructor); + auto hostOsInfoType = utils.new_usertype("HostOsInfo"); hostOsInfoType["isWindowsHost"] = &HostOsInfo::isWindowsHost; hostOsInfoType["isMacHost"] = &HostOsInfo::isMacHost; diff --git a/src/plugins/lua/meta/project.lua b/src/plugins/lua/meta/project.lua index 9254e7a7ef6..3c5b568d048 100644 --- a/src/plugins/lua/meta/project.lua +++ b/src/plugins/lua/meta/project.lua @@ -9,8 +9,21 @@ project.RunMode { Debug = "RunConfiguration.DebugRunMode", } +---@enum Platforms +project.Platforms { + Desktop = 0, +} + +---@class Kit +project.Kit = {} + +---Returns the list of supported platforms (device types) for this kit. +---@return [Id] The list of supported platforms (device types) for this kit. +function project.Kit:supportedPlatforms() end + ---@class RunConfiguration ---@field runnable ProcessRunData +---@field kit Kit project.RunConfiguration = {} ---@class Project diff --git a/src/plugins/lua/meta/utils.lua b/src/plugins/lua/meta/utils.lua index 950561133ee..fe0fd376689 100644 --- a/src/plugins/lua/meta/utils.lua +++ b/src/plugins/lua/meta/utils.lua @@ -18,6 +18,9 @@ function utils.waitms_cb(ms, callback) end ---@return QString Arbitrary UUID string. function utils.createUuid() end +---@class Id +utils.Id = {} + ---@class FilePath utils.FilePath = {} From 3b8426611457ced698ac5d962821583814fbfac2 Mon Sep 17 00:00:00 2001 From: Justyna Hudziak Date: Fri, 27 Sep 2024 14:54:24 +0200 Subject: [PATCH 21/76] Lua: Support custom display name in Project class Change-Id: I790dc328694c660dc79c0e0d88cb6d01c091f057 Reviewed-by: Marcus Tillmanns --- src/plugins/lua/bindings/project.cpp | 8 +++++++- src/plugins/lua/meta/project.lua | 4 +++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/plugins/lua/bindings/project.cpp b/src/plugins/lua/bindings/project.cpp index e104d5c4d66..22cc904ea50 100644 --- a/src/plugins/lua/bindings/project.cpp +++ b/src/plugins/lua/bindings/project.cpp @@ -48,6 +48,8 @@ void setupProjectModule() result.new_usertype( "Project", sol::no_constructor, + "displayName", + sol::property(&Project::displayName), "directory", sol::property(&Project::projectDirectory), "activeRunConfiguration", @@ -64,7 +66,8 @@ void setupProjectModule() }; result["runStartupProject"] = - [guard](const sol::optional &runnable) { + [guard](const sol::optional &runnable, + const sol::optional &displayName) { auto project = ProjectManager::instance()->startupProject(); if (!project) throw sol::error("No startup project"); @@ -83,6 +86,9 @@ void setupProjectModule() rc->setEnvironment(runnable->environment); } + if (displayName) + rc->setDisplayName(displayName.value()); + BuildForRunConfigStatus status = BuildManager::potentiallyBuildForRunConfig( runConfiguration); diff --git a/src/plugins/lua/meta/project.lua b/src/plugins/lua/meta/project.lua index 3c5b568d048..7a90c67c154 100644 --- a/src/plugins/lua/meta/project.lua +++ b/src/plugins/lua/meta/project.lua @@ -27,6 +27,7 @@ function project.Kit:supportedPlatforms() end project.RunConfiguration = {} ---@class Project +---@field displayName string The display name of the project. ---@field directory FilePath The directory of the project. project.Project = {} @@ -46,6 +47,7 @@ function project.canRunStartupProject(runMode) end ---Starts the active run configuration of the current startup project. It will be build first if necessary. ---@param runnable? ProcessRunData Override the run configuration with the specified runnable. -function project.runStartupProject(runnable) end +---@param displayName? string Override the run configuration display name with the provided name. +function project.runStartupProject(runnable, displayName) end return project From 1be344940733d5549e0fe89477e5dbc1ebbc179f Mon Sep 17 00:00:00 2001 From: Justyna Hudziak Date: Fri, 27 Sep 2024 14:54:24 +0200 Subject: [PATCH 22/76] Lua: Add additional bindings for Widget Type Change-Id: Iea5089e44d550223e157b2e75c827bc6077d9238 Reviewed-by: Marcus Tillmanns --- src/libs/utils/layoutbuilder.cpp | 20 ++++++++++++++++++++ src/libs/utils/layoutbuilder.h | 6 ++++++ src/plugins/lua/bindings/gui.cpp | 4 ++++ src/plugins/lua/meta/gui.lua | 2 ++ 4 files changed, 32 insertions(+) diff --git a/src/libs/utils/layoutbuilder.cpp b/src/libs/utils/layoutbuilder.cpp index 0ae96b90799..0a18c72ef79 100644 --- a/src/libs/utils/layoutbuilder.cpp +++ b/src/libs/utils/layoutbuilder.cpp @@ -740,6 +740,26 @@ void Widget::show() access(this)->show(); } +bool Widget::isVisible() const +{ + return access(this)->isVisible(); +} + +bool Widget::isEnabled() const +{ + return access(this)->isEnabled(); +} + +void Widget::setVisible(bool visible) +{ + access(this)-> setVisible(visible); +} + +void Widget::setEnabled(bool enabled) +{ + access(this)->setEnabled(enabled); +} + void Widget::setNoMargins(int) { setContentsMargins(0, 0, 0, 0); diff --git a/src/libs/utils/layoutbuilder.h b/src/libs/utils/layoutbuilder.h index cbe29b55d02..5019f2e8232 100644 --- a/src/libs/utils/layoutbuilder.h +++ b/src/libs/utils/layoutbuilder.h @@ -231,6 +231,12 @@ public: QWidget *emerge() const; void show(); + bool isVisible() const; + bool isEnabled() const; + + void setVisible(bool); + void setEnabled(bool); + void setAutoFillBackground(bool); void setLayout(const Layout &layout); void setSize(int, int); diff --git a/src/plugins/lua/bindings/gui.cpp b/src/plugins/lua/bindings/gui.cpp index ca26c77d8d5..9a5c2de6700 100644 --- a/src/plugins/lua/bindings/gui.cpp +++ b/src/plugins/lua/bindings/gui.cpp @@ -430,6 +430,10 @@ void setupGuiModule() &Widget::activateWindow, "close", &Widget::close, + "visible", + sol::property(&Widget::isVisible, &Widget::setVisible), + "enabled", + sol::property(&Widget::isEnabled, &Widget::setEnabled), sol::base_classes, sol::bases()); diff --git a/src/plugins/lua/meta/gui.lua b/src/plugins/lua/meta/gui.lua index 1d7f04c4678..9b34883f1b6 100644 --- a/src/plugins/lua/meta/gui.lua +++ b/src/plugins/lua/meta/gui.lua @@ -12,6 +12,8 @@ gui.layout = {} ---The base class of all widget classes, an empty widget itself. ---@class Widget : Object +---@field visible bool Whether the widget is visible or not. +---@field enabled bool Whether the widget is enabled or not. gui.widget = {} ---@alias LayoutChild string|BaseAspect|Layout|Widget|function From 47a0f935ba089c8d02357584e7af937b70e670a3 Mon Sep 17 00:00:00 2001 From: Justyna Hudziak Date: Fri, 27 Sep 2024 14:54:24 +0200 Subject: [PATCH 23/76] Lua: Add onFinished callback to Process class Change-Id: I98645f9d33842eb16b80e768523d63d660fe1813 Reviewed-by: Marcus Tillmanns --- src/plugins/lua/bindings/qtcprocess.cpp | 11 +++++++++++ src/plugins/lua/meta/process.lua | 1 + 2 files changed, 12 insertions(+) diff --git a/src/plugins/lua/bindings/qtcprocess.cpp b/src/plugins/lua/bindings/qtcprocess.cpp index d5a02440590..0aa6ccfa9b3 100644 --- a/src/plugins/lua/bindings/qtcprocess.cpp +++ b/src/plugins/lua/bindings/qtcprocess.cpp @@ -60,6 +60,7 @@ void setupProcessModule() const auto stdOut = parameter.get>("stdout"); const auto stdErr = parameter.get>("stderr"); const auto stdIn = parameter.get>("stdin"); + const auto onFinished = parameter.get>("onFinished"); auto p = std::make_unique(); @@ -86,6 +87,16 @@ void setupProcessModule() }); // clang-format on } + + if (onFinished) { + // clang-format off + QObject::connect(p.get(), &Process::done, + p.get(), + [p = p.get(), cb = *onFinished]() { + void_safe_call(cb); + }); + // clang-format on + } return p; }; diff --git a/src/plugins/lua/meta/process.lua b/src/plugins/lua/meta/process.lua index 017524fc7cd..21c2a7127d2 100644 --- a/src/plugins/lua/meta/process.lua +++ b/src/plugins/lua/meta/process.lua @@ -24,6 +24,7 @@ process.Process = {} ---@field stdin? string The input to write to stdin. ---@field stdout? function The callback to call when the process writes to stdout. ---@field stderr? function The callback to call when the process writes to stderr. +---@field onFinished? function () The callback to call when the process finishes. process.ProcessParameters = {} ---Creates a new process object. From c70e7d76f596e017c3391a149a480f049d452c89 Mon Sep 17 00:00:00 2001 From: Justyna Hudziak Date: Fri, 27 Sep 2024 14:54:24 +0200 Subject: [PATCH 24/76] Lua: Add access for plugin application data path Change-Id: Ib5f60818b8b2590d3a5d09a7900110956f98b4cf Reviewed-by: Marcus Tillmanns --- src/plugins/lua/luaengine.cpp | 4 +++- src/plugins/lua/meta/qtc.lua | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/plugins/lua/luaengine.cpp b/src/plugins/lua/luaengine.cpp index a13c0fd8474..f70b0d5e269 100644 --- a/src/plugins/lua/luaengine.cpp +++ b/src/plugins/lua/luaengine.cpp @@ -72,7 +72,9 @@ QObject *ScriptPluginSpec::setup( "name", sol::property([](ScriptPluginSpec &self) { return self.name; }), "pluginDirectory", - sol::property([pluginLocation]() { return pluginLocation; })); + sol::property([pluginLocation]() { return pluginLocation; }), + "appDataPath", + sol::property([appDataPath]() { return appDataPath; })); auto guardObject = std::make_unique(); auto guardObjectPtr = guardObject.get(); diff --git a/src/plugins/lua/meta/qtc.lua b/src/plugins/lua/meta/qtc.lua index f5eb17ab3e1..2db56b3394c 100644 --- a/src/plugins/lua/meta/qtc.lua +++ b/src/plugins/lua/meta/qtc.lua @@ -3,6 +3,7 @@ ---@class PluginSpec ---@field name string The name of the plugin. ---@field pluginDirectory FilePath The directory of the plugin. +---@field appDataPath FilePath The application data directory of the plugin. PluginSpec = {} ---The global qtc object defined in the Lua plugin. ---@class qtc From b788cf8ee51a63157ace5d03e7b9036f7ee04908 Mon Sep 17 00:00:00 2001 From: Justyna Hudziak Date: Fri, 27 Sep 2024 14:54:24 +0200 Subject: [PATCH 25/76] Lua: Add function to stop running configurations Change-Id: I85cb9113efeb0c7b1bdd6e12eb7cabe369458dee Reviewed-by: Marcus Tillmanns --- src/plugins/lua/bindings/project.cpp | 20 ++++++++++++++++++++ src/plugins/lua/meta/project.lua | 6 ++++++ 2 files changed, 26 insertions(+) diff --git a/src/plugins/lua/bindings/project.cpp b/src/plugins/lua/bindings/project.cpp index 22cc904ea50..e140ca92790 100644 --- a/src/plugins/lua/bindings/project.cpp +++ b/src/plugins/lua/bindings/project.cpp @@ -113,6 +113,26 @@ void setupProjectModule() } }; + result["stopRunConfigurationsByName"] = + [](const QString &displayName, const std::optional &force) -> int { + const auto runControls = ProjectExplorerPlugin::instance()->allRunControls(); + + int stoppedCount = 0; + for (const auto rc : runControls) { + if (rc && rc->displayName() == displayName) { + stoppedCount++; + + if (force.has_value() && force.value()) { + rc->forceStop(); + } else { + rc->initiateStop(); + } + } + } + + return stoppedCount; + }; + result["RunMode"] = lua.create_table_with( "Normal", Constants::NORMAL_RUN_MODE, "Debug", Constants::DEBUG_RUN_MODE); diff --git a/src/plugins/lua/meta/project.lua b/src/plugins/lua/meta/project.lua index 7a90c67c154..37f5881c447 100644 --- a/src/plugins/lua/meta/project.lua +++ b/src/plugins/lua/meta/project.lua @@ -50,4 +50,10 @@ function project.canRunStartupProject(runMode) end ---@param displayName? string Override the run configuration display name with the provided name. function project.runStartupProject(runnable, displayName) end +---Stops any configuration with display names equal to the provided name. +---@param displayName string The name for projects to stop. +---@param force? boolean Whether to close project forcefully (false assumeed if not provided). +---@return int Number of stopped configurations. +function project.stopRunConfigurationsByName(displayName, force) end + return project From b2114507da04ad9d2fc1283db2379831185f54e1 Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Mon, 7 Oct 2024 10:32:50 +0200 Subject: [PATCH 26/76] ExtensionManager: Use QPushButton::clicked, not pressed "Clicked" is "press and release", and we use that when reacting to buttons. Opening the window on "pressed" leads to the "released" event not being handled by the QPushButton, which confuses Qt on macOS and leads to an ugly gray background staying around after using it. Change-Id: Ieff15d222cdaeffd498594ca300e960421493940 Reviewed-by: Alessandro Portale --- src/plugins/extensionmanager/extensionsbrowser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/extensionmanager/extensionsbrowser.cpp b/src/plugins/extensionmanager/extensionsbrowser.cpp index 2d2d696210c..2e14aa6df19 100644 --- a/src/plugins/extensionmanager/extensionsbrowser.cpp +++ b/src/plugins/extensionmanager/extensionsbrowser.cpp @@ -590,7 +590,7 @@ ExtensionsBrowser::ExtensionsBrowser(ExtensionsModel *model, QWidget *parent) d->sortFilterProxyModel, &SortFilterProxyModel::setSortOption); connect(d->filterChooser, &OptionChooser::currentIndexChanged, d->sortFilterProxyModel, &SortFilterProxyModel::setFilterOption); - connect(settingsToolButton, &QAbstractButton::pressed, this, []() { + connect(settingsToolButton, &QAbstractButton::clicked, this, []() { ICore::showOptionsDialog(Constants::EXTENSIONMANAGER_SETTINGSPAGE_ID); }); connect(&settings(), &AspectContainer::changed, this, [this]() { From f6399637d448519b639a682f1f2d5f5a8fda5866 Mon Sep 17 00:00:00 2001 From: Alessandro Portale Date: Fri, 27 Sep 2024 16:57:38 +0200 Subject: [PATCH 27/76] ExtensionManager: Omit download numbers in the browser for now Reinstate them when they have more substance. Change-Id: I1a061adca56cdf8aa4a27dfac796605a1fe53e78 Reviewed-by: Marcus Tillmanns --- src/plugins/extensionmanager/extensionsmodel.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/plugins/extensionmanager/extensionsmodel.cpp b/src/plugins/extensionmanager/extensionsmodel.cpp index b3d63073f90..cf348b99673 100644 --- a/src/plugins/extensionmanager/extensionsmodel.cpp +++ b/src/plugins/extensionmanager/extensionsmodel.cpp @@ -150,7 +150,8 @@ QVariant ExtensionsModelPrivate::dataFromRemoteExtension(int index, int role) co case RoleName: return json.value("display_name"); case RoleDownloadCount: - return json.value("downloads"); + break; // TODO: Reinstate download numbers when they have more substance + // return json.value("downloads"); case RoleId: return json.value(EXTENSION_KEY_ID); case RoleDateUpdated: From be71ee702f3f3e6b08e0f50fa938a143d20cc27f Mon Sep 17 00:00:00 2001 From: Justyna Hudziak Date: Fri, 27 Sep 2024 14:54:24 +0200 Subject: [PATCH 28/76] Lua: Add functions for accessing standard paths Change-Id: I8ff44b5562478f8123d3807826bc8ac9d6c9799e Reviewed-by: Marcus Tillmanns --- src/plugins/lua/bindings/qt.cpp | 29 +++++++++++++++++++++++++++++ src/plugins/lua/bindings/utils.cpp | 28 ++++++++++++++++++++++++++++ src/plugins/lua/meta/qt.lua | 29 +++++++++++++++++++++++++++++ src/plugins/lua/meta/utils.lua | 15 +++++++++++++++ 4 files changed, 101 insertions(+) diff --git a/src/plugins/lua/bindings/qt.cpp b/src/plugins/lua/bindings/qt.cpp index fc929a84531..8b8cef7301a 100644 --- a/src/plugins/lua/bindings/qt.cpp +++ b/src/plugins/lua/bindings/qt.cpp @@ -10,6 +10,7 @@ #include #include #include +#include namespace Lua::Internal { @@ -128,6 +129,34 @@ void setupQtModule() "ExeOther", QFileDevice::ExeOther ) ); + + qt["QStandardPaths"] = lua.create_table_with( + "StandardLocation", lua.create_table_with( + "DesktopLocation", QStandardPaths::DesktopLocation, + "DocumentsLocation", QStandardPaths::DocumentsLocation, + "FontsLocation", QStandardPaths::FontsLocation, + "ApplicationsLocation", QStandardPaths::ApplicationsLocation, + "MusicLocation", QStandardPaths::MusicLocation, + "MoviesLocation", QStandardPaths::MoviesLocation, + "PicturesLocation", QStandardPaths::PicturesLocation, + "TempLocation", QStandardPaths::TempLocation, + "HomeLocation", QStandardPaths::HomeLocation, + "AppLocalDataLocation", QStandardPaths::AppLocalDataLocation, + "CacheLocation", QStandardPaths::CacheLocation, + "GenericDataLocation", QStandardPaths::GenericDataLocation, + "RuntimeLocation", QStandardPaths::RuntimeLocation, + "ConfigLocation", QStandardPaths::ConfigLocation, + "DownloadLocation", QStandardPaths::DownloadLocation, + "GenericCacheLocation", QStandardPaths::GenericCacheLocation, + "GenericConfigLocation", QStandardPaths::GenericConfigLocation, + "AppDataLocation", QStandardPaths::AppDataLocation, + "AppConfigLocation", QStandardPaths::AppConfigLocation, + "PublicShareLocation", QStandardPaths::PublicShareLocation, + "TemplatesLocation", QStandardPaths::TemplatesLocation, + "StateLocation", QStandardPaths::StateLocation, + "GenericStateLocation", QStandardPaths::GenericStateLocation + ) + ); // clang-format on return qt; diff --git a/src/plugins/lua/bindings/utils.cpp b/src/plugins/lua/bindings/utils.cpp index dcea1688070..0937950dcc0 100644 --- a/src/plugins/lua/bindings/utils.cpp +++ b/src/plugins/lua/bindings/utils.cpp @@ -182,6 +182,34 @@ void setupUtilsModule() utils["FilePath"]["searchInPath_cb"] = utils["__searchInPath_cb__"]; utils["FilePath"]["searchInPath"] = wrap(utils["__searchInPath_cb__"]); + utils["standardLocations"] = [](QStandardPaths::StandardLocation location) { + const auto locationsStrings = QStandardPaths::standardLocations( + static_cast(location)); + + QList locationsPaths; + std::transform(locationsStrings.constBegin(), locationsStrings.constEnd(), + std::back_inserter(locationsPaths), &FilePath::fromString); + return locationsPaths; + }; + utils["standardLocation"] = + [](QStandardPaths::StandardLocation location) -> sol::optional { + const auto paths = QStandardPaths::standardLocations( + static_cast(location)); + if (paths.isEmpty()) + return sol::nullopt; + + return FilePath::fromString(paths.first()); + }; + utils["writableLocation"] = + [](QStandardPaths::StandardLocation location) -> sol::optional { + const auto path = QStandardPaths::writableLocation( + static_cast(location)); + if (path.isEmpty()) + return sol::nullopt; + + return FilePath::fromString(path); + }; + utils.new_usertype( "CommandLine", sol::call_constructor, diff --git a/src/plugins/lua/meta/qt.lua b/src/plugins/lua/meta/qt.lua index 3588dcf6038..0c819164c46 100644 --- a/src/plugins/lua/meta/qt.lua +++ b/src/plugins/lua/meta/qt.lua @@ -110,4 +110,33 @@ qt.QFileDevice = { } } +qt.QStandardPaths = { + ---@enum StandardLocation + StandardLocation = { + DesktopLocation = 0, + DocumentsLocation = 0, + FontsLocation = 0, + ApplicationsLocation = 0, + MusicLocation = 0, + MoviesLocation = 0, + PicturesLocation = 0, + TempLocation = 0, + HomeLocation = 0, + AppLocalDataLocation = 0, + CacheLocation = 0, + GenericDataLocation = 0, + RuntimeLocation = 0, + ConfigLocation = 0, + DownloadLocation = 0, + GenericCacheLocation = 0, + GenericConfigLocation = 0, + AppDataLocation = 0, + AppConfigLocation = 0, + PublicShareLocation = 0, + TemplatesLocation = 0, + StateLocation = 0, + GenericStateLocation = 0, + } +} + return qt diff --git a/src/plugins/lua/meta/utils.lua b/src/plugins/lua/meta/utils.lua index fe0fd376689..9e526370710 100644 --- a/src/plugins/lua/meta/utils.lua +++ b/src/plugins/lua/meta/utils.lua @@ -100,6 +100,21 @@ function utils.FilePath:permissions() end ---@param permissions Permission The complete OR-ed together combination of permissions for the file. function utils.FilePath:setPermissions() end +---Returns the list of paths for the given standard location. +---@param location StandardLocation The standard location to get paths for. +---@return [FilePath] The list of paths for the given standard location. +function utils.standardLocations(location) end + +---Returns the first available paths for the given standard location. +---@param location StandardLocation The standard location to get the path for. +---@return FilePath|nil The first available paths for the given standard location or nil if no location is available. +function utils.standardLocation(location) end + +---Returns the writable paths for the given standard location. +---@param location StandardLocation The standard location to get path for. +---@return FilePath|nil The writable paths for the given standard location or nil if no writable location is available. +function utils.writableLocation(location) end + ---@class CommandLine ---@field command FilePath The command to execute. ---@field arguments string[] The arguments to pass to the command. From bb44a7b3d56408ecbd7a6270b384c270e44ca1a8 Mon Sep 17 00:00:00 2001 From: Alessandro Portale Date: Mon, 30 Sep 2024 13:22:54 +0200 Subject: [PATCH 29/76] Wizards: Fix QDS compatible Qt Quick Prototype wizard Adapt to the removal of DirectoryFontLoader.qml in the qds branch. Fixes: QTCREATORBUG-31657 Change-Id: Id282cd33667aebdd562bf028f724cdde46a98f20 Reviewed-by: Knud Dollereder --- .../wizards/projects/qtquickuiprototype/wizard.json | 5 ----- 1 file changed, 5 deletions(-) diff --git a/share/qtcreator/templates/wizards/projects/qtquickuiprototype/wizard.json b/share/qtcreator/templates/wizards/projects/qtquickuiprototype/wizard.json index 7ce0c621901..a1534182145 100644 --- a/share/qtcreator/templates/wizards/projects/qtquickuiprototype/wizard.json +++ b/share/qtcreator/templates/wizards/projects/qtquickuiprototype/wizard.json @@ -152,11 +152,6 @@ "target": "%{ProjectDirectory}/%{ImportModuleName}/Constants.qml", "condition": "%{QdsProjectStyle}" }, - { - "source": "%{QdsWizardPath}/shared-plugin/name/DirectoryFontLoader.qml.tpl", - "target": "%{ProjectDirectory}/%{ImportModuleName}/DirectoryFontLoader.qml", - "condition": "%{QdsProjectStyle}" - }, { "source": "%{QdsWizardPath}/shared-plugin/name/EventListModel.qml.tpl", "target": "%{ProjectDirectory}/%{ImportModuleName}/EventListModel.qml", From 1338c8ef6b744b347f0cdda6dfd6d5a6b06bbaf0 Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Fri, 20 Sep 2024 12:37:04 +0200 Subject: [PATCH 30/76] Android: Reuse task tree for AndroidSignalOperation Change-Id: I771be32bdc2456e04791be1d9f10bd979209b703 Reviewed-by: Alessandro Portale --- .../android/androidsignaloperation.cpp | 141 +++++++----------- src/plugins/android/androidsignaloperation.h | 32 +--- 2 files changed, 61 insertions(+), 112 deletions(-) diff --git a/src/plugins/android/androidsignaloperation.cpp b/src/plugins/android/androidsignaloperation.cpp index 0b44f3d5f60..8f0fbd2a7e6 100644 --- a/src/plugins/android/androidsignaloperation.cpp +++ b/src/plugins/android/androidsignaloperation.cpp @@ -1,99 +1,73 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 -#include "androidconfigurations.h" #include "androidsignaloperation.h" +#include "androidconfigurations.h" + #include -#include +using namespace Tasking; using namespace Utils; +using namespace std::chrono_literals; -namespace Android { -namespace Internal { +namespace Android::Internal { -AndroidSignalOperation::AndroidSignalOperation() - : m_adbPath(AndroidConfig::adbToolPath()) - , m_timeout(new QTimer(this)) -{ - m_timeout->setInterval(5000); - connect(m_timeout, &QTimer::timeout, this, &AndroidSignalOperation::handleTimeout); -} - -AndroidSignalOperation::~AndroidSignalOperation() = default; - -bool AndroidSignalOperation::handleCrashMessage() -{ - if (m_adbProcess->exitStatus() == QProcess::NormalExit) - return false; - m_errorMessage = QLatin1String(" adb process exit code: ") + QString::number(m_adbProcess->exitCode()); - const QString adbError = m_adbProcess->errorString(); - if (!adbError.isEmpty()) - m_errorMessage += QLatin1String(" adb process error: ") + adbError; - return true; -} - -void AndroidSignalOperation::adbFindRunAsFinished() -{ - QTC_ASSERT(m_state == RunAs, return); - m_timeout->stop(); - - handleCrashMessage(); - const QString runAs = QString::fromLatin1(m_adbProcess->readAllRawStandardOutput()); - m_adbProcess.release()->deleteLater(); - if (runAs.isEmpty() || !m_errorMessage.isEmpty()) { - m_errorMessage.prepend(QLatin1String("Cannot find User for process: ") - + QString::number(m_pid)); - m_state = Idle; - emit finished(m_errorMessage); - } else { - startAdbProcess(Kill, {m_adbPath, {"shell", "run-as", runAs, "kill", - QString("-%1").arg(m_signal), QString::number(m_pid)}}, - [this] { adbKillFinished(); }); - } -} - -void AndroidSignalOperation::adbKillFinished() -{ - QTC_ASSERT(m_state == Kill, return); - m_timeout->stop(); - - if (!handleCrashMessage()) - m_errorMessage = QString::fromLatin1(m_adbProcess->readAllRawStandardError()); - m_adbProcess.release()->deleteLater(); - if (!m_errorMessage.isEmpty()) - m_errorMessage.prepend(QLatin1String("Cannot kill process: ") + QString::number(m_pid)); - m_state = Idle; - emit finished(m_errorMessage); -} - -void AndroidSignalOperation::handleTimeout() -{ - m_adbProcess.reset(); - m_timeout->stop(); - m_state = Idle; - m_errorMessage = QLatin1String("adb process timed out"); - emit finished(m_errorMessage); -} +AndroidSignalOperation::AndroidSignalOperation() = default; void AndroidSignalOperation::signalOperationViaADB(qint64 pid, int signal) { - QTC_ASSERT(m_state == Idle, return); - m_pid = pid; - m_signal = signal; - startAdbProcess(RunAs, {m_adbPath, {"shell", "cat", QString("/proc/%1/cmdline").arg(m_pid)}}, - [this] { adbFindRunAsFinished(); }); -} + struct InternalStorage { + FilePath adbPath; + QString runAs = {}; + QString errorMessage = {}; + }; -void AndroidSignalOperation::startAdbProcess(State state, const Utils::CommandLine &commandLine, - FinishHandler handler) -{ - m_state = state; - m_timeout->start(); - m_adbProcess.reset(new Process); - connect(m_adbProcess.get(), &Process::done, this, handler); - m_adbProcess->setCommand(commandLine); - m_adbProcess->start(); + const Storage storage({AndroidConfig::adbToolPath()}); + + const auto onCatSetup = [storage, pid](Process &process) { + process.setCommand({storage->adbPath, {"shell", "cat", QString("/proc/%1/cmdline").arg(pid)}}); + }; + const auto onCatDone = [storage, pid](const Process &process, DoneWith result) { + if (result == DoneWith::Success) { + storage->runAs = process.stdOut(); + if (!storage->runAs.isEmpty()) + return true; + storage->errorMessage = QLatin1String("Cannot find User for process: ") + + QString::number(pid); + } else if (result == DoneWith::Error) { + storage->errorMessage = QLatin1String(" adb process exit code: ") + + QString::number(process.exitCode()); + const QString adbError = process.errorString(); + if (!adbError.isEmpty()) + storage->errorMessage += QLatin1String(" adb process error: ") + adbError; + } else { + storage->errorMessage = QLatin1String("adb process timed out"); + } + return false; + }; + + const auto onKillSetup = [storage, pid, signal](Process &process) { + process.setCommand({storage->adbPath, {"shell", "run-as", storage->runAs, "kill", + QString("-%1").arg(signal), QString::number(pid)}}); + }; + const auto onKillDone = [storage, pid](const Process &process, DoneWith result) { + if (result == DoneWith::Error) { + storage->errorMessage = QLatin1String("Cannot kill process: ") + QString::number(pid) + + process.stdErr(); + } else if (result == DoneWith::Cancel) { + storage->errorMessage = QLatin1String("adb process timed out"); + } + }; + + const auto onDone = [this, storage] { emit finished(storage->errorMessage); }; + + const Group recipe { + ProcessTask(onCatSetup, onCatDone).withTimeout(5s), + ProcessTask(onKillSetup, onKillDone).withTimeout(5s), + onGroupDone(onDone) + }; + m_taskTreeRunner.start(recipe); } void AndroidSignalOperation::killProcess(qint64 pid) @@ -114,5 +88,4 @@ void AndroidSignalOperation::interruptProcess(qint64 pid) signalOperationViaADB(pid, 2); } -} // Internal -} // Android +} // namespace Android::Internal diff --git a/src/plugins/android/androidsignaloperation.h b/src/plugins/android/androidsignaloperation.h index 53c1d61a899..6387bd77fe3 100644 --- a/src/plugins/android/androidsignaloperation.h +++ b/src/plugins/android/androidsignaloperation.h @@ -5,16 +5,13 @@ #include -#include -#include +#include -namespace Android { -namespace Internal { +namespace Android::Internal { class AndroidSignalOperation : public ProjectExplorer::DeviceProcessSignalOperation { public: - ~AndroidSignalOperation() override; void killProcess(qint64 pid) override; void killProcess(const QString &filePath) override; void interruptProcess(qint64 pid) override; @@ -23,32 +20,11 @@ protected: explicit AndroidSignalOperation(); private: - enum State { - Idle, - RunAs, - Kill - }; - - using FinishHandler = std::function; - - bool handleCrashMessage(); - void adbFindRunAsFinished(); - void adbKillFinished(); - void handleTimeout(); - void signalOperationViaADB(qint64 pid, int signal); - void startAdbProcess(State state, const Utils::CommandLine &commandLine, FinishHandler handler); - Utils::FilePath m_adbPath; - std::unique_ptr m_adbProcess; - QTimer *m_timeout; - - State m_state = Idle; - qint64 m_pid = 0; - int m_signal = 0; + Tasking::TaskTreeRunner m_taskTreeRunner; friend class AndroidDevice; }; -} // namespace Internal -} // namespace Android +} // namespace Android::Internal From 2d7d154ff4359d0af4a2790205cba6aba1107bb4 Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Wed, 25 Sep 2024 18:06:36 +0200 Subject: [PATCH 31/76] Android: Reuse ANDROID_RUNCONFIG_ID constant Change-Id: Ic5d6c31f0a6b6d725203f99554c9f32753ab7071 Reviewed-by: Alessandro Portale --- src/plugins/android/androidrunconfiguration.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/android/androidrunconfiguration.cpp b/src/plugins/android/androidrunconfiguration.cpp index 33ce4caa9ed..3b7da499440 100644 --- a/src/plugins/android/androidrunconfiguration.cpp +++ b/src/plugins/android/androidrunconfiguration.cpp @@ -100,7 +100,7 @@ class AndroidRunConfigurationFactory : public RunConfigurationFactory public: AndroidRunConfigurationFactory() { - registerRunConfiguration("Qt4ProjectManager.AndroidRunConfiguration:"); + registerRunConfiguration(Android::Constants::ANDROID_RUNCONFIG_ID); addSupportedTargetDeviceType(Android::Constants::ANDROID_DEVICE_TYPE); } }; From f14b2dd64eeb7dfbe9b8862ba97ee70180d0ea4c Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Fri, 27 Sep 2024 14:26:04 +0200 Subject: [PATCH 32/76] Android: Dismantle AndroidRunSupport Merge it with AndroidRunner. Change-Id: I8cf78abd3232539d2fbe4f6dfe64143bf4996f03 Reviewed-by: Alessandro Portale --- src/plugins/android/CMakeLists.txt | 1 - src/plugins/android/android.qbs | 2 - src/plugins/android/androidplugin.cpp | 2 +- src/plugins/android/androidruncontrol.cpp | 53 ----------------------- src/plugins/android/androidruncontrol.h | 10 ----- src/plugins/android/androidrunner.cpp | 21 +++++++++ src/plugins/android/androidrunner.h | 2 + 7 files changed, 24 insertions(+), 67 deletions(-) delete mode 100644 src/plugins/android/androidruncontrol.cpp delete mode 100644 src/plugins/android/androidruncontrol.h diff --git a/src/plugins/android/CMakeLists.txt b/src/plugins/android/CMakeLists.txt index 94a52d5148e..60b549a7f2a 100644 --- a/src/plugins/android/CMakeLists.txt +++ b/src/plugins/android/CMakeLists.txt @@ -27,7 +27,6 @@ add_qtc_plugin(Android androidqmltoolingsupport.cpp androidqmltoolingsupport.h androidqtversion.cpp androidqtversion.h androidrunconfiguration.cpp androidrunconfiguration.h - androidruncontrol.cpp androidruncontrol.h androidrunner.cpp androidrunner.h androidrunnerworker.cpp androidrunnerworker.h androidsdkdownloader.cpp androidsdkdownloader.h diff --git a/src/plugins/android/android.qbs b/src/plugins/android/android.qbs index de16bda375c..6618e7c9cfb 100644 --- a/src/plugins/android/android.qbs +++ b/src/plugins/android/android.qbs @@ -55,8 +55,6 @@ QtcPlugin { "androidqtversion.h", "androidrunconfiguration.cpp", "androidrunconfiguration.h", - "androidruncontrol.cpp", - "androidruncontrol.h", "androidrunner.cpp", "androidrunner.h", "androidrunnerworker.cpp", diff --git a/src/plugins/android/androidplugin.cpp b/src/plugins/android/androidplugin.cpp index 5f860134f8f..232a3e5f590 100644 --- a/src/plugins/android/androidplugin.cpp +++ b/src/plugins/android/androidplugin.cpp @@ -13,7 +13,7 @@ #include "androidqmltoolingsupport.h" #include "androidqtversion.h" #include "androidrunconfiguration.h" -#include "androidruncontrol.h" +#include "androidrunner.h" #include "androidsettingswidget.h" #include "androidtoolchain.h" #include "androidtr.h" diff --git a/src/plugins/android/androidruncontrol.cpp b/src/plugins/android/androidruncontrol.cpp deleted file mode 100644 index 023e14525c3..00000000000 --- a/src/plugins/android/androidruncontrol.cpp +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (C) 2016 BogDan Vatra -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#include "androidruncontrol.h" - -#include "androidconstants.h" -#include "androidglobal.h" -#include "androidrunconfiguration.h" -#include "androidrunner.h" - -#include - -#include - -using namespace ProjectExplorer; - -namespace Android::Internal { - -class AndroidRunSupport final : public AndroidRunner -{ -public: - explicit AndroidRunSupport(RunControl *runControl); - ~AndroidRunSupport() override; -}; - -AndroidRunSupport::AndroidRunSupport(RunControl *runControl) - : AndroidRunner(runControl) -{ - runControl->setIcon(Utils::Icons::RUN_SMALL_TOOLBAR); -} - -AndroidRunSupport::~AndroidRunSupport() -{ - stop(); -} - -class AndroidRunWorkerFactory final : public RunWorkerFactory -{ -public: - AndroidRunWorkerFactory() - { - setProduct(); - addSupportedRunMode(ProjectExplorer::Constants::NORMAL_RUN_MODE); - addSupportedRunConfig(Constants::ANDROID_RUNCONFIG_ID); - } -}; - -void setupAndroidRunWorker() -{ - static AndroidRunWorkerFactory theAndroidRunWorkerFactory; -} - -} // Android::Internal diff --git a/src/plugins/android/androidruncontrol.h b/src/plugins/android/androidruncontrol.h deleted file mode 100644 index 9c6fee8f251..00000000000 --- a/src/plugins/android/androidruncontrol.h +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright (C) 2016 BogDan Vatra -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#pragma once - -namespace Android::Internal { - -void setupAndroidRunWorker(); - -} // Android::Internal diff --git a/src/plugins/android/androidrunner.cpp b/src/plugins/android/androidrunner.cpp index f5febfc275a..b72ab54f477 100644 --- a/src/plugins/android/androidrunner.cpp +++ b/src/plugins/android/androidrunner.cpp @@ -5,6 +5,7 @@ #include "androidrunner.h" #include "androidavdmanager.h" +#include "androidconstants.h" #include "androiddevice.h" #include "androidmanager.h" #include "androidrunnerworker.h" @@ -12,8 +13,11 @@ #include #include + #include + #include +#include #include #include @@ -31,6 +35,7 @@ namespace Android::Internal { AndroidRunner::AndroidRunner(RunControl *runControl) : RunWorker(runControl) { + runControl->setIcon(Utils::Icons::RUN_SMALL_TOOLBAR); setId("AndroidRunner"); static const int metaTypes[] = { qRegisterMetaType>("QList"), @@ -152,4 +157,20 @@ void AndroidRunner::remoteStdErr(const QString &output) m_outputParser.processOutput(output); } +class AndroidRunWorkerFactory final : public RunWorkerFactory +{ +public: + AndroidRunWorkerFactory() + { + setProduct(); + addSupportedRunMode(ProjectExplorer::Constants::NORMAL_RUN_MODE); + addSupportedRunConfig(Constants::ANDROID_RUNCONFIG_ID); + } +}; + +void setupAndroidRunWorker() +{ + static AndroidRunWorkerFactory theAndroidRunWorkerFactory; +} + } // namespace Android::Internal diff --git a/src/plugins/android/androidrunner.h b/src/plugins/android/androidrunner.h index 7ec2babb7b0..748b3879d00 100644 --- a/src/plugins/android/androidrunner.h +++ b/src/plugins/android/androidrunner.h @@ -48,4 +48,6 @@ private: Tasking::TaskTreeRunner m_taskTreeRunner; }; +void setupAndroidRunWorker(); + } // namespace Android::Internal From 6a2f35459603cebfcdb28810f69a9d1bb326e7cb Mon Sep 17 00:00:00 2001 From: Artem Sokolovskii Date: Mon, 7 Oct 2024 09:39:13 +0200 Subject: [PATCH 33/76] SCXMLEditor: Fix uninitialized m_maxWidth Change-Id: If1988179931c8ed14d79b6ff9a6257a576c1deee Reviewed-by: Alessandro Portale --- src/plugins/scxmleditor/plugin_interface/tagtextitem.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/scxmleditor/plugin_interface/tagtextitem.h b/src/plugins/scxmleditor/plugin_interface/tagtextitem.h index 4ffcdbb9426..0c940a8126c 100644 --- a/src/plugins/scxmleditor/plugin_interface/tagtextitem.h +++ b/src/plugins/scxmleditor/plugin_interface/tagtextitem.h @@ -55,7 +55,7 @@ private: QPointF m_movePoint; QPointF m_startPos; TextItem *m_textItem; - qreal m_maxWidth; + qreal m_maxWidth = -1.0; }; } // namespace PluginInterface From 7d75b0a2a7d4423f2b35a659172393961f699b74 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Wed, 2 Oct 2024 14:00:15 +0200 Subject: [PATCH 34/76] TextEditor: Fix line annotations for multiline text Fixes: QTCREATORBUG-29951 Change-Id: Ie6bd70b46ae05bd3aaa7859bc872a8651a106ab0 Reviewed-by: David Schulz --- src/plugins/texteditor/textmark.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/texteditor/textmark.cpp b/src/plugins/texteditor/textmark.cpp index a7a7288d8ce..32fabea7fcd 100644 --- a/src/plugins/texteditor/textmark.cpp +++ b/src/plugins/texteditor/textmark.cpp @@ -177,7 +177,7 @@ TextMark::AnnotationRects TextMark::annotationRects(const QRectF &boundingRect, const qreal fadeOutOffset) const { AnnotationRects rects; - rects.text = lineAnnotation(); + rects.text = lineAnnotation().simplified(); if (rects.text.isEmpty()) return rects; rects.fadeInRect = boundingRect; From 927bd79488d6918691d5da0a1606e3d6a569a738 Mon Sep 17 00:00:00 2001 From: Alessandro Portale Date: Wed, 2 Oct 2024 19:24:15 +0200 Subject: [PATCH 35/76] ExtensionManager: Implement badge for recently published items This adds a "New" onto the upper left card corner for recently published items. For QtC 15, we mark all remote extensions as recently published. Fixes: QTCREATORBUG-31587 Change-Id: If460f33ebb76c72bb1af6935deb2db7678dcf550 Reviewed-by: Marcus Tillmanns --- .../extensionmanager/extensionsbrowser.cpp | 36 ++++++++++++++++++- .../extensionmanager/extensionsbrowser.h | 1 + .../extensionmanager/extensionsmodel.cpp | 17 +++++++-- .../extensionmanager/extensionsmodel.h | 3 +- 4 files changed, 53 insertions(+), 4 deletions(-) diff --git a/src/plugins/extensionmanager/extensionsbrowser.cpp b/src/plugins/extensionmanager/extensionsbrowser.cpp index 2e14aa6df19..91a58f62259 100644 --- a/src/plugins/extensionmanager/extensionsbrowser.cpp +++ b/src/plugins/extensionmanager/extensionsbrowser.cpp @@ -267,6 +267,10 @@ public: const QPixmap icon = itemIcon(index, SizeSmall); painter->drawPixmap(iconBgR.topLeft(), icon); } + { + const QPixmap badge = itemBadge(index, SizeSmall); + painter->drawPixmap(bgR.topLeft(), badge); + } if (isPack) { constexpr int circleSize = 18; constexpr int circleOverlap = 3; // Protrusion from lower right corner of iconRect @@ -700,6 +704,8 @@ QLabel *tfLabel(const TextFormat &tf, bool singleLine) return label; } +const int iconRectRounding = 4; + QPixmap itemIcon(const QModelIndex &index, Size size) { const QSize iconBgS = size == SizeSmall ? iconBgSizeSmall : iconBgSizeBig; @@ -730,7 +736,6 @@ QPixmap itemIcon(const QModelIndex &index, Size size) const ItemType itemType = index.data(RoleItemType).value(); const QIcon &icon = (itemType == ItemTypePack) ? (size == SizeSmall ? packS : packB) : (size == SizeSmall ? extensionS : extensionB); - const int iconRectRounding = 4; const qreal iconOpacityDisabled = 0.6; QPainter p(&pixmap); @@ -744,4 +749,33 @@ QPixmap itemIcon(const QModelIndex &index, Size size) return pixmap; } +QPixmap itemBadge(const QModelIndex &index, [[maybe_unused]] Size size) +{ + const QString badgeText = index.data(RoleBadge).toString(); + if (badgeText.isNull()) + return {}; + + constexpr TextFormat badgeTF + {Theme::Token_Basic_White, UiElement::UiElementLabelSmall}; + + const QFont font = badgeTF.font(); + const int textWidth = QFontMetrics(font).horizontalAdvance(badgeText); + const QSize badgeS(ExPaddingGapM + textWidth + ExPaddingGapM, + ExPaddingGapS + badgeTF.lineHeight() + ExPaddingGapS); + const QRect badgeR(QPoint(), badgeS); + const qreal dpr = qApp->devicePixelRatio(); + QPixmap pixmap(badgeS * dpr); + pixmap.fill(Qt::transparent); + pixmap.setDevicePixelRatio(dpr); + + QPainter p(&pixmap); + WelcomePageHelpers::drawCardBackground(&p, badgeR, + creatorColor(Theme::Token_Notification_Neutral), + Qt::NoPen, iconRectRounding); + p.setFont(font); + p.setPen(badgeTF.color()); + p.drawText(badgeR, Qt::AlignCenter, badgeText); + return pixmap; +} + } // ExtensionManager::Internal diff --git a/src/plugins/extensionmanager/extensionsbrowser.h b/src/plugins/extensionmanager/extensionsbrowser.h index 0b4254e02cd..620c581de71 100644 --- a/src/plugins/extensionmanager/extensionsbrowser.h +++ b/src/plugins/extensionmanager/extensionsbrowser.h @@ -50,5 +50,6 @@ enum Size { SizeBig, }; QPixmap itemIcon(const QModelIndex &index, Size size); +QPixmap itemBadge(const QModelIndex &index, Size size); } // ExtensionManager::Internal diff --git a/src/plugins/extensionmanager/extensionsmodel.cpp b/src/plugins/extensionmanager/extensionsmodel.cpp index cf348b99673..e28f716e90f 100644 --- a/src/plugins/extensionmanager/extensionsmodel.cpp +++ b/src/plugins/extensionmanager/extensionsmodel.cpp @@ -240,6 +240,13 @@ int ExtensionsModel::rowCount([[maybe_unused]] const QModelIndex &parent) const return d->responseItems.count() + d->localPlugins.count(); } +static QString badgeText(const QModelIndex &index) +{ + if (index.data(RoleDownloadUrl).isNull()) + return {}; + return Tr::tr("New"); +} + ExtensionState extensionState(const QModelIndex &index) { if (index.data(RoleItemType) != ItemTypeExtension) @@ -265,10 +272,16 @@ static QString searchText(const QModelIndex &index) QVariant ExtensionsModel::data(const QModelIndex &index, int role) const { - if (role == RoleExtensionState) + switch (role) { + case RoleBadge: + return badgeText(index); + case RoleExtensionState: return extensionState(index); - if (role == RoleSearchText) + case RoleSearchText: return searchText(index); + default: + break; + } const bool isRemoteExtension = index.row() < d->responseItems.count(); const int itemIndex = index.row() - (isRemoteExtension ? 0 : d->responseItems.count()); diff --git a/src/plugins/extensionmanager/extensionsmodel.h b/src/plugins/extensionmanager/extensionsmodel.h index eb3d289630c..ce51d5a15d9 100644 --- a/src/plugins/extensionmanager/extensionsmodel.h +++ b/src/plugins/extensionmanager/extensionsmodel.h @@ -27,7 +27,9 @@ enum ExtensionState { enum Role { RoleName = Qt::UserRole, + RoleBadge, RoleCopyright, + RoleDateUpdated, RoleDependencies, RoleDescriptionLong, RoleDescriptionShort, @@ -39,7 +41,6 @@ enum Role { RoleLicense, RolePlatforms, RolePlugins, - RoleDateUpdated, RoleSearchText, RoleTags, RoleVendor, From 9eadb18df060e581350f0e523f36d0554ef6f3c2 Mon Sep 17 00:00:00 2001 From: Alessandro Portale Date: Fri, 4 Oct 2024 13:41:11 +0200 Subject: [PATCH 36/76] ExtensionManager: Hide the filter combobox in QtC 15 There is not much data to filter by, yet, in QtC 15. Therefore, we hide the filter combobox for now. Fixes: QTCREATORBUG-31751 Change-Id: I1acc14a27c57ddb432efe614d0c2a0817a57b8b2 Reviewed-by: Marcus Tillmanns --- src/plugins/extensionmanager/extensionsbrowser.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/plugins/extensionmanager/extensionsbrowser.cpp b/src/plugins/extensionmanager/extensionsbrowser.cpp index 91a58f62259..da2e9881dd0 100644 --- a/src/plugins/extensionmanager/extensionsbrowser.cpp +++ b/src/plugins/extensionmanager/extensionsbrowser.cpp @@ -525,6 +525,7 @@ ExtensionsBrowser::ExtensionsBrowser(ExtensionsModel *model, QWidget *parent) Tr::tr("Filter by: %1")); d->filterChooser->addItems(Utils::transform(SortFilterProxyModel::filterOptions(), &SortFilterProxyModel::FilterOption::displayName)); + d->filterChooser->hide(); // TODO: Unhide when ready. See QTCREATORBUG-31751 d->sortChooser = new OptionChooser(":/extensionmanager/images/sort.png", Tr::tr("Sort by: %1")); d->sortChooser->addItems(Utils::transform(SortFilterProxyModel::sortOptions(), @@ -556,11 +557,11 @@ ExtensionsBrowser::ExtensionsBrowser(ExtensionsModel *model, QWidget *parent) customMargins(0, VPaddingM, extraListViewWidth() + gapSize, VPaddingM), }, Row { - d->filterChooser, - Space(HGapS), d->sortChooser, + d->filterChooser, st, settingsToolButton, + spacing(HGapS), customMargins(0, 0, extraListViewWidth() + gapSize, 0), }, d->extensionsView, From 52fce7a46931f57d19358a7ec6958db897f1d60a Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Thu, 21 Dec 2023 00:48:52 +0100 Subject: [PATCH 37/76] ILocatorFilter: Refactor ILocatorFilter::matchers() function Introduce LocatorStorage::storage() method, to be used from the bodies of locator task handlers. Replace the return value of ILocatorFilter::matchers() with a list of ExecutableItems. Change-Id: I467bb9f217465af74a017095d4fffdf74c4ba7bd Reviewed-by: Eike Ziller --- .../autotest/qtest/datataglocatorfilter.cpp | 35 ++++++++++--------- .../clangcodemodel/clangdlocatorfilters.cpp | 15 +++----- .../cmakelocatorfilter.cpp | 14 ++++---- src/plugins/coreplugin/actionsfilter.cpp | 16 ++++----- .../coreplugin/locator/commandlocator.cpp | 14 ++++---- .../coreplugin/locator/executefilter.cpp | 14 ++++---- .../locator/externaltoolsfilter.cpp | 17 +++++---- .../coreplugin/locator/filesystemfilter.cpp | 11 +++--- .../coreplugin/locator/ilocatorfilter.cpp | 27 ++++++++------ .../coreplugin/locator/ilocatorfilter.h | 14 ++------ .../coreplugin/locator/javascriptfilter.cpp | 23 ++++++------ .../locator/locatorfiltersfilter.cpp | 14 ++++---- .../locator/opendocumentsfilter.cpp | 8 ++--- .../locator/spotlightlocatorfilter.cpp | 15 ++++---- .../coreplugin/locator/urllocatorfilter.cpp | 14 ++++---- src/plugins/cppeditor/cpplocatorfilter.cpp | 21 ++++------- src/plugins/help/helpindexfilter.cpp | 15 ++++---- src/plugins/languageclient/locatorfilter.cpp | 30 +++++++--------- src/plugins/macros/macrolocatorfilter.cpp | 14 ++++---- .../projectexplorer/projectexplorer.cpp | 15 ++++---- .../qmljstools/qmljsfunctionfilter.cpp | 11 +++--- src/plugins/texteditor/bookmarkfilter.cpp | 12 +++---- src/plugins/texteditor/linenumberfilter.cpp | 14 ++++---- 23 files changed, 168 insertions(+), 215 deletions(-) diff --git a/src/plugins/autotest/qtest/datataglocatorfilter.cpp b/src/plugins/autotest/qtest/datataglocatorfilter.cpp index e6a436666ce..54569efea43 100644 --- a/src/plugins/autotest/qtest/datataglocatorfilter.cpp +++ b/src/plugins/autotest/qtest/datataglocatorfilter.cpp @@ -15,34 +15,35 @@ #include +using namespace Core; +using namespace Tasking; +using namespace Utils; + namespace Autotest::Internal { -static void linkAcceptor(const Utils::Link &link) +static void linkAcceptor(const Link &link) { if (link.hasValidTarget()) - Core::EditorManager::openEditorAt(link); + EditorManager::openEditorAt(link); } -using LinkAcceptor = std::function; +using LinkAcceptor = std::function; -static Core::LocatorMatcherTasks dataTagMatchers(const LinkAcceptor &acceptor) +static LocatorMatcherTasks dataTagMatchers(const LinkAcceptor &acceptor) { - using namespace Tasking; - - Storage storage; - - const auto onSetup = [storage, acceptor] { - const QString input = storage->input(); + const auto onSetup = [acceptor] { + const LocatorStorage &storage = *LocatorStorage::storage(); + const QString input = storage.input(); const TestTreeItem *qtTestRoot = theQtTestFramework().rootNode(); if (!qtTestRoot) return; - Core::LocatorFilterEntries entries; + LocatorFilterEntries entries; qtTestRoot->forAllChildItems([&entries, &input, acceptor = acceptor](TestTreeItem *it) { if (it->type() != TestTreeItem::TestDataTag) return; if (it->name().contains(input)) { - Core::LocatorFilterEntry entry; + LocatorFilterEntry entry; entry.displayName = it->data(0, Qt::DisplayRole).toString(); { const TestTreeItem *parent = it->parentItem(); @@ -52,18 +53,18 @@ static Core::LocatorMatcherTasks dataTagMatchers(const LinkAcceptor &acceptor) entry.displayExtra = grandParent->name() + "::" + parent->name(); } } - entry.linkForEditor = std::make_optional(it->data(0, LinkRole).value()); + entry.linkForEditor = std::make_optional(it->data(0, LinkRole).value()); entry.acceptor = [link = entry.linkForEditor, acceptor = acceptor] { if (link) acceptor(*link); - return Core::AcceptResult(); + return AcceptResult(); }; entries.append(entry); } }); - storage->reportOutput(entries); + storage.reportOutput(entries); }; - return {{Sync(onSetup), storage}}; + return {Sync(onSetup)}; } DataTagLocatorFilter::DataTagLocatorFilter() @@ -79,7 +80,7 @@ DataTagLocatorFilter::DataTagLocatorFilter() setEnabled(ProjectManager::startupProject()); } -Core::LocatorMatcherTasks DataTagLocatorFilter::matchers() +LocatorMatcherTasks DataTagLocatorFilter::matchers() { return dataTagMatchers(&linkAcceptor); } diff --git a/src/plugins/clangcodemodel/clangdlocatorfilters.cpp b/src/plugins/clangcodemodel/clangdlocatorfilters.cpp index 18fd250a982..92994fe7360 100644 --- a/src/plugins/clangcodemodel/clangdlocatorfilters.cpp +++ b/src/plugins/clangcodemodel/clangdlocatorfilters.cpp @@ -24,6 +24,7 @@ using namespace Core; using namespace LanguageClient; using namespace LanguageServerProtocol; using namespace ProjectExplorer; +using namespace Tasking; using namespace TextEditor; using namespace Utils; @@ -173,29 +174,23 @@ static void filterCurrentResults(QPromise &promise, const LocatorStorage & static LocatorMatcherTask currentDocumentMatcher() { - using namespace Tasking; - - Storage storage; Storage resultStorage; - const auto onQuerySetup = [=](CurrentDocumentSymbolsRequest &request) { - Q_UNUSED(request) - }; const auto onQueryDone = [resultStorage](const CurrentDocumentSymbolsRequest &request) { *resultStorage = request.currentDocumentSymbolsData(); }; - const auto onFilterSetup = [=](Async &async) { - async.setConcurrentCallData(filterCurrentResults, *storage, *resultStorage, + const auto onFilterSetup = [resultStorage](Async &async) { + async.setConcurrentCallData(filterCurrentResults, *LocatorStorage::storage(), *resultStorage, TextDocument::currentTextDocument()->plainText()); }; const Group root { resultStorage, - CurrentDocumentSymbolsRequestTask(onQuerySetup, onQueryDone, CallDoneIf::Success), + CurrentDocumentSymbolsRequestTask({}, onQueryDone, CallDoneIf::Success), AsyncTask(onFilterSetup) }; - return {root, storage}; + return root; } LocatorMatcherTasks ClangdCurrentDocumentFilter::matchers() diff --git a/src/plugins/cmakeprojectmanager/cmakelocatorfilter.cpp b/src/plugins/cmakeprojectmanager/cmakelocatorfilter.cpp index 9dc375d22c6..c3712e06979 100644 --- a/src/plugins/cmakeprojectmanager/cmakelocatorfilter.cpp +++ b/src/plugins/cmakeprojectmanager/cmakelocatorfilter.cpp @@ -19,6 +19,7 @@ using namespace Core; using namespace ProjectExplorer; +using namespace Tasking; using namespace Utils; namespace CMakeProjectManager::Internal { @@ -29,12 +30,9 @@ using BuildAcceptor = std::function; static LocatorMatcherTasks cmakeMatchers(const BuildAcceptor &acceptor) { - using namespace Tasking; - - Storage storage; - - const auto onSetup = [storage, acceptor] { - const QString input = storage->input(); + const auto onSetup = [acceptor] { + const LocatorStorage &storage = *LocatorStorage::storage(); + const QString input = storage.input(); const QRegularExpression regexp = ILocatorFilter::createRegExp(input, ILocatorFilter::caseSensitivity(input)); if (!regexp.isValid()) @@ -90,10 +88,10 @@ static LocatorMatcherTasks cmakeMatchers(const BuildAcceptor &acceptor) } } } - storage->reportOutput( + storage.reportOutput( std::accumulate(std::begin(entries), std::end(entries), LocatorFilterEntries())); }; - return {{Sync(onSetup), storage}}; + return {Sync(onSetup)}; } static void setupFilter(ILocatorFilter *filter) diff --git a/src/plugins/coreplugin/actionsfilter.cpp b/src/plugins/coreplugin/actionsfilter.cpp index 8b5f23df71f..a2b8e129866 100644 --- a/src/plugins/coreplugin/actionsfilter.cpp +++ b/src/plugins/coreplugin/actionsfilter.cpp @@ -24,6 +24,7 @@ #include #include +using namespace Tasking; using namespace Utils; static const char lastTriggeredC[] = "LastTriggeredActions"; @@ -174,11 +175,7 @@ static void matches(QPromise &promise, const LocatorStorage &storage, LocatorMatcherTasks ActionsFilter::matchers() { - using namespace Tasking; - - Storage storage; - - const auto onSetup = [this, storage](Async &async) { + const auto onSetup = [this](Async &async) { m_entries.clear(); m_indexes.clear(); QList processedMenus; @@ -186,15 +183,16 @@ LocatorMatcherTasks ActionsFilter::matchers() for (QAction* action : menuBarActions()) collectEntriesForAction(action, {}, processedMenus); collectEntriesForCommands(); - if (storage->input().simplified().isEmpty()) { - storage->reportOutput(m_entries); + const LocatorStorage &storage = *LocatorStorage::storage(); + if (storage.input().simplified().isEmpty()) { + storage.reportOutput(m_entries); return SetupResult::StopWithSuccess; } - async.setConcurrentCallData(matches, *storage, m_entries); + async.setConcurrentCallData(matches, storage, m_entries); return SetupResult::Continue; }; - return {{AsyncTask(onSetup), storage}}; + return {AsyncTask(onSetup)}; } LocatorFilterEntry::Acceptor ActionsFilter::acceptor(const ActionFilterEntryData &data) const diff --git a/src/plugins/coreplugin/locator/commandlocator.cpp b/src/plugins/coreplugin/locator/commandlocator.cpp index 2d997dd020a..a1c8bcbc7fb 100644 --- a/src/plugins/coreplugin/locator/commandlocator.cpp +++ b/src/plugins/coreplugin/locator/commandlocator.cpp @@ -10,6 +10,7 @@ #include #include +using namespace Tasking; using namespace Utils; namespace Core { @@ -25,12 +26,9 @@ CommandLocator::CommandLocator(Id id, const QString &displayName, const QString LocatorMatcherTasks CommandLocator::matchers() { - using namespace Tasking; - - Storage storage; - - const auto onSetup = [storage, commands = m_commands] { - const QString input = storage->input(); + const auto onSetup = [commands = m_commands] { + const LocatorStorage &storage = *LocatorStorage::storage(); + const QString input = storage.input(); const Qt::CaseSensitivity inputCaseSensitivity = caseSensitivity(input); LocatorFilterEntries goodEntries; LocatorFilterEntries betterEntries; @@ -63,9 +61,9 @@ LocatorMatcherTasks CommandLocator::matchers() goodEntries.append(entry); } } - storage->reportOutput(betterEntries + goodEntries); + storage.reportOutput(betterEntries + goodEntries); }; - return {{Sync(onSetup), storage}}; + return {Sync(onSetup)}; } } // namespace Core diff --git a/src/plugins/coreplugin/locator/executefilter.cpp b/src/plugins/coreplugin/locator/executefilter.cpp index 629099207ed..5feeae26592 100644 --- a/src/plugins/coreplugin/locator/executefilter.cpp +++ b/src/plugins/coreplugin/locator/executefilter.cpp @@ -18,6 +18,7 @@ #include #include +using namespace Tasking; using namespace Utils; namespace Core::Internal { @@ -40,12 +41,9 @@ ExecuteFilter::~ExecuteFilter() LocatorMatcherTasks ExecuteFilter::matchers() { - using namespace Tasking; - - Storage storage; - - const auto onSetup = [this, storage] { - const QString input = storage->input(); + const auto onSetup = [this] { + const LocatorStorage &storage = *LocatorStorage::storage(); + const QString input = storage.input(); LocatorFilterEntries entries; if (!input.isEmpty()) { // avoid empty entry LocatorFilterEntry entry; @@ -69,9 +67,9 @@ LocatorMatcherTasks ExecuteFilter::matchers() others.append(entry); } } - storage->reportOutput(entries + others); + storage.reportOutput(entries + others); }; - return {{Sync(onSetup), storage}}; + return {Sync(onSetup)}; } void ExecuteFilter::acceptCommand(const QString &cmd) diff --git a/src/plugins/coreplugin/locator/externaltoolsfilter.cpp b/src/plugins/coreplugin/locator/externaltoolsfilter.cpp index 86811e55b0b..1389c9169bb 100644 --- a/src/plugins/coreplugin/locator/externaltoolsfilter.cpp +++ b/src/plugins/coreplugin/locator/externaltoolsfilter.cpp @@ -13,6 +13,8 @@ #include +using namespace Tasking; + namespace Core::Internal { ExternalToolsFilter::ExternalToolsFilter() @@ -27,12 +29,9 @@ ExternalToolsFilter::ExternalToolsFilter() LocatorMatcherTasks ExternalToolsFilter::matchers() { - using namespace Tasking; - - Storage storage; - - const auto onSetup = [storage] { - const QString input = storage->input(); + const auto onSetup = [] { + const LocatorStorage &storage = *LocatorStorage::storage(); + const QString input = storage.input(); LocatorFilterEntries bestEntries; LocatorFilterEntries betterEntries; @@ -77,10 +76,10 @@ LocatorMatcherTasks ExternalToolsFilter::matchers() return AcceptResult(); }; - storage->reportOutput(bestEntries + betterEntries + goodEntries - + LocatorFilterEntries{configEntry}); + storage.reportOutput(bestEntries + betterEntries + goodEntries + + LocatorFilterEntries{configEntry}); }; - return {{Sync(onSetup), storage}}; + return {Sync(onSetup)}; } } // Core::Internal diff --git a/src/plugins/coreplugin/locator/filesystemfilter.cpp b/src/plugins/coreplugin/locator/filesystemfilter.cpp index 6b484635e40..2bc451dcf70 100644 --- a/src/plugins/coreplugin/locator/filesystemfilter.cpp +++ b/src/plugins/coreplugin/locator/filesystemfilter.cpp @@ -31,6 +31,7 @@ #include #include +using namespace Tasking; using namespace Utils; namespace Core::Internal { @@ -304,17 +305,13 @@ static void matches(QPromise &promise, const LocatorStorage &storage, LocatorMatcherTasks FileSystemFilter::matchers() { - using namespace Tasking; - - Storage storage; - - const auto onSetup = [storage, includeHidden = m_includeHidden, shortcut = shortcutString()] + const auto onSetup = [includeHidden = m_includeHidden, shortcut = shortcutString()] (Async &async) { - async.setConcurrentCallData(matches, *storage, shortcut, + async.setConcurrentCallData(matches, *LocatorStorage::storage(), shortcut, DocumentManager::fileDialogInitialDirectory(), includeHidden); }; - return {{AsyncTask(onSetup), storage}}; + return {AsyncTask(onSetup)}; } class FileSystemFilterOptions : public QDialog diff --git a/src/plugins/coreplugin/locator/ilocatorfilter.cpp b/src/plugins/coreplugin/locator/ilocatorfilter.cpp index 371a679d030..a40b3a5624e 100644 --- a/src/plugins/coreplugin/locator/ilocatorfilter.cpp +++ b/src/plugins/coreplugin/locator/ilocatorfilter.cpp @@ -291,6 +291,14 @@ void LocatorStorage::reportOutput(const LocatorFilterEntries &outputData) const d->reportOutput(outputData); } +// Please note the thread_local keyword below guarantees a separate instance per thread. +static thread_local Storage s_locatorStorage = {}; + +Storage &LocatorStorage::storage() +{ + return s_locatorStorage; +} + void LocatorStorage::finalize() const { QTC_ASSERT(d, return); @@ -366,16 +374,16 @@ void LocatorMatcher::start() const auto onTaskTreeSetup = [iterator, input = d->m_input, collectorStorage](TaskTree &taskTree) { const std::shared_ptr deduplicator = collectorStorage->m_deduplicator; - const Storage storage = iterator->storage; - const auto onSetup = [storage, input, index = iterator.iteration(), deduplicator] { - *storage = std::make_shared(input, index, deduplicator); + const auto onSetup = [input, index = iterator.iteration(), deduplicator] { + *LocatorStorage::storage() + = std::make_shared(input, index, deduplicator); }; taskTree.setRecipe({ finishAllAndSuccess, - storage, + LocatorStorage::storage(), onGroupSetup(onSetup), - iterator->task, - onGroupDone([storage] { storage->finalize(); }) + *iterator, + onGroupDone([] { LocatorStorage::storage()->finalize(); }) }); }; @@ -1359,10 +1367,9 @@ static void filter(QPromise &promise, const LocatorStor */ LocatorMatcherTask LocatorFileCache::matcher() const { - Storage storage; std::weak_ptr weak = d; - const auto onSetup = [storage, weak](Async &async) { + const auto onSetup = [weak](Async &async) { auto that = weak.lock(); if (!that) // LocatorMatcher is running after *this LocatorFileCache was destructed. return SetupResult::StopWithSuccess; @@ -1372,7 +1379,7 @@ LocatorMatcherTask LocatorFileCache::matcher() const // no provider is set or it returned empty generator that->bumpExecutionId(); - async.setConcurrentCallData(&filter, *storage, *that); + async.setConcurrentCallData(&filter, *LocatorStorage::storage(), *that); return SetupResult::Continue; }; const auto onDone = [weak](const Async &async) { @@ -1392,7 +1399,7 @@ LocatorMatcherTask LocatorFileCache::matcher() const that->update(async.result()); }; - return {AsyncTask(onSetup, onDone, CallDoneIf::Success), storage}; + return AsyncTask(onSetup, onDone, CallDoneIf::Success); } } // Core diff --git a/src/plugins/coreplugin/locator/ilocatorfilter.h b/src/plugins/coreplugin/locator/ilocatorfilter.h index 368f0313814..5a37f6d82dc 100644 --- a/src/plugins/coreplugin/locator/ilocatorfilter.h +++ b/src/plugins/coreplugin/locator/ilocatorfilter.h @@ -126,6 +126,8 @@ public: LocatorStorage() = default; QString input() const; void reportOutput(const LocatorFilterEntries &outputData) const; + // Only use it from inside the bodies of Task handlers. + static Tasking::Storage &storage(); private: friend class LocatorMatcher; @@ -134,17 +136,7 @@ private: std::shared_ptr d; }; -class CORE_EXPORT LocatorMatcherTask final -{ -public: - // The main task. Initial data (searchTerm) should be taken from storage.input(). - // Results reporting is done via the storage.reportOutput(). - Tasking::GroupItem task = Tasking::Group{}; - - // When constructing the task, don't place the storage inside the task above. - Tasking::Storage storage; -}; - +using LocatorMatcherTask = Tasking::GroupItem; using LocatorMatcherTasks = QList; using LocatorMatcherTaskCreator = std::function; class LocatorMatcherPrivate; diff --git a/src/plugins/coreplugin/locator/javascriptfilter.cpp b/src/plugins/coreplugin/locator/javascriptfilter.cpp index c63271bb8df..c4c174d7822 100644 --- a/src/plugins/coreplugin/locator/javascriptfilter.cpp +++ b/src/plugins/coreplugin/locator/javascriptfilter.cpp @@ -366,15 +366,15 @@ JavaScriptFilter::~JavaScriptFilter() = default; LocatorMatcherTasks JavaScriptFilter::matchers() { - Storage storage; if (!m_javaScriptEngine) m_javaScriptEngine.reset(new JavaScriptEngine); QPointer engine = m_javaScriptEngine.get(); - const auto onSetup = [storage, engine] { + const auto onSetup = [engine] { + const LocatorStorage &storage = *LocatorStorage::storage(); if (!engine) return SetupResult::StopWithError; - if (storage->input().trimmed().isEmpty()) { + if (storage.input().trimmed().isEmpty()) { LocatorFilterEntry entry; entry.displayName = Tr::tr("Reset Engine"); entry.acceptor = [engine] { @@ -385,21 +385,22 @@ LocatorMatcherTasks JavaScriptFilter::matchers() } return AcceptResult(); }; - storage->reportOutput({entry}); + storage.reportOutput({entry}); return SetupResult::StopWithSuccess; } return SetupResult::Continue; }; - const auto onJavaScriptSetup = [storage, engine](JavaScriptRequest &request) { + const auto onJavaScriptSetup = [engine](JavaScriptRequest &request) { request.setEngine(engine); - request.setEvaluateData(storage->input()); + request.setEvaluateData(LocatorStorage::storage()->input()); }; - const auto onJavaScriptDone = [storage](const JavaScriptRequest &request, DoneWith result) { + const auto onJavaScriptDone = [](const JavaScriptRequest &request, DoneWith result) { + const LocatorStorage &storage = *LocatorStorage::storage(); if (result != DoneWith::Success) { LocatorFilterEntry entry; entry.displayName = request.output().m_output; - storage->reportOutput({entry}); + storage.reportOutput({entry}); return; } const auto acceptor = [](const QString &clipboardContents) { @@ -408,7 +409,7 @@ LocatorMatcherTasks JavaScriptFilter::matchers() return AcceptResult(); }; }; - const QString input = storage->input(); + const QString input = storage.input(); const QString output = request.output().m_output; const QString expression = input + " = " + output; @@ -423,7 +424,7 @@ LocatorMatcherTasks JavaScriptFilter::matchers() copyExpressionEntry.displayName = Tr::tr("Copy to clipboard: %1").arg(expression); copyExpressionEntry.acceptor = acceptor(expression); - storage->reportOutput({entry, copyResultEntry, copyExpressionEntry}); + storage.reportOutput({entry, copyResultEntry, copyExpressionEntry}); }; const Group root { @@ -431,7 +432,7 @@ LocatorMatcherTasks JavaScriptFilter::matchers() JavaScriptRequestTask(onJavaScriptSetup, onJavaScriptDone) }; - return {{root, storage}}; + return {root}; } } // namespace Core::Internal diff --git a/src/plugins/coreplugin/locator/locatorfiltersfilter.cpp b/src/plugins/coreplugin/locator/locatorfiltersfilter.cpp index fa44d967e67..ee24a262438 100644 --- a/src/plugins/coreplugin/locator/locatorfiltersfilter.cpp +++ b/src/plugins/coreplugin/locator/locatorfiltersfilter.cpp @@ -9,6 +9,7 @@ #include +using namespace Tasking; using namespace Utils; namespace Core::Internal { @@ -26,12 +27,9 @@ LocatorFiltersFilter::LocatorFiltersFilter(): LocatorMatcherTasks LocatorFiltersFilter::matchers() { - using namespace Tasking; - - Storage storage; - - const auto onSetup = [storage, icon = m_icon] { - if (!storage->input().isEmpty()) + const auto onSetup = [icon = m_icon] { + const LocatorStorage &storage = *LocatorStorage::storage(); + if (!storage.input().isEmpty()) return; QMap uniqueFilters; @@ -60,9 +58,9 @@ LocatorMatcherTasks LocatorFiltersFilter::matchers() entries.append(entry); } } - storage->reportOutput(entries); + storage.reportOutput(entries); }; - return {{Sync(onSetup), storage}}; + return {Sync(onSetup)}; } } // Core::Internal diff --git a/src/plugins/coreplugin/locator/opendocumentsfilter.cpp b/src/plugins/coreplugin/locator/opendocumentsfilter.cpp index ede24d5b892..b080894fcb2 100644 --- a/src/plugins/coreplugin/locator/opendocumentsfilter.cpp +++ b/src/plugins/coreplugin/locator/opendocumentsfilter.cpp @@ -70,15 +70,13 @@ static void matchEditors(QPromise &promise, const LocatorStorage &storage, LocatorMatcherTasks OpenDocumentsFilter::matchers() { - Storage storage; - - const auto onSetup = [storage](Async &async) { + const auto onSetup = [](Async &async) { const QList editorsData = Utils::transform(DocumentModel::entries(), [](const DocumentModel::Entry *e) { return Entry{e->filePath(), e->displayName()}; }); - async.setConcurrentCallData(matchEditors, *storage, editorsData); + async.setConcurrentCallData(matchEditors, *LocatorStorage::storage(), editorsData); }; - return {{AsyncTask(onSetup), storage}}; + return {AsyncTask(onSetup)}; } } // namespace Core::Internal diff --git a/src/plugins/coreplugin/locator/spotlightlocatorfilter.cpp b/src/plugins/coreplugin/locator/spotlightlocatorfilter.cpp index bcc685c9532..78fdf895fcf 100644 --- a/src/plugins/coreplugin/locator/spotlightlocatorfilter.cpp +++ b/src/plugins/coreplugin/locator/spotlightlocatorfilter.cpp @@ -24,6 +24,7 @@ #include #include +using namespace Tasking; using namespace Utils; namespace Core::Internal { @@ -176,16 +177,12 @@ static void matches(QPromise &promise, LocatorMatcherTasks SpotlightLocatorFilter::matchers() { - using namespace Tasking; - - Storage storage; - - const auto onSetup = [storage, - command = m_command, + const auto onSetup = [command = m_command, insensArgs = m_arguments, sensArgs = m_caseSensitiveArguments, sortResults = m_sortResults](Async &async) { - const Link link = Link::fromString(storage->input(), true); + const LocatorStorage &storage = *LocatorStorage::storage(); + const Link link = Link::fromString(storage.input(), true); const FilePath input = link.targetFilePath; if (input.isEmpty()) return SetupResult::StopWithSuccess; @@ -196,11 +193,11 @@ LocatorMatcherTasks SpotlightLocatorFilter::matchers() ? insensArgs : sensArgs; const CommandLine cmd(FilePath::fromString(command), expander->expand(args), CommandLine::Raw); - async.setConcurrentCallData(matches, *storage, cmd, sortResults); + async.setConcurrentCallData(matches, storage, cmd, sortResults); return SetupResult::Continue; }; - return {{AsyncTask(onSetup), storage}}; + return {AsyncTask(onSetup)}; } bool SpotlightLocatorFilter::openConfigDialog(QWidget *parent, bool &needsRefresh) diff --git a/src/plugins/coreplugin/locator/urllocatorfilter.cpp b/src/plugins/coreplugin/locator/urllocatorfilter.cpp index 7457f0907cc..d96b6411ed6 100644 --- a/src/plugins/coreplugin/locator/urllocatorfilter.cpp +++ b/src/plugins/coreplugin/locator/urllocatorfilter.cpp @@ -18,6 +18,7 @@ #include #include +using namespace Tasking; using namespace Utils; namespace Core { @@ -163,12 +164,9 @@ UrlLocatorFilter::UrlLocatorFilter(const QString &displayName, Id id) LocatorMatcherTasks UrlLocatorFilter::matchers() { - using namespace Tasking; - - Storage storage; - - const auto onSetup = [storage, urls = remoteUrls()] { - const QString input = storage->input(); + const auto onSetup = [urls = remoteUrls()] { + const LocatorStorage &storage = *LocatorStorage::storage(); + const QString input = storage.input(); LocatorFilterEntries entries; for (const QString &url : urls) { const QString name = url.arg(input); @@ -182,9 +180,9 @@ LocatorMatcherTasks UrlLocatorFilter::matchers() entry.highlightInfo = {int(name.lastIndexOf(input)), int(input.length())}; entries.append(entry); } - storage->reportOutput(entries); + storage.reportOutput(entries); }; - return {{Sync(onSetup), storage}}; + return {Sync(onSetup)}; } const char kDisplayNameKey[] = "displayName"; diff --git a/src/plugins/cppeditor/cpplocatorfilter.cpp b/src/plugins/cppeditor/cpplocatorfilter.cpp index 7526d3dc9f9..006da4fc92d 100644 --- a/src/plugins/cppeditor/cpplocatorfilter.cpp +++ b/src/plugins/cppeditor/cpplocatorfilter.cpp @@ -19,6 +19,7 @@ using namespace Core; using namespace CPlusPlus; +using namespace Tasking; using namespace Utils; namespace CppEditor { @@ -101,14 +102,10 @@ void matchesFor(QPromise &promise, const LocatorStorage &storage, LocatorMatcherTask locatorMatcher(IndexItem::ItemType type, const EntryFromIndex &converter) { - using namespace Tasking; - - Storage storage; - - const auto onSetup = [=](Async &async) { - async.setConcurrentCallData(matchesFor, *storage, type, converter); + const auto onSetup = [type, converter](Async &async) { + async.setConcurrentCallData(matchesFor, *LocatorStorage::storage(), type, converter); }; - return {AsyncTask(onSetup), storage}; + return AsyncTask(onSetup); } LocatorMatcherTask allSymbolsMatcher() @@ -298,14 +295,10 @@ FilePath currentFileName() LocatorMatcherTask currentDocumentMatcher() { - using namespace Tasking; - - Storage storage; - - const auto onSetup = [=](Async &async) { - async.setConcurrentCallData(matchesForCurrentDocument, *storage, currentFileName()); + const auto onSetup = [](Async &async) { + async.setConcurrentCallData(matchesForCurrentDocument, *LocatorStorage::storage(), currentFileName()); }; - return {AsyncTask(onSetup), storage}; + return AsyncTask(onSetup); } using MatcherCreator = std::function; diff --git a/src/plugins/help/helpindexfilter.cpp b/src/plugins/help/helpindexfilter.cpp index 2820c634a3d..e78bb37439e 100644 --- a/src/plugins/help/helpindexfilter.cpp +++ b/src/plugins/help/helpindexfilter.cpp @@ -82,9 +82,7 @@ static void matches(QPromise &promise, const LocatorStorage &storag LocatorMatcherTasks HelpIndexFilter::matchers() { - Storage storage; - - const auto onSetup = [this, storage](Async &async) { + const auto onSetup = [this](Async &async) { if (m_needsUpdate) { m_needsUpdate = false; LocalHelpManager::setupGuiHelpEngine(); @@ -92,18 +90,19 @@ LocatorMatcherTasks HelpIndexFilter::matchers() m_lastIndicesCache.clear(); m_lastEntry.clear(); } - const QStringList cache = m_lastEntry.isEmpty() || !storage->input().contains(m_lastEntry) + const LocatorStorage &storage = *LocatorStorage::storage(); + const QStringList cache = m_lastEntry.isEmpty() || !storage.input().contains(m_lastEntry) ? m_allIndicesCache : m_lastIndicesCache; - async.setConcurrentCallData(matches, *storage, cache, m_icon); + async.setConcurrentCallData(matches, storage, cache, m_icon); }; - const auto onDone = [this, storage](const Async &async) { + const auto onDone = [this](const Async &async) { if (async.isResultAvailable()) { m_lastIndicesCache = async.result(); - m_lastEntry = storage->input(); + m_lastEntry = LocatorStorage::storage()->input(); } }; - return {{AsyncTask(onSetup, onDone, CallDoneIf::Success), storage}}; + return {AsyncTask(onSetup, onDone, CallDoneIf::Success)}; } void HelpIndexFilter::invalidateCache() diff --git a/src/plugins/languageclient/locatorfilter.cpp b/src/plugins/languageclient/locatorfilter.cpp index 4fb8cea19a2..dd33ae45360 100644 --- a/src/plugins/languageclient/locatorfilter.cpp +++ b/src/plugins/languageclient/locatorfilter.cpp @@ -15,6 +15,7 @@ using namespace Core; using namespace LanguageServerProtocol; +using namespace Tasking; using namespace Utils; namespace LanguageClient { @@ -44,15 +45,12 @@ void filterResults(QPromise &promise, const LocatorStorage &storage, Clien LocatorMatcherTask locatorMatcher(Client *client, int maxResultCount, const QList &filter) { - using namespace Tasking; - - Storage storage; Storage> resultStorage; - const auto onQuerySetup = [storage, client, maxResultCount](ClientWorkspaceSymbolRequest &request) { + const auto onQuerySetup = [client, maxResultCount](ClientWorkspaceSymbolRequest &request) { request.setClient(client); WorkspaceSymbolParams params; - params.setQuery(storage->input()); + params.setQuery(LocatorStorage::storage()->input()); if (maxResultCount > 0) params.setLimit(maxResultCount); request.setParams(params); @@ -64,11 +62,12 @@ LocatorMatcherTask locatorMatcher(Client *client, int maxResultCount, *resultStorage = result->toList(); }; - const auto onFilterSetup = [storage, resultStorage, client, filter](Async &async) { + const auto onFilterSetup = [resultStorage, client, filter](Async &async) { const QList results = *resultStorage; if (results.isEmpty()) return SetupResult::StopWithSuccess; - async.setConcurrentCallData(filterResults, *storage, client, results, filter); + async.setConcurrentCallData(filterResults, *LocatorStorage::storage(), client, results, + filter); return SetupResult::Continue; }; @@ -77,7 +76,7 @@ LocatorMatcherTask locatorMatcher(Client *client, int maxResultCount, ClientWorkspaceSymbolRequestTask(onQuerySetup, onQueryDone, CallDoneIf::Success), AsyncTask(onFilterSetup) }; - return {root, storage}; + return root; } LocatorMatcherTask allSymbolsMatcher(Client *client, int maxResultCount) @@ -114,28 +113,23 @@ static void filterCurrentResults(QPromise &promise, const LocatorStorage & LocatorMatcherTask currentDocumentMatcher() { - using namespace Tasking; - - Storage storage; Storage resultStorage; - const auto onQuerySetup = [](CurrentDocumentSymbolsRequest &request) { - Q_UNUSED(request) - }; const auto onQueryDone = [resultStorage](const CurrentDocumentSymbolsRequest &request) { *resultStorage = request.currentDocumentSymbolsData(); }; - const auto onFilterSetup = [storage, resultStorage](Async &async) { - async.setConcurrentCallData(filterCurrentResults, *storage, *resultStorage); + const auto onFilterSetup = [resultStorage](Async &async) { + async.setConcurrentCallData(filterCurrentResults, *LocatorStorage::storage(), + *resultStorage); }; const Group root { resultStorage, - CurrentDocumentSymbolsRequestTask(onQuerySetup, onQueryDone, CallDoneIf::Success), + CurrentDocumentSymbolsRequestTask({}, onQueryDone, CallDoneIf::Success), AsyncTask(onFilterSetup) }; - return {root, storage}; + return root; } using MatcherCreator = std::function; diff --git a/src/plugins/macros/macrolocatorfilter.cpp b/src/plugins/macros/macrolocatorfilter.cpp index 4cc819d8b73..a77bbd570b2 100644 --- a/src/plugins/macros/macrolocatorfilter.cpp +++ b/src/plugins/macros/macrolocatorfilter.cpp @@ -14,6 +14,7 @@ using namespace Core; using namespace Macros; using namespace Macros::Internal; +using namespace Tasking; using namespace Utils; MacroLocatorFilter::MacroLocatorFilter() @@ -28,12 +29,9 @@ MacroLocatorFilter::MacroLocatorFilter() LocatorMatcherTasks MacroLocatorFilter::matchers() { - using namespace Tasking; - - Storage storage; - - const auto onSetup = [storage, icon = m_icon] { - const QString input = storage->input(); + const auto onSetup = [icon = m_icon] { + const LocatorStorage &storage = *LocatorStorage::storage(); + const QString input = storage.input(); const Qt::CaseSensitivity entryCaseSensitivity = caseSensitivity(input); const QMap ¯os = MacroManager::macros(); LocatorFilterEntries goodEntries; @@ -69,7 +67,7 @@ LocatorMatcherTasks MacroLocatorFilter::matchers() goodEntries.append(filterEntry); } } - storage->reportOutput(betterEntries + goodEntries); + storage.reportOutput(betterEntries + goodEntries); }; - return {{Sync(onSetup), storage}}; + return {Sync(onSetup)}; } diff --git a/src/plugins/projectexplorer/projectexplorer.cpp b/src/plugins/projectexplorer/projectexplorer.cpp index 184c5cfd74a..adfd6bdd26d 100644 --- a/src/plugins/projectexplorer/projectexplorer.cpp +++ b/src/plugins/projectexplorer/projectexplorer.cpp @@ -4253,14 +4253,13 @@ static RunConfiguration *runConfigurationForDisplayName(const QString &displayNa }); } +using namespace Tasking; + static LocatorMatcherTasks runConfigurationMatchers(const RunAcceptor &acceptor) { - using namespace Tasking; - - Storage storage; - - const auto onSetup = [storage, acceptor] { - const QString input = storage->input(); + const auto onSetup = [acceptor] { + const LocatorStorage &storage = *LocatorStorage::storage(); + const QString input = storage.input(); const Target *target = ProjectManager::startupTarget(); if (!target) return; @@ -4280,9 +4279,9 @@ static LocatorMatcherTasks runConfigurationMatchers(const RunAcceptor &acceptor) entries.append(entry); } } - storage->reportOutput(entries); + storage.reportOutput(entries); }; - return {{Sync(onSetup), storage}}; + return {Sync(onSetup)}; } static void runAcceptor(RunConfiguration *config) diff --git a/src/plugins/qmljstools/qmljsfunctionfilter.cpp b/src/plugins/qmljstools/qmljsfunctionfilter.cpp index c6f8dfa4fd0..21915e7be92 100644 --- a/src/plugins/qmljstools/qmljsfunctionfilter.cpp +++ b/src/plugins/qmljstools/qmljsfunctionfilter.cpp @@ -12,6 +12,7 @@ using namespace Core; using namespace QmlJSTools::Internal; +using namespace Tasking; using namespace Utils; Q_DECLARE_METATYPE(LocatorData::Entry) @@ -74,13 +75,9 @@ static void matches(QPromise &promise, const LocatorStorage &storage, LocatorMatcherTasks QmlJSFunctionsFilter::matchers() { - using namespace Tasking; - - Storage storage; - - const auto onSetup = [storage, entries = m_data->entries()](Async &async) { - async.setConcurrentCallData(matches, *storage, entries); + const auto onSetup = [entries = m_data->entries()](Async &async) { + async.setConcurrentCallData(matches, *LocatorStorage::storage(), entries); }; - return {{AsyncTask(onSetup), storage}}; + return {AsyncTask(onSetup)}; } diff --git a/src/plugins/texteditor/bookmarkfilter.cpp b/src/plugins/texteditor/bookmarkfilter.cpp index 0938a0e81b8..f03b9f21902 100644 --- a/src/plugins/texteditor/bookmarkfilter.cpp +++ b/src/plugins/texteditor/bookmarkfilter.cpp @@ -12,6 +12,7 @@ #include using namespace Core; +using namespace Tasking; using namespace Utils; namespace TextEditor::Internal { @@ -36,12 +37,11 @@ private: LocatorMatcherTasks BookmarkFilter::matchers() { - using namespace Tasking; - - Storage storage; - - const auto onSetup = [this, storage] { storage->reportOutput(match(storage->input())); }; - return {{Sync(onSetup), storage}}; + const auto onSetup = [this] { + const LocatorStorage &storage = *LocatorStorage::storage(); + storage.reportOutput(match(storage.input())); + }; + return {Sync(onSetup)}; } LocatorFilterEntries BookmarkFilter::match(const QString &input) const diff --git a/src/plugins/texteditor/linenumberfilter.cpp b/src/plugins/texteditor/linenumberfilter.cpp index b532313330c..3d2bf792060 100644 --- a/src/plugins/texteditor/linenumberfilter.cpp +++ b/src/plugins/texteditor/linenumberfilter.cpp @@ -8,6 +8,7 @@ #include using namespace Core; +using namespace Tasking; using namespace Utils; namespace TextEditor::Internal { @@ -29,12 +30,9 @@ public: private: LocatorMatcherTasks matchers() final { - using namespace Tasking; - - Storage storage; - - const auto onSetup = [storage] { - const QStringList lineAndColumn = storage->input().split(':'); + const auto onSetup = [] { + const LocatorStorage &storage = *LocatorStorage::storage(); + const QStringList lineAndColumn = storage.input().split(':'); int sectionCount = lineAndColumn.size(); int line = 0; int column = 0; @@ -64,10 +62,10 @@ private: EditorManager::activateEditor(editor); return AcceptResult(); }; - storage->reportOutput({entry}); + storage.reportOutput({entry}); } }; - return {{Sync(onSetup), storage}}; + return {Sync(onSetup)}; } }; From d245374da787a59f7788dd54b74c236ee82202aa Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Thu, 19 Sep 2024 19:26:32 +0200 Subject: [PATCH 38/76] ILocatorFilter: Remove LocatorMatcherTask typedef Use ExecutableItem directly instead. Add some static specifiers. Change-Id: Ie5ef467d428f8bee7fc800241357be38c85faa15 Reviewed-by: Eike Ziller --- .../clangcodemodel/clangdlocatorfilters.cpp | 2 +- .../coreplugin/locator/ilocatorfilter.cpp | 2 +- .../coreplugin/locator/ilocatorfilter.h | 5 ++--- src/plugins/cppeditor/cpplocatorfilter.cpp | 22 +++++++++---------- .../cppeditor/cpplocatorfilter_test.cpp | 4 ++-- src/plugins/languageclient/locatorfilter.cpp | 14 ++++++------ 6 files changed, 24 insertions(+), 25 deletions(-) diff --git a/src/plugins/clangcodemodel/clangdlocatorfilters.cpp b/src/plugins/clangcodemodel/clangdlocatorfilters.cpp index 92994fe7360..f2f66fa29e3 100644 --- a/src/plugins/clangcodemodel/clangdlocatorfilters.cpp +++ b/src/plugins/clangcodemodel/clangdlocatorfilters.cpp @@ -172,7 +172,7 @@ static void filterCurrentResults(QPromise &promise, const LocatorStorage & [](const Entry &entry) { return entry.entry; })); } -static LocatorMatcherTask currentDocumentMatcher() +static ExecutableItem currentDocumentMatcher() { Storage resultStorage; diff --git a/src/plugins/coreplugin/locator/ilocatorfilter.cpp b/src/plugins/coreplugin/locator/ilocatorfilter.cpp index a40b3a5624e..ee5e88451e7 100644 --- a/src/plugins/coreplugin/locator/ilocatorfilter.cpp +++ b/src/plugins/coreplugin/locator/ilocatorfilter.cpp @@ -1365,7 +1365,7 @@ static void filter(QPromise &promise, const LocatorStor When this cache started a new search in meantime, the cache was invalidated or even deleted, the update of the cache after a successful run of the task is ignored. */ -LocatorMatcherTask LocatorFileCache::matcher() const +ExecutableItem LocatorFileCache::matcher() const { std::weak_ptr weak = d; diff --git a/src/plugins/coreplugin/locator/ilocatorfilter.h b/src/plugins/coreplugin/locator/ilocatorfilter.h index 5a37f6d82dc..399631873c7 100644 --- a/src/plugins/coreplugin/locator/ilocatorfilter.h +++ b/src/plugins/coreplugin/locator/ilocatorfilter.h @@ -136,8 +136,7 @@ private: std::shared_ptr d; }; -using LocatorMatcherTask = Tasking::GroupItem; -using LocatorMatcherTasks = QList; +using LocatorMatcherTasks = QList; using LocatorMatcherTaskCreator = std::function; class LocatorMatcherPrivate; @@ -307,7 +306,7 @@ public: std::optional filePaths() const; static FilePathsGenerator filePathsGenerator(const Utils::FilePaths &filePaths); - LocatorMatcherTask matcher() const; + Tasking::ExecutableItem matcher() const; using MatchedEntries = std::array; static Utils::FilePaths processFilePaths(const QFuture &future, diff --git a/src/plugins/cppeditor/cpplocatorfilter.cpp b/src/plugins/cppeditor/cpplocatorfilter.cpp index 006da4fc92d..b1e7c552e0a 100644 --- a/src/plugins/cppeditor/cpplocatorfilter.cpp +++ b/src/plugins/cppeditor/cpplocatorfilter.cpp @@ -26,7 +26,7 @@ namespace CppEditor { using EntryFromIndex = std::function; -void matchesFor(QPromise &promise, const LocatorStorage &storage, +static void matchesFor(QPromise &promise, const LocatorStorage &storage, IndexItem::ItemType wantedType, const EntryFromIndex &converter) { const QString input = storage.input(); @@ -100,7 +100,7 @@ void matchesFor(QPromise &promise, const LocatorStorage &storage, LocatorFilterEntries())); } -LocatorMatcherTask locatorMatcher(IndexItem::ItemType type, const EntryFromIndex &converter) +static ExecutableItem locatorMatcher(IndexItem::ItemType type, const EntryFromIndex &converter) { const auto onSetup = [type, converter](Async &async) { async.setConcurrentCallData(matchesFor, *LocatorStorage::storage(), type, converter); @@ -108,7 +108,7 @@ LocatorMatcherTask locatorMatcher(IndexItem::ItemType type, const EntryFromIndex return AsyncTask(onSetup); } -LocatorMatcherTask allSymbolsMatcher() +static ExecutableItem allSymbolsMatcher() { const auto converter = [](const IndexItem::Ptr &info) { LocatorFilterEntry filterEntry; @@ -126,7 +126,7 @@ LocatorMatcherTask allSymbolsMatcher() return locatorMatcher(IndexItem::All, converter); } -LocatorMatcherTask classMatcher() +static ExecutableItem classMatcher() { const auto converter = [](const IndexItem::Ptr &info) { LocatorFilterEntry filterEntry; @@ -142,7 +142,7 @@ LocatorMatcherTask classMatcher() return locatorMatcher(IndexItem::Class, converter); } -LocatorMatcherTask functionMatcher() +static ExecutableItem functionMatcher() { const auto converter = [](const IndexItem::Ptr &info) { QString name = info->symbolName(); @@ -163,7 +163,7 @@ LocatorMatcherTask functionMatcher() return locatorMatcher(IndexItem::Function, converter); } -QList itemsOfCurrentDocument(const FilePath ¤tFileName) +static QList itemsOfCurrentDocument(const FilePath ¤tFileName) { if (currentFileName.isEmpty()) return {}; @@ -185,7 +185,7 @@ QList itemsOfCurrentDocument(const FilePath ¤tFileName) return results; } -LocatorFilterEntry::HighlightInfo highlightInfo(const QRegularExpressionMatch &match, +static LocatorFilterEntry::HighlightInfo highlightInfo(const QRegularExpressionMatch &match, LocatorFilterEntry::HighlightInfo::DataType dataType) { const FuzzyMatcher::HighlightingPositions positions = @@ -194,7 +194,7 @@ LocatorFilterEntry::HighlightInfo highlightInfo(const QRegularExpressionMatch &m return LocatorFilterEntry::HighlightInfo(positions.starts, positions.lengths, dataType); } -void matchesForCurrentDocument(QPromise &promise, const LocatorStorage &storage, +static void matchesForCurrentDocument(QPromise &promise, const LocatorStorage &storage, const FilePath ¤tFileName) { const QString input = storage.input(); @@ -287,13 +287,13 @@ void matchesForCurrentDocument(QPromise &promise, const LocatorStorage &st [](const Entry &entry) { return entry.entry; })); } -FilePath currentFileName() +static FilePath currentFileName() { IEditor *currentEditor = EditorManager::currentEditor(); return currentEditor ? currentEditor->document()->filePath() : FilePath(); } -LocatorMatcherTask currentDocumentMatcher() +static ExecutableItem currentDocumentMatcher() { const auto onSetup = [](Async &async) { async.setConcurrentCallData(matchesForCurrentDocument, *LocatorStorage::storage(), currentFileName()); @@ -301,7 +301,7 @@ LocatorMatcherTask currentDocumentMatcher() return AsyncTask(onSetup); } -using MatcherCreator = std::function; +using MatcherCreator = std::function; static MatcherCreator creatorForType(MatcherType type) { diff --git a/src/plugins/cppeditor/cpplocatorfilter_test.cpp b/src/plugins/cppeditor/cpplocatorfilter_test.cpp index a621d1c1103..ffb9eaa24f3 100644 --- a/src/plugins/cppeditor/cpplocatorfilter_test.cpp +++ b/src/plugins/cppeditor/cpplocatorfilter_test.cpp @@ -28,7 +28,7 @@ QTC_DECLARE_MYTESTDATADIR("../../../tests/cpplocators/") class CppLocatorFilterTestCase : public CppEditor::Tests::TestCase { public: - CppLocatorFilterTestCase(const QList &matchers, + CppLocatorFilterTestCase(const LocatorMatcherTasks &matchers, const QString &fileName, const QString &searchText, const ResultDataList &expectedResults) @@ -54,7 +54,7 @@ class CppCurrentDocumentFilterTestCase : public CppEditor::Tests::TestCase { public: CppCurrentDocumentFilterTestCase(const FilePath &filePath, - const QList &matchers, + const LocatorMatcherTasks &matchers, const ResultDataList &expectedResults, const QString &searchText = QString()) { diff --git a/src/plugins/languageclient/locatorfilter.cpp b/src/plugins/languageclient/locatorfilter.cpp index dd33ae45360..5dc90ad5b32 100644 --- a/src/plugins/languageclient/locatorfilter.cpp +++ b/src/plugins/languageclient/locatorfilter.cpp @@ -20,7 +20,7 @@ using namespace Utils; namespace LanguageClient { -void filterResults(QPromise &promise, const LocatorStorage &storage, Client *client, +static void filterResults(QPromise &promise, const LocatorStorage &storage, Client *client, const QList &results, const QList &filter) { const auto doFilter = [&](const SymbolInformation &info) { @@ -42,7 +42,7 @@ void filterResults(QPromise &promise, const LocatorStorage &storage, Clien storage.reportOutput(Utils::transform(filteredResults, generateEntry)); } -LocatorMatcherTask locatorMatcher(Client *client, int maxResultCount, +static ExecutableItem locatorMatcher(Client *client, int maxResultCount, const QList &filter) { Storage> resultStorage; @@ -79,17 +79,17 @@ LocatorMatcherTask locatorMatcher(Client *client, int maxResultCount, return root; } -LocatorMatcherTask allSymbolsMatcher(Client *client, int maxResultCount) +static ExecutableItem allSymbolsMatcher(Client *client, int maxResultCount) { return locatorMatcher(client, maxResultCount, {}); } -LocatorMatcherTask classMatcher(Client *client, int maxResultCount) +static ExecutableItem classMatcher(Client *client, int maxResultCount) { return locatorMatcher(client, maxResultCount, {SymbolKind::Class, SymbolKind::Struct}); } -LocatorMatcherTask functionMatcher(Client *client, int maxResultCount) +static ExecutableItem functionMatcher(Client *client, int maxResultCount) { return locatorMatcher(client, maxResultCount, {SymbolKind::Method, SymbolKind::Function, SymbolKind::Constructor}); @@ -111,7 +111,7 @@ static void filterCurrentResults(QPromise &promise, const LocatorStorage & docSymbolModifier)); } -LocatorMatcherTask currentDocumentMatcher() +static ExecutableItem currentDocumentMatcher() { Storage resultStorage; @@ -132,7 +132,7 @@ LocatorMatcherTask currentDocumentMatcher() return root; } -using MatcherCreator = std::function; +using MatcherCreator = std::function; static MatcherCreator creatorForType(MatcherType type) { From 0f1526ed258281f70000b0cfc0134e8087504c7a Mon Sep 17 00:00:00 2001 From: Marcus Tillmanns Date: Mon, 7 Oct 2024 12:26:15 +0200 Subject: [PATCH 39/76] Lua: Remove unsupported Flags State and GenericStateLocation are only supported with Qt 6.7 and onwards Change-Id: I48490a090c04185706b793b70238037393a5d7bf Reviewed-by: Jarek Kobus --- src/plugins/lua/bindings/qt.cpp | 7 ++----- src/plugins/lua/meta/qt.lua | 2 -- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/src/plugins/lua/bindings/qt.cpp b/src/plugins/lua/bindings/qt.cpp index 8b8cef7301a..6f4daeb5862 100644 --- a/src/plugins/lua/bindings/qt.cpp +++ b/src/plugins/lua/bindings/qt.cpp @@ -152,11 +152,8 @@ void setupQtModule() "AppDataLocation", QStandardPaths::AppDataLocation, "AppConfigLocation", QStandardPaths::AppConfigLocation, "PublicShareLocation", QStandardPaths::PublicShareLocation, - "TemplatesLocation", QStandardPaths::TemplatesLocation, - "StateLocation", QStandardPaths::StateLocation, - "GenericStateLocation", QStandardPaths::GenericStateLocation - ) - ); + "TemplatesLocation", QStandardPaths::TemplatesLocation + )); // clang-format on return qt; diff --git a/src/plugins/lua/meta/qt.lua b/src/plugins/lua/meta/qt.lua index 0c819164c46..168c8092171 100644 --- a/src/plugins/lua/meta/qt.lua +++ b/src/plugins/lua/meta/qt.lua @@ -134,8 +134,6 @@ qt.QStandardPaths = { AppConfigLocation = 0, PublicShareLocation = 0, TemplatesLocation = 0, - StateLocation = 0, - GenericStateLocation = 0, } } From 6309a3c8d72977156c5699d1b51ea4ba76c3cb2e Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Mon, 7 Oct 2024 12:05:15 +0200 Subject: [PATCH 40/76] ClangFormat: Fix terminology It is either `ClangFormat` (the product) or `clang-format` (the executable). Change-Id: I018abd8c6f3d33a7d93259f79ce09174e451a5df Reviewed-by: Artem Sokolovskii Reviewed-by: Leena Miettinen --- share/qtcreator/translations/qtcreator_de.ts | 8 ++++---- share/qtcreator/translations/qtcreator_fr.ts | 8 ++++---- src/plugins/beautifier/beautifiertool.cpp | 2 +- src/plugins/beautifier/clangformat/clangformat.cpp | 6 +++--- .../clangformat/clangformatglobalconfigwidget.cpp | 10 ++++++---- 5 files changed, 18 insertions(+), 16 deletions(-) diff --git a/share/qtcreator/translations/qtcreator_de.ts b/share/qtcreator/translations/qtcreator_de.ts index f645ae120b9..8bc892f3070 100644 --- a/share/qtcreator/translations/qtcreator_de.ts +++ b/share/qtcreator/translations/qtcreator_de.ts @@ -15239,12 +15239,12 @@ Zum Beispiel bewirkt die Angabe "Revision: 15" dass der Branch auf Rev Fallback-Stil: - Clang Format command: - Ausführbare Datei von Clang Format: + ClangFormat command: + Ausführbare Datei von ClangFormat: - Clang Format - Clang Format + ClangFormat + ClangFormat Use file uncrustify.cfg defined in project files diff --git a/share/qtcreator/translations/qtcreator_fr.ts b/share/qtcreator/translations/qtcreator_fr.ts index 7b728df9070..6014cf39f1d 100644 --- a/share/qtcreator/translations/qtcreator_fr.ts +++ b/share/qtcreator/translations/qtcreator_fr.ts @@ -15352,12 +15352,12 @@ Par exemple, « Revision : 15 » laissera la branche à la révis Style de repli : - Clang Format command: - Commande de Clang Format : + ClangFormat command: + Commande de ClangFormat : - Clang Format - Clang Format + ClangFormat + ClangFormat No description available. diff --git a/src/plugins/beautifier/beautifiertool.cpp b/src/plugins/beautifier/beautifiertool.cpp index 2914b5c58c0..9e55cf18363 100644 --- a/src/plugins/beautifier/beautifiertool.cpp +++ b/src/plugins/beautifier/beautifiertool.cpp @@ -150,7 +150,7 @@ AbstractSettings::AbstractSettings(const QString &name, const QString &ending) command.setSettingsKey("command"); command.setExpectedKind(PathChooser::ExistingCommand); command.setCommandVersionArguments({"--version"}); - command.setPromptDialogTitle(BeautifierTool::msgCommandPromptDialogTitle("Clang Format")); + command.setPromptDialogTitle(BeautifierTool::msgCommandPromptDialogTitle("ClangFormat")); command.setValidatePlaceHolder(true); command.addOnChanged(this, [this] { m_version = {}; version(); }); diff --git a/src/plugins/beautifier/clangformat/clangformat.cpp b/src/plugins/beautifier/clangformat/clangformat.cpp index 14c7313503f..7a250d6b94a 100644 --- a/src/plugins/beautifier/clangformat/clangformat.cpp +++ b/src/plugins/beautifier/clangformat/clangformat.cpp @@ -54,8 +54,8 @@ public: : AbstractSettings(SETTINGS_NAME, ".clang-format") { command.setDefaultValue("clang-format"); - command.setPromptDialogTitle(BeautifierTool::msgCommandPromptDialogTitle("Clang Format")); - command.setLabelText(Tr::tr("Clang Format command:")); + command.setPromptDialogTitle(BeautifierTool::msgCommandPromptDialogTitle("ClangFormat")); + command.setLabelText(Tr::tr("ClangFormat command:")); usePredefinedStyle.setSettingsKey("usePredefinedStyle"); usePredefinedStyle.setDefaultValue(true); @@ -530,7 +530,7 @@ public: ClangFormatSettingsPage() { setId("ClangFormat"); - setDisplayName(Tr::tr("Clang Format")); + setDisplayName(Tr::tr("ClangFormat")); setCategory(Constants::OPTION_CATEGORY); setWidgetCreator([] { return new ClangFormatSettingsPageWidget; }); } diff --git a/src/plugins/clangformat/clangformatglobalconfigwidget.cpp b/src/plugins/clangformat/clangformatglobalconfigwidget.cpp index 7134ecd2e37..86bca4e40d4 100644 --- a/src/plugins/clangformat/clangformatglobalconfigwidget.cpp +++ b/src/plugins/clangformat/clangformatglobalconfigwidget.cpp @@ -375,9 +375,11 @@ public: private: void slotImportClicked() final { - const FilePath filePath = - FileUtils::getOpenFilePath(this, Tr::tr("Import Code Format"), {}, - Tr::tr("Clang Format (*clang-format*);;All files (*)")); + const FilePath filePath = FileUtils::getOpenFilePath( + this, + Tr::tr("Import Code Format"), + {}, + Tr::tr("ClangFormat (*clang-format*);;All files (*)")); if (!filePath.isEmpty()) { QString name = QInputDialog::getText( this, @@ -407,7 +409,7 @@ private: this, Tr::tr("Export Code Format"), FileUtils::homePath(), - Tr::tr("Clang Format (*clang-format*);;All files (*)")); + Tr::tr("ClangFormat (*clang-format*);;All files (*)")); if (!filePath.isEmpty()) { FilePath clangFormatFile = filePathToCurrentSettings(currentPreferences); clangFormatFile.copyFile(filePath); From 7294c5652ec413b24d3b4f47ab16a7230ecc2bdc Mon Sep 17 00:00:00 2001 From: Marcus Tillmanns Date: Mon, 7 Oct 2024 13:51:47 +0200 Subject: [PATCH 41/76] Wizards: Add include(GNUInstallDirs) Change-Id: Ib61a9c8dee735dab0799f5b10a1f114c82c84fba Reviewed-by: Eike Ziller --- .../templates/wizards/projects/consoleapp/CMakeLists-Qt6.txt | 2 ++ .../wizards/projects/qtwidgetsapplication/CMakeLists-Qt6.txt | 2 ++ 2 files changed, 4 insertions(+) diff --git a/share/qtcreator/templates/wizards/projects/consoleapp/CMakeLists-Qt6.txt b/share/qtcreator/templates/wizards/projects/consoleapp/CMakeLists-Qt6.txt index a4161a01f5d..31e0827243f 100644 --- a/share/qtcreator/templates/wizards/projects/consoleapp/CMakeLists-Qt6.txt +++ b/share/qtcreator/templates/wizards/projects/consoleapp/CMakeLists-Qt6.txt @@ -25,6 +25,8 @@ target_link_libraries(%{ProjectName} Qt::Core ) +include(GNUInstallDirs) + install(TARGETS %{ProjectName} BUNDLE DESTINATION . RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} diff --git a/share/qtcreator/templates/wizards/projects/qtwidgetsapplication/CMakeLists-Qt6.txt b/share/qtcreator/templates/wizards/projects/qtwidgetsapplication/CMakeLists-Qt6.txt index 7f63269cdd0..fab47ee1a65 100644 --- a/share/qtcreator/templates/wizards/projects/qtwidgetsapplication/CMakeLists-Qt6.txt +++ b/share/qtcreator/templates/wizards/projects/qtwidgetsapplication/CMakeLists-Qt6.txt @@ -32,6 +32,8 @@ target_link_libraries(%{ProjectName} Qt::Widgets ) +include(GNUInstallDirs) + install(TARGETS %{ProjectName} BUNDLE DESTINATION . RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} From 0242ab89911f4e9f2ab7b00c7a457dad153b1b0b Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Mon, 7 Oct 2024 12:55:38 +0200 Subject: [PATCH 42/76] QmlJSEditor: Do not clear out unrelated issues MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Yet another fallout of 1b57e95c14d78119bbf8358bb52dfc1be0cde140. Fixes: QTCREATORBUG-31760 Change-Id: Ia08e14a04eead91021c48598c0b42865fbc944bd Reviewed-by: André Hartmann --- src/plugins/qmljseditor/qmltaskmanager.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/plugins/qmljseditor/qmltaskmanager.cpp b/src/plugins/qmljseditor/qmltaskmanager.cpp index 5388b6d5522..7bb85d9acca 100644 --- a/src/plugins/qmljseditor/qmltaskmanager.cpp +++ b/src/plugins/qmljseditor/qmltaskmanager.cpp @@ -139,9 +139,6 @@ void QmlTaskManager::updateSemanticMessagesNow() void QmlTaskManager::updateMessagesNow(bool updateSemantic) { - // clear out the qmllint warnings when qmlls was disabled after being enabled - TaskHub::clearTasks(ProjectExplorer::Constants::TASK_CATEGORY_COMPILE); - // don't restart a small update if a big one is running if (!updateSemantic && m_updatingSemantic) return; From 623854d4527f1dee850fe1a646c10cc2a29bfdd2 Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Mon, 7 Oct 2024 14:46:34 +0200 Subject: [PATCH 43/76] Force minimum of Qt 6.5 for "Qt 6" version of CMake wizards The console and widgets app got a new template for simplified CMake files with Qt 6. These require Qt 6.5 or later, so state that both in the label and the CMake files. Change-Id: I23e39b82017f8f11ab720fa701786912e46ea26d Reviewed-by: Leena Miettinen Reviewed-by: Marcus Tillmanns --- .../templates/wizards/projects/consoleapp/CMakeLists-Qt6.txt | 4 ++-- .../templates/wizards/projects/consoleapp/wizard.json | 2 +- .../wizards/projects/qtwidgetsapplication/CMakeLists-Qt6.txt | 4 ++-- .../wizards/projects/qtwidgetsapplication/wizard.json | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/share/qtcreator/templates/wizards/projects/consoleapp/CMakeLists-Qt6.txt b/share/qtcreator/templates/wizards/projects/consoleapp/CMakeLists-Qt6.txt index 31e0827243f..162310fb356 100644 --- a/share/qtcreator/templates/wizards/projects/consoleapp/CMakeLists-Qt6.txt +++ b/share/qtcreator/templates/wizards/projects/consoleapp/CMakeLists-Qt6.txt @@ -2,9 +2,9 @@ cmake_minimum_required(VERSION 3.19) project(%{ProjectName} LANGUAGES CXX) @if %{HasTranslation} -find_package(Qt6 REQUIRED COMPONENTS Core LinguistTools) +find_package(Qt6 6.5 REQUIRED COMPONENTS Core LinguistTools) @else -find_package(Qt6 REQUIRED COMPONENTS Core) +find_package(Qt6 6.5 REQUIRED COMPONENTS Core) @endif qt_standard_project_setup() diff --git a/share/qtcreator/templates/wizards/projects/consoleapp/wizard.json b/share/qtcreator/templates/wizards/projects/consoleapp/wizard.json index 9e59d4d8c33..759ec220f85 100644 --- a/share/qtcreator/templates/wizards/projects/consoleapp/wizard.json +++ b/share/qtcreator/templates/wizards/projects/consoleapp/wizard.json @@ -58,7 +58,7 @@ "condition": "%{JS: value('Plugins').indexOf('CMakeProjectManager') >= 0}" }, { - "trKey": "CMake for Qt 6", + "trKey": "CMake for Qt 6.5 and Later", "value": "cmake-qt6", "condition": "%{JS: value('Plugins').indexOf('CMakeProjectManager') >= 0}" }, diff --git a/share/qtcreator/templates/wizards/projects/qtwidgetsapplication/CMakeLists-Qt6.txt b/share/qtcreator/templates/wizards/projects/qtwidgetsapplication/CMakeLists-Qt6.txt index fab47ee1a65..f2395d7a0b5 100644 --- a/share/qtcreator/templates/wizards/projects/qtwidgetsapplication/CMakeLists-Qt6.txt +++ b/share/qtcreator/templates/wizards/projects/qtwidgetsapplication/CMakeLists-Qt6.txt @@ -2,9 +2,9 @@ cmake_minimum_required(VERSION 3.19) project(%{ProjectName} LANGUAGES CXX) @if %{HasTranslation} -find_package(Qt6 REQUIRED COMPONENTS Core Widgets LinguistTools) +find_package(Qt6 6.5 REQUIRED COMPONENTS Core Widgets LinguistTools) @else -find_package(Qt6 REQUIRED COMPONENTS Core Widgets) +find_package(Qt6 6.5 REQUIRED COMPONENTS Core Widgets) @endif qt_standard_project_setup() diff --git a/share/qtcreator/templates/wizards/projects/qtwidgetsapplication/wizard.json b/share/qtcreator/templates/wizards/projects/qtwidgetsapplication/wizard.json index 9e3fd48bca3..de20629065d 100644 --- a/share/qtcreator/templates/wizards/projects/qtwidgetsapplication/wizard.json +++ b/share/qtcreator/templates/wizards/projects/qtwidgetsapplication/wizard.json @@ -64,7 +64,7 @@ "condition": "%{JS: value('Plugins').indexOf('CMakeProjectManager') >= 0}" }, { - "trKey": "CMake for Qt 6", + "trKey": "CMake for Qt 6.5 and Later", "value": "cmake-qt6", "condition": "%{JS: value('Plugins').indexOf('CMakeProjectManager') >= 0}" }, From 1d06ed5d905e3eb2f9889b04f552445de9a4d229 Mon Sep 17 00:00:00 2001 From: Alessandro Portale Date: Mon, 7 Oct 2024 13:18:34 +0200 Subject: [PATCH 44/76] ExtensionManager: Fix warnings about detaching containers Change-Id: I9ed40d7c464c1690c1091016691591f34e70fb6c Reviewed-by: Artem Sokolovskii --- src/plugins/extensionmanager/extensionsmodel.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/plugins/extensionmanager/extensionsmodel.cpp b/src/plugins/extensionmanager/extensionsmodel.cpp index e28f716e90f..8639fa1457d 100644 --- a/src/plugins/extensionmanager/extensionsmodel.cpp +++ b/src/plugins/extensionmanager/extensionsmodel.cpp @@ -49,7 +49,7 @@ public: void ExtensionsModelPrivate::addUnlistedLocalPlugins() { QStringList responseExtensions; - for (const QJsonValueConstRef &responseItem : responseItems) + for (const QJsonValueConstRef &responseItem : qAsConst(responseItems)) responseExtensions << responseItem.toObject().value("id").toString(); localPlugins.clear(); @@ -114,7 +114,7 @@ QVariant ExtensionsModelPrivate::dataFromRemotePlugin(const QJsonObject &json, i const QJsonArray sources = json.value("sources").toArray(); const QString thisPlatform = customOsTypeToString(HostOsInfo::hostOs()); const QString thisArch = QSysInfo::currentCpuArchitecture(); - for (const QJsonValue source : sources) { + for (const QJsonValue &source : sources) { const QJsonObject sourceObject = source.toObject(); const QJsonObject platform = sourceObject.value("platform").toObject(); if (platform.isEmpty() // Might be a Lua plugin @@ -296,8 +296,8 @@ QModelIndex ExtensionsModel::indexOfId(const QString &extensionId) const if (localIndex >= 0) return index(d->responseItems.count() + localIndex); - for (int remoteIndex = 0; const QJsonValueConstRef vlaue : d->responseItems) { - if (vlaue.toObject().value(EXTENSION_KEY_ID) == extensionId) + for (int remoteIndex = 0; const QJsonValueConstRef &value : std::as_const(d->responseItems)) { + if (value.toObject().value(EXTENSION_KEY_ID) == extensionId) return index(remoteIndex); ++remoteIndex; } From 92e6b7061be8c2215b0eb863c1d0f90ec4975eca Mon Sep 17 00:00:00 2001 From: David Schulz Date: Fri, 4 Oct 2024 06:12:04 +0200 Subject: [PATCH 45/76] ProjectExplorer: remove label from ArgumentsAspect BaseAspect already contain that information Change-Id: I55fea913c2eec536b8946dc69a1d62e4d8ced7ac Reviewed-by: Marcus Tillmanns --- .../projectexplorer/runconfigurationaspects.cpp | 13 ++----------- .../projectexplorer/runconfigurationaspects.h | 2 -- 2 files changed, 2 insertions(+), 13 deletions(-) diff --git a/src/plugins/projectexplorer/runconfigurationaspects.cpp b/src/plugins/projectexplorer/runconfigurationaspects.cpp index bc4e1369bd5..936a28a849c 100644 --- a/src/plugins/projectexplorer/runconfigurationaspects.cpp +++ b/src/plugins/projectexplorer/runconfigurationaspects.cpp @@ -314,12 +314,11 @@ ArgumentsAspect::ArgumentsAspect(AspectContainer *container) : BaseAspect(container) { setDisplayName(Tr::tr("Arguments")); + setLabelText(Tr::tr("Command line arguments:")); setId("ArgumentsAspect"); setSettingsKey("RunConfiguration.Arguments"); addDataExtractor(this, &ArgumentsAspect::arguments, &Data::arguments); - - m_labelText = Tr::tr("Command line arguments:"); } void ArgumentsAspect::setMacroExpander(const MacroExpander *expander) @@ -369,14 +368,6 @@ void ArgumentsAspect::setArguments(const QString &arguments) m_multiLineChooser->setPlainText(arguments); } -/*! - Sets the displayed label text to \a labelText. -*/ -void ArgumentsAspect::setLabelText(const QString &labelText) -{ - m_labelText = labelText; -} - /*! Adds a button to reset the main value of this aspect to the value computed by \a resetter. @@ -502,7 +493,7 @@ void ArgumentsAspect::addToLayoutImpl(Layout &builder) containerLayout->setAlignment(m_resetButton, Qt::AlignTop); } - builder.addItems({m_labelText, container}); + addLabeledItem(builder, container); } /*! diff --git a/src/plugins/projectexplorer/runconfigurationaspects.h b/src/plugins/projectexplorer/runconfigurationaspects.h index c27cb18f10a..629b3059e2a 100644 --- a/src/plugins/projectexplorer/runconfigurationaspects.h +++ b/src/plugins/projectexplorer/runconfigurationaspects.h @@ -100,7 +100,6 @@ public: QString unexpandedArguments() const; void setArguments(const QString &arguments); - void setLabelText(const QString &labelText); void setResetter(const std::function &resetter); void resetArguments(); void setMacroExpander(const Utils::MacroExpander *macroExpander); @@ -117,7 +116,6 @@ private: QWidget *setupChooser(); QString m_arguments; - QString m_labelText; QPointer m_chooser; QPointer m_multiLineChooser; QPointer m_multiLineButton; From ffd8f8326d5d964c893484df4bfd53ad43a68252 Mon Sep 17 00:00:00 2001 From: David Schulz Date: Fri, 4 Oct 2024 06:09:09 +0200 Subject: [PATCH 46/76] ProjectExplorer: disable workspace runconfiguration container ... instead of the individual aspects. The widgets of ArgumentsAspect and WorkingDirectoryAspect needs to be registered as subwidgets. Otherwise the enabled state is not propagated from the container to the individual aspects. Change-Id: I6f96db8041386b41d6414ec865e7213940bbe78f Reviewed-by: Marcus Tillmanns --- src/libs/utils/aspects.cpp | 8 ++++++++ src/libs/utils/aspects.h | 1 + src/plugins/projectexplorer/runconfigurationaspects.cpp | 7 ++++++- src/plugins/projectexplorer/workspaceproject.cpp | 4 +--- 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/libs/utils/aspects.cpp b/src/libs/utils/aspects.cpp index 07150b3d00a..bd84a41614a 100644 --- a/src/libs/utils/aspects.cpp +++ b/src/libs/utils/aspects.cpp @@ -294,6 +294,14 @@ void BaseAspect::addLabeledItem(Layout &parent, QWidget *widget) } } +void BaseAspect::addLabeledItems(Layouting::Layout &parent, const QList &widgets) +{ + if (QLabel *l = createLabel()) + parent.addItem(l); + for (auto widget : widgets) + parent.addItem(widget); +} + /*! Sets \a labelText as text for the separate label in the visual representation of this aspect. diff --git a/src/libs/utils/aspects.h b/src/libs/utils/aspects.h index f1c59c908b2..6cac1b6e8e2 100644 --- a/src/libs/utils/aspects.h +++ b/src/libs/utils/aspects.h @@ -237,6 +237,7 @@ protected: QLabel *createLabel(); void addLabeledItem(Layouting::Layout &parent, QWidget *widget); + void addLabeledItems(Layouting::Layout &parent, const QList &widgets); void setDataCreatorHelper(const DataCreator &creator) const; void setDataClonerHelper(const DataCloner &cloner) const; diff --git a/src/plugins/projectexplorer/runconfigurationaspects.cpp b/src/plugins/projectexplorer/runconfigurationaspects.cpp index 936a28a849c..a7d2186995c 100644 --- a/src/plugins/projectexplorer/runconfigurationaspects.cpp +++ b/src/plugins/projectexplorer/runconfigurationaspects.cpp @@ -157,6 +157,7 @@ WorkingDirectoryAspect::WorkingDirectoryAspect(AspectContainer *container) : BaseAspect(container) { setDisplayName(Tr::tr("Working Directory")); + setLabelText(Tr::tr("Working directory:")); setId("WorkingDirectoryAspect"); setSettingsKey("RunConfiguration.WorkingDirectory"); } @@ -206,7 +207,10 @@ void WorkingDirectoryAspect::addToLayoutImpl(Layout &builder) m_chooser->setReadOnly(isReadOnly()); m_resetButton->setEnabled(!isReadOnly()); - builder.addItems({Tr::tr("Working directory:"), m_chooser.data(), m_resetButton.data()}); + registerSubWidget(m_chooser); + registerSubWidget(m_resetButton); + + addLabeledItems(builder, {m_chooser.data(), m_resetButton.data()}); } void WorkingDirectoryAspect::resetPath() @@ -492,6 +496,7 @@ void ArgumentsAspect::addToLayoutImpl(Layout &builder) containerLayout->addWidget(m_resetButton); containerLayout->setAlignment(m_resetButton, Qt::AlignTop); } + registerSubWidget(container); addLabeledItem(builder, container); } diff --git a/src/plugins/projectexplorer/workspaceproject.cpp b/src/plugins/projectexplorer/workspaceproject.cpp index 61e2b4b6894..f5ca390bc85 100644 --- a/src/plugins/projectexplorer/workspaceproject.cpp +++ b/src/plugins/projectexplorer/workspaceproject.cpp @@ -368,7 +368,6 @@ public: const BuildTargetInfo bti = buildTargetInfo(); executable.setLabelText(Tr::tr("Executable:")); - executable.setReadOnly(true); executable.setValue(bti.targetFilePath); auto argumentsAsString = [this]() { @@ -378,12 +377,10 @@ public: }; arguments.setLabelText(Tr::tr("Arguments:")); - arguments.setReadOnly(true); arguments.setMacroExpander(macroExpander()); arguments.setArguments(argumentsAsString()); workingDirectory.setLabelText(Tr::tr("Working directory:")); - workingDirectory.setReadOnly(true); workingDirectory.setDefaultWorkingDirectory(bti.workingDirectory); setCommandLineGetter([this] { @@ -405,6 +402,7 @@ public: }); connect(target, &Target::buildSystemUpdated, this, &RunConfiguration::update); + setEnabled(false); } TextDisplay hint{this}; From ef2d83c7b74cba89e2cd075c510336f0a6d703fd Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Mon, 7 Oct 2024 15:04:36 +0200 Subject: [PATCH 47/76] QtSupport: Fix QtVersionItem::uniqueId() Amends 7540dbeb8ea091c8a39adc158f91384cc47e9bf2. Change-Id: I137c5e467c312f40b6645ccf7436dc812793084a Reviewed-by: Eike Ziller --- src/plugins/qtsupport/qtoptionspage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/qtsupport/qtoptionspage.cpp b/src/plugins/qtsupport/qtoptionspage.cpp index 95b8d19a9c7..e817495e363 100644 --- a/src/plugins/qtsupport/qtoptionspage.cpp +++ b/src/plugins/qtsupport/qtoptionspage.cpp @@ -230,7 +230,7 @@ QVariant QtVersionItem::data(int column, int role) const int QtVersionItem::uniqueId() const { if (const auto v = std::get_if(&m_version)) - return v ? (*v)->uniqueId() : -1; + return *v ? (*v)->uniqueId() : -1; return *std::get_if(&m_version); } From 836d555742d8e0797daac27594d854b22adbf0d5 Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Mon, 7 Oct 2024 13:40:42 +0200 Subject: [PATCH 48/76] Crashpad: Fix compilation on Windows It was trying to modify a const QString. Change-Id: I431abb387cf964d4e8869371fd8f7f04c0b055e7 Reviewed-by: Cristian Adam --- src/app/main.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/app/main.cpp b/src/app/main.cpp index 9da6030f5e5..755169fc8db 100644 --- a/src/app/main.cpp +++ b/src/app/main.cpp @@ -418,12 +418,11 @@ bool startCrashpad(const AppInfo &appInfo, bool crashReportingEnabled) const QString databasePath = appInfo.crashReports.path(); const QString handlerPath = (appInfo.libexec / "crashpad_handler").path(); #ifdef Q_OS_WIN - handlerPath += ".exe"; base::FilePath database(databasePath.toStdWString()); - base::FilePath handler(handlerPath.toStdWString()); + base::FilePath handler(HostOsInfo::withExecutableSuffix(handlerPath).toStdWString()); #elif defined(Q_OS_MACOS) || defined(Q_OS_LINUX) base::FilePath database(databasePath.toStdString()); - base::FilePath handler(handlerPath.toStdString()); + base::FilePath handler(HostOsInfo::withExecutableSuffix(handlerPath).toStdString()); #endif std::unique_ptr db = CrashReportDatabase::Initialize(database); From 6c668279df7d812bb8fa26ac67e837c51276ffae Mon Sep 17 00:00:00 2001 From: Pino Toscano Date: Sat, 5 Oct 2024 03:39:06 +0200 Subject: [PATCH 49/76] AppStatisticMonitor: add empty data provider for non-implemented OSes Add a NullDataProvider to support building & running on OSes that do not have an actual data provider implemented (currently Linux, Windows, macOS). Limit also the instantiation of a LinuxDataProvider to Linux, as that data provider is built only on Linux. Change-Id: Ia9bea9e6d76ee6558efe62e16a9fcf559ab0a4d7 Reviewed-by: Artem Sokolovskii --- .../appstatisticsmonitor/idataprovider.cpp | 24 ++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/plugins/appstatisticsmonitor/idataprovider.cpp b/src/plugins/appstatisticsmonitor/idataprovider.cpp index 23d443c76e2..0d5d8a2fe8c 100644 --- a/src/plugins/appstatisticsmonitor/idataprovider.cpp +++ b/src/plugins/appstatisticsmonitor/idataprovider.cpp @@ -329,14 +329,36 @@ private: }; #endif +// ------------------------- NullDataProvider -------------------------------- + +class NullDataProvider : public IDataProvider +{ +public: + NullDataProvider(qint64 pid, QObject *parent = nullptr) + : IDataProvider(pid, parent) + {} + + double getCpuConsumption() + { + return 0.0; + } + + double getMemoryConsumption() + { + return 0.0; + } +}; + IDataProvider *createDataProvider(qint64 pid) { #ifdef Q_OS_WIN return new WindowsDataProvider(pid); #elif defined(Q_OS_MACOS) return new MacDataProvider(pid); -#else // Q_OS_LINUX +#elif defined(Q_OS_LINUX) return new LinuxDataProvider(pid); +#else + return new NullDataProvider(pid); #endif } From cd85bed2f720d7d143079c222b613e084232d247 Mon Sep 17 00:00:00 2001 From: David Schulz Date: Mon, 7 Oct 2024 12:53:29 +0200 Subject: [PATCH 50/76] ProjectExplorer: make cloned workspace run configurations editable Change-Id: Ic2c90da28f3cc498a698e948d99b13e296c3ca0d Reviewed-by: Marcus Tillmanns --- src/plugins/projectexplorer/project.cpp | 2 +- .../projectexplorer/runconfiguration.cpp | 14 ++++---- .../projectexplorer/runconfiguration.h | 3 +- .../runsettingspropertiespage.cpp | 2 +- .../projectexplorer/workspaceproject.cpp | 32 +++++++++++++------ 5 files changed, 34 insertions(+), 19 deletions(-) diff --git a/src/plugins/projectexplorer/project.cpp b/src/plugins/projectexplorer/project.cpp index 5ca9b57b3ee..d1a9f2af869 100644 --- a/src/plugins/projectexplorer/project.cpp +++ b/src/plugins/projectexplorer/project.cpp @@ -547,7 +547,7 @@ bool Project::copySteps(Target *sourceTarget, Target *newTarget) } for (RunConfiguration *sourceRc : sourceTarget->runConfigurations()) { - RunConfiguration *newRc = RunConfigurationFactory::clone(newTarget, sourceRc); + RunConfiguration *newRc = sourceRc->clone(newTarget); if (!newRc) { runconfigurationError << sourceRc->displayName(); continue; diff --git a/src/plugins/projectexplorer/runconfiguration.cpp b/src/plugins/projectexplorer/runconfiguration.cpp index f5b858d141d..edeb1d1e609 100644 --- a/src/plugins/projectexplorer/runconfiguration.cpp +++ b/src/plugins/projectexplorer/runconfiguration.cpp @@ -356,6 +356,13 @@ void RunConfiguration::update() ProjectExplorerPlugin::updateRunActions(); } +RunConfiguration *RunConfiguration::clone(Target *parent) +{ + Store map; + toMap(map); + return RunConfigurationFactory::restore(parent, map); +} + BuildTargetInfo RunConfiguration::buildTargetInfo() const { BuildSystem *bs = target()->buildSystem(); @@ -656,13 +663,6 @@ RunConfiguration *RunConfigurationFactory::restore(Target *parent, const Store & return nullptr; } -RunConfiguration *RunConfigurationFactory::clone(Target *parent, RunConfiguration *source) -{ - Store map; - source->toMap(map); - return restore(parent, map); -} - const QList RunConfigurationFactory::creatorsForTarget(Target *parent) { QList items; diff --git a/src/plugins/projectexplorer/runconfiguration.h b/src/plugins/projectexplorer/runconfiguration.h index 113bc54426b..9fa2a21633c 100644 --- a/src/plugins/projectexplorer/runconfiguration.h +++ b/src/plugins/projectexplorer/runconfiguration.h @@ -174,6 +174,8 @@ public: const Utils::MacroExpander *macroExpander() const { return &m_expander; } + virtual RunConfiguration *clone(Target *parent); + protected: RunConfiguration(Target *target, Utils::Id id); @@ -233,7 +235,6 @@ public: virtual ~RunConfigurationFactory(); static RunConfiguration *restore(Target *parent, const Utils::Store &map); - static RunConfiguration *clone(Target *parent, RunConfiguration *source); static const QList creatorsForTarget(Target *parent); Utils::Id runConfigurationId() const { return m_runConfigurationId; } diff --git a/src/plugins/projectexplorer/runsettingspropertiespage.cpp b/src/plugins/projectexplorer/runsettingspropertiespage.cpp index ec18f68c603..c10870c2af0 100644 --- a/src/plugins/projectexplorer/runsettingspropertiespage.cpp +++ b/src/plugins/projectexplorer/runsettingspropertiespage.cpp @@ -210,7 +210,7 @@ void RunSettingsWidget::cloneRunConfiguration() if (name.isEmpty()) return; - RunConfiguration *newRc = RunConfigurationFactory::clone(m_target, activeRunConfiguration); + RunConfiguration *newRc = activeRunConfiguration->clone(m_target); if (!newRc) return; diff --git a/src/plugins/projectexplorer/workspaceproject.cpp b/src/plugins/projectexplorer/workspaceproject.cpp index f5ca390bc85..40637cb7ce7 100644 --- a/src/plugins/projectexplorer/workspaceproject.cpp +++ b/src/plugins/projectexplorer/workspaceproject.cpp @@ -235,6 +235,8 @@ void WorkspaceBuildSystem::reparse(bool force) if (force || oldFilters != m_filters) scan(target()->project()->projectDirectory()); + else + emitBuildSystemUpdated(); } void WorkspaceBuildSystem::triggerParsing() @@ -369,6 +371,7 @@ public: const BuildTargetInfo bti = buildTargetInfo(); executable.setLabelText(Tr::tr("Executable:")); executable.setValue(bti.targetFilePath); + executable.setSettingsKey("Workspace.RunConfiguration.Executable"); auto argumentsAsString = [this]() { return CommandLine{ @@ -379,36 +382,47 @@ public: arguments.setLabelText(Tr::tr("Arguments:")); arguments.setMacroExpander(macroExpander()); arguments.setArguments(argumentsAsString()); + arguments.setSettingsKey("Workspace.RunConfiguration.Arguments"); workingDirectory.setLabelText(Tr::tr("Working directory:")); workingDirectory.setDefaultWorkingDirectory(bti.workingDirectory); + workingDirectory.setSettingsKey("Workspace.RunConfiguration.WorkingDirectory"); setCommandLineGetter([this] { - const BuildTargetInfo bti = buildTargetInfo(); - CommandLine cmdLine{ - macroExpander()->expand(bti.targetFilePath), - Utils::transform( - bti.additionalData.toMap()["arguments"].toStringList(), - [this](const QString &arg) { return macroExpander()->expand(arg); })}; - - return cmdLine; + return CommandLine(executable.effectiveBinary(), + arguments.arguments(), + CommandLine::Raw); }); setUpdater([this, argumentsAsString] { + if (enabled.value()) // skip the update for cloned run configurations + return; const BuildTargetInfo bti = buildTargetInfo(); executable.setValue(bti.targetFilePath); arguments.setArguments(argumentsAsString()); workingDirectory.setDefaultWorkingDirectory(bti.workingDirectory); }); + auto enabledUpdater = [this] { setEnabled(enabled.value()); }; + connect(&enabled, &BaseAspect::changed, this, enabledUpdater); + connect(this, &AspectContainer::fromMapFinished, this, enabledUpdater); connect(target, &Target::buildSystemUpdated, this, &RunConfiguration::update); - setEnabled(false); + enabledUpdater(); + enabled.setSettingsKey("Workspace.RunConfiguration.Enabled"); + } + + RunConfiguration *clone(Target *parent) override + { + RunConfiguration *result = RunConfiguration::clone(parent); + dynamic_cast(result)->enabled.setValue(true); + return result; } TextDisplay hint{this}; FilePathAspect executable{this}; ArgumentsAspect arguments{this}; WorkingDirectoryAspect workingDirectory{this}; + BoolAspect enabled{this}; }; class WorkspaceProjectRunConfigurationFactory : public RunConfigurationFactory From 075876e8b2377d89ddf2a6c43b503d61b6fde5b9 Mon Sep 17 00:00:00 2001 From: Pino Toscano Date: Sat, 5 Oct 2024 03:27:02 +0200 Subject: [PATCH 51/76] ProcessStub: limit ptrace only to Linux The current code tries to use Linux ptrace on any OSes different than Windows and macOS, leading to build failure on other non-Linux OSes. Fix this in a couple of places: - in onInferiorStarted(), create a new Linux block for the code not run on Windows and macOS - in onInferiorStarted(), add a new block for any other OS to do the needed sendPid() call - in setupUnixInferior(), drop the global !Q_OS_WIN, and limit the setChildProcessModifier() call with ptrace calls to Linux Change-Id: Idfde3ee890eb94c6972343b70d0fe639a36343ae Reviewed-by: Marcus Tillmanns --- src/tools/process_stub/main.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/tools/process_stub/main.cpp b/src/tools/process_stub/main.cpp index 3749333e460..1ab190b652d 100644 --- a/src/tools/process_stub/main.cpp +++ b/src/tools/process_stub/main.cpp @@ -254,8 +254,7 @@ void onInferiorStarted() // In debug mode we use the poll timer to send the pid. if (!debugMode) sendPid(inferiorId); -#else - +#elif defined(Q_OS_LINUX) if (debugMode) { qCInfo(log) << "Waiting for SIGTRAP from inferiors execve ..."; if (!waitFor(SIGTRAP)) @@ -271,12 +270,13 @@ void onInferiorStarted() qCInfo(log) << "Sending pid:" << inferiorId; sendPid(inferiorId); +#else + sendPid(inferiorId); #endif } void setupUnixInferior() { -#ifndef Q_OS_WIN if (debugMode) { qCInfo(log) << "Debug mode enabled"; #ifdef Q_OS_DARWIN @@ -287,7 +287,7 @@ void setupUnixInferior() // Suspend ourselves ... raise(SIGSTOP); }); -#else +#elif defined(Q_OS_LINUX) // PTRACE_TRACEME will stop execution of the child process as soon as execve is called. inferiorProcess.setChildProcessModifier([] { ptrace(PTRACE_TRACEME, 0, 0, 0); @@ -296,7 +296,6 @@ void setupUnixInferior() }); #endif } -#endif } void setupWindowsInferior() From c8f593e4dcdcf23e34662db843797f0f55930400 Mon Sep 17 00:00:00 2001 From: David Schulz Date: Fri, 27 Sep 2024 13:32:29 +0200 Subject: [PATCH 52/76] ProjectExplorer: disable project file defined build configurations So they cannot be edited, but reset this when cloning the build configuration. Change-Id: Ib1cd54ac7cca02ad0971149c48969e9db39a21c1 Reviewed-by: Christian Stenger --- src/libs/utils/aspects.cpp | 9 +++++++++ src/libs/utils/aspects.h | 3 ++- .../cmakebuildconfiguration.cpp | 2 +- .../incredibuild/commandbuilderaspect.cpp | 2 +- src/plugins/mcusupport/mcubuildstep.cpp | 2 +- src/plugins/projectexplorer/buildmanager.cpp | 4 ++-- src/plugins/projectexplorer/buildstep.cpp | 16 ++++++++-------- src/plugins/projectexplorer/buildstep.h | 8 +++++--- src/plugins/projectexplorer/buildstepspage.cpp | 10 +++++----- src/plugins/projectexplorer/workspaceproject.cpp | 6 ++++++ src/plugins/qbsprojectmanager/qbsproject.cpp | 2 +- .../appmanagercmakepackagestep.cpp | 2 +- .../appmanagerdeploypackagestep.cpp | 2 +- .../appmanagerinstallpackagestep.cpp | 2 +- 14 files changed, 44 insertions(+), 26 deletions(-) diff --git a/src/libs/utils/aspects.cpp b/src/libs/utils/aspects.cpp index bd84a41614a..0eeb083d877 100644 --- a/src/libs/utils/aspects.cpp +++ b/src/libs/utils/aspects.cpp @@ -3170,6 +3170,7 @@ void AspectContainer::addToLayoutImpl(Layouting::Layout &parent) void AspectContainer::registerAspect(BaseAspect *aspect, bool takeOwnership) { aspect->setAutoApply(isAutoApply()); + aspect->setEnabled(isEnabled()); d->m_items.append(aspect); if (takeOwnership) d->m_ownedItems.append(aspect); @@ -3324,6 +3325,14 @@ void AspectContainer::setUndoStack(QUndoStack *undoStack) aspect->setUndoStack(undoStack); } +void AspectContainer::setEnabled(bool enabled) +{ + BaseAspect::setEnabled(enabled); + + for (BaseAspect *aspect : std::as_const(d->m_items)) + aspect->setEnabled(enabled); +} + void AspectContainer::setMacroExpander(MacroExpander *expander) { BaseAspect::setMacroExpander(expander); diff --git a/src/libs/utils/aspects.h b/src/libs/utils/aspects.h index 6cac1b6e8e2..6c3b62cdbe7 100644 --- a/src/libs/utils/aspects.h +++ b/src/libs/utils/aspects.h @@ -98,7 +98,7 @@ public: QUndoStack *undoStack() const; bool isEnabled() const; - void setEnabled(bool enabled); + virtual void setEnabled(bool enabled); void setEnabler(BoolAspect *checker); bool isReadOnly() const; @@ -997,6 +997,7 @@ public: void setAutoApply(bool on) override; bool isDirty() override; void setUndoStack(QUndoStack *undoStack) override; + void setEnabled(bool enabled) override; void setMacroExpander(MacroExpander *expander); diff --git a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp index cccc08d4b59..31d0a4bbc8d 100644 --- a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp +++ b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp @@ -1946,7 +1946,7 @@ void CMakeBuildConfiguration::setBuildPresetToBuildSteps(const ProjectExplorer:: // Leave only the first build step enabled if (i > 0) - cbs->setEnabled(false); + cbs->setStepEnabled(false); } } diff --git a/src/plugins/incredibuild/commandbuilderaspect.cpp b/src/plugins/incredibuild/commandbuilderaspect.cpp index ea071123330..4655cde53e6 100644 --- a/src/plugins/incredibuild/commandbuilderaspect.cpp +++ b/src/plugins/incredibuild/commandbuilderaspect.cpp @@ -104,7 +104,7 @@ void CommandBuilderAspectPrivate::tryToMigrate() for (Utils::Id stepId : migratableSteps) { if (BuildStep *bs = m_buildStep->stepList()->firstStepWithId(stepId)) { m_activeCommandBuilder = p; - bs->setEnabled(false); + bs->setStepEnabled(false); m_buildStep->project()->saveSettings(); return; } diff --git a/src/plugins/mcusupport/mcubuildstep.cpp b/src/plugins/mcusupport/mcubuildstep.cpp index 3da8ee80759..706c3e6a2a8 100644 --- a/src/plugins/mcusupport/mcubuildstep.cpp +++ b/src/plugins/mcusupport/mcubuildstep.cpp @@ -198,7 +198,7 @@ void MCUBuildStepFactory::updateDeployStep(ProjectExplorer::Target *target, bool } else { if (!step) return; - step->setEnabled(enabled); + step->setStepEnabled(enabled); } } diff --git a/src/plugins/projectexplorer/buildmanager.cpp b/src/plugins/projectexplorer/buildmanager.cpp index db194b2551a..75df07a1167 100644 --- a/src/plugins/projectexplorer/buildmanager.cpp +++ b/src/plugins/projectexplorer/buildmanager.cpp @@ -964,7 +964,7 @@ bool BuildManager::buildLists(const QList &bsls, const QStringL const QString name = displayNameForStepId(list->id()); const QList steps = list->steps(); for (BuildStep *step : steps) - buildItems.append({step, step->enabled(), name}); + buildItems.append({step, step->stepEnabled(), name}); d->m_isDeploying = d->m_isDeploying || list->id() == Constants::BUILDSTEPS_DEPLOY; } @@ -977,7 +977,7 @@ bool BuildManager::buildLists(const QList &bsls, const QStringL void BuildManager::appendStep(BuildStep *step, const QString &name) { - buildQueueAppend({{step, step->enabled(), name}}); + buildQueueAppend({{step, step->stepEnabled(), name}}); } template diff --git a/src/plugins/projectexplorer/buildstep.cpp b/src/plugins/projectexplorer/buildstep.cpp index 19eb143d245..e614e1f9f18 100644 --- a/src/plugins/projectexplorer/buildstep.cpp +++ b/src/plugins/projectexplorer/buildstep.cpp @@ -129,14 +129,14 @@ QWidget *BuildStep::createConfigWidget() void BuildStep::fromMap(const Store &map) { - m_enabled = map.value(buildStepEnabledKey, true).toBool(); + m_stepEnabled = map.value(buildStepEnabledKey, true).toBool(); ProjectConfiguration::fromMap(map); } void BuildStep::toMap(Store &map) const { ProjectConfiguration::toMap(map); - map.insert(buildStepEnabledKey, m_enabled); + map.insert(buildStepEnabledKey, m_stepEnabled); } BuildConfiguration *BuildStep::buildConfiguration() const @@ -235,12 +235,12 @@ QVariant BuildStep::data(Id id) const return {}; } -void BuildStep::setEnabled(bool b) +void BuildStep::setStepEnabled(bool b) { - if (m_enabled == b) + if (m_stepEnabled == b) return; - m_enabled = b; - emit enabledChanged(); + m_stepEnabled = b; + emit stepEnabledChanged(); } BuildStepList *BuildStep::stepList() const @@ -248,9 +248,9 @@ BuildStepList *BuildStep::stepList() const return m_stepList; } -bool BuildStep::enabled() const +bool BuildStep::stepEnabled() const { - return m_enabled; + return m_stepEnabled; } BuildStepFactory::BuildStepFactory() diff --git a/src/plugins/projectexplorer/buildstep.h b/src/plugins/projectexplorer/buildstep.h index 75184892abd..a7ac8b3f2bc 100644 --- a/src/plugins/projectexplorer/buildstep.h +++ b/src/plugins/projectexplorer/buildstep.h @@ -43,8 +43,8 @@ public: void fromMap(const Utils::Store &map) override; void toMap(Utils::Store &map) const override; - bool enabled() const; - void setEnabled(bool b); + bool stepEnabled() const; + void setStepEnabled(bool b); BuildStepList *stepList() const; @@ -90,6 +90,8 @@ signals: void addOutput(const QString &string, OutputFormat format, OutputNewlineSetting newlineSetting = DoAppendNewline); + void stepEnabledChanged(); + void progress(int percentage, const QString &message); protected: @@ -112,7 +114,7 @@ private: ProjectConfiguration *projectConfiguration() const; BuildStepList * const m_stepList; - bool m_enabled = true; + bool m_stepEnabled = true; bool m_immutable = false; bool m_widgetExpandedByDefault = true; std::optional m_wasExpanded; diff --git a/src/plugins/projectexplorer/buildstepspage.cpp b/src/plugins/projectexplorer/buildstepspage.cpp index 21fb4c20932..0971de90eaa 100644 --- a/src/plugins/projectexplorer/buildstepspage.cpp +++ b/src/plugins/projectexplorer/buildstepspage.cpp @@ -153,7 +153,7 @@ BuildStepsWidgetData::BuildStepsWidgetData(BuildStep *s) : detailsWidget->setWidget(widget); toolWidget = new ToolWidget(detailsWidget); - toolWidget->setBuildStepEnabled(step->enabled()); + toolWidget->setBuildStepEnabled(step->stepEnabled()); detailsWidget->setToolWidget(toolWidget); detailsWidget->setContentsMargins(0, 0, 0, 0); @@ -239,8 +239,8 @@ void BuildStepListWidget::addBuildStep(int pos) s->detailsWidget->setSummaryText(s->step->summaryText()); }); - connect(s->step, &BuildStep::enabledChanged, this, [s] { - s->toolWidget->setBuildStepEnabled(s->step->enabled()); + connect(s->step, &BuildStep::stepEnabledChanged, this, [s] { + s->toolWidget->setBuildStepEnabled(s->step->stepEnabled()); }); @@ -314,8 +314,8 @@ void BuildStepListWidget::updateBuildStepButtonsState() connect(s->toolWidget, &ToolWidget::disabledClicked, this, [s] { BuildStep *bs = s->step; - bs->setEnabled(!bs->enabled()); - s->toolWidget->setBuildStepEnabled(bs->enabled()); + bs->setStepEnabled(!bs->stepEnabled()); + s->toolWidget->setBuildStepEnabled(bs->stepEnabled()); }); s->toolWidget->setRemoveEnabled(!m_buildStepList->at(i)->isImmutable()); connect(s->toolWidget, &ToolWidget::removeClicked, diff --git a/src/plugins/projectexplorer/workspaceproject.cpp b/src/plugins/projectexplorer/workspaceproject.cpp index 40637cb7ce7..96453a0c976 100644 --- a/src/plugins/projectexplorer/workspaceproject.cpp +++ b/src/plugins/projectexplorer/workspaceproject.cpp @@ -483,8 +483,11 @@ public: resetExtraInfo(); if (extraInfos["forSetup"].toBool()) { originalExtraInfo = extraInfos; + setEnabled(false); buildInfoResetConnection = connect( this, &BaseAspect::changed, this, &WorkspaceBuildConfiguration::resetExtraInfo); + for (BuildStep *step : buildSteps()->steps()) + step->setEnabled(false); } } @@ -513,6 +516,9 @@ public: { originalExtraInfo.reset(); disconnect(buildInfoResetConnection); + setEnabled(true); + for (auto step : buildSteps()->steps()) + step->setEnabled(true); } std::optional originalExtraInfo; diff --git a/src/plugins/qbsprojectmanager/qbsproject.cpp b/src/plugins/qbsprojectmanager/qbsproject.cpp index b3acf6847de..925b91c61f0 100644 --- a/src/plugins/qbsprojectmanager/qbsproject.cpp +++ b/src/plugins/qbsprojectmanager/qbsproject.cpp @@ -532,7 +532,7 @@ FilePath QbsBuildSystem::installRoot() if (dc) { const QList steps = dc->stepList()->steps(); for (const BuildStep * const step : steps) { - if (!step->enabled()) + if (!step->stepEnabled()) continue; if (const auto qbsInstallStep = qobject_cast(step)) return qbsInstallStep->installRoot(); diff --git a/src/plugins/qtapplicationmanager/appmanagercmakepackagestep.cpp b/src/plugins/qtapplicationmanager/appmanagercmakepackagestep.cpp index 0f9ae37f712..18d2f476761 100644 --- a/src/plugins/qtapplicationmanager/appmanagercmakepackagestep.cpp +++ b/src/plugins/qtapplicationmanager/appmanagercmakepackagestep.cpp @@ -33,7 +33,7 @@ public: const auto updaterSlot = [step] { const TargetInformation targetInformation(step->target()); step->setBuildTargets({targetInformation.cmakeBuildTarget}); - step->setEnabled(!targetInformation.isBuiltin); + step->setStepEnabled(!targetInformation.isBuiltin); }; QObject::connect(step->target(), &Target::activeRunConfigurationChanged, step, updaterSlot); QObject::connect(step->target(), &Target::activeDeployConfigurationChanged, step, updaterSlot); diff --git a/src/plugins/qtapplicationmanager/appmanagerdeploypackagestep.cpp b/src/plugins/qtapplicationmanager/appmanagerdeploypackagestep.cpp index 6263028a6e4..36bb6071db9 100644 --- a/src/plugins/qtapplicationmanager/appmanagerdeploypackagestep.cpp +++ b/src/plugins/qtapplicationmanager/appmanagerdeploypackagestep.cpp @@ -59,7 +59,7 @@ public: targetDirectory.setValue(targetInformation.runDirectory); targetDirectory.setDefaultValue(targetDirectory.value()); - setEnabled(!targetInformation.isBuiltin); + setStepEnabled(!targetInformation.isBuiltin); }; connect(target(), &Target::activeRunConfigurationChanged, this, updateAspects); diff --git a/src/plugins/qtapplicationmanager/appmanagerinstallpackagestep.cpp b/src/plugins/qtapplicationmanager/appmanagerinstallpackagestep.cpp index 49ba78f669f..28c8a53945e 100644 --- a/src/plugins/qtapplicationmanager/appmanagerinstallpackagestep.cpp +++ b/src/plugins/qtapplicationmanager/appmanagerinstallpackagestep.cpp @@ -83,7 +83,7 @@ AppManagerInstallPackageStep::AppManagerInstallPackageStep(BuildStepList *bsl, I packageFile.setDefaultPathValue(packageFilePath); } - setEnabled(!targetInformation.isBuiltin); + setStepEnabled(!targetInformation.isBuiltin); }; connect(target(), &Target::activeRunConfigurationChanged, this, updateAspects); From e80089be354936232e304b71b869fefed4c97bde Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Mon, 30 Sep 2024 13:10:06 +0200 Subject: [PATCH 53/76] Axivion: Lift domain name restriction The dashboard may be some host inside the local network accessible by its host name. Change-Id: I517fad65c46629c2c60fd1f3f607d79263480545 Reviewed-by: Jarek Kobus Reviewed-by: Mohammad Mehdi Salem Naraghi --- src/plugins/axivion/axivionsettings.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/axivion/axivionsettings.cpp b/src/plugins/axivion/axivionsettings.cpp index 9112c728497..74c0c695b86 100644 --- a/src/plugins/axivion/axivionsettings.cpp +++ b/src/plugins/axivion/axivionsettings.cpp @@ -269,7 +269,7 @@ const QList AxivionSettings::validPathMappings() const static bool hostValid(const QString &host) { static const QRegularExpression ip(R"(^(\d+).(\d+).(\d+).(\d+)$)"); - static const QRegularExpression dn(R"(^([a-zA-Z0-9][a-zA-Z0-9-]+\.)+[a-zA-Z0-9][a-zA-Z0-9-]+$)"); + static const QRegularExpression dn(R"(^([a-zA-Z0-9][a-zA-Z0-9-]+\.)*[a-zA-Z0-9][a-zA-Z0-9-]+$)"); const QRegularExpressionMatch match = ip.match(host); if (match.hasMatch()) { for (int i = 1; i < 5; ++i) { @@ -279,7 +279,7 @@ static bool hostValid(const QString &host) } return true; } - return (host == "localhost") || dn.match(host).hasMatch(); + return dn.match(host).hasMatch(); } static bool isUrlValid(const QString &in) From 3b8f537c26369e882fbab5f3b6cb8f3e0386a98d Mon Sep 17 00:00:00 2001 From: Marcus Tillmanns Date: Mon, 7 Oct 2024 16:23:43 +0200 Subject: [PATCH 54/76] ProjectExplorer: Fix duplicate macroExpander An AspectContainer already has a macroExpander so we use that mechanism as the manual handling was error prone. Change-Id: Id0787fcc83f8192ab4402b43290e7bfeca4f13f1 Reviewed-by: David Schulz --- src/plugins/projectexplorer/runconfiguration.cpp | 2 ++ src/plugins/projectexplorer/runconfiguration.h | 2 -- .../projectexplorer/runconfigurationaspects.cpp | 15 +++++---------- .../projectexplorer/runconfigurationaspects.h | 2 -- 4 files changed, 7 insertions(+), 14 deletions(-) diff --git a/src/plugins/projectexplorer/runconfiguration.cpp b/src/plugins/projectexplorer/runconfiguration.cpp index edeb1d1e609..0c920487d90 100644 --- a/src/plugins/projectexplorer/runconfiguration.cpp +++ b/src/plugins/projectexplorer/runconfiguration.cpp @@ -148,6 +148,8 @@ RunConfiguration::RunConfiguration(Target *target, Utils::Id id) forceDisplayNameSerialization(); connect(target, &Target::parsingFinished, this, &RunConfiguration::update); + setMacroExpander(&m_expander); + m_expander.setDisplayName(Tr::tr("Run Settings")); m_expander.setAccumulating(true); m_expander.registerSubProvider([target] { diff --git a/src/plugins/projectexplorer/runconfiguration.h b/src/plugins/projectexplorer/runconfiguration.h index 9fa2a21633c..84b385330f0 100644 --- a/src/plugins/projectexplorer/runconfiguration.h +++ b/src/plugins/projectexplorer/runconfiguration.h @@ -172,8 +172,6 @@ public: void update(); - const Utils::MacroExpander *macroExpander() const { return &m_expander; } - virtual RunConfiguration *clone(Target *parent); protected: diff --git a/src/plugins/projectexplorer/runconfigurationaspects.cpp b/src/plugins/projectexplorer/runconfigurationaspects.cpp index a7d2186995c..a3081663bb5 100644 --- a/src/plugins/projectexplorer/runconfigurationaspects.cpp +++ b/src/plugins/projectexplorer/runconfigurationaspects.cpp @@ -19,8 +19,8 @@ #include #include #include -#include #include +#include #include #include @@ -162,11 +162,6 @@ WorkingDirectoryAspect::WorkingDirectoryAspect(AspectContainer *container) setSettingsKey("RunConfiguration.WorkingDirectory"); } -void WorkingDirectoryAspect::setMacroExpander(const MacroExpander *expander) -{ - m_macroExpander = expander; -} - void WorkingDirectoryAspect::setEnvironment(EnvironmentAspect *envAspect) { m_envAspect = envAspect; @@ -179,8 +174,8 @@ void WorkingDirectoryAspect::addToLayoutImpl(Layout &builder) { QTC_CHECK(!m_chooser); m_chooser = new PathChooser; - if (QTC_GUARD(m_macroExpander)) - m_chooser->setMacroExpander(m_macroExpander); + if (QTC_GUARD(macroExpander())) + m_chooser->setMacroExpander(macroExpander()); m_chooser->setHistoryCompleter(settingsKey()); m_chooser->setExpectedKind(Utils::PathChooser::Directory); m_chooser->setPromptDialogTitle(Tr::tr("Select Working Directory")); @@ -254,8 +249,8 @@ FilePath WorkingDirectoryAspect::workingDirectory() const const Environment env = m_envAspect ? m_envAspect->environment() : Environment::systemEnvironment(); QString workingDir = m_workingDirectory.path(); - if (m_macroExpander) - workingDir = m_macroExpander->expandProcessArgs(workingDir); + if (auto expander = macroExpander()) + workingDir = expander->expandProcessArgs(workingDir); QString res = workingDir.isEmpty() ? QString() : QDir::cleanPath(env.expandVariables(workingDir)); diff --git a/src/plugins/projectexplorer/runconfigurationaspects.h b/src/plugins/projectexplorer/runconfigurationaspects.h index 629b3059e2a..5f5f2f5b45c 100644 --- a/src/plugins/projectexplorer/runconfigurationaspects.h +++ b/src/plugins/projectexplorer/runconfigurationaspects.h @@ -69,7 +69,6 @@ public: Utils::FilePath unexpandedWorkingDirectory() const; void setDefaultWorkingDirectory(const Utils::FilePath &defaultWorkingDirectory); Utils::PathChooser *pathChooser() const; - void setMacroExpander(const Utils::MacroExpander *expander); void setEnvironment(EnvironmentAspect *envAspect); private: @@ -83,7 +82,6 @@ private: Utils::FilePath m_defaultWorkingDirectory; QPointer m_chooser; QPointer m_resetButton; - const Utils::MacroExpander *m_macroExpander = nullptr; }; class PROJECTEXPLORER_EXPORT ArgumentsAspect : public Utils::BaseAspect From a8a19767b452d8ae9dd25ea726e763533060d523 Mon Sep 17 00:00:00 2001 From: Marcus Tillmanns Date: Mon, 7 Oct 2024 16:24:53 +0200 Subject: [PATCH 55/76] ProjectExplorer: Allow ProcessStep to resolve relative paths Change-Id: I35a06f7d32e528cc8b524c6db86d8d62be2c8201 Reviewed-by: David Schulz --- src/plugins/projectexplorer/processstep.cpp | 14 +++++++++++++- src/plugins/projectexplorer/processstep.h | 5 ++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/plugins/projectexplorer/processstep.cpp b/src/plugins/projectexplorer/processstep.cpp index 6d495335978..d899fb5e4d1 100644 --- a/src/plugins/projectexplorer/processstep.cpp +++ b/src/plugins/projectexplorer/processstep.cpp @@ -19,6 +19,8 @@ namespace ProjectExplorer::Internal { const char PROCESS_COMMAND_KEY[] = "ProjectExplorer.ProcessStep.Command"; const char PROCESS_WORKINGDIRECTORY_KEY[] = "ProjectExplorer.ProcessStep.WorkingDirectory"; +const char PROCESS_WORKINGDIRECTORYRELATIVEBASE_KEY[] + = "ProjectExplorer.ProcessStep.WorkingDirectoryRelativeBasePath"; const char PROCESS_ARGUMENTS_KEY[] = "ProjectExplorer.ProcessStep.Arguments"; ProcessStep::ProcessStep(BuildStepList *bsl, Id id) @@ -38,10 +40,18 @@ ProcessStep::ProcessStep(BuildStepList *bsl, Id id) m_workingDirectory.setLabelText(Tr::tr("Working directory:")); m_workingDirectory.setExpectedKind(PathChooser::Directory); + m_workingDirRelativeBasePath.setSettingsKey(PROCESS_WORKINGDIRECTORYRELATIVEBASE_KEY); + m_workingDirRelativeBasePath.setValue(QString()); + m_workingDirRelativeBasePath.setVisible(false); + m_workingDirRelativeBasePath.setExpectedKind(PathChooser::Directory); + setWorkingDirectoryProvider([this] { const FilePath workingDir = m_workingDirectory(); + const FilePath relativeBasePath = m_workingDirRelativeBasePath(); if (workingDir.isEmpty()) return FilePath::fromString(fallbackWorkingDirectory()); + else if (workingDir.isRelativePath() && !relativeBasePath.isEmpty()) + return relativeBasePath.resolvePath(workingDir); return workingDir; }); @@ -69,9 +79,11 @@ void ProcessStep::setArguments(const QStringList &arguments) m_arguments.setValue(arguments.join(" ")); } -void ProcessStep::setWorkingDirectory(const Utils::FilePath &workingDirectory) +void ProcessStep::setWorkingDirectory( + const Utils::FilePath &workingDirectory, const Utils::FilePath &relativeBasePath) { m_workingDirectory.setValue(workingDirectory); + m_workingDirRelativeBasePath.setValue(relativeBasePath); } void ProcessStep::setupOutputFormatter(OutputFormatter *formatter) diff --git a/src/plugins/projectexplorer/processstep.h b/src/plugins/projectexplorer/processstep.h index 09ffe26420b..ff36ebb28c3 100644 --- a/src/plugins/projectexplorer/processstep.h +++ b/src/plugins/projectexplorer/processstep.h @@ -15,7 +15,9 @@ public: void setCommand(const Utils::FilePath &command); void setArguments(const QStringList &arguments); - void setWorkingDirectory(const Utils::FilePath &workingDirectory); + void setWorkingDirectory( + const Utils::FilePath &workingDirectory, + const Utils::FilePath &relativeBasePath = Utils::FilePath()); private: void setupOutputFormatter(Utils::OutputFormatter *formatter) final; @@ -23,6 +25,7 @@ private: Utils::FilePathAspect m_command{this}; Utils::StringAspect m_arguments{this}; Utils::FilePathAspect m_workingDirectory{this}; + Utils::FilePathAspect m_workingDirRelativeBasePath{this}; }; class ProcessStepFactory final : public BuildStepFactory From 826bf2f7f62bee5cd0067d748fb7e4e20f043926 Mon Sep 17 00:00:00 2001 From: Marcus Tillmanns Date: Mon, 7 Oct 2024 16:25:47 +0200 Subject: [PATCH 56/76] ProjectExplorer: Don't prematurely reject non existing directories Working Directories may contain macros that still need to be expanded. Change-Id: Iba31d439aab9c918bef40b6ad1a55d25fe77cb7b Reviewed-by: David Schulz --- src/plugins/projectexplorer/workspaceproject.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/plugins/projectexplorer/workspaceproject.cpp b/src/plugins/projectexplorer/workspaceproject.cpp index 96453a0c976..90554b92dba 100644 --- a/src/plugins/projectexplorer/workspaceproject.cpp +++ b/src/plugins/projectexplorer/workspaceproject.cpp @@ -209,9 +209,6 @@ void WorkspaceBuildSystem::reparse(bool force) FilePath workingDirectory = FilePath::fromUserInput( targetObject["workingDirectory"].toString()); - if (!workingDirectory.isDir()) - workingDirectory = FilePath::currentWorkingPath(); - const QString name = targetObject["name"].toString(); const FilePath executable = FilePath::fromUserInput( targetObject["executable"].toString()); From cca7efd14602eccde55d6512e2a3ed693ce170be Mon Sep 17 00:00:00 2001 From: Marcus Tillmanns Date: Mon, 7 Oct 2024 16:28:19 +0200 Subject: [PATCH 57/76] ProjectExplorer: Let the ProcessStep figure out relative paths The WorkingDir may contain macros that still need to be expanded so we need to tell it what we wan't as parent path. Change-Id: I7af8115196b70b5a02217d5709bf0a0cc532ce69 Reviewed-by: David Schulz --- src/plugins/projectexplorer/workspaceproject.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/plugins/projectexplorer/workspaceproject.cpp b/src/plugins/projectexplorer/workspaceproject.cpp index 90554b92dba..afa92713c44 100644 --- a/src/plugins/projectexplorer/workspaceproject.cpp +++ b/src/plugins/projectexplorer/workspaceproject.cpp @@ -464,9 +464,7 @@ public: FilePath wd = FilePath::fromUserInput(bs["workingDirectory"].toString()); if (wd.isEmpty()) wd = "%{ActiveProject:BuildConfig:Path}"; - else if (wd.isRelativePath()) - wd = project()->projectDirectory().resolvePath(wd); - step->setWorkingDirectory(wd); + step->setWorkingDirectory(wd, project()->projectDirectory()); steps->appendStep(step); } initializeExtraInfo(extraInfos); From d055fb2a0658da46e50456a03165e96ce6b27109 Mon Sep 17 00:00:00 2001 From: Andre Hartmann Date: Tue, 8 Oct 2024 08:54:18 +0200 Subject: [PATCH 58/76] QmlDesignerPlugin: Fix "unused parameter" warning Change-Id: I3f7db9811a8f792ca8a287b094370d0c33ea8c2f Reviewed-by: Tim Jenssen --- src/plugins/qmldesigner/qmldesignerplugin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/qmldesigner/qmldesignerplugin.cpp b/src/plugins/qmldesigner/qmldesignerplugin.cpp index 1cbb3e5edb3..2913a8e6f6d 100644 --- a/src/plugins/qmldesigner/qmldesignerplugin.cpp +++ b/src/plugins/qmldesigner/qmldesignerplugin.cpp @@ -269,7 +269,7 @@ QmlDesignerPlugin::~QmlDesignerPlugin() // INHERITED FROM ExtensionSystem::Plugin // //////////////////////////////////////////////////// -bool QmlDesignerPlugin::initialize(const QStringList & /*arguments*/, QString *errorMessage/* = 0*/) +bool QmlDesignerPlugin::initialize(const QStringList & /*arguments*/, QString * /*errorMessage*/) { if constexpr (isUsingQmlDesignerLite()) { if (!QmlDesignerBasePlugin::isLiteModeEnabled()) { From e03aa820b43e7ca400f64c83977dfd9bf01354b6 Mon Sep 17 00:00:00 2001 From: Marcus Tillmanns Date: Thu, 26 Sep 2024 12:52:11 +0200 Subject: [PATCH 59/76] Lua LSP: Add parameter for async options Allows using async code to create the options of a language client. This is useful for instance if you need to get values from a SecrectAspect Change-Id: Ica23b7f0df00bff3af7520524905a59ceb5b8e8c Reviewed-by: David Schulz --- .../lualanguageclient/lualanguageclient.cpp | 33 +++++++++++++++++++ src/plugins/lua/meta/lsp.lua | 1 + 2 files changed, 34 insertions(+) diff --git a/src/plugins/languageclient/lualanguageclient/lualanguageclient.cpp b/src/plugins/languageclient/lualanguageclient/lualanguageclient.cpp index 82f4a091dc2..ebc1e522fad 100644 --- a/src/plugins/languageclient/lualanguageclient/lualanguageclient.cpp +++ b/src/plugins/languageclient/lualanguageclient/lualanguageclient.cpp @@ -11,6 +11,8 @@ #include #include +#include + #include #include @@ -18,6 +20,7 @@ #include #include +#include #include #include @@ -207,6 +210,8 @@ public: TransportType m_transportType{TransportType::StdIO}; std::function(CommandLine &)> m_cmdLineCallback; std::function(QString &)> m_initOptionsCallback; + sol::function m_asyncInitOptions; + bool m_isUpdatingAsyncOptions{false}; AspectContainer *m_aspects{nullptr}; QString m_name; Utils::Id m_settingsTypeId; @@ -324,6 +329,13 @@ public: &LanguageClientManager::clientRemoved, this, &LuaClientWrapper::onClientRemoved); + + if (auto asyncInit = options.get>( + "initializationOptionsAsync")) { + m_asyncInitOptions = *asyncInit; + QMetaObject::invokeMethod( + this, &LuaClientWrapper::updateAsyncOptions, Qt::QueuedConnection); + } } void onClientRemoved(Client *c, bool unexpected) @@ -462,6 +474,25 @@ public: clients.front()->sendMessage(request); } + void updateAsyncOptions() + { + if (m_isUpdatingAsyncOptions) + return; + QTC_ASSERT(m_asyncInitOptions, return); + m_isUpdatingAsyncOptions = true; + std::function cb = guardedCallback(this, [this](sol::object options) { + if (options.is()) + m_initializationOptions = ::Lua::toJsonString(options.as()); + else if (options.is()) + m_initializationOptions = options.as(); + + emit optionsChanged(); + m_isUpdatingAsyncOptions = false; + }); + + ::Lua::Async::start(m_asyncInitOptions, cb); + } + void updateOptions() { if (m_cmdLineCallback) { @@ -479,6 +510,8 @@ public: // optionsChanged() needs to be called for it as well, but only once per updateOptions() emit optionsChanged(); } + if (m_asyncInitOptions) + updateAsyncOptions(); } static CommandLine cmdFromTable(const sol::table &tbl) diff --git a/src/plugins/lua/meta/lsp.lua b/src/plugins/lua/meta/lsp.lua index 37a3c2671e5..10c42c6e68b 100644 --- a/src/plugins/lua/meta/lsp.lua +++ b/src/plugins/lua/meta/lsp.lua @@ -11,6 +11,7 @@ local lsp = {} ---@field languageFilter LanguageFilter The language filter deciding which files to open with the language server. ---@field startBehavior? "AlwaysOn"|"RequiresFile"|"RequiresProject" ---@field initializationOptions? function|table|string The initialization options to pass to the language server, either a JSON string, a table, or a function that returns either. +---@field initializationOptionsAsync? function A callback that will return the initialization options as a JSON String or a table. Inside the callback you can use Async functions. ---@field settings? AspectContainer The settings object to associate with the language server. ---@field onStartFailed? function This callback is called when client failed to start. ---@field showInSettings? boolean Whether the client should show up in the general Language Server list. From 5b8d37b1de402bb2d3d661ed1f4c00bd605a27a3 Mon Sep 17 00:00:00 2001 From: Marcus Tillmanns Date: Mon, 7 Oct 2024 16:27:17 +0200 Subject: [PATCH 60/76] ProjectExplorer: Remove unnecessary setMacroExpander call Change-Id: I8ef1cdc70d50516653c35789a1b1d795137912dc Reviewed-by: David Schulz Reviewed-by: hjk --- src/plugins/projectexplorer/workspaceproject.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/plugins/projectexplorer/workspaceproject.cpp b/src/plugins/projectexplorer/workspaceproject.cpp index afa92713c44..fbba5d3a556 100644 --- a/src/plugins/projectexplorer/workspaceproject.cpp +++ b/src/plugins/projectexplorer/workspaceproject.cpp @@ -377,7 +377,6 @@ public: }; arguments.setLabelText(Tr::tr("Arguments:")); - arguments.setMacroExpander(macroExpander()); arguments.setArguments(argumentsAsString()); arguments.setSettingsKey("Workspace.RunConfiguration.Arguments"); From dcd0b5ff11e2bc6aa9a8715fcaef1e81f25c8aad Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 1 Oct 2024 17:27:43 +0200 Subject: [PATCH 61/76] WebAssembly: Use newer approach for channel setup Change-Id: I3f7cfbbbe0734c651ad33fcb88850b9445be1df5 Reviewed-by: Alessandro Portale --- src/plugins/projectexplorer/runcontrol.cpp | 15 +++++++++++++++ src/plugins/projectexplorer/runcontrol.h | 3 +++ .../webassembly/webassemblyrunconfiguration.cpp | 4 ++-- 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/plugins/projectexplorer/runcontrol.cpp b/src/plugins/projectexplorer/runcontrol.cpp index 14f2094c166..62b11f11570 100644 --- a/src/plugins/projectexplorer/runcontrol.cpp +++ b/src/plugins/projectexplorer/runcontrol.cpp @@ -298,9 +298,11 @@ public: bool useDebugChannel = false; bool useQmlChannel = false; bool usePerfChannel = false; + bool useWorkerChannel = false; QUrl debugChannel; QUrl qmlChannel; QUrl perfChannel; + QUrl workerChannel; }; class RunControlPrivate : public QObject, public RunControlPrivateData @@ -606,6 +608,8 @@ void RunControlPrivate::startPortsGathererIfNeededAndContinueStart() qmlChannel = getNextChannel(); if (usePerfChannel) perfChannel = getNextChannel(); + if (useWorkerChannel) + workerChannel = getNextChannel(); continueStart(); } else { @@ -700,6 +704,17 @@ QUrl RunControl::perfChannel() const return d->perfChannel; } +void RunControl::requestWorkerChannel() +{ + d->enablePortsGatherer(); + d->useWorkerChannel = true; +} + +QUrl RunControl::workerChannel() const +{ + return d->workerChannel; +} + void RunControlPrivate::continueStart() { checkState(RunControlState::Starting); diff --git a/src/plugins/projectexplorer/runcontrol.h b/src/plugins/projectexplorer/runcontrol.h index 69bcf1cdc1d..3003e83fef0 100644 --- a/src/plugins/projectexplorer/runcontrol.h +++ b/src/plugins/projectexplorer/runcontrol.h @@ -258,6 +258,9 @@ public: bool usesPerfChannel() const; QUrl perfChannel() const; + void requestWorkerChannel(); + QUrl workerChannel() const; + signals: void appendMessage(const QString &msg, Utils::OutputFormat format); void aboutToStart(); diff --git a/src/plugins/webassembly/webassemblyrunconfiguration.cpp b/src/plugins/webassembly/webassemblyrunconfiguration.cpp index 664625669c6..62d96ae5f6d 100644 --- a/src/plugins/webassembly/webassemblyrunconfiguration.cpp +++ b/src/plugins/webassembly/webassemblyrunconfiguration.cpp @@ -205,7 +205,7 @@ public: EmrunRunWorker(RunControl *runControl) : SimpleTargetRunner(runControl) { - runControl->enablePortsGatherer(); + runControl->requestWorkerChannel(); setStartModifier([this, runControl] { const QString browserId = @@ -213,7 +213,7 @@ public: setCommandLine(emrunCommand(runControl->target(), runControl->buildKey(), browserId, - QString::number(runControl->findEndPoint().port()))); + QString::number(runControl->workerChannel().port()))); setEnvironment(runControl->buildEnvironment()); }); } From 4061d4b1ca21a975bebca039dfd522ba19a68237 Mon Sep 17 00:00:00 2001 From: hjk Date: Wed, 2 Oct 2024 16:35:03 +0200 Subject: [PATCH 62/76] Replace a few expected_str by Utils::Result Change-Id: I160c4dea583958e4cf55ff4de5b9f9c4937ac07f Reviewed-by: Marcus Tillmanns --- .../advanceddockingsystem/dockmanager.cpp | 16 +-- src/libs/advanceddockingsystem/dockmanager.h | 2 +- .../gocmdbridge/client/bridgedfileaccess.cpp | 73 ++++++------ .../gocmdbridge/client/bridgedfileaccess.h | 16 +-- src/libs/utils/devicefileaccess.cpp | 108 +++++++++--------- src/libs/utils/devicefileaccess.h | 25 ++-- src/libs/utils/filepath.cpp | 49 ++++---- src/libs/utils/filepath.h | 10 +- src/libs/utils/fileutils.cpp | 2 +- src/libs/utils/fsengine/fsenginehandler.cpp | 8 +- src/libs/utils/savefile.cpp | 2 +- src/plugins/android/androidbuildapkstep.cpp | 2 +- src/plugins/coreplugin/fileutils.cpp | 2 +- src/plugins/coreplugin/session.cpp | 4 +- src/plugins/debugger/loadcoredialog.cpp | 2 +- src/plugins/docker/dockerdevice.cpp | 2 +- .../languageclient/languageclientutils.cpp | 4 +- .../projectexplorer/buildconfiguration.cpp | 2 +- .../assetslibrary/assetslibrarymodel.cpp | 4 +- .../qtsupport/gettingstartedwelcomepage.cpp | 2 +- src/plugins/remotelinux/genericdeploystep.cpp | 16 ++- src/plugins/remotelinux/linuxdevice.cpp | 26 ++--- src/plugins/squish/squishtesttreeview.cpp | 2 +- src/plugins/squish/suiteconf.cpp | 2 +- src/plugins/terminal/shellintegration.cpp | 10 +- 25 files changed, 194 insertions(+), 197 deletions(-) diff --git a/src/libs/advanceddockingsystem/dockmanager.cpp b/src/libs/advanceddockingsystem/dockmanager.cpp index dc1f0085bec..e15c495f6ea 100644 --- a/src/libs/advanceddockingsystem/dockmanager.cpp +++ b/src/libs/advanceddockingsystem/dockmanager.cpp @@ -1311,7 +1311,7 @@ expected_str DockManager::cloneWorkspace(const QString &originalFileNam const FilePath clonePath = workspaceNameToFilePath(cloneName); - const expected_str copyResult = originalPath.copyFile(clonePath); + const Result copyResult = originalPath.copyFile(clonePath); if (!copyResult) return make_unexpected(Tr::tr("Could not clone \"%1\" due to: %2") .arg(originalPath.toUserOutput(), copyResult.error())); @@ -1337,21 +1337,21 @@ expected_str DockManager::renameWorkspace(const QString &originalFileNa return originalFileName; } -expected_str DockManager::resetWorkspacePreset(const QString &fileName) +Result DockManager::resetWorkspacePreset(const QString &fileName) { qCInfo(adsLog) << "Reset workspace" << fileName; Workspace *w = workspace(fileName); if (!w) - return make_unexpected(Tr::tr("Workspace \"%1\" does not exist.").arg(fileName)); + return Result::Error(Tr::tr("Workspace \"%1\" does not exist.").arg(fileName)); if (!w->isPreset()) - return make_unexpected(Tr::tr("Workspace \"%1\" is not a preset.").arg(fileName)); + return Result::Error(Tr::tr("Workspace \"%1\" is not a preset.").arg(fileName)); const FilePath filePath = w->filePath(); if (!filePath.removeFile()) - return make_unexpected(Tr::tr("Cannot remove \"%1\".").arg(filePath.toUserOutput())); + return Result::Error(Tr::tr("Cannot remove \"%1\".").arg(filePath.toUserOutput())); return presetDirectory().pathAppended(fileName).copyFile(filePath); } @@ -1400,7 +1400,7 @@ expected_str DockManager::importWorkspace(const QString &filePath) const FilePath targetFilePath = userDirectory().pathAppended(fileName); - const expected_str copyResult = sourceFilePath.copyFile(targetFilePath); + const Result copyResult = sourceFilePath.copyFile(targetFilePath); if (!copyResult) return make_unexpected( Tr::tr("Could not copy \"%1\" to \"%2\" due to: %3") @@ -1441,7 +1441,7 @@ expected_str DockManager::exportWorkspace(const QString &targetFilePath Tr::tr("The workspace \"%1\" does not exist ").arg(workspaceFile.toUserOutput())); // Finally copy the workspace to the target - const expected_str copyResult = workspaceFile.copyFile(targetFile); + const Result copyResult = workspaceFile.copyFile(targetFile); if (!copyResult) return make_unexpected( Tr::tr("Could not copy \"%1\" to \"%2\" due to: %3") @@ -1675,7 +1675,7 @@ void DockManager::syncWorkspacePresets() continue; } - const expected_str copyResult = filePath.copyFile( + const Result copyResult = filePath.copyFile( userDirectory().pathAppended(filePath.fileName())); if (!copyResult) qWarning() << QString("Could not copy '%1' to '%2' due to %3") diff --git a/src/libs/advanceddockingsystem/dockmanager.h b/src/libs/advanceddockingsystem/dockmanager.h index f0e30a5418a..aa527be8861 100644 --- a/src/libs/advanceddockingsystem/dockmanager.h +++ b/src/libs/advanceddockingsystem/dockmanager.h @@ -739,7 +739,7 @@ public: Utils::expected_str renameWorkspace(const QString &originalFileName, const QString &newName); - Utils::expected_str resetWorkspacePreset(const QString &fileName); + Utils::Result resetWorkspacePreset(const QString &fileName); /** * \brief Save the currently active workspace. diff --git a/src/libs/gocmdbridge/client/bridgedfileaccess.cpp b/src/libs/gocmdbridge/client/bridgedfileaccess.cpp index dcd17b23e30..67e864047c7 100644 --- a/src/libs/gocmdbridge/client/bridgedfileaccess.cpp +++ b/src/libs/gocmdbridge/client/bridgedfileaccess.cpp @@ -33,61 +33,60 @@ expected_str run(const CommandLine &cmdLine, const QByteArray &inputDat return p.readAllStandardOutput().trimmed(); } -Utils::expected_str FileAccess::init(const Utils::FilePath &pathToBridge) +Result FileAccess::init(const FilePath &pathToBridge) { m_client = std::make_unique(pathToBridge); auto startResult = m_client->start(); if (!startResult) - return make_unexpected(QString("Could not start cmdbridge: %1").arg(startResult.error())); + return Result::Error(QString("Could not start cmdbridge: %1").arg(startResult.error())); try { if (!startResult->isValid()) startResult->waitForFinished(); m_environment = startResult->takeResult(); } catch (const std::exception &e) { - return make_unexpected( + return Result::Error( Tr::tr("Error starting cmdbridge: %1").arg(QString::fromLocal8Bit(e.what()))); } - return {}; + return Result::Ok; } -expected_str FileAccess::deployAndInit( - const FilePath &libExecPath, const FilePath &remoteRootPath) +Result FileAccess::deployAndInit(const FilePath &libExecPath, const FilePath &remoteRootPath) { if (remoteRootPath.isEmpty()) - return make_unexpected(Tr::tr("Remote root path is empty")); + return Result::Error(Tr::tr("Remote root path is empty")); if (!remoteRootPath.isAbsolutePath()) - return make_unexpected(Tr::tr("Remote root path is not absolute")); + return Result::Error(Tr::tr("Remote root path is not absolute")); const auto whichDD = run({remoteRootPath.withNewPath("which"), {"dd"}}); if (!whichDD) // TODO: Support Windows? - return make_unexpected(Tr::tr("Could not find dd on remote host: %1").arg(whichDD.error())); + return Result::Error(Tr::tr("Could not find dd on remote host: %1").arg(whichDD.error())); qCDebug(faLog) << "Found dd on remote host:" << *whichDD; const expected_str unameOs = run({remoteRootPath.withNewPath("uname"), {"-s"}}); if (!unameOs) { - return make_unexpected( + return Result::Error( QString("Could not determine OS on remote host: %1").arg(unameOs.error())); } Utils::expected_str osType = osTypeFromString(*unameOs); if (!osType) - return make_unexpected(osType.error()); + return Result::Error(osType.error()); qCDebug(faLog) << "Remote host OS:" << *unameOs; const expected_str unameArch = run({remoteRootPath.withNewPath("uname"), {"-m"}}); if (!unameArch) { - return make_unexpected( + return Result::Error( QString("Could not determine architecture on remote host: %1").arg(unameArch.error())); } const Utils::expected_str osArch = osArchFromString(*unameArch); if (!osArch) - return make_unexpected(osArch.error()); + return Result::Error(osArch.error()); qCDebug(faLog) << "Remote host architecture:" << *unameArch; @@ -95,7 +94,7 @@ expected_str FileAccess::deployAndInit( = Client::getCmdBridgePath(*osType, *osArch, libExecPath); if (!cmdBridgePath) { - return make_unexpected( + return Result::Error( QString("Could not determine compatible cmdbridge for remote host: %1") .arg(cmdBridgePath.error())); } @@ -106,7 +105,7 @@ expected_str FileAccess::deployAndInit( const auto cmdBridgeFileData = cmdBridgePath->fileContents(); if (!cmdBridgeFileData) { - return make_unexpected( + return Result::Error( QString("Could not read cmdbridge file: %1").arg(cmdBridgeFileData.error())); } @@ -114,7 +113,7 @@ expected_str FileAccess::deployAndInit( {remoteRootPath.withNewPath("mktemp"), {"-t", "cmdbridge.XXXXXXXXXX"}}); if (!tmpFile) { - return make_unexpected( + return Result::Error( QString("Could not create temporary file: %1").arg(tmpFile.error())); } @@ -125,7 +124,7 @@ expected_str FileAccess::deployAndInit( const auto makeExecutable = run({remoteRootPath.withNewPath("chmod"), {"+x", *tmpFile}}); if (!makeExecutable) { - return make_unexpected( + return Result::Error( QString("Could not make temporary file executable: %1").arg(makeExecutable.error())); } @@ -468,26 +467,26 @@ expected_str FileAccess::writeFileContents(const FilePath &filePath, } } -expected_str FileAccess::removeFile(const Utils::FilePath &filePath) const +Result FileAccess::removeFile(const FilePath &filePath) const { try { Utils::expected_str> f = m_client->removeFile(filePath.nativePath()); if (!f) - return make_unexpected(f.error()); + return Result::Error(f.error()); f->waitForFinished(); } catch (const std::system_error &e) { if (e.code().value() == ENOENT) - return make_unexpected(Tr::tr("File does not exist")); + return Result::Error(Tr::tr("File does not exist")); qCWarning(faLog) << "Error removing file:" << e.what(); - return make_unexpected( + return Result::Error( Tr::tr("Error removing file: %1").arg(QString::fromLocal8Bit(e.what()))); } catch (const std::exception &e) { qCWarning(faLog) << "Error removing file:" << e.what(); - return make_unexpected( + return Result::Error( Tr::tr("Error removing file: %1").arg(QString::fromLocal8Bit(e.what()))); } - return {}; + return Result::Ok; } bool FileAccess::removeRecursively(const Utils::FilePath &filePath, QString *error) const @@ -530,37 +529,35 @@ bool FileAccess::createDirectory(const Utils::FilePath &filePath) const } } -expected_str FileAccess::copyFile(const Utils::FilePath &filePath, - const Utils::FilePath &target) const +Result FileAccess::copyFile(const FilePath &filePath, const FilePath &target) const { try { auto f = m_client->copyFile(filePath.nativePath(), target.nativePath()); - QTC_ASSERT_EXPECTED(f, return {}); + QTC_ASSERT_EXPECTED(f, return Result::Ok); f->waitForFinished(); - return {}; + return Result::Ok; } catch (const std::exception &e) { - return make_unexpected( + return Result::Error( Tr::tr("Error copying file: %1").arg(QString::fromLocal8Bit(e.what()))); } } -expected_str FileAccess::renameFile( - const Utils::FilePath &filePath, const Utils::FilePath &target) const +Result FileAccess::renameFile(const FilePath &filePath, const FilePath &target) const { try { Utils::expected_str> f = m_client->renameFile(filePath.nativePath(), target.nativePath()); if (!f) - return make_unexpected(f.error()); + return Result::Error(f.error()); f->waitForFinished(); if (!f) - return make_unexpected(f.error()); + return Result::Error(f.error()); } catch (const std::exception &e) { - return make_unexpected( + return Result::Error( Tr::tr("Error renaming file: %1").arg(QString::fromLocal8Bit(e.what()))); } - return {}; + return Result::Ok; } Environment FileAccess::deviceEnvironment() const @@ -574,15 +571,15 @@ expected_str> FileAccess::watch(const FilePath return m_client->watch(filePath.nativePath()); } -Utils::expected_str FileAccess::signalProcess(int pid, ControlSignal signal) const +Result FileAccess::signalProcess(int pid, ControlSignal signal) const { try { auto f = m_client->signalProcess(pid, signal); - QTC_ASSERT_EXPECTED(f, return {}); + QTC_ASSERT_EXPECTED(f, return Result::Ok); f->waitForFinished(); - return {}; + return Result::Ok; } catch (const std::exception &e) { - return make_unexpected( + return Result::Error( Tr::tr("Error killing process: %1").arg(QString::fromLocal8Bit(e.what()))); }; } diff --git a/src/libs/gocmdbridge/client/bridgedfileaccess.h b/src/libs/gocmdbridge/client/bridgedfileaccess.h index 2d6ffb72278..54fcbd58bc3 100644 --- a/src/libs/gocmdbridge/client/bridgedfileaccess.h +++ b/src/libs/gocmdbridge/client/bridgedfileaccess.h @@ -27,17 +27,17 @@ class QTCREATOR_CMDBRIDGE_EXPORT FileAccess : public Utils::DeviceFileAccess public: ~FileAccess() override; - Utils::expected_str deployAndInit( + Utils::Result deployAndInit( const Utils::FilePath &libExecPath, const Utils::FilePath &remoteRootPath); - Utils::expected_str init(const Utils::FilePath &pathToBridge); + Utils::Result init(const Utils::FilePath &pathToBridge); - Utils::expected_str signalProcess(int pid, Utils::ControlSignal signal) const; + Utils::Result signalProcess(int pid, Utils::ControlSignal signal) const; Utils::Environment deviceEnvironment() const override; protected: - Utils::expected_str reinit(); + Utils::Result reinit(); void iterateDirectory(const Utils::FilePath &filePath, const Utils::FilePath::IterateDirCallback &callBack, @@ -69,16 +69,16 @@ protected: Utils::expected_str writeFileContents(const Utils::FilePath &filePath, const QByteArray &data) const override; - Utils::expected_str removeFile(const Utils::FilePath &filePath) const override; + Utils::Result removeFile(const Utils::FilePath &filePath) const override; bool removeRecursively(const Utils::FilePath &filePath, QString *error) const override; bool ensureExistingFile(const Utils::FilePath &filePath) const override; bool createDirectory(const Utils::FilePath &filePath) const override; - Utils::expected_str copyFile(const Utils::FilePath &filePath, - const Utils::FilePath &target) const override; + Utils::Result copyFile(const Utils::FilePath &filePath, + const Utils::FilePath &target) const override; - Utils::expected_str renameFile( + Utils::Result renameFile( const Utils::FilePath &filePath, const Utils::FilePath &target) const override; Utils::expected_str createTempFile(const Utils::FilePath &filePath) override; diff --git a/src/libs/utils/devicefileaccess.cpp b/src/libs/utils/devicefileaccess.cpp index ab07c83dee4..e318cc7df0a 100644 --- a/src/libs/utils/devicefileaccess.cpp +++ b/src/libs/utils/devicefileaccess.cpp @@ -117,22 +117,21 @@ bool DeviceFileAccess::hasHardLinks(const FilePath &filePath) const return false; } -expected_str DeviceFileAccess::ensureWritableDirectory(const FilePath &filePath) const +Result DeviceFileAccess::ensureWritableDirectory(const FilePath &filePath) const { if (isWritableDirectory(filePath)) - return {}; + return Result::Ok; if (exists(filePath)) { - return make_unexpected(Tr::tr("Path \"%1\" exists but is not a writable directory.") + return Result::Error(Tr::tr("Path \"%1\" exists but is not a writable directory.") .arg(filePath.toUserOutput())); } const bool result = createDirectory(filePath); if (result) - return {}; + return Result::Ok; - return make_unexpected( - Tr::tr("Failed to create directory \"%1\".").arg(filePath.toUserOutput())); + return Result::Error(Tr::tr("Failed to create directory \"%1\".").arg(filePath.toUserOutput())); } bool DeviceFileAccess::ensureExistingFile(const FilePath &filePath) const @@ -155,11 +154,10 @@ bool DeviceFileAccess::exists(const FilePath &filePath) const return false; } -expected_str DeviceFileAccess::removeFile(const FilePath &filePath) const +Result DeviceFileAccess::removeFile(const FilePath &filePath) const { - Q_UNUSED(filePath) QTC_CHECK(false); - return make_unexpected( + return Result::Error( Tr::tr("removeFile is not implemented for \"%1\".").arg(filePath.toUserOutput())); } @@ -171,18 +169,17 @@ bool DeviceFileAccess::removeRecursively(const FilePath &filePath, QString *erro return false; } -expected_str DeviceFileAccess::copyFile(const FilePath &filePath, const FilePath &target) const +Result DeviceFileAccess::copyFile(const FilePath &filePath, const FilePath &target) const { - Q_UNUSED(filePath) Q_UNUSED(target) QTC_CHECK(false); - return make_unexpected( + return Result::Error( Tr::tr("copyFile is not implemented for \"%1\".").arg(filePath.toUserOutput())); } -expected_str copyRecursively_fallback(const FilePath &src, const FilePath &target) +static Result copyRecursively_fallback(const FilePath &src, const FilePath &target) { - expected_str result; + Result result = Result::Ok; src.iterateDirectory( [&target, &src, &result](const FilePath &path) { const FilePath relative = path.relativePathFrom(src); @@ -202,16 +199,15 @@ expected_str copyRecursively_fallback(const FilePath &src, const FilePath return result; } -expected_str DeviceFileAccess::copyRecursively(const FilePath &src, - const FilePath &target) const +Result DeviceFileAccess::copyRecursively(const FilePath &src, const FilePath &target) const { if (!src.isDir()) { - return make_unexpected( + return Result::Error( Tr::tr("Cannot copy from \"%1\", it is not a directory.").arg(src.toUserOutput())); } - const expected_str result = target.ensureWritableDir(); + const Result result = target.ensureWritableDir(); if (!result) { - return make_unexpected(Tr::tr("Cannot copy \"%1\" to \"%2\": %3") + return Result::Error(Tr::tr("Cannot copy \"%1\" to \"%2\": %3") .arg(src.toUserOutput()) .arg(target.toUserOutput()) .arg(result.error())); @@ -254,7 +250,7 @@ expected_str DeviceFileAccess::copyRecursively(const FilePath &src, if (srcProcess.result() != ProcessResult::FinishedWithSuccess) { targetProcess.kill(); - return make_unexpected( + return Result::Error( Tr::tr("Failed to copy recursively from \"%1\" to \"%2\" while " "trying to create tar archive from source: %3") .arg(src.toUserOutput(), target.toUserOutput(), srcProcess.readAllStandardError())); @@ -263,23 +259,22 @@ expected_str DeviceFileAccess::copyRecursively(const FilePath &src, targetProcess.waitForFinished(); if (targetProcess.result() != ProcessResult::FinishedWithSuccess) { - return make_unexpected(Tr::tr("Failed to copy recursively from \"%1\" to \"%2\" while " + return Result::Error(Tr::tr("Failed to copy recursively from \"%1\" to \"%2\" while " "trying to extract tar archive to target: %3") .arg(src.toUserOutput(), target.toUserOutput(), targetProcess.readAllStandardError())); } - return {}; + return Result::Ok; #endif } -expected_str DeviceFileAccess::renameFile(const FilePath &filePath, const FilePath &target) const +Result DeviceFileAccess::renameFile(const FilePath &filePath, const FilePath &target) const { - Q_UNUSED(filePath) Q_UNUSED(target) QTC_CHECK(false); - return make_unexpected( + return Result::Error( Tr::tr("renameFile is not implemented for \"%1\".").arg(filePath.toUserOutput())); } @@ -684,22 +679,22 @@ bool DesktopDeviceFileAccess::hasHardLinks(const FilePath &filePath) const return false; } -expected_str DesktopDeviceFileAccess::ensureWritableDirectory(const FilePath &filePath) const +Result DesktopDeviceFileAccess::ensureWritableDirectory(const FilePath &filePath) const { const QFileInfo fi(filePath.path()); if (fi.isDir() && fi.isWritable()) - return {}; + return Result::Ok; if (fi.exists()) { - return make_unexpected(Tr::tr("Path \"%1\" exists but is not a writable directory.") + return Result::Error(Tr::tr("Path \"%1\" exists but is not a writable directory.") .arg(filePath.toUserOutput())); } const bool result = QDir().mkpath(filePath.path()); if (result) - return {}; + return Result::Ok; - return make_unexpected( + return Result::Error( Tr::tr("Failed to create directory \"%1\".").arg(filePath.toUserOutput())); } @@ -724,12 +719,12 @@ bool DesktopDeviceFileAccess::exists(const FilePath &filePath) const return !filePath.isEmpty() && QFileInfo::exists(filePath.path()); } -expected_str DesktopDeviceFileAccess::removeFile(const FilePath &filePath) const +Result DesktopDeviceFileAccess::removeFile(const FilePath &filePath) const { QFile f(filePath.path()); if (!f.remove()) - return make_unexpected(f.errorString()); - return {}; + return Result::Error(f.errorString()); + return Result::Ok; } static bool checkToRefuseRemoveStandardLocationDirectory(const QString &dirPath, @@ -806,26 +801,26 @@ bool DesktopDeviceFileAccess::removeRecursively(const FilePath &filePath, QStrin return true; } -expected_str DesktopDeviceFileAccess::copyFile(const FilePath &filePath, +Result DesktopDeviceFileAccess::copyFile(const FilePath &filePath, const FilePath &target) const { QFile srcFile(filePath.path()); if (srcFile.copy(target.path())) - return {}; - return make_unexpected( + return Result::Ok; + return Result::Error( Tr::tr("Failed to copy file \"%1\" to \"%2\": %3") .arg(filePath.toUserOutput(), target.toUserOutput(), srcFile.errorString())); } -expected_str DesktopDeviceFileAccess::renameFile( +Result DesktopDeviceFileAccess::renameFile( const FilePath &filePath, const FilePath &target) const { QFile f(filePath.path()); if (f.rename(target.path())) - return {}; - return make_unexpected( + return Result::Ok; + return Result::Error( Tr::tr("Failed to rename file \"%1\" to \"%2\": %3") .arg(filePath.toUserOutput(), target.toUserOutput(), f.errorString())); } @@ -1060,9 +1055,14 @@ QByteArray DesktopDeviceFileAccess::fileId(const FilePath &filePath) const // UnixDeviceAccess +static QString disconnectedMessage() +{ + return Tr::tr("Device is not connected"); +} + static Utils::unexpected make_unexpected_disconnected() { - return make_unexpected(Tr::tr("Device is not connected")); + return make_unexpected(disconnectedMessage()); } UnixDeviceFileAccess::~UnixDeviceFileAccess() = default; @@ -1175,20 +1175,21 @@ bool UnixDeviceFileAccess::exists(const FilePath &filePath) const return runInShellSuccess({"test", {"-e", path}, OsType::OsTypeLinux}); } -expected_str UnixDeviceFileAccess::removeFile(const FilePath &filePath) const +Result UnixDeviceFileAccess::removeFile(const FilePath &filePath) const { if (disconnected()) - return make_unexpected_disconnected(); + return Result::Error(disconnectedMessage()); RunResult result = runInShell({"rm", {filePath.path()}, OsType::OsTypeLinux}); if (result.exitCode != 0) - return make_unexpected(QString::fromUtf8(result.stdErr)); - return {}; + return Result::Error(QString::fromUtf8(result.stdErr)); + return Result::Ok; } bool UnixDeviceFileAccess::removeRecursively(const FilePath &filePath, QString *error) const { if (disconnected()) return false; + QTC_ASSERT(filePath.path().startsWith('/'), return false); const QString path = filePath.cleanPath().path(); @@ -1206,36 +1207,35 @@ bool UnixDeviceFileAccess::removeRecursively(const FilePath &filePath, QString * return result.exitCode == 0; } -expected_str UnixDeviceFileAccess::copyFile(const FilePath &filePath, - const FilePath &target) const +Result UnixDeviceFileAccess::copyFile(const FilePath &filePath, const FilePath &target) const { if (disconnected()) - return make_unexpected_disconnected(); + return Result::Error(disconnectedMessage()); const RunResult result = runInShell( {"cp", {filePath.path(), target.path()}, OsType::OsTypeLinux}); if (result.exitCode != 0) { - return make_unexpected(Tr::tr("Failed to copy file \"%1\" to \"%2\": %3") + return Result::Error(Tr::tr("Failed to copy file \"%1\" to \"%2\": %3") .arg(filePath.toUserOutput(), target.toUserOutput(), QString::fromUtf8(result.stdErr))); } - return {}; + return Result::Ok; } -expected_str UnixDeviceFileAccess::renameFile(const FilePath &filePath, const FilePath &target) const +Result UnixDeviceFileAccess::renameFile(const FilePath &filePath, const FilePath &target) const { if (disconnected()) - return make_unexpected_disconnected(); + return Result::Error(disconnectedMessage()); - auto result = runInShell({"mv", {filePath.path(), target.path()}, OsType::OsTypeLinux}); + RunResult result = runInShell({"mv", {filePath.path(), target.path()}, OsType::OsTypeLinux}); if (result.exitCode != 0) { - return make_unexpected(Tr::tr("Failed to rename file \"%1\" to \"%2\": %3") + return Result::Error(Tr::tr("Failed to rename file \"%1\" to \"%2\": %3") .arg(filePath.toUserOutput(), target.toUserOutput(), QString::fromUtf8(result.stdErr))); } - return {}; + return Result::Ok; } FilePath UnixDeviceFileAccess::symLinkTarget(const FilePath &filePath) const diff --git a/src/libs/utils/devicefileaccess.h b/src/libs/utils/devicefileaccess.h index 97aa014ab21..d5c82a0076c 100644 --- a/src/libs/utils/devicefileaccess.h +++ b/src/libs/utils/devicefileaccess.h @@ -38,16 +38,15 @@ protected: virtual bool isDirectory(const FilePath &filePath) const; virtual bool isSymLink(const FilePath &filePath) const; virtual bool hasHardLinks(const FilePath &filePath) const; - virtual expected_str ensureWritableDirectory(const FilePath &filePath) const; + virtual Result ensureWritableDirectory(const FilePath &filePath) const; virtual bool ensureExistingFile(const FilePath &filePath) const; virtual bool createDirectory(const FilePath &filePath) const; virtual bool exists(const FilePath &filePath) const; - virtual expected_str removeFile(const FilePath &filePath) const; + virtual Result removeFile(const FilePath &filePath) const; virtual bool removeRecursively(const FilePath &filePath, QString *error) const; - virtual expected_str copyFile(const FilePath &filePath, const FilePath &target) const; - virtual expected_str copyRecursively(const FilePath &filePath, - const FilePath &target) const; - virtual expected_str renameFile(const FilePath &filePath, const FilePath &target) const; + virtual Result copyFile(const FilePath &filePath, const FilePath &target) const; + virtual Result copyRecursively(const FilePath &filePath, const FilePath &target) const; + virtual Result renameFile(const FilePath &filePath, const FilePath &target) const; virtual FilePath symLinkTarget(const FilePath &filePath) const; virtual FilePathInfo filePathInfo(const FilePath &filePath) const; @@ -97,14 +96,14 @@ protected: bool isDirectory(const FilePath &filePath) const override; bool isSymLink(const FilePath &filePath) const override; bool hasHardLinks(const FilePath &filePath) const override; - expected_str ensureWritableDirectory(const FilePath &filePath) const override; + Result ensureWritableDirectory(const FilePath &filePath) const override; bool ensureExistingFile(const FilePath &filePath) const override; bool createDirectory(const FilePath &filePath) const override; bool exists(const FilePath &filePath) const override; - expected_str removeFile(const FilePath &filePath) const override; + Result removeFile(const FilePath &filePath) const override; bool removeRecursively(const FilePath &filePath, QString *error) const override; - expected_str copyFile(const FilePath &filePath, const FilePath &target) const override; - expected_str renameFile(const FilePath &filePath, const FilePath &target) const override; + Result copyFile(const FilePath &filePath, const FilePath &target) const override; + Result renameFile(const FilePath &filePath, const FilePath &target) const override; FilePath symLinkTarget(const FilePath &filePath) const override; FilePathInfo filePathInfo(const FilePath &filePath) const override; @@ -159,10 +158,10 @@ protected: bool ensureExistingFile(const FilePath &filePath) const override; bool createDirectory(const FilePath &filePath) const override; bool exists(const FilePath &filePath) const override; - expected_str removeFile(const FilePath &filePath) const override; + Result removeFile(const FilePath &filePath) const override; bool removeRecursively(const FilePath &filePath, QString *error) const override; - expected_str copyFile(const FilePath &filePath, const FilePath &target) const override; - expected_str renameFile(const FilePath &filePath, const FilePath &target) const override; + Result copyFile(const FilePath &filePath, const FilePath &target) const override; + Result renameFile(const FilePath &filePath, const FilePath &target) const override; FilePathInfo filePathInfo(const FilePath &filePath) const override; FilePath symLinkTarget(const FilePath &filePath) const override; diff --git a/src/libs/utils/filepath.cpp b/src/libs/utils/filepath.cpp index d52b6fea04c..c7231a9976a 100644 --- a/src/libs/utils/filepath.cpp +++ b/src/libs/utils/filepath.cpp @@ -551,7 +551,7 @@ void FilePath::setParts(const QStringView scheme, const QStringView host, QStrin \sa createDir() */ -expected_str FilePath::ensureWritableDir() const +Result FilePath::ensureWritableDir() const { return fileAccess()->ensureWritableDirectory(*this); } @@ -1980,7 +1980,7 @@ OsType FilePath::osType() const return s_deviceHooks.osType(*this); } -expected_str FilePath::removeFile() const +Result FilePath::removeFile() const { return fileAccess()->removeFile(*this); } @@ -1997,18 +1997,18 @@ bool FilePath::removeRecursively(QString *error) const return fileAccess()->removeRecursively(*this, error); } -expected_str FilePath::copyRecursively(const FilePath &target) const +Result FilePath::copyRecursively(const FilePath &target) const { return fileAccess()->copyRecursively(*this, target); } -expected_str FilePath::copyFile(const FilePath &target) const +Result FilePath::copyFile(const FilePath &target) const { if (!isSameDevice(target)) { // FIXME: This does not scale. const expected_str contents = fileContents(); if (!contents) { - return make_unexpected( + return Result::Error( Tr::tr("Error while trying to copy file: %1").arg(contents.error())); } @@ -2016,38 +2016,41 @@ expected_str FilePath::copyFile(const FilePath &target) const const expected_str copyResult = target.writeFileContents(*contents); if (!copyResult) - return make_unexpected(Tr::tr("Could not copy file: %1").arg(copyResult.error())); + return Result::Error(Tr::tr("Could not copy file: %1").arg(copyResult.error())); if (!target.setPermissions(perms)) { target.removeFile(); - return make_unexpected( + return Result::Error( Tr::tr("Could not set permissions on \"%1\"").arg(target.toString())); } - return {}; + return Result::Ok; } return fileAccess()->copyFile(*this, target); } -expected_str FilePath::renameFile(const FilePath &target) const +Result FilePath::renameFile(const FilePath &target) const { if (isSameDevice(target)) return fileAccess()->renameFile(*this, target); - return copyFile(target).and_then([this, &target] { - return removeFile().or_else( - [this, &target](const QString &removeError) -> expected_str { - // If we fail to remove the source file, we remove the target file to return to the - // original state. - expected_str rmResult = target.removeFile(); - QTC_CHECK_EXPECTED(rmResult); - return make_unexpected( - Tr::tr("Failed to move %1 to %2. Removing the source file failed: %3") - .arg(toUserOutput()) - .arg(target.toUserOutput()) - .arg(removeError)); - }); - }); + const Result copyResult = copyFile(target); + if (!copyResult) + return copyResult; + + const Result removeResult = removeFile(); + if (removeResult) + return Result::Ok; + + // If we fail to remove the source file, we remove the target file to return to the + // original state. + Result rmResult = target.removeFile(); + QTC_CHECK_EXPECTED(rmResult); + return Result::Error( + Tr::tr("Failed to move %1 to %2. Removing the source file failed: %3") + .arg(toUserOutput()) + .arg(target.toUserOutput()) + .arg(rmResult.error())); } qint64 FilePath::fileSize() const diff --git a/src/libs/utils/filepath.h b/src/libs/utils/filepath.h index 982ec3ea94f..b79ef3c1d71 100644 --- a/src/libs/utils/filepath.h +++ b/src/libs/utils/filepath.h @@ -152,7 +152,7 @@ public: bool isWritableDir() const; bool isWritableFile() const; - expected_str ensureWritableDir() const; + Result ensureWritableDir() const; bool ensureExistingFile() const; bool isExecutableFile() const; bool isReadableFile() const; @@ -170,11 +170,11 @@ public: QFile::Permissions permissions() const; bool setPermissions(QFile::Permissions permissions) const; OsType osType() const; - expected_str removeFile() const; + Result removeFile() const; bool removeRecursively(QString *error = nullptr) const; - expected_str copyRecursively(const FilePath &target) const; - expected_str copyFile(const FilePath &target) const; - expected_str renameFile(const FilePath &target) const; + Result copyRecursively(const FilePath &target) const; + Result copyFile(const FilePath &target) const; + Result renameFile(const FilePath &target) const; qint64 fileSize() const; qint64 bytesAvailable() const; bool createDir() const; diff --git a/src/libs/utils/fileutils.cpp b/src/libs/utils/fileutils.cpp index 319235d7c49..d011cd5a4d8 100644 --- a/src/libs/utils/fileutils.cpp +++ b/src/libs/utils/fileutils.cpp @@ -735,7 +735,7 @@ bool FileUtils::copyIfDifferent(const FilePath &srcFilePath, const FilePath &tgt tgtFilePath.removeFile(); } - const expected_str copyResult = srcFilePath.copyFile(tgtFilePath); + const Result copyResult = srcFilePath.copyFile(tgtFilePath); // TODO forward error to caller instead of assert, since IO errors can always be expected QTC_ASSERT_EXPECTED(copyResult, return false); diff --git a/src/libs/utils/fsengine/fsenginehandler.cpp b/src/libs/utils/fsengine/fsenginehandler.cpp index 4580ebdcb57..2fbd853963f 100644 --- a/src/libs/utils/fsengine/fsenginehandler.cpp +++ b/src/libs/utils/fsengine/fsenginehandler.cpp @@ -220,18 +220,18 @@ bool FSEngineImpl::remove() bool FSEngineImpl::copy(const QString &newName) { - expected_str result = m_filePath.copyFile(FilePath::fromString(newName)); + Result result = m_filePath.copyFile(FilePath::fromString(newName)); if (!result) setError(QFile::CopyError, result.error()); - return result.has_value(); + return bool(result); } bool FSEngineImpl::rename(const QString &newName) { - auto result = m_filePath.renameFile(FilePath::fromString(newName)); + Result result = m_filePath.renameFile(FilePath::fromString(newName)); if (!result) setError(QFile::RenameError, result.error()); - return result.has_value(); + return bool(result); } bool FSEngineImpl::renameOverwrite(const QString &newName) diff --git a/src/libs/utils/savefile.cpp b/src/libs/utils/savefile.cpp index 65f9fa41a41..9ccdf1cea52 100644 --- a/src/libs/utils/savefile.cpp +++ b/src/libs/utils/savefile.cpp @@ -197,7 +197,7 @@ bool SaveFile::commit() } } - expected_str renameResult = m_tempFile->filePath().renameFile(finalFileName); + Result renameResult = m_tempFile->filePath().renameFile(finalFileName); if (!renameResult) { // The case when someone else was able to create finalFileName after we've renamed it. // Higher level call may try to save this file again but here we do nothing and diff --git a/src/plugins/android/androidbuildapkstep.cpp b/src/plugins/android/androidbuildapkstep.cpp index 8ed611b19c4..ef1a93d7577 100644 --- a/src/plugins/android/androidbuildapkstep.cpp +++ b/src/plugins/android/androidbuildapkstep.cpp @@ -679,7 +679,7 @@ static bool copyFileIfNewer(const FilePath &sourceFilePath, if (!destinationFilePath.parentDir().ensureWritableDir()) return false; - expected_str result = sourceFilePath.copyFile(destinationFilePath); + Result result = sourceFilePath.copyFile(destinationFilePath); QTC_ASSERT_EXPECTED(result, return false); return true; } diff --git a/src/plugins/coreplugin/fileutils.cpp b/src/plugins/coreplugin/fileutils.cpp index b5f719f4a22..1b6af89db22 100644 --- a/src/plugins/coreplugin/fileutils.cpp +++ b/src/plugins/coreplugin/fileutils.cpp @@ -187,7 +187,7 @@ bool FileUtils::renameFile(const FilePath &orgFilePath, const FilePath &newFileP if (vc && vc->supportsOperation(IVersionControl::MoveOperation)) result = vc->vcsMove(orgFilePath, newFilePath); if (!result) // The moving via vcs failed or the vcs does not support moving, fall back - result = orgFilePath.renameFile(newFilePath).has_value(); + result = bool(orgFilePath.renameFile(newFilePath)); if (result) { DocumentManager::renamedFile(orgFilePath, newFilePath); updateHeaderFileGuardIfApplicable(orgFilePath, newFilePath, handleGuards); diff --git a/src/plugins/coreplugin/session.cpp b/src/plugins/coreplugin/session.cpp index 5fa186e3e24..88e4749b51f 100644 --- a/src/plugins/coreplugin/session.cpp +++ b/src/plugins/coreplugin/session.cpp @@ -351,9 +351,9 @@ bool SessionManager::deleteSession(const QString &session) FilePath sessionFile = sessionNameToFileName(session); if (!sessionFile.exists()) return false; - expected_str result = sessionFile.removeFile(); + Result result = sessionFile.removeFile(); QTC_CHECK_EXPECTED(result); - return result.has_value(); + return bool(result); } void SessionManager::deleteSessions(const QStringList &sessions) diff --git a/src/plugins/debugger/loadcoredialog.cpp b/src/plugins/debugger/loadcoredialog.cpp index 937c77b8e19..cc1b5ce3ebc 100644 --- a/src/plugins/debugger/loadcoredialog.cpp +++ b/src/plugins/debugger/loadcoredialog.cpp @@ -232,7 +232,7 @@ void AttachCoreDialog::accepted() const expected_str resultPath = pattern.createTempFile(); if (!resultPath) return make_unexpected(resultPath.error()); - const expected_str result = srcPath.copyFile(resultPath.value()); + const Result result = srcPath.copyFile(resultPath.value()); if (!result) return make_unexpected(result.error()); diff --git a/src/plugins/docker/dockerdevice.cpp b/src/plugins/docker/dockerdevice.cpp index aecf3dd82ba..78cbfa32e55 100644 --- a/src/plugins/docker/dockerdevice.cpp +++ b/src/plugins/docker/dockerdevice.cpp @@ -582,7 +582,7 @@ DockerDevice::DockerDevice() return make_unexpected(cmdBridgePath.error()); auto fAccess = std::make_unique(d); - expected_str initResult; + Result initResult = Result::Ok; if (!cmdBridgePath->isSameDevice(Docker::Internal::settings().dockerBinaryPath())) { initResult = fAccess->deployAndInit(Core::ICore::libexecPath(), rootPath()); } else { diff --git a/src/plugins/languageclient/languageclientutils.cpp b/src/plugins/languageclient/languageclientutils.cpp index 67a008ab074..e5685e296bc 100644 --- a/src/plugins/languageclient/languageclientutils.cpp +++ b/src/plugins/languageclient/languageclientutils.cpp @@ -381,7 +381,7 @@ bool applyDocumentChange(const Client *client, const DocumentChange &change) } } } - return oldPath.renameFile(newPath).has_value(); + return bool(oldPath.renameFile(newPath)); } else if (const auto deleteOperation = std::get_if(&change)) { const FilePath filePath = deleteOperation->uri().toFilePath(client->hostPathMapper()); if (const std::optional options = deleteOperation->options()) { @@ -390,7 +390,7 @@ bool applyDocumentChange(const Client *client, const DocumentChange &change) if (filePath.isDir() && options->recursive().value_or(false)) return filePath.removeRecursively(); } - return filePath.removeFile().has_value(); + return bool(filePath.removeFile()); } return false; } diff --git a/src/plugins/projectexplorer/buildconfiguration.cpp b/src/plugins/projectexplorer/buildconfiguration.cpp index 580cfdd699f..7e6be34f7c3 100644 --- a/src/plugins/projectexplorer/buildconfiguration.cpp +++ b/src/plugins/projectexplorer/buildconfiguration.cpp @@ -295,7 +295,7 @@ MacroExpander *BuildConfiguration::macroExpander() const bool BuildConfiguration::createBuildDirectory() { - const bool result = buildDirectory().ensureWritableDir().has_value(); + const bool result = bool(buildDirectory().ensureWritableDir()); buildDirectoryAspect()->validateInput(); return result; } diff --git a/src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.cpp b/src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.cpp index d12d824ddc8..3b7524faa00 100644 --- a/src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.cpp +++ b/src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.cpp @@ -158,8 +158,8 @@ QString AssetsLibraryModel::addNewFolder(const QString &folderPath) { Utils::FilePath uniqueDirPath = Utils::FilePath::fromString(UniqueName::generatePath(folderPath)); - auto res = uniqueDirPath.ensureWritableDir(); - if (!res.has_value()) { + const Utils::Result res = uniqueDirPath.ensureWritableDir(); + if (!res) { qWarning() << __FUNCTION__ << res.error(); return {}; } diff --git a/src/plugins/qtsupport/gettingstartedwelcomepage.cpp b/src/plugins/qtsupport/gettingstartedwelcomepage.cpp index 5f09c3aa636..90662a89d4c 100644 --- a/src/plugins/qtsupport/gettingstartedwelcomepage.cpp +++ b/src/plugins/qtsupport/gettingstartedwelcomepage.cpp @@ -139,7 +139,7 @@ static FilePath copyToAlternativeLocation(const FilePath &proFile, QMessageBox::NoButton); return {}; } else { - expected_str result = projectDir.copyRecursively(targetDir); + Result result = projectDir.copyRecursively(targetDir); if (result) { // set vars to new location diff --git a/src/plugins/remotelinux/genericdeploystep.cpp b/src/plugins/remotelinux/genericdeploystep.cpp index 936f55348bb..06318a2d5d3 100644 --- a/src/plugins/remotelinux/genericdeploystep.cpp +++ b/src/plugins/remotelinux/genericdeploystep.cpp @@ -78,9 +78,7 @@ private: GroupItem GenericDeployStep::mkdirTask(const Storage &storage) { - using ResultType = expected_str; - - const auto onSetup = [storage](Async &async) { + const auto onSetup = [storage](Async &async) { FilePaths remoteDirs; for (const FileToTransfer &file : *storage) remoteDirs << file.m_target.parentDir(); @@ -88,9 +86,9 @@ GroupItem GenericDeployStep::mkdirTask(const Storage &storage) FilePath::sort(remoteDirs); FilePath::removeDuplicates(remoteDirs); - async.setConcurrentCallData([remoteDirs](QPromise &promise) { + async.setConcurrentCallData([remoteDirs](QPromise &promise) { for (const FilePath &dir : remoteDirs) { - const expected_str result = dir.ensureWritableDir(); + const Result result = dir.ensureWritableDir(); promise.addResult(result); if (!result) promise.future().cancel(); @@ -98,7 +96,7 @@ GroupItem GenericDeployStep::mkdirTask(const Storage &storage) }); }; - const auto onError = [this](const Async &async) { + const auto onError = [this](const Async &async) { const int numResults = async.future().resultCount(); if (numResults == 0) { addErrorMessage( @@ -107,13 +105,13 @@ GroupItem GenericDeployStep::mkdirTask(const Storage &storage) } for (int i = 0; i < numResults; ++i) { - const ResultType result = async.future().resultAt(i); - if (!result.has_value()) + const Result result = async.future().resultAt(i); + if (!result) addErrorMessage(result.error()); } }; - return AsyncTask(onSetup, onError, CallDoneIf::Error); + return AsyncTask(onSetup, onError, CallDoneIf::Error); } static FileTransferMethod effectiveTransferMethodFor(const FileToTransfer &fileToTransfer, diff --git a/src/plugins/remotelinux/linuxdevice.cpp b/src/plugins/remotelinux/linuxdevice.cpp index 558e31b6bdf..2c028034eb1 100644 --- a/src/plugins/remotelinux/linuxdevice.cpp +++ b/src/plugins/remotelinux/linuxdevice.cpp @@ -1066,7 +1066,7 @@ LinuxDevice::LinuxDevice() }); addDeviceAction({Tr::tr("Open Remote Shell"), [](const IDevice::Ptr &device, QWidget *) { - expected_str result = device->openTerminal(Environment(), FilePath()); + Result result = device->openTerminal(Environment(), FilePath()); if (!result) QMessageBox::warning(nullptr, Tr::tr("Error"), result.error()); @@ -1567,18 +1567,18 @@ private: QHash m_batches; }; -static void createDir(QPromise> &promise, const FilePath &pathToCreate) +static void createDir(QPromise &promise, const FilePath &pathToCreate) { - const expected_str result = pathToCreate.ensureWritableDir(); + const Result result = pathToCreate.ensureWritableDir(); promise.addResult(result); if (!result) promise.future().cancel(); }; -static void copyFile(QPromise> &promise, const FileToTransfer &file) +static void copyFile(QPromise &promise, const FileToTransfer &file) { - const expected_str result = file.m_source.copyFile(file.m_target); + const Result result = file.m_source.copyFile(file.m_target); promise.addResult(result); if (!result) @@ -1606,13 +1606,13 @@ private: const LoopList iteratorParentDirs(QList(allParentDirs.cbegin(), allParentDirs.cend())); - const auto onCreateDirSetup = [iteratorParentDirs](Async> &async) { + const auto onCreateDirSetup = [iteratorParentDirs](Async &async) { async.setConcurrentCallData(createDir, *iteratorParentDirs); }; const auto onCreateDirDone = [this, - iteratorParentDirs](const Async> &async) { - const expected_str result = async.result(); + iteratorParentDirs](const Async &async) { + const Result result = async.result(); if (result) emit progress( Tr::tr("Created directory: \"%1\".\n").arg(iteratorParentDirs->toUserOutput())); @@ -1623,13 +1623,13 @@ private: const LoopList iterator(m_setup.m_files); const Storage counterStorage; - const auto onCopySetup = [iterator](Async> &async) { + const auto onCopySetup = [iterator](Async &async) { async.setConcurrentCallData(copyFile, *iterator); }; const auto onCopyDone = [this, iterator, counterStorage]( - const Async> &async) { - const expected_str result = async.result(); + const Async &async) { + const Result result = async.result(); int &counter = *counterStorage; ++counter; @@ -1648,12 +1648,12 @@ private: const Group recipe { For (iteratorParentDirs) >> Do { parallelIdealThreadCountLimit, - AsyncTask>(onCreateDirSetup, onCreateDirDone), + AsyncTask(onCreateDirSetup, onCreateDirDone), }, For (iterator) >> Do { parallelLimit(2), counterStorage, - AsyncTask>(onCopySetup, onCopyDone), + AsyncTask(onCopySetup, onCopyDone), }, }; diff --git a/src/plugins/squish/squishtesttreeview.cpp b/src/plugins/squish/squishtesttreeview.cpp index e6dd495aea9..6421b89593b 100644 --- a/src/plugins/squish/squishtesttreeview.cpp +++ b/src/plugins/squish/squishtesttreeview.cpp @@ -185,7 +185,7 @@ void SquishTestTreeItemDelegate::setEditorData(QWidget *editor, const QModelInde static bool copyScriptTemplates(const SuiteConf &suiteConf, const Utils::FilePath &destination) { - Utils::expected_str result = destination.ensureWritableDir(); + Utils::Result result = destination.ensureWritableDir(); QTC_ASSERT_EXPECTED(result, return false); const bool scripted = suiteConf.objectMapStyle() == "script"; diff --git a/src/plugins/squish/suiteconf.cpp b/src/plugins/squish/suiteconf.cpp index 03a93b6a172..9e6ebfdea5c 100644 --- a/src/plugins/squish/suiteconf.cpp +++ b/src/plugins/squish/suiteconf.cpp @@ -323,7 +323,7 @@ bool SuiteConf::ensureObjectMapExists() const return true; const Utils::FilePath objectMap = scripts.pathAppended("objectmap_template" + extension); - Utils::expected_str result = destinationObjectMap.parentDir().ensureWritableDir(); + Utils::Result result = destinationObjectMap.parentDir().ensureWritableDir(); QTC_ASSERT_EXPECTED(result, return false); result = objectMap.copyFile(destinationObjectMap); QTC_ASSERT_EXPECTED(result, return false); diff --git a/src/plugins/terminal/shellintegration.cpp b/src/plugins/terminal/shellintegration.cpp index 300da2aff20..11dce74eca3 100644 --- a/src/plugins/terminal/shellintegration.cpp +++ b/src/plugins/terminal/shellintegration.cpp @@ -172,7 +172,7 @@ void ShellIntegration::prepareProcess(Utils::Process &process) const FilePath rcPath = filesToCopy.bash.rcFile; const FilePath tmpRc = FilePath::fromUserInput( m_tempDir.filePath(filesToCopy.bash.rcFile.fileName())); - expected_str copyResult = rcPath.copyFile(tmpRc); + const Result copyResult = rcPath.copyFile(tmpRc); QTC_ASSERT_EXPECTED(copyResult, return); if (cmd.arguments() == "-l") @@ -181,7 +181,7 @@ void ShellIntegration::prepareProcess(Utils::Process &process) cmd = {cmd.executable(), {"--init-file", tmpRc.nativePath()}}; } else if (cmd.executable().baseName() == "zsh") { for (const FileToCopy &file : filesToCopy.zsh.files) { - const expected_str copyResult = file.source.copyFile( + const Result copyResult = file.source.copyFile( FilePath::fromUserInput(m_tempDir.filePath(file.destName))); QTC_ASSERT_EXPECTED(copyResult, return); } @@ -196,7 +196,7 @@ void ShellIntegration::prepareProcess(Utils::Process &process) const FilePath rcPath = filesToCopy.pwsh.script; const FilePath tmpRc = FilePath::fromUserInput( m_tempDir.filePath(filesToCopy.pwsh.script.fileName())); - expected_str copyResult = rcPath.copyFile(tmpRc); + const Result copyResult = rcPath.copyFile(tmpRc); QTC_ASSERT_EXPECTED(copyResult, return); cmd.addArgs(QString("-noexit -command try { . '%1' } catch {Write-Host \"Shell " @@ -207,7 +207,7 @@ void ShellIntegration::prepareProcess(Utils::Process &process) const FilePath rcPath = filesToCopy.clink.script; const FilePath tmpRc = FilePath::fromUserInput( m_tempDir.filePath(filesToCopy.clink.script.fileName())); - expected_str copyResult = rcPath.copyFile(tmpRc); + const Result copyResult = rcPath.copyFile(tmpRc); QTC_ASSERT_EXPECTED(copyResult, return); env.set("CLINK_HISTORY_LABEL", "QtCreator"); @@ -216,7 +216,7 @@ void ShellIntegration::prepareProcess(Utils::Process &process) FilePath xdgDir = FilePath::fromUserInput(m_tempDir.filePath("fish_xdg_data")); FilePath subDir = xdgDir.resolvePath(QString("fish/vendor_conf.d")); QTC_ASSERT(subDir.createDir(), return); - expected_str copyResult = filesToCopy.fish.script.copyFile( + const Result copyResult = filesToCopy.fish.script.copyFile( subDir.resolvePath(filesToCopy.fish.script.fileName())); QTC_ASSERT_EXPECTED(copyResult, return); From ea60709dd9dc676738032cf82282b354b1ed809e Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 8 Oct 2024 08:53:10 +0200 Subject: [PATCH 63/76] Axivion: Code cosmetics settings page Just the code, the layout may need adjustment, too. I find the "far away" Add/Remove/Edit column a bit ugly. Change-Id: I617fc3d3c7b73e4cc92817833b857078681b9603 Reviewed-by: Christian Stenger --- src/plugins/axivion/axivionsettings.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/plugins/axivion/axivionsettings.cpp b/src/plugins/axivion/axivionsettings.cpp index 74c0c695b86..1c15d4979d0 100644 --- a/src/plugins/axivion/axivionsettings.cpp +++ b/src/plugins/axivion/axivionsettings.cpp @@ -388,17 +388,17 @@ AxivionSettingsWidget::AxivionSettingsWidget() auto addButton = new QPushButton(Tr::tr("Add..."), this); m_edit = new QPushButton(Tr::tr("Edit..."), this); m_remove = new QPushButton(Tr::tr("Remove"), this); - Column{ - Row{ - Form{Tr::tr("Default dashboard server:"), m_dashboardServers, br}, + Column { + Row { + Form { Tr::tr("Default dashboard server:"), m_dashboardServers, br }, st, - Column{addButton, m_edit, st, m_remove}, + Column { addButton, m_edit, st, m_remove }, }, Space(10), br, - Row{settings().highlightMarks}, - st} - .attachTo(this); + Row {settings().highlightMarks }, + st + }.attachTo(this); connect(addButton, &QPushButton::clicked, this, [this] { // add an empty item unconditionally From e3474184f6746be30d375bb730ff3099df7bada6 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Mon, 7 Oct 2024 15:37:21 +0200 Subject: [PATCH 64/76] QbsProjectManager: Shorten display name of QbsKitAspect Otherwise, valuable screen estate is taken away from all aspect values. Task-number: QTCREATORBUG-31685 Change-Id: I3fe1802604e08bbc86d36a9b18ca44b8e7486beb Reviewed-by: Christian Stenger --- src/plugins/qbsprojectmanager/qbskitaspect.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/plugins/qbsprojectmanager/qbskitaspect.cpp b/src/plugins/qbsprojectmanager/qbskitaspect.cpp index a708601e219..f9fd3e6ec14 100644 --- a/src/plugins/qbsprojectmanager/qbskitaspect.cpp +++ b/src/plugins/qbsprojectmanager/qbskitaspect.cpp @@ -89,7 +89,10 @@ public: QbsKitAspectFactory() { setId(QbsKitAspect::id()); - setDisplayName(Tr::tr("Additional Qbs Profile Settings")); + setDisplayName(Tr::tr("Qbs Profile Additions")); + setDescription(Tr::tr("Additional module properties to set in " + "the Qbs profile corresponding to this kit.\n" + "You will rarely need to do this.")); setPriority(22000); } From 37989cf7bdde6d00bf9bd152ec307c00fca7dd53 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Mon, 7 Oct 2024 14:57:00 +0200 Subject: [PATCH 65/76] QmakeProjectManager: Get rid of custom parse delay Use the same update interval as the other build systems and remove needlessly stateful logic that made it difficult to understand what's going on. Fixes: QTCREATORBUG-31636 Change-Id: I39ef5a9d6834f5e7f7b457e2e2466fb912ee92e2 Reviewed-by: Christian Stenger --- src/plugins/projectexplorer/buildsystem.cpp | 15 --------------- src/plugins/projectexplorer/buildsystem.h | 3 --- src/plugins/qmakeprojectmanager/qmakeproject.cpp | 16 ++++++---------- 3 files changed, 6 insertions(+), 28 deletions(-) diff --git a/src/plugins/projectexplorer/buildsystem.cpp b/src/plugins/projectexplorer/buildsystem.cpp index 6b98866135a..52c5b73f024 100644 --- a/src/plugins/projectexplorer/buildsystem.cpp +++ b/src/plugins/projectexplorer/buildsystem.cpp @@ -141,26 +141,11 @@ void BuildSystem::requestDelayedParse() requestParseHelper(1000); } -void BuildSystem::requestParseWithCustomDelay(int delayInMs) -{ - requestParseHelper(delayInMs); -} - void BuildSystem::cancelDelayedParseRequest() { d->m_delayedParsingTimer.stop(); } -void BuildSystem::setParseDelay(int delayInMs) -{ - d->m_delayedParsingTimer.setInterval(delayInMs); -} - -int BuildSystem::parseDelay() const -{ - return d->m_delayedParsingTimer.interval(); -} - bool BuildSystem::isParsing() const { return d->m_isParsing; diff --git a/src/plugins/projectexplorer/buildsystem.h b/src/plugins/projectexplorer/buildsystem.h index f18cbbbea71..1681f28e5f3 100644 --- a/src/plugins/projectexplorer/buildsystem.h +++ b/src/plugins/projectexplorer/buildsystem.h @@ -56,10 +56,7 @@ public: void requestParse(); void requestDelayedParse(); - void requestParseWithCustomDelay(int delayInMs = 1000); void cancelDelayedParseRequest(); - void setParseDelay(int delayInMs); - int parseDelay() const; bool isParsing() const; bool hasParsingData() const; diff --git a/src/plugins/qmakeprojectmanager/qmakeproject.cpp b/src/plugins/qmakeprojectmanager/qmakeproject.cpp index c8ae2c884e7..1f5e3ce5f98 100644 --- a/src/plugins/qmakeprojectmanager/qmakeproject.cpp +++ b/src/plugins/qmakeprojectmanager/qmakeproject.cpp @@ -68,8 +68,6 @@ using namespace Utils; namespace QmakeProjectManager { namespace Internal { -const int UPDATE_INTERVAL = 3000; - static Q_LOGGING_CATEGORY(qmakeBuildSystemLog, "qtc.qmake.buildsystem", QtWarningMsg); #define TRACE(msg) \ @@ -204,8 +202,6 @@ QmakeBuildSystem::QmakeBuildSystem(QmakeBuildConfiguration *bc) , m_qmakeVfs(new QMakeVfs) , m_cppCodeModelUpdater(ProjectUpdaterFactory::createCppProjectUpdater()) { - setParseDelay(0); - m_rootProFile = std::make_unique(this, projectFilePath()); connect(BuildManager::instance(), &BuildManager::buildQueueFinished, @@ -588,10 +584,11 @@ void QmakeBuildSystem::startAsyncTimer(QmakeProFile::AsyncUpdateDelay delay) return; } - const int interval = qMin(parseDelay(), - delay == QmakeProFile::ParseLater ? UPDATE_INTERVAL : 0); - TRACE("interval: " << interval); - requestParseWithCustomDelay(interval); + TRACE("delay: " << delay); + switch (delay) { + case QmakeProFile::ParseNow: requestParse(); break; + case QmakeProFile::ParseLater: requestDelayedParse(); break; + } } void QmakeBuildSystem::incrementPendingEvaluateFutures() @@ -666,7 +663,6 @@ bool QmakeBuildSystem::wasEvaluateCanceled() void QmakeBuildSystem::asyncUpdate() { TaskHub::clearTasks(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM); - setParseDelay(UPDATE_INTERVAL); TRACE(""); if (m_invalidateQmakeVfsContents) { @@ -945,7 +941,7 @@ void QmakeBuildSystem::activeTargetWasChanged(Target *t) return; m_invalidateQmakeVfsContents = true; - scheduleUpdateAll(QmakeProFile::ParseLater); + scheduleUpdateAllNowOrLater(); } static void notifyChangedHelper(const FilePath &fileName, QmakeProFile *file) From 471067bd7864f43eafaa7f1b3fe0d1e83dfb18b0 Mon Sep 17 00:00:00 2001 From: hjk Date: Fri, 4 Oct 2024 15:42:07 +0200 Subject: [PATCH 66/76] Debugger: Integrate core file unpacking into linear startup Change-Id: I5bc257af7df24e3a22caba37dcbfe3665e8f6aa1 Reviewed-by: Christian Stenger --- src/plugins/debugger/debuggerruncontrol.cpp | 145 +++++++++----------- src/plugins/debugger/debuggerruncontrol.h | 3 + 2 files changed, 69 insertions(+), 79 deletions(-) diff --git a/src/plugins/debugger/debuggerruncontrol.cpp b/src/plugins/debugger/debuggerruncontrol.cpp index c1e70eeda7c..50c4428d8e1 100644 --- a/src/plugins/debugger/debuggerruncontrol.cpp +++ b/src/plugins/debugger/debuggerruncontrol.cpp @@ -83,92 +83,27 @@ static QString noDebuggerInKitMessage() return Tr::tr("The kit does not have a debugger set."); } -class CoreUnpacker final : public RunWorker -{ -public: - CoreUnpacker(RunControl *runControl, const FilePath &coreFilePath) - : RunWorker(runControl), m_coreFilePath(coreFilePath) - {} - - FilePath coreFileName() const { return m_tempCoreFilePath; } - -private: - ~CoreUnpacker() final - { - if (m_tempCoreFile.isOpen()) - m_tempCoreFile.close(); - - m_tempCoreFilePath.removeFile(); - } - - void start() final - { - { - Utils::TemporaryFile tmp("tmpcore-XXXXXX"); - tmp.open(); - m_tempCoreFilePath = FilePath::fromString(tmp.fileName()); - } - - m_coreUnpackProcess.setWorkingDirectory(TemporaryDirectory::masterDirectoryFilePath()); - connect(&m_coreUnpackProcess, &Process::done, this, [this] { - if (m_coreUnpackProcess.error() == QProcess::UnknownError) { - reportStopped(); - return; - } - reportFailure("Error unpacking " + m_coreFilePath.toUserOutput()); - }); - - const QString msg = Tr::tr("Unpacking core file to %1"); - appendMessage(msg.arg(m_tempCoreFilePath.toUserOutput()), LogMessageFormat); - - if (m_coreFilePath.endsWith(".lzo")) { - m_coreUnpackProcess.setCommand({"lzop", {"-o", m_tempCoreFilePath.path(), - "-x", m_coreFilePath.path()}}); - reportStarted(); - m_coreUnpackProcess.start(); - return; - } - - if (m_coreFilePath.endsWith(".gz")) { - appendMessage(msg.arg(m_tempCoreFilePath.toUserOutput()), LogMessageFormat); - m_tempCoreFile.setFileName(m_tempCoreFilePath.path()); - m_tempCoreFile.open(QFile::WriteOnly); - connect(&m_coreUnpackProcess, &Process::readyReadStandardOutput, this, [this] { - m_tempCoreFile.write(m_coreUnpackProcess.readAllRawStandardOutput()); - }); - m_coreUnpackProcess.setCommand({"gzip", {"-c", "-d", m_coreFilePath.path()}}); - reportStarted(); - m_coreUnpackProcess.start(); - return; - } - - QTC_CHECK(false); - reportFailure("Unknown file extension in " + m_coreFilePath.toUserOutput()); - } - - QFile m_tempCoreFile; - FilePath m_coreFilePath; - FilePath m_tempCoreFilePath; - Process m_coreUnpackProcess; -}; - class DebuggerRunToolPrivate { public: - QPointer coreUnpacker; bool addQmlServerInferiorCommandLineArgumentIfNeeded = false; int snapshotCounter = 0; int engineStartsNeeded = 0; int engineStopsNeeded = 0; QString runId; + // Core unpacker + QFile m_tempCoreFile; + FilePath m_tempCoreFilePath; + Process m_coreUnpackProcess; + // Terminal Process terminalProc; DebuggerRunTool::AllowTerminal allowTerminal = DebuggerRunTool::DoAllowTerminal; // DebugServer Process debuggerServerProc; - Utils::ProcessHandle serverAttachPid; + ProcessHandle serverAttachPid; bool serverUseMulti = true; bool serverEssential = true; }; @@ -369,11 +304,6 @@ void DebuggerRunTool::setStartMessage(const QString &msg) void DebuggerRunTool::setCoreFilePath(const FilePath &coreFile, bool isSnapshot) { - if (coreFile.endsWith(".gz") || coreFile.endsWith(".lzo")) { - d->coreUnpacker = new CoreUnpacker(runControl(), coreFile); - addStartDependency(d->coreUnpacker); - } - m_runParameters.coreFile = coreFile; m_runParameters.isSnapshot = isSnapshot; } @@ -405,6 +335,63 @@ void DebuggerRunTool::addSearchDirectory(const Utils::FilePath &dir) void DebuggerRunTool::start() { + startCoreFileSetupIfNeededAndContinueStartup(); +} + +void DebuggerRunTool::startCoreFileSetupIfNeededAndContinueStartup() +{ + const FilePath coreFile = m_runParameters.coreFile; + if (!coreFile.endsWith(".gz") && !coreFile.endsWith(".lzo")) { + continueAfterCoreFileSetup(); + return; + } + + { + TemporaryFile tmp("tmpcore-XXXXXX"); + tmp.open(); + d->m_tempCoreFilePath = FilePath::fromString(tmp.fileName()); + } + + d->m_coreUnpackProcess.setWorkingDirectory(TemporaryDirectory::masterDirectoryFilePath()); + connect(&d->m_coreUnpackProcess, &Process::done, this, [this] { + if (d->m_coreUnpackProcess.error() == QProcess::UnknownError) { + m_runParameters.coreFile = d->m_tempCoreFilePath; + continueAfterCoreFileSetup(); + return; + } + reportFailure("Error unpacking " + m_runParameters.coreFile.toUserOutput()); + }); + + const QString msg = Tr::tr("Unpacking core file to %1"); + appendMessage(msg.arg(d->m_tempCoreFilePath.toUserOutput()), LogMessageFormat); + + if (coreFile.endsWith(".lzo")) { + d->m_coreUnpackProcess.setCommand({"lzop", {"-o", d->m_tempCoreFilePath.path(), + "-x", coreFile.path()}}); + d->m_coreUnpackProcess.start(); + return; + } + + if (coreFile.endsWith(".gz")) { + d->m_tempCoreFile.setFileName(d->m_tempCoreFilePath.path()); + d->m_tempCoreFile.open(QFile::WriteOnly); + connect(&d->m_coreUnpackProcess, &Process::readyReadStandardOutput, this, [this] { + d->m_tempCoreFile.write(d->m_coreUnpackProcess.readAllRawStandardOutput()); + }); + d->m_coreUnpackProcess.setCommand({"gzip", {"-c", "-d", coreFile.path()}}); + d->m_coreUnpackProcess.start(); + return; + } + + QTC_CHECK(false); + reportFailure("Unknown file extension in " + coreFile.toUserOutput()); +} + +void DebuggerRunTool::continueAfterCoreFileSetup() +{ + if (d->m_tempCoreFile.isOpen()) + d->m_tempCoreFile.close(); + startTerminalIfNeededAndContinueStartup(); } @@ -497,9 +484,6 @@ void DebuggerRunTool::continueAfterTerminalStart() // return; // } - if (d->coreUnpacker) - m_runParameters.coreFile = d->coreUnpacker->coreFileName(); - if (!fixupParameters()) return; @@ -978,6 +962,9 @@ void DebuggerRunTool::addSolibSearchDir(const QString &str) DebuggerRunTool::~DebuggerRunTool() { + if (d->m_tempCoreFilePath.exists()) + d->m_tempCoreFilePath.removeFile(); + if (m_runParameters.isSnapshot && !m_runParameters.coreFile.isEmpty()) m_runParameters.coreFile.removeFile(); diff --git a/src/plugins/debugger/debuggerruncontrol.h b/src/plugins/debugger/debuggerruncontrol.h index 4caf61112d4..4a2898fc3cd 100644 --- a/src/plugins/debugger/debuggerruncontrol.h +++ b/src/plugins/debugger/debuggerruncontrol.h @@ -111,6 +111,9 @@ private: void handleEngineStarted(Internal::DebuggerEngine *engine); void handleEngineFinished(Internal::DebuggerEngine *engine); + void startCoreFileSetupIfNeededAndContinueStartup(); + void continueAfterCoreFileSetup(); + void startTerminalIfNeededAndContinueStartup(); void continueAfterTerminalStart(); From 64763c9d7ed77d60bb7f183ca34f5fce530cda12 Mon Sep 17 00:00:00 2001 From: Marcus Tillmanns Date: Mon, 7 Oct 2024 13:38:18 +0200 Subject: [PATCH 67/76] Lua: Refactor Clipboard access Clipboard is now accessed via "qt.clipboard()" to stay in line with other code that returns a global singleton. Also fixed documentation. Change-Id: I4298f036ef6558e48f36d156d6482fc0bde5d898 Reviewed-by: Artur Twardy Reviewed-by: hjk --- src/plugins/lua/bindings/qt.cpp | 30 ++++++++++++++---------------- src/plugins/lua/meta/qt.lua | 25 +++++++++++++------------ 2 files changed, 27 insertions(+), 28 deletions(-) diff --git a/src/plugins/lua/bindings/qt.cpp b/src/plugins/lua/bindings/qt.cpp index 6f4daeb5862..355c6c6958a 100644 --- a/src/plugins/lua/bindings/qt.cpp +++ b/src/plugins/lua/bindings/qt.cpp @@ -29,29 +29,27 @@ void setupQtModule() "currentCompletion", &QCompleter::currentCompletion, "completionMode", - sol::property(&QCompleter::completionMode, - [](QCompleter *c, QCompleter::CompletionMode mode) { - c->setCompletionMode(mode); - }), + sol::property( + &QCompleter::completionMode, + [](QCompleter *c, QCompleter::CompletionMode mode) { c->setCompletionMode(mode); }), "onActivated", sol::property([guard = pluginSpec](QCompleter &obj, sol::function callback) { - QObject::connect(&obj, - QOverload::of(&QCompleter::activated), - guard->connectionGuard.get(), - [callback](const QString &arg) { - void_safe_call(callback, arg); - });}) - ); + QObject::connect( + &obj, + QOverload::of(&QCompleter::activated), + guard->connectionGuard.get(), + [callback](const QString &arg) { void_safe_call(callback, arg); }); + })); qt.new_usertype( "QClipboard", - sol::call_constructor, - &QApplication::clipboard, + sol::no_constructor, "text", - sol::property([](QClipboard &self) { return self.text(); }, - [](QClipboard &self, const QString &value) { self.setText(value); }) - ); + sol::property( + [](QClipboard &self) { return self.text(); }, + [](QClipboard &self, const QString &value) { self.setText(value); })); + qt["clipboard"] = &QApplication::clipboard; mirrorEnum(qt, QMetaEnum::fromType(), "QCompleterCompletionMode"); diff --git a/src/plugins/lua/meta/qt.lua b/src/plugins/lua/meta/qt.lua index 168c8092171..7543302c600 100644 --- a/src/plugins/lua/meta/qt.lua +++ b/src/plugins/lua/meta/qt.lua @@ -11,27 +11,28 @@ qt.CompleterCompletionMode = { UnfilteredPopupCompletion = 2, }; ----Creates QCompleter. ---@class QCompleter ---@field completionMode CompleterCompletionMode The completion mode. local QCompleter = {} +---Creates a new Completer. +---@param params string[] The list of suggestions. +---@return QCompleter completer The new Completer. +function qt.QCompleter.create(params) end + ---Returns current completion. ---@return string function qt.QCompleter:currentCompletion() end +---@param callback function The function to be called when user choice is selected from popup. +function qt.QCompleter.onActivated(callback) end ----@param params string list A list of suggestions. ----@return QCompleter Created Completer. -function qt.QCompleter.create(params) end +---@class QClipboard A Lua wrapper for the Qt `QClipboard` class. +---@field text string The text content of the clipboard. Gets or sets the text content of the clipboard. +qt.QClipboard = {} ----@param function The function to be called when user choice is selected from popup. -function qt.QCompleter.onActivated(function) end - ----@class QClipboard ---- A Lua wrapper for the Qt `QClipboard` class. - -qt.QClipboard() Creates QClipboard object, which is a singleton instance of the system clipboard. ----@field text The text content of the clipboard. Gets or sets the text content of the clipboard. +---Returns the global clipboard object. +---@return QClipboard globalClipboard The global clipboard object. +function qt.clipboard() end ---@enum TextElideMode qt.TextElideMode = { From 355daa4d99b57f46753cb8de812d808eb39a94b1 Mon Sep 17 00:00:00 2001 From: Marcus Tillmanns Date: Mon, 7 Oct 2024 13:39:45 +0200 Subject: [PATCH 68/76] Lua: Use "setClipboardAndSelection" Change-Id: Ia5a16ebed44a47f44a16076e39cf8a21387b98ec Reviewed-by: Artur Twardy Reviewed-by: hjk --- src/plugins/lua/bindings/qt.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/plugins/lua/bindings/qt.cpp b/src/plugins/lua/bindings/qt.cpp index 355c6c6958a..1eff2211dec 100644 --- a/src/plugins/lua/bindings/qt.cpp +++ b/src/plugins/lua/bindings/qt.cpp @@ -5,6 +5,8 @@ #include "utils.h" +#include + #include #include #include @@ -47,7 +49,7 @@ void setupQtModule() "text", sol::property( [](QClipboard &self) { return self.text(); }, - [](QClipboard &self, const QString &value) { self.setText(value); })); + [](QClipboard &, const QString &text) { Utils::setClipboardAndSelection(text); })); qt["clipboard"] = &QApplication::clipboard; From 3feb6351d3c9eb406fc5115d6d579a8897a4c545 Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Mon, 7 Oct 2024 16:19:31 +0200 Subject: [PATCH 69/76] Debugger: Fix capitalization Amends aed3eee06ab09b31197aba2b6b5a0f977b76ecde Change-Id: I8b23d4ff2613b4ac0873acc7b960419bf1363814 Reviewed-by: Christian Stenger Reviewed-by: Leena Miettinen --- src/plugins/debugger/debuggerengine.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/debugger/debuggerengine.cpp b/src/plugins/debugger/debuggerengine.cpp index 00100592c5b..50ab3ba5d22 100644 --- a/src/plugins/debugger/debuggerengine.cpp +++ b/src/plugins/debugger/debuggerengine.cpp @@ -510,7 +510,7 @@ public: QAction m_abortAction{Tr::tr("Abort Debugging")}; QAction m_stepIntoAction{Tr::tr("Step Into")}; QAction m_stepOutAction{Tr::tr("Step Out")}; - QAction m_toggleEnableBreakpointsAction{Tr::tr("Disable all Breakpoints")}; + QAction m_toggleEnableBreakpointsAction{Tr::tr("Disable All Breakpoints")}; QAction m_runToLineAction{Tr::tr("Run to Line")}; // In the debug menu QAction m_runToSelectedFunctionAction{Tr::tr("Run to Selected Function")}; QAction m_jumpToLineAction{Tr::tr("Jump to Line")}; From e7d366d7ceb8dcdb5dbe1a03891da303d691dd4f Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Mon, 7 Oct 2024 16:25:02 +0200 Subject: [PATCH 70/76] Core: Be a little less modest with the initial settings dialog size Task-number: QTCREATORBUG-31685 Change-Id: Ibfae4f28e0118f332249ff0aaccff539b659116b Reviewed-by: Eike Ziller --- src/plugins/coreplugin/dialogs/settingsdialog.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/coreplugin/dialogs/settingsdialog.cpp b/src/plugins/coreplugin/dialogs/settingsdialog.cpp index dee9ebe6409..828f396433e 100644 --- a/src/plugins/coreplugin/dialogs/settingsdialog.cpp +++ b/src/plugins/coreplugin/dialogs/settingsdialog.cpp @@ -42,8 +42,8 @@ #include -const int kInitialWidth = 750; -const int kInitialHeight = 450; +const int kInitialWidth = 800; +const int kInitialHeight = 500; const int kMaxMinimumWidth = 250; const int kMaxMinimumHeight = 250; From 79a789bbf44063897965fbf452d9644025e54e96 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Fri, 4 Oct 2024 18:04:21 +0200 Subject: [PATCH 71/76] ProjectExplorer: Simplify DeviceTypeKitAspect Change-Id: Ic3dcb9e38340ed6859806029538a68a448be25d6 Reviewed-by: hjk --- src/plugins/projectexplorer/kitaspects.cpp | 70 ++++++++++------------ 1 file changed, 31 insertions(+), 39 deletions(-) diff --git a/src/plugins/projectexplorer/kitaspects.cpp b/src/plugins/projectexplorer/kitaspects.cpp index 0ca1a348281..7f0deaf75a0 100644 --- a/src/plugins/projectexplorer/kitaspects.cpp +++ b/src/plugins/projectexplorer/kitaspects.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -35,6 +36,8 @@ #include #include +#include + using namespace Utils; namespace ProjectExplorer { @@ -197,47 +200,36 @@ class DeviceTypeKitAspectImpl final : public KitAspect { public: DeviceTypeKitAspectImpl(Kit *workingCopy, const KitAspectFactory *factory) - : KitAspect(workingCopy, factory), m_comboBox(createSubWidget()) + : KitAspect(workingCopy, factory) { - for (IDeviceFactory *factory : IDeviceFactory::allDeviceFactories()) - m_comboBox->addItem(factory->displayName(), factory->deviceType().toSetting()); - m_comboBox->setToolTip(factory->description()); - refresh(); - connect(m_comboBox, &QComboBox::currentIndexChanged, - this, &DeviceTypeKitAspectImpl::currentTypeChanged); + using ItemData = std::pair; + const auto model = new ListModel(this); + model->setDataAccessor([](const ItemData &d, int column, int role) -> QVariant { + if (column != 0) + return {}; + if (role == Qt::DisplayRole) + return d.first; + if (role == Qt::UserRole) + return d.second.toSetting(); + return {}; + }); + const auto sortModel = new SortModel(this); + sortModel->setSourceModel(model); + auto getter = [](const Kit &k) { return DeviceTypeKitAspect::deviceTypeId(&k).toSetting(); }; + auto setter = [](Kit &k, const QVariant &type) { + DeviceTypeKitAspect::setDeviceTypeId(&k, Id::fromSetting(type)); + }; + auto resetModel = [](QAbstractItemModel &m) { + // FIXME: Change to parameter-less signature. + auto model = static_cast *>( + static_cast(m).sourceModel()); + model->clear(); + for (IDeviceFactory *factory : IDeviceFactory::allDeviceFactories()) + model->appendItem(std::make_pair(factory->displayName(), factory->deviceType())); + }; + setListAspectSpec( + {sortModel, std::move(getter), std::move(setter), std::move(resetModel), Qt::UserRole}); } - - ~DeviceTypeKitAspectImpl() override { delete m_comboBox; } - -private: - void addToInnerLayout(Layouting::Layout &builder) override - { - addMutableAction(m_comboBox); - builder.addItem(m_comboBox); - } - - void makeReadOnly() override { m_comboBox->setEnabled(false); } - - void refresh() override - { - Id devType = DeviceTypeKitAspect::deviceTypeId(kit()); - if (!devType.isValid()) - m_comboBox->setCurrentIndex(-1); - for (int i = 0; i < m_comboBox->count(); ++i) { - if (m_comboBox->itemData(i) == devType.toSetting()) { - m_comboBox->setCurrentIndex(i); - break; - } - } - } - - void currentTypeChanged(int idx) - { - Id type = idx < 0 ? Id() : Id::fromSetting(m_comboBox->itemData(idx)); - DeviceTypeKitAspect::setDeviceTypeId(kit(), type); - } - - QComboBox *m_comboBox; }; } // namespace Internal From 598505ce76be59a10856735f69fc37ef369e1b1c Mon Sep 17 00:00:00 2001 From: Andre Hartmann Date: Tue, 8 Oct 2024 09:15:08 +0200 Subject: [PATCH 72/76] Git: InstantBlame: No line diff for modified lines Avoids the following error message: qtc.vcs.git.instantblame: "fatal: bad object 0000000000000000000000000000000000000000\n" Change-Id: I44e45f02e9aaa6d31910441034b77a034b59d499 Reviewed-by: Orgad Shaneh --- src/plugins/git/instantblame.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/plugins/git/instantblame.cpp b/src/plugins/git/instantblame.cpp index 63e892a34ca..29eeaaecedb 100644 --- a/src/plugins/git/instantblame.cpp +++ b/src/plugins/git/instantblame.cpp @@ -407,6 +407,10 @@ void InstantBlame::perform() const CommitInfo info = parseBlameOutput(output.split('\n'), filePath, line, m_author); m_blameMark.reset(new BlameMark(filePath, line, info)); + static const QString uncommittedHash(40, '0'); + if (info.hash == uncommittedHash) + return; + // Get line diff: `git log -n 1 -p -L47,47:README.md a5c4c34c9ab4` const QString origLineString = QString("%1,%1").arg(info.originalLine); const QString fileLineRange = "-L" + origLineString + ":" + info.originalFileName; From 212f373cae37dbec39d711e7f0417ab9c4589123 Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Tue, 8 Oct 2024 09:22:56 +0200 Subject: [PATCH 73/76] Core: Move CredentialQuery from Axivion into Core plugin Change-Id: I9febc0d5f8f141b77435fc0877522791d41aaadd Reviewed-by: hjk Reviewed-by: Marcus Tillmanns --- src/plugins/axivion/CMakeLists.txt | 3 +-- src/plugins/axivion/axivion.qbs | 3 --- src/plugins/axivion/axivionplugin.cpp | 2 +- src/plugins/coreplugin/CMakeLists.txt | 4 +++- src/plugins/coreplugin/coreplugin.qbs | 3 +++ .../{axivion => coreplugin}/credentialquery.cpp | 4 ++-- src/plugins/{axivion => coreplugin}/credentialquery.h | 10 ++++++---- 7 files changed, 16 insertions(+), 13 deletions(-) rename src/plugins/{axivion => coreplugin}/credentialquery.cpp (96%) rename src/plugins/{axivion => coreplugin}/credentialquery.h (86%) diff --git a/src/plugins/axivion/CMakeLists.txt b/src/plugins/axivion/CMakeLists.txt index a08aa434284..e427a425c58 100644 --- a/src/plugins/axivion/CMakeLists.txt +++ b/src/plugins/axivion/CMakeLists.txt @@ -1,14 +1,13 @@ add_qtc_plugin(Axivion PLUGIN_DEPENDS Core Debugger ProjectExplorer TextEditor - DEPENDS Qt::Network Qt::Widgets ExtensionSystem Utils qtkeychain + DEPENDS Qt::Network Qt::Widgets ExtensionSystem Utils SOURCES axivion.qrc axivionperspective.cpp axivionperspective.h axivionplugin.cpp axivionplugin.h axivionsettings.cpp axivionsettings.h axiviontr.h - credentialquery.h credentialquery.cpp dashboard/dto.cpp dashboard/dto.h dashboard/concat.cpp dashboard/concat.h dashboard/error.h dashboard/error.cpp diff --git a/src/plugins/axivion/axivion.qbs b/src/plugins/axivion/axivion.qbs index 671b292d9c5..f61fa928407 100644 --- a/src/plugins/axivion/axivion.qbs +++ b/src/plugins/axivion/axivion.qbs @@ -9,7 +9,6 @@ QtcPlugin { Depends { name: "ProjectExplorer" } Depends { name: "TextEditor" } Depends { name: "Utils" } - Depends { name: "qtkeychain" } Depends { name: "Qt.widgets" } Depends { name: "Qt.network" } @@ -22,8 +21,6 @@ QtcPlugin { "axivionsettings.cpp", "axivionsettings.h", "axiviontr.h", - "credentialquery.cpp", - "credentialquery.h", "dynamiclistmodel.cpp", "dynamiclistmodel.h", "issueheaderview.cpp", diff --git a/src/plugins/axivion/axivionplugin.cpp b/src/plugins/axivion/axivionplugin.cpp index 79fe71c770f..6ec2eca29f0 100644 --- a/src/plugins/axivion/axivionplugin.cpp +++ b/src/plugins/axivion/axivionplugin.cpp @@ -6,10 +6,10 @@ #include "axivionperspective.h" #include "axivionsettings.h" #include "axiviontr.h" -#include "credentialquery.h" #include "dashboard/dto.h" #include "dashboard/error.h" +#include #include #include #include diff --git a/src/plugins/coreplugin/CMakeLists.txt b/src/plugins/coreplugin/CMakeLists.txt index eddbd316f37..5db7fb3362e 100644 --- a/src/plugins/coreplugin/CMakeLists.txt +++ b/src/plugins/coreplugin/CMakeLists.txt @@ -1,5 +1,5 @@ add_qtc_plugin(Core - DEPENDS Qt::PrintSupport Qt::Qml Qt::Sql Qt::Gui Qt::GuiPrivate TerminalLib + DEPENDS Qt::PrintSupport Qt::Qml Qt::Sql Qt::Gui Qt::GuiPrivate TerminalLib qtkeychain PUBLIC_DEPENDS Aggregation ExtensionSystem Utils SOURCES actionmanager/actioncontainer.cpp @@ -29,6 +29,8 @@ add_qtc_plugin(Core coreplugin.cpp coreplugin.h coreplugintr.h + credentialquery.cpp + credentialquery.h designmode.cpp designmode.h dialogs/addtovcsdialog.cpp diff --git a/src/plugins/coreplugin/coreplugin.qbs b/src/plugins/coreplugin/coreplugin.qbs index 41edaff0de7..96316a9c9df 100644 --- a/src/plugins/coreplugin/coreplugin.qbs +++ b/src/plugins/coreplugin/coreplugin.qbs @@ -16,6 +16,7 @@ QtcPlugin { Depends { name: "Utils" } Depends { name: "Aggregation" } Depends { name: "TerminalLib" } + Depends { name: "qtkeychain" } cpp.dynamicLibraries: { if (qbs.targetOS.contains("windows")) @@ -43,6 +44,8 @@ QtcPlugin { "coreplugin.cpp", "coreplugin.h", "coreplugintr.h", + "credentialquery.cpp", + "credentialquery.h", "designmode.cpp", "designmode.h", "diffservice.cpp", diff --git a/src/plugins/axivion/credentialquery.cpp b/src/plugins/coreplugin/credentialquery.cpp similarity index 96% rename from src/plugins/axivion/credentialquery.cpp rename to src/plugins/coreplugin/credentialquery.cpp index f183c083736..92c1ddfa359 100644 --- a/src/plugins/axivion/credentialquery.cpp +++ b/src/plugins/coreplugin/credentialquery.cpp @@ -8,7 +8,7 @@ using namespace QKeychain; using namespace Tasking; -namespace Axivion::Internal { +namespace Core { CredentialQueryTaskAdapter::~CredentialQueryTaskAdapter() = default; @@ -51,4 +51,4 @@ void CredentialQueryTaskAdapter::start() job->start(); } -} // Axivion::Internal +} // Core diff --git a/src/plugins/axivion/credentialquery.h b/src/plugins/coreplugin/credentialquery.h similarity index 86% rename from src/plugins/axivion/credentialquery.h rename to src/plugins/coreplugin/credentialquery.h index d8a958ab53e..22ec24921f5 100644 --- a/src/plugins/axivion/credentialquery.h +++ b/src/plugins/coreplugin/credentialquery.h @@ -3,13 +3,15 @@ #pragma once +#include "core_global.h" + #include -namespace Axivion::Internal { +namespace Core { enum class CredentialOperation { Get, Set, Delete }; -class CredentialQuery +class CORE_EXPORT CredentialQuery { public: void setOperation(CredentialOperation operation) { m_operation = operation; } @@ -30,7 +32,7 @@ private: friend class CredentialQueryTaskAdapter; }; -class CredentialQueryTaskAdapter final : public Tasking::TaskAdapter +class CORE_EXPORT CredentialQueryTaskAdapter final : public Tasking::TaskAdapter { private: ~CredentialQueryTaskAdapter(); @@ -40,4 +42,4 @@ private: using CredentialQueryTask = Tasking::CustomTask; -} // Axivion::Internal +} // Core From 62f0c8e27b0e9aabc941a9ae3c24d3216ce7578a Mon Sep 17 00:00:00 2001 From: Alessandro Portale Date: Sat, 5 Oct 2024 21:28:34 +0200 Subject: [PATCH 74/76] ExtensionManager: Display extension release status Unless "status" is "published", write the status right to the extension name. In orange. Fixes: QTCREATORBUG-31588 Change-Id: I25f3385ca27a2d3719cd360f3fc8adf6d9163a8b Reviewed-by: Cristian Adam --- .../extensionmanager/extensionsbrowser.cpp | 57 +++++++++++++------ .../extensionmanager/extensionsmodel.cpp | 8 +++ .../extensionmanager/extensionsmodel.h | 2 + 3 files changed, 50 insertions(+), 17 deletions(-) diff --git a/src/plugins/extensionmanager/extensionsbrowser.cpp b/src/plugins/extensionmanager/extensionsbrowser.cpp index da2e9881dd0..a044c961590 100644 --- a/src/plugins/extensionmanager/extensionsbrowser.cpp +++ b/src/plugins/extensionmanager/extensionsbrowser.cpp @@ -171,6 +171,8 @@ public: constexpr static QSize dividerS{1, 16}; constexpr static TextFormat itemNameTF {Theme::Token_Text_Default, UiElement::UiElementH6}; + constexpr static TextFormat releaseStatusTF + {Theme::Token_Notification_Alert, UiElement::UiElementLabelSmall}; constexpr static TextFormat countTF {Theme::Token_Text_Default, UiElement::UiElementLabelSmall, Qt::AlignCenter | Qt::TextDontClip}; @@ -190,23 +192,23 @@ public: void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override { - // +---------------+-------+---------------+----------------------------------------------------------------------+---------------+---------+ - // | | | | (ExPaddingGapL) | | | - // | | | +-----------------------------+---------+--------+---------+-----------+ | | - // | | | | |(HGapXxs)||(HGapXxs)|| | | - // | | | +-----------------------------+---------+--------+---------+-----------+ | | - // | | | | (VGapXxs) | | | - // | | | +--------+--------+--------------+--------+--------+---------+---------+ | | - // |(ExPaddingGapL)| |(ExPaddingGapL)||(HGapXs)|(h16)|(HGapXs)||(HGapXxs)||(ExPaddingGapL)|(gapSize)| - // | |(50x50)| +--------+--------+--------------+--------+--------+---------+---------+ | | - // | | | | (VGapXxs) | | | - // | | | +----------------------------------------------------------------------+ | | - // | | | | | | | - // | | | +----------------------------------------------------------------------+ | | - // | | | | (ExPaddingGapL) | | | - // +---------------+-------+---------------+----------------------------------------------------------------------+---------------+---------+ - // | (gapSize) | - // +----------------------------------------------------------------------------------------------------------------------------------------+ + // +---------------+-------+---------------+-----------------------------------------------------------------------------------+---------------+---------+ + // | | | | (ExPaddingGapL) | | | + // | | | +----------+---------+---------------+---------+--------------+---------+-----------+ | | + // | | | ||(HGapXxs)||(HGapXxs)||(HGapXxs)|| | | + // | | | +----------+---------+---------------+---------+--------------+---------+-----------+ | | + // | | | | (VGapXxs) | | | + // | | | +---------------------+--------+--------------+--------+--------+---------+---------+ | | + // |(ExPaddingGapL)| |(ExPaddingGapL)| |(HGapXs)|(h16)|(HGapXs)||(HGapXxs)||(ExPaddingGapL)|(gapSize)| + // | |(50x50)| +---------------------+--------+--------------+--------+--------+---------+---------+ | | + // | | | | (VGapXxs) | | | + // | | | +-----------------------------------------------------------------------------------+ | | + // | | | | | | | + // | | | +-----------------------------------------------------------------------------------+ | | + // | | | | (ExPaddingGapL) | | | + // +---------------+-------+---------------+-----------------------------------------------------------------------------------+---------------+---------+ + // | (gapSize) | + // +-----------------------------------------------------------------------------------------------------------------------------------------------------+ const QRect bgRGlobal = option.rect.adjusted(0, 0, -gapSize, -gapSize); const QRect bgR = bgRGlobal.translated(-option.rect.topLeft()); @@ -290,11 +292,32 @@ public: QRect effectiveR = itemNameR; if (showState) effectiveR.setRight(stateR.left() - HGapXxs - 1); + const QString releaseStatus = statusDisplayString(index); + const bool showReleaseStatus = !releaseStatus.isEmpty(); + + if (showReleaseStatus) { + const QFont releaseStatusF = releaseStatusTF.font(); + const int releaseStatusAdv = + QFontMetrics(releaseStatusF).horizontalAdvance(releaseStatus) + + (showState ? ExVPaddingGapXl - HGapXxs + : HGapXxs); + effectiveR.setWidth(effectiveR.width() - releaseStatusAdv); + } + painter->setPen(itemNameTF.color()); painter->setFont(itemNameTF.font()); const QString titleElided = painter->fontMetrics().elidedText(itemName, Qt::ElideRight, effectiveR.width()); painter->drawText(effectiveR, itemNameTF.drawTextFlags, titleElided); + + if (showReleaseStatus) { + const int titleElidedAdv = painter->fontMetrics().horizontalAdvance(titleElided); + const QRect releaseStatusR(effectiveR.x() + titleElidedAdv + HGapXxs, + effectiveR.y(), 1, effectiveR.height() - 1); + painter->setPen(releaseStatusTF.color()); + painter->setFont(releaseStatusTF.font()); + painter->drawText(releaseStatusR, releaseStatusTF.drawTextFlags, releaseStatus); + } } if (showState) { const FilePath checkmarkMask = ":/extensionmanager/images/checkmark.png"; diff --git a/src/plugins/extensionmanager/extensionsmodel.cpp b/src/plugins/extensionmanager/extensionsmodel.cpp index 8639fa1457d..bea38dd368f 100644 --- a/src/plugins/extensionmanager/extensionsmodel.cpp +++ b/src/plugins/extensionmanager/extensionsmodel.cpp @@ -156,6 +156,8 @@ QVariant ExtensionsModelPrivate::dataFromRemoteExtension(int index, int role) co return json.value(EXTENSION_KEY_ID); case RoleDateUpdated: return QDate::fromString(json.value("updated_at").toString(), Qt::ISODate); + case RoleStatus: + return json.value("status"); case RoleTags: return json.value("tags").toVariant().toStringList(); case RoleVendor: @@ -338,4 +340,10 @@ PluginSpec *pluginSpecForId(const QString &pluginId) return findOrDefault(PluginManager::plugins(), equal(&PluginSpec::id, pluginId)); } +QString statusDisplayString(const QModelIndex &index) +{ + const QString statusString = index.data(RoleStatus).toString(); + return statusString != "published" ? statusString : QString(); +} + } // ExtensionManager::Internal diff --git a/src/plugins/extensionmanager/extensionsmodel.h b/src/plugins/extensionmanager/extensionsmodel.h index ce51d5a15d9..87b4a6d73b6 100644 --- a/src/plugins/extensionmanager/extensionsmodel.h +++ b/src/plugins/extensionmanager/extensionsmodel.h @@ -42,6 +42,7 @@ enum Role { RolePlatforms, RolePlugins, RoleSearchText, + RoleStatus, RoleTags, RoleVendor, RoleVendorId, @@ -66,6 +67,7 @@ private: QString customOsTypeToString(Utils::OsType osType); ExtensionSystem::PluginSpec *pluginSpecForId(const QString &pluginId); +QString statusDisplayString(const QModelIndex &index); #ifdef WITH_TESTS QObject *createExtensionsModelTest(); From cfb64f3518a362f248839d656160f566ff436ca3 Mon Sep 17 00:00:00 2001 From: Marcus Tillmanns Date: Fri, 27 Sep 2024 12:11:32 +0200 Subject: [PATCH 75/76] Lua: Move inspect and async into resources Change-Id: I257323861823ed7858efdb265a78cc572c2e7273 Reviewed-by: Eike Ziller --- qt_attributions.json | 9 +++---- src/plugins/lua/CMakeLists.txt | 3 ++- src/plugins/lua/lua.qbs | 1 - src/plugins/lua/luaengine.cpp | 17 +++++++++++++ src/plugins/lua/luaengine.h | 1 + src/plugins/lua/luaplugin.cpp | 5 ++-- .../{bindings => scripts}/ASYNC-LICENSE.txt | 0 .../plugins/lua/scripts}/INSPECT-LICENSE.txt | 0 .../{bindings/async.cpp => scripts/async.lua} | 25 +++---------------- .../plugins/lua/scripts}/inspect.lua | 0 10 files changed, 31 insertions(+), 30 deletions(-) rename src/plugins/lua/{bindings => scripts}/ASYNC-LICENSE.txt (100%) rename {share/qtcreator/lua-plugins/luatests => src/plugins/lua/scripts}/INSPECT-LICENSE.txt (100%) rename src/plugins/lua/{bindings/async.cpp => scripts/async.lua} (74%) rename {share/qtcreator/lua-plugins/luatests => src/plugins/lua/scripts}/inspect.lua (100%) diff --git a/qt_attributions.json b/qt_attributions.json index 987502609df..008ff353943 100644 --- a/qt_attributions.json +++ b/qt_attributions.json @@ -612,11 +612,11 @@ "QDocModule": "qtcreator", "QtParts": ["tools"], "QtUsage": "Used for async/await support in Lua modules.", - "Path": "src/plugins/lua/bindings", + "Path": "src/plugins/lua/scripts", "Description": "lua-async-await implements the async/await pattern in Lua.", "Homepage": "https://github.com/ms-jpq/lua-async-await", "License": "MIT License", - "LicenseFile": "src/plugins/lua/bindings/ASYNC-LICENSE.txt", + "LicenseFile": "src/plugins/lua/scripts/ASYNC-LICENSE.txt", "Copyright": "Copyright (c) 2008 Paul Evans" }, { @@ -625,11 +625,11 @@ "QDocModule": "qtcreator", "QtParts": ["tools"], "QtUsage": "Used for pretty printing from Lua scripts.", - "Path": "share/qtcreator/lua-plugins/luatests", + "Path": "src/plugins/lua/scripts", "Description": "inspect.lua is a library for pretty printing complex objects in Lua.", "Homepage": "https://github.com/kikito/inspect.lua", "License": "MIT License", - "LicenseFile": "share/qtcreator/lua-plugins/luatests/INSPECT-LICENSE.txt", + "LicenseFile": "src/plugins/lua/scripts/INSPECT-LICENSE.txt", "Copyright": "Copyright (c) 2022 Enrique García Cota" }, { @@ -662,4 +662,3 @@ "Copyright": "Copyright 2011 The Apache Software Foundation" } ] - diff --git a/src/plugins/lua/CMakeLists.txt b/src/plugins/lua/CMakeLists.txt index 51fc92496ee..7bc0aa2efbd 100644 --- a/src/plugins/lua/CMakeLists.txt +++ b/src/plugins/lua/CMakeLists.txt @@ -4,7 +4,6 @@ add_qtc_plugin(Lua PUBLIC_DEFINES LUA_AVAILABLE SOURCES bindings/action.cpp - bindings/async.cpp bindings/async.h bindings/core.cpp bindings/fetch.cpp @@ -49,7 +48,9 @@ if(TARGET Lua) qt_add_resources(Lua lua_script_rcc PREFIX "/lua" FILES + scripts/async.lua scripts/ilua.lua + scripts/inspect.lua ) set_source_files_properties(luauibindings.cpp PROPERTY SKIP_AUTOMOC ON PROPERTY SKIP_AUTOGEN ON) diff --git a/src/plugins/lua/lua.qbs b/src/plugins/lua/lua.qbs index 65b4205332a..5e6298387af 100644 --- a/src/plugins/lua/lua.qbs +++ b/src/plugins/lua/lua.qbs @@ -39,7 +39,6 @@ QtcPlugin { files: [ "action.cpp", - "async.cpp", "core.cpp", "fetch.cpp", "gui.cpp", diff --git a/src/plugins/lua/luaengine.cpp b/src/plugins/lua/luaengine.cpp index f70b0d5e269..dca1bb25733 100644 --- a/src/plugins/lua/luaengine.cpp +++ b/src/plugins/lua/luaengine.cpp @@ -171,6 +171,23 @@ void registerProvider(const QString &packageName, const PackageProvider &provide d->m_providers[packageName] = provider; } +void registerProvider(const QString &packageName, const FilePath &path) +{ + registerProvider(packageName, [path](sol::state_view lua) -> sol::object { + auto content = path.fileContents(); + if (!content) + throw sol::error(content.error().toStdString()); + + sol::protected_function_result res + = lua.script(content->data(), path.fileName().toStdString()); + if (!res.valid()) { + sol::error err = res; + throw err; + } + return res.get(0); + }); +} + void autoRegister(const std::function ®isterFunction) { d->m_autoProviders.append(registerFunction); diff --git a/src/plugins/lua/luaengine.h b/src/plugins/lua/luaengine.h index 81efef952e3..36cd6f10e47 100644 --- a/src/plugins/lua/luaengine.h +++ b/src/plugins/lua/luaengine.h @@ -51,6 +51,7 @@ LUA_EXPORT Utils::expected_str prepareSetup( sol::state_view lua, const LuaPluginSpec &pluginSpec); LUA_EXPORT void registerProvider(const QString &packageName, const PackageProvider &provider); +LUA_EXPORT void registerProvider(const QString &packageName, const Utils::FilePath &path); LUA_EXPORT void autoRegister(const std::function ®isterFunction); LUA_EXPORT void registerHook( QString name, const std::function &hookProvider); diff --git a/src/plugins/lua/luaplugin.cpp b/src/plugins/lua/luaplugin.cpp index 56518230bd7..cb173b943d4 100644 --- a/src/plugins/lua/luaplugin.cpp +++ b/src/plugins/lua/luaplugin.cpp @@ -34,7 +34,6 @@ using namespace ExtensionSystem; namespace Lua::Internal { void setupActionModule(); -void setupAsyncModule(); void setupCoreModule(); void setupFetchModule(); void setupGuiModule(); @@ -254,8 +253,10 @@ public: { setupLuaEngine(this); + registerProvider("async", ":/lua/scripts/async.lua"); + registerProvider("inspect", ":/lua/scripts/inspect.lua"); + setupActionModule(); - setupAsyncModule(); setupCoreModule(); setupFetchModule(); setupGuiModule(); diff --git a/src/plugins/lua/bindings/ASYNC-LICENSE.txt b/src/plugins/lua/scripts/ASYNC-LICENSE.txt similarity index 100% rename from src/plugins/lua/bindings/ASYNC-LICENSE.txt rename to src/plugins/lua/scripts/ASYNC-LICENSE.txt diff --git a/share/qtcreator/lua-plugins/luatests/INSPECT-LICENSE.txt b/src/plugins/lua/scripts/INSPECT-LICENSE.txt similarity index 100% rename from share/qtcreator/lua-plugins/luatests/INSPECT-LICENSE.txt rename to src/plugins/lua/scripts/INSPECT-LICENSE.txt diff --git a/src/plugins/lua/bindings/async.cpp b/src/plugins/lua/scripts/async.lua similarity index 74% rename from src/plugins/lua/bindings/async.cpp rename to src/plugins/lua/scripts/async.lua index 54868af6f0b..7958ea5d8af 100644 --- a/src/plugins/lua/bindings/async.cpp +++ b/src/plugins/lua/scripts/async.lua @@ -1,11 +1,3 @@ -// Copyright (C) 2024 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#include "../luaengine.h" - -namespace Lua::Internal { - -static const char *async_source = R"( -- From: https://github.com/ms-jpq/lua-async-await -- Licensed under MIT local co = coroutine @@ -70,13 +62,15 @@ end -- sugar over coroutine local await = function(defer) local _, isMain = coroutine.running() - assert(not isMain, "a.wait was called outside of a running coroutine. You need to start one using a.sync(my_function)() first") + assert(not isMain, + "a.wait was called outside of a running coroutine. You need to start one using a.sync(my_function)() first") assert(type(defer) == "function", "type error :: expected func :: was: " .. type(defer)) return co.yield(defer) end local await_all = function(defer) local _, isMain = coroutine.running() - assert(not isMain, "a.wait_all was called outside of a running coroutine. You need to start one using a.sync(my_function)() first") + assert(not isMain, + "a.wait_all was called outside of a running coroutine. You need to start one using a.sync(my_function)() first") assert(type(defer) == "table", "type error :: expected table") return co.yield(join(defer)) end @@ -86,14 +80,3 @@ return { wait_all = await_all, wrap = wrap, } -)"; - -void setupAsyncModule() -{ - registerProvider("async", [](sol::state_view lua) -> sol::object { - sol::protected_function_result res = lua.script(async_source, "async.cpp"); - return res.get(0); - }); -} - -} // namespace Lua::Internal diff --git a/share/qtcreator/lua-plugins/luatests/inspect.lua b/src/plugins/lua/scripts/inspect.lua similarity index 100% rename from share/qtcreator/lua-plugins/luatests/inspect.lua rename to src/plugins/lua/scripts/inspect.lua From 2109e64a7c6f4bb52d692f58cb52527d8a91decb Mon Sep 17 00:00:00 2001 From: Marcus Tillmanns Date: Fri, 27 Sep 2024 12:20:58 +0200 Subject: [PATCH 76/76] Lua: Replace lua repl script Change-Id: Iea236081b9cfecd29d7c5c2290570010c9a83276 Reviewed-by: Eike Ziller --- src/plugins/lua/luaplugin.cpp | 27 +- src/plugins/lua/scripts/ilua.lua | 410 +++++-------------------------- 2 files changed, 82 insertions(+), 355 deletions(-) diff --git a/src/plugins/lua/luaplugin.cpp b/src/plugins/lua/luaplugin.cpp index cb173b943d4..a1821094500 100644 --- a/src/plugins/lua/luaplugin.cpp +++ b/src/plugins/lua/luaplugin.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -78,7 +79,7 @@ public: { auto label = new QLabel(parent); const QString text = index.data().toString(); - label->setText(text); + label->setText(text.startsWith("__ERROR__") ? text.mid(9) : text); label->setFont(option.font); label->setTextInteractionFlags( Qt::TextInteractionFlag::TextSelectableByMouse @@ -87,6 +88,29 @@ public: label->setSelection(0, text.size()); return label; } + + void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) + const override + { + QStyleOptionViewItem opt = option; + initStyleOption(&opt, index); + + bool isError = opt.text.startsWith("__ERROR__"); + + if (isError) + opt.text = opt.text.mid(9); + + if (opt.state & QStyle::State_Selected) { + painter->fillRect(opt.rect, opt.palette.highlight()); + painter->setPen(opt.palette.highlightedText().color()); + } else if (isError) { + painter->setPen(creatorColor(Theme::Token_Notification_Danger)); + } else { + painter->setPen(opt.palette.text().color()); + } + + painter->drawText(opt.rect, opt.displayAlignment, opt.text); + } }; class LuaReplView : public QListView @@ -135,6 +159,7 @@ public: m_model.setStringList(m_model.stringList() << msgs); scrollToBottom(); }; + lua["LuaCopyright"] = LUA_COPYRIGHT; sol::table async = lua.script("return require('async')", "_ilua_").get(); sol::function wrap = async["wrap"]; diff --git a/src/plugins/lua/scripts/ilua.lua b/src/plugins/lua/scripts/ilua.lua index 3efaf0b788a..0918a249088 100644 --- a/src/plugins/lua/scripts/ilua.lua +++ b/src/plugins/lua/scripts/ilua.lua @@ -1,359 +1,61 @@ --- ilua.lua --- A more friendly Lua interactive prompt --- doesn't need '=' --- will try to print out tables recursively, subject to the pretty_print_limit value. --- Steve Donovan, 2007 --- -local pretty_print_limit = 20 -local max_depth = 7 -local table_clever = true -local prompt = '> ' -local verbose = false -local strict = true --- suppress strict warnings -_ = true - --- imported global functions -local sub = string.sub -local match = string.match -local find = string.find -local push = table.insert -local pop = table.remove -local append = table.insert -local concat = table.concat -local floor = math.floor -local write = io.write -local read = io.read - -local collisions = {} -local G_LIB = {} -local declared = {} -local line_handler_fn, global_handler_fn -local print_handlers = {} - -ilua = {} -local num_prec -local num_all - -local jstack = {} - -local function oprint(...) - print(...) -end - -local function join(tbl, delim, limit, depth) - if not limit then limit = pretty_print_limit end - if not depth then depth = max_depth end - local n = #tbl - local res = '' - local k = 0 - -- very important to avoid disgracing ourselves with circular referencs... - if #jstack > depth then - return "..." - end - for i, t in ipairs(jstack) do - if tbl == t then - return "" - end - end - push(jstack, tbl) - -- this is a hack to work out if a table is 'list-like' or 'map-like' - -- you can switch it off with ilua.table_options {clever = false} - local is_list - if table_clever then - local index1 = n > 0 and tbl[1] - local index2 = n > 1 and tbl[2] - is_list = index1 and index2 - end - if is_list then - for i, v in ipairs(tbl) do - res = res .. delim .. val2str(v) - k = k + 1 - if k > limit then - res = res .. " ... " - break - end - end - else - for key, v in pairs(tbl) do - if type(key) == 'number' then - key = '[' .. tostring(key) .. ']' - else - key = tostring(key) - end - res = res .. delim .. key .. '=' .. val2str(v) - k = k + 1 - if k > limit then - res = res .. " ... " - break - end - end - end - pop(jstack) - return sub(res, 2) -end - - -function val2str(val) - local tp = type(val) - if print_handlers[tp] then - local s = print_handlers[tp](val) - return s or '?' - end - if tp == 'function' then - return tostring(val) - elseif tp == 'table' then - if val.__tostring then - return tostring(val) - else - return '{' .. join(val, ',') .. '}' - end - elseif tp == 'string' then - return "'" .. val .. "'" - elseif tp == 'number' then - -- we try only to apply floating-point precision for numbers deemed to be floating-point, - -- unless the 3rd arg to precision() is true. - if num_prec and (num_all or floor(val) ~= val) then - return num_prec:format(val) - else - return tostring(val) - end - else - return tostring(val) - end -end - -function _pretty_print(...) - local arg = table.pack(...) - for i, val in ipairs(arg) do - oprint(val2str(val)) - end - _G['_'] = arg[1] -end - -function compile(line) - if verbose then oprint(line) end - local f, err = load(line, 'local') - return err, f -end - -function evaluate(chunk) - local ok, res = pcall(chunk) - if not ok then - return res - end - return nil -- meaning, fine! -end - -function eval_lua(line) - -- is the line handler interested? - if line_handler_fn then - line = line_handler_fn(line) - -- returning nil here means that the handler doesn't want - -- Lua to see the string - if not line then return end - end - -- is it an expression? - local err, chunk = compile('_pretty_print(' .. line .. ')') - if err then - -- otherwise, a statement? - err, chunk = compile(line) - end - -- if compiled ok, then evaluate the chunk - if not err then - err = evaluate(chunk) - end - -- if there was any error, print it out - if err then - oprint(err) - end -end - -local function quit(code, msg) - io.stderr:write(msg, '\n') - os.exit(code) -end - --- functions available in scripts -function ilua.precision(len, prec, all) - if not len then - num_prec = nil - else - num_prec = '%' .. len .. '.' .. prec .. 'f' - end - num_all = all -end - -function ilua.table_options(t) - if t.limit then pretty_print_limit = t.limit end - if t.depth then max_depth = t.depth end - if t.clever ~= nil then table_clever = t.clever end -end - --- inject @tbl into the global namespace -function ilua.import(tbl, dont_complain, lib) - lib = lib or '' - if type(tbl) == 'table' then - for k, v in pairs(tbl) do - local key = rawget(_G, k) - -- NB to keep track of collisions! - if key and k ~= '_M' and k ~= '_NAME' and k ~= '_PACKAGE' and k ~= '_VERSION' then - append(collisions, { k, lib, G_LIB[k] }) - end - _G[k] = v - G_LIB[k] = lib - end - end - if not dont_complain and #collisions > 0 then - for i, coll in ipairs(collisions) do - local name, lib, oldlib = coll[1], coll[2], coll[3] - write('warning: ', lib, '.', name, ' overwrites ') - if oldlib then - write(oldlib, '.', name, '\n') - else - write('global ', name, '\n') - end - end - end -end - -function ilua.print_handler(name, handler) - print_handlers[name] = handler -end - -function ilua.line_handler(handler) - line_handler_fn = handler -end - -function ilua.global_handler(handler) - global_handler_fn = handler -end - -function ilua.print_variables() - for name, v in pairs(declared) do - print(name, type(_G[name])) - end -end - --- --- strict.lua --- checks uses of undeclared global variables --- All global variables must be 'declared' through a regular assignment --- (even assigning nil will do) in a main chunk before being used --- anywhere. --- -local function set_strict() - local mt = getmetatable(_G) - if mt == nil then - mt = {} - setmetatable(_G, mt) - end - - local function what() - local d = debug.getinfo(3, "S") - return d and d.what or "C" - end - - mt.__newindex = function(t, n, v) - declared[n] = true - rawset(t, n, v) - end - - mt.__index = function(t, n) - if not declared[n] and what() ~= "C" then - local lookup = global_handler_fn and global_handler_fn(n) - if not lookup then - error("variable '" .. n .. "' is not declared", 2) - else - return lookup - end - end - return rawget(t, n) - end -end - ---- Initial operations which may not succeed! --- try to bring in any ilua configuration file; don't complain if this is unsuccessful -pcall(function() - require 'ilua-defs' -end) - --- process command-line parameters -if arg then - local i = 1 - - local function parm_value(opt, parm, def) - local val = parm:sub(3) - if #val == 0 then - i = i + 1 - if i > #arg then - if not def then - quit(-1, "expecting parameter for option '-" .. opt .. "'") - else - return def - end - end - val = arg[i] - end - return val - end - - while i <= #arg do - local v = arg[i] - local opt = v:sub(1, 1) - if opt == '-' then - opt = v:sub(2, 2) - if opt == 'h' then - quit(0, "ilua (-l lib) (-L lib) (lua files)") - elseif opt == 'l' then - require(parm_value(opt, v)) - elseif opt == 'L' then - local lib = parm_value(opt, v) - local tbl = require(lib) - -- we cannot always trust require to return the table! - if type(tbl) ~= 'table' then - tbl = _G[lib] - end - ilua.import(tbl, true, lib) - elseif opt == 't' or opt == 'T' then - local file - if opt == 'T' then - file = 'ilua_' .. os.date('%y_%m_%d_%H_%M') .. '.log' - else - file = parm_value(opt, v, "ilua.log") - end - print('saving transcript "' .. file .. '"') - elseif opt == 's' then - strict = false - elseif opt == 'v' then - verbose = true - end - else -- a plain file to be executed immediately - dofile(v) - end - i = i + 1 - end -end - -print 'ILUA: Lua 5.4.6 Copyright (C) 1994-2007 Lua.org, PUC-Rio' - --- any import complaints? -ilua.import() - --- enable 'not declared' error -if strict then - set_strict() -end - local a = require('async') +local inspect = require('inspect') -a.sync(function() - local line = a.wait(readline(prompt)) +local prompt = '> ' - while line do - ---if line == 'quit' then break end - eval_lua(line) - ---saveline(line) - line = a.wait(readline(prompt)) +local function errHandler(err) + return debug.traceback(err, 2) +end + +---Returns the number of arguments and a table with the arguments +---We need this because select('#', ...) is the only way to figure out the number of arguments +---because #table will not count nil values +---@return integer nArguments The number of arguments provided to wrap(...) +---@return table arguments The arguments packed a table +local function wrap(...) return select('#', ...), { ... } end + +local function eval(code) + if #code == 0 then + return end + + --We load the code once as is, and once by adding a return statement in front of it + local asFunc, errFunc = load(code) + local asReturn = load('return ' .. code) + --If the code with return statement did not compile we will use the code without it + if not asReturn then + --If the code without the return did not compile either we print an error + if not asFunc then + print("__ERROR__" .. errFunc) + return + end + asReturn = asFunc + end + + --We call the compiled code in protected mode, which will capture and errors thrown by it. + local numberOfReturnValues, result = wrap(xpcall(asReturn, errHandler)) + + --result[1] contains true or false depending on whether the function ran successfully + if not result[1] then + print("__ERROR__" .. result[2]) + --numberOfReturnValues is the real number of values returned from xpcall + elseif numberOfReturnValues > 1 then + --We concatenate all the return values into a single string + local str = "" + --Skip the first value which is the boolean from xpcall + for i = 2, numberOfReturnValues do + str = str .. inspect(result[i]) .. '\t' + end + print(str) + end +end + +print(LuaCopyright) + +--Main Loop +a.sync(function() + repeat + local input = a.wait(readline(prompt)) + eval(input) + until false end)()