aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/libs/3rdparty/qtkeychain/qtkeychain.qbs1
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/lib/state_p.h2
-rw-r--r--src/libs/nanotrace/nanotrace.cpp2
-rw-r--r--src/libs/nanotrace/nanotrace.h2
-rw-r--r--src/libs/nanotrace/nanotraceglobals.h2
-rw-r--r--src/libs/nanotrace/nanotracehr.cpp2
-rw-r--r--src/libs/nanotrace/nanotracehr.h2
-rw-r--r--src/libs/nanotrace/python/figures.py2
-rw-r--r--src/libs/nanotrace/python/nanotrace.py2
-rw-r--r--src/libs/nanotrace/python/reader.py2
m---------src/libs/qlitehtml0
-rw-r--r--src/libs/qmljs/qmljsplugindumper.cpp6
-rw-r--r--src/libs/qtcreatorcdbext/CMakeLists.txt2
-rw-r--r--src/libs/solutions/tasking/tasktree.cpp151
-rw-r--r--src/libs/solutions/tasking/tasktree.h37
-rw-r--r--src/libs/solutions/terminal/terminalview.cpp3
-rw-r--r--src/libs/utils/async.h8
-rw-r--r--src/libs/utils/devicefileaccess.cpp4
-rw-r--r--src/libs/utils/macroexpander.cpp2
-rw-r--r--src/libs/utils/process.cpp30
-rw-r--r--src/libs/utils/process.h6
-rw-r--r--src/plugins/android/androidconfigurations.cpp59
-rw-r--r--src/plugins/android/androidconstants.h2
-rw-r--r--src/plugins/android/androidsdkmanager.cpp3
-rw-r--r--src/plugins/autotest/qtest/datataglocatorfilter.cpp2
-rw-r--r--src/plugins/autotest/qtest/qttestframework.cpp25
-rw-r--r--src/plugins/axivion/CMakeLists.txt5
-rw-r--r--src/plugins/axivion/axivion.qbs6
-rw-r--r--src/plugins/axivion/axivion.qrc4
-rw-r--r--src/plugins/axivion/axivionoutputpane.cpp512
-rw-r--r--src/plugins/axivion/axivionoutputpane.h33
-rw-r--r--src/plugins/axivion/axivionplugin.cpp524
-rw-r--r--src/plugins/axivion/axivionplugin.h2
-rw-r--r--src/plugins/axivion/axivionprojectsettings.cpp29
-rw-r--r--src/plugins/axivion/axivionsettings.cpp63
-rw-r--r--src/plugins/axivion/axivionsettings.h3
-rw-r--r--src/plugins/axivion/axiviontr.h2
-rw-r--r--src/plugins/axivion/credentialquery.cpp10
-rw-r--r--src/plugins/axivion/credentialquery.h5
-rw-r--r--src/plugins/axivion/dashboard/dto.cpp628
-rw-r--r--src/plugins/axivion/dashboard/dto.h114
-rw-r--r--src/plugins/axivion/dynamiclistmodel.cpp194
-rw-r--r--src/plugins/axivion/dynamiclistmodel.h69
-rw-r--r--src/plugins/axivion/images/sortAsc.pngbin0 -> 113 bytes
-rw-r--r--src/plugins/axivion/images/sortAsc@2x.pngbin0 -> 137 bytes
-rw-r--r--src/plugins/axivion/images/sortDesc.pngbin0 -> 118 bytes
-rw-r--r--src/plugins/axivion/images/sortDesc@2x.pngbin0 -> 142 bytes
-rw-r--r--src/plugins/axivion/issueheaderview.cpp141
-rw-r--r--src/plugins/axivion/issueheaderview.h44
-rw-r--r--src/plugins/clangcodemodel/clangmodelmanagersupport.cpp5
-rw-r--r--src/plugins/clangcodemodel/clangmodelmanagersupport.h2
-rw-r--r--src/plugins/cmakeprojectmanager/cmakeproject.cpp13
-rw-r--r--src/plugins/cmakeprojectmanager/cmakeprojectimporter.cpp4
-rw-r--r--src/plugins/cmakeprojectmanager/cmakeprojectimporter.h1
-rw-r--r--src/plugins/cmakeprojectmanager/cmakespecificsettings.cpp12
-rw-r--r--src/plugins/cmakeprojectmanager/cmaketoolmanager.cpp34
-rw-r--r--src/plugins/cmakeprojectmanager/presetsparser.h1
-rw-r--r--src/plugins/compilationdatabaseprojectmanager/compilationdatabaseproject.cpp6
-rw-r--r--src/plugins/compilationdatabaseprojectmanager/compilationdatabaseproject.h3
-rw-r--r--src/plugins/compilationdatabaseprojectmanager/compilationdbparser.cpp4
-rw-r--r--src/plugins/coreplugin/coreplugin.cpp35
-rw-r--r--src/plugins/coreplugin/editormanager/editormanager.cpp6
-rw-r--r--src/plugins/coreplugin/editormanager/editorwindow.cpp6
-rw-r--r--src/plugins/coreplugin/find/ifindfilter.cpp2
-rw-r--r--src/plugins/coreplugin/icore.cpp41
-rw-r--r--src/plugins/coreplugin/icore.h4
-rw-r--r--src/plugins/coreplugin/windowsupport.cpp62
-rw-r--r--src/plugins/coreplugin/windowsupport.h7
-rw-r--r--src/plugins/cpaster/CMakeLists.txt1
-rw-r--r--src/plugins/cpaster/cpaster.qbs2
-rw-r--r--src/plugins/cpaster/stickynotespasteprotocol.cpp249
-rw-r--r--src/plugins/cpaster/stickynotespasteprotocol.h44
-rw-r--r--src/plugins/cppeditor/builtincursorinfo.cpp42
-rw-r--r--src/plugins/cppeditor/builtincursorinfo.h2
-rw-r--r--src/plugins/cppeditor/builtineditordocumentprocessor.cpp2
-rw-r--r--src/plugins/cppeditor/cppchecksymbols.cpp30
-rw-r--r--src/plugins/cppeditor/cppchecksymbols.h4
-rw-r--r--src/plugins/cppeditor/cppcodeformatter.cpp1
-rw-r--r--src/plugins/cppeditor/cppfunctiondecldeflink.cpp22
-rw-r--r--src/plugins/cppeditor/cppfunctiondecldeflink.h2
-rw-r--r--src/plugins/cppeditor/cppindexingsupport.cpp2
-rw-r--r--src/plugins/cppeditor/cpplocalsymbols.cpp36
-rw-r--r--src/plugins/cppeditor/cpplocalsymbols.h2
-rw-r--r--src/plugins/cppeditor/cpplocalsymbols_test.cpp2
-rw-r--r--src/plugins/cppeditor/cppuseselectionsupdater.cpp14
-rw-r--r--src/plugins/cppeditor/cppuseselectionsupdater.h2
-rw-r--r--src/plugins/cppeditor/semantichighlighter.cpp39
-rw-r--r--src/plugins/cppeditor/semantichighlighter.h10
-rw-r--r--src/plugins/cvs/cvsplugin.cpp10
-rw-r--r--src/plugins/debugger/cdb/cdbengine.cpp8
-rw-r--r--src/plugins/debugger/debuggeritemmanager.cpp9
-rw-r--r--src/plugins/debugger/lldb/lldbengine.cpp25
-rw-r--r--src/plugins/debugger/lldb/lldbengine.h2
-rw-r--r--src/plugins/diffeditor/diffeditorwidgetcontroller.cpp9
-rw-r--r--src/plugins/effectcomposer/effectcomposerview.h1
-rw-r--r--src/plugins/git/gitsettings.cpp2
-rw-r--r--src/plugins/ios/devicectlutils.cpp2
-rw-r--r--src/plugins/ios/iosrunner.cpp2
-rw-r--r--src/plugins/ios/iossettingspage.cpp8
-rw-r--r--src/plugins/languageclient/callhierarchy.cpp2
-rw-r--r--src/plugins/mercurial/mercurialplugin.cpp8
-rw-r--r--src/plugins/mesonprojectmanager/toolssettingsaccessor.cpp16
-rw-r--r--src/plugins/perforce/perforceplugin.cpp2
-rw-r--r--src/plugins/projectexplorer/abstractprocessstep.cpp21
-rw-r--r--src/plugins/projectexplorer/buildaspects.cpp2
-rw-r--r--src/plugins/projectexplorer/jsonwizard/jsonwizardfactory.cpp2
-rw-r--r--src/plugins/projectexplorer/projectwindow.cpp10
-rw-r--r--src/plugins/python/pythonkitaspect.cpp15
-rw-r--r--src/plugins/python/pythonproject.cpp5
-rw-r--r--src/plugins/qmljseditor/qmllssettings.cpp1
-rw-r--r--src/plugins/qtapplicationmanager/appmanagercmakepackagestep.cpp2
-rw-r--r--src/plugins/qtapplicationmanager/appmanagerdeployconfigurationfactory.cpp2
-rw-r--r--src/plugins/qtapplicationmanager/appmanagerdeploypackagestep.cpp4
-rw-r--r--src/plugins/qtapplicationmanager/appmanagerinstallpackagestep.cpp4
-rw-r--r--src/plugins/qtapplicationmanager/appmanagerrunconfiguration.cpp4
-rw-r--r--src/plugins/qtapplicationmanager/appmanagerruncontrol.cpp8
-rw-r--r--src/plugins/qtapplicationmanager/appmanagerstringaspect.cpp12
-rw-r--r--src/plugins/qtsupport/qscxmlcgenerator.cpp11
-rw-r--r--src/plugins/qtsupport/qscxmlcgenerator.h4
-rw-r--r--src/plugins/qtsupport/qtsupportplugin.cpp4
-rw-r--r--src/plugins/qtsupport/translationwizardpage.cpp4
-rw-r--r--src/plugins/qtsupport/uicgenerator.cpp11
-rw-r--r--src/plugins/qtsupport/uicgenerator.h4
-rw-r--r--src/plugins/remotelinux/genericdeploystep.cpp9
-rw-r--r--src/plugins/remotelinux/linuxdevice.cpp46
-rw-r--r--src/plugins/squish/squishnavigationwidget.cpp7
-rw-r--r--src/plugins/subversion/subversionplugin.cpp6
-rw-r--r--src/plugins/texteditor/texteditor.cpp12
-rw-r--r--src/plugins/texteditor/texteditor.h2
-rw-r--r--src/plugins/texteditor/texteditoractionhandler.cpp4
-rw-r--r--src/plugins/texteditor/texteditorsettings.cpp31
-rw-r--r--src/plugins/texteditor/texteditorsettings.h2
-rw-r--r--src/plugins/vcsbase/vcsbaseeditor.cpp18
m---------src/shared/qbs0
134 files changed, 2550 insertions, 1326 deletions
diff --git a/src/libs/3rdparty/qtkeychain/qtkeychain.qbs b/src/libs/3rdparty/qtkeychain/qtkeychain.qbs
index 6a1073a953..b5f8e7dc13 100644
--- a/src/libs/3rdparty/qtkeychain/qtkeychain.qbs
+++ b/src/libs/3rdparty/qtkeychain/qtkeychain.qbs
@@ -72,6 +72,7 @@ QtcLibrary {
Group {
name: "qtkeychain dbus support"
cpp.defines: outer.concat(["KEYCHAIN_DBUS=1"])
+ cpp.cxxFlags: outer.concat("-Wno-cast-function-type")
files: [
"gnomekeyring.cpp",
"gnomekeyring_p.h",
diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/state_p.h b/src/libs/3rdparty/syntax-highlighting/src/lib/state_p.h
index 4aee141681..9971f7f660 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/lib/state_p.h
+++ b/src/libs/3rdparty/syntax-highlighting/src/lib/state_p.h
@@ -36,7 +36,7 @@ public:
return state.d.data();
}
- int size() const
+ std::size_t size() const
{
return m_contextStack.size();
}
diff --git a/src/libs/nanotrace/nanotrace.cpp b/src/libs/nanotrace/nanotrace.cpp
index c5adeb4d72..8a96b12584 100644
--- a/src/libs/nanotrace/nanotrace.cpp
+++ b/src/libs/nanotrace/nanotrace.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "nanotrace.h"
diff --git a/src/libs/nanotrace/nanotrace.h b/src/libs/nanotrace/nanotrace.h
index ed17797e34..76b0120ae1 100644
--- a/src/libs/nanotrace/nanotrace.h
+++ b/src/libs/nanotrace/nanotrace.h
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#pragma once
diff --git a/src/libs/nanotrace/nanotraceglobals.h b/src/libs/nanotrace/nanotraceglobals.h
index 649408d69c..64af31aab9 100644
--- a/src/libs/nanotrace/nanotraceglobals.h
+++ b/src/libs/nanotrace/nanotraceglobals.h
@@ -1,5 +1,5 @@
// Copyright (C) 2023 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#pragma once
diff --git a/src/libs/nanotrace/nanotracehr.cpp b/src/libs/nanotrace/nanotracehr.cpp
index 3f02bd527d..ada5bf65f5 100644
--- a/src/libs/nanotrace/nanotracehr.cpp
+++ b/src/libs/nanotrace/nanotracehr.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2023 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "nanotracehr.h"
diff --git a/src/libs/nanotrace/nanotracehr.h b/src/libs/nanotrace/nanotracehr.h
index 74b1381b06..62ec7dc03c 100644
--- a/src/libs/nanotrace/nanotracehr.h
+++ b/src/libs/nanotrace/nanotracehr.h
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#pragma once
diff --git a/src/libs/nanotrace/python/figures.py b/src/libs/nanotrace/python/figures.py
index cb806ea40d..7f92a3b57e 100644
--- a/src/libs/nanotrace/python/figures.py
+++ b/src/libs/nanotrace/python/figures.py
@@ -1,5 +1,5 @@
# Copyright (C) 2022 The Qt Company Ltd.
-# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
import pandas as pd
import plotly.graph_objects as go
import plotly.subplots as sp
diff --git a/src/libs/nanotrace/python/nanotrace.py b/src/libs/nanotrace/python/nanotrace.py
index 880f17d7bf..a173c3c52b 100644
--- a/src/libs/nanotrace/python/nanotrace.py
+++ b/src/libs/nanotrace/python/nanotrace.py
@@ -1,5 +1,5 @@
# Copyright (C) 2022 The Qt Company Ltd.
-# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
import reader as rd
import figures as fgs
diff --git a/src/libs/nanotrace/python/reader.py b/src/libs/nanotrace/python/reader.py
index 023bddb15f..ed6b8b5b1e 100644
--- a/src/libs/nanotrace/python/reader.py
+++ b/src/libs/nanotrace/python/reader.py
@@ -1,5 +1,5 @@
# Copyright (C) 2022 The Qt Company Ltd.
-# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
import os
import io
import json
diff --git a/src/libs/qlitehtml b/src/libs/qlitehtml
-Subproject 9248bd827b3859e6898860c15a63c6cd57ca543
+Subproject 7e8eb0f5eaee53b0aeb04208bdaba74fcffc3a3
diff --git a/src/libs/qmljs/qmljsplugindumper.cpp b/src/libs/qmljs/qmljsplugindumper.cpp
index b2591fbf0a..36f2cd802d 100644
--- a/src/libs/qmljs/qmljsplugindumper.cpp
+++ b/src/libs/qmljs/qmljsplugindumper.cpp
@@ -569,6 +569,9 @@ void PluginDumper::loadQmltypesFile(const FilePaths &qmltypesFilePaths,
Utils::onFinished(loadQmlTypeDescription(qmltypesFilePaths), this,
[this, qmltypesFilePaths, libraryPath, libraryInfo]
(const QFuture<PluginDumper::QmlTypeDescription> &typesFuture) {
+ if (typesFuture.isCanceled() || typesFuture.resultCount() == 0)
+ return;
+
PluginDumper::QmlTypeDescription typesResult = typesFuture.result();
if (!typesResult.dependencies.isEmpty())
{
@@ -576,6 +579,9 @@ void PluginDumper::loadQmltypesFile(const FilePaths &qmltypesFilePaths,
QSharedPointer<QSet<FilePath>>()), this,
[typesResult, libraryInfo, libraryPath, this] (const QFuture<PluginDumper::DependencyInfo> &loadFuture)
{
+ if (loadFuture.isCanceled() || loadFuture.resultCount() == 0)
+ return;
+
PluginDumper::DependencyInfo loadResult = loadFuture.result();
QStringList errors = typesResult.errors;
QStringList warnings = typesResult.errors;
diff --git a/src/libs/qtcreatorcdbext/CMakeLists.txt b/src/libs/qtcreatorcdbext/CMakeLists.txt
index 8a737e3fad..47eca2cd16 100644
--- a/src/libs/qtcreatorcdbext/CMakeLists.txt
+++ b/src/libs/qtcreatorcdbext/CMakeLists.txt
@@ -205,7 +205,7 @@ if (_library_enabled)
# Deploy lldb.exe and its Python dependency
find_package(Clang QUIET)
if (LLVM_TOOLS_BINARY_DIR AND LLVM_LIBRARY_DIRS)
- foreach(lldb_file lldb.exe lldb-vscode.exe liblldb.dll python311.zip python311.dll)
+ foreach(lldb_file lldb.exe lldb-dap.exe liblldb.dll python311.zip python311.dll)
if (EXISTS ${LLVM_TOOLS_BINARY_DIR}/${lldb_file})
install(FILES ${LLVM_TOOLS_BINARY_DIR}/${lldb_file}
DESTINATION bin/clang/bin
diff --git a/src/libs/solutions/tasking/tasktree.cpp b/src/libs/solutions/tasking/tasktree.cpp
index 255fe5243a..c6e87d2774 100644
--- a/src/libs/solutions/tasking/tasktree.cpp
+++ b/src/libs/solutions/tasking/tasktree.cpp
@@ -7,10 +7,12 @@
#include <QEventLoop>
#include <QFutureWatcher>
#include <QHash>
+#include <QMetaEnum>
#include <QMutex>
#include <QPromise>
#include <QPointer>
#include <QSet>
+#include <QTime>
#include <QTimer>
using namespace std::chrono;
@@ -1191,6 +1193,17 @@ const GroupItem stopOnSuccessOrError = workflowPolicy(WorkflowPolicy::StopOnSucc
const GroupItem finishAllAndSuccess = workflowPolicy(WorkflowPolicy::FinishAllAndSuccess);
const GroupItem finishAllAndError = workflowPolicy(WorkflowPolicy::FinishAllAndError);
+// Please note the thread_local keyword below guarantees a separate instance per thread.
+// The s_activeTaskTrees is currently used internally only and is not exposed in the public API.
+// It serves for withLog() implementation now. Add a note here when a new usage is introduced.
+static thread_local QList<TaskTree *> s_activeTaskTrees = {};
+
+static TaskTree *activeTaskTree()
+{
+ QT_ASSERT(s_activeTaskTrees.size(), return nullptr);
+ return s_activeTaskTrees.back();
+}
+
DoneResult toDoneResult(bool success)
{
return success ? DoneResult::Success : DoneResult::Error;
@@ -1402,8 +1415,8 @@ void GroupItem::addChildren(const QList<GroupItem> &children)
}
}
-GroupItem GroupItem::withTimeout(const GroupItem &item, milliseconds timeout,
- const std::function<void()> &handler)
+ExecutableItem ExecutableItem::withTimeout(milliseconds timeout,
+ const std::function<void()> &handler) const
{
const auto onSetup = [timeout](milliseconds &timeoutData) { timeoutData = timeout; };
return Group {
@@ -1414,7 +1427,41 @@ GroupItem GroupItem::withTimeout(const GroupItem &item, milliseconds timeout,
handler ? TimeoutTask(onSetup, [handler] { handler(); }, CallDoneIf::Success)
: TimeoutTask(onSetup)
},
- item
+ *this
+ };
+}
+
+static QString currentTime() { return QTime::currentTime().toString(Qt::ISODateWithMs); }
+
+ExecutableItem ExecutableItem::withLog(const QString &logName) const
+{
+ const auto header = [logName] {
+ return QString("TASK TREE LOG [%1] \"%2\"").arg(currentTime(), logName);
+ };
+ struct LogStorage
+ {
+ time_point<system_clock, nanoseconds> start;
+ int asyncCount = 0;
+ };
+ const Storage<LogStorage> storage;
+ return Group {
+ storage,
+ onGroupSetup([storage, header] {
+ storage->start = system_clock::now();
+ storage->asyncCount = activeTaskTree()->asyncCount();
+ qDebug().noquote() << header() << "started.";
+ }),
+ *this,
+ onGroupDone([storage, header](DoneWith result) {
+ const auto elapsed = duration_cast<milliseconds>(system_clock::now() - storage->start);
+ const int asyncCountDiff = activeTaskTree()->asyncCount() - storage->asyncCount;
+ QT_CHECK(asyncCountDiff >= 0);
+ const QMetaEnum doneWithEnum = QMetaEnum::fromType<DoneWith>();
+ const QString syncType = asyncCountDiff ? QString("asynchronously")
+ : QString("synchronously");
+ qDebug().noquote().nospace() << header() << " finished " << syncType << " with "
+ << doneWithEnum.valueToKey(int(result)) << " within " << elapsed.count() << "ms.";
+ })
};
}
@@ -1427,16 +1474,26 @@ class RuntimeTask;
class ExecutionContextActivator
{
public:
- ExecutionContextActivator(RuntimeIteration *iteration) { activateContext(iteration); }
- ExecutionContextActivator(RuntimeContainer *container) { activateContext(container); }
+ ExecutionContextActivator(RuntimeIteration *iteration) {
+ activateTaskTree(iteration);
+ activateContext(iteration);
+ }
+ ExecutionContextActivator(RuntimeContainer *container) {
+ activateTaskTree(container);
+ activateContext(container);
+ }
~ExecutionContextActivator() {
for (int i = m_activeStorages.size() - 1; i >= 0; --i) // iterate in reverse order
m_activeStorages[i].m_storageData->threadData().popStorage();
for (int i = m_activeLoops.size() - 1; i >= 0; --i) // iterate in reverse order
m_activeLoops[i].m_loopData->threadData().popIteration();
+ QT_ASSERT(s_activeTaskTrees.size(), return);
+ s_activeTaskTrees.pop_back();
}
private:
+ void activateTaskTree(RuntimeIteration *iteration);
+ void activateTaskTree(RuntimeContainer *container);
void activateContext(RuntimeIteration *iteration);
void activateContext(RuntimeContainer *container);
QList<Loop> m_activeLoops;
@@ -1490,9 +1547,8 @@ public:
void start();
void stop();
+ void bumpAsyncCount();
void advanceProgress(int byValue);
- void emitStartedAndProgress();
- void emitProgress();
void emitDone(DoneWith result);
void callSetupHandler(StorageBase storage, StoragePtr storagePtr) {
callStorageHandler(storage, storagePtr, &StorageHandler::m_setupHandler);
@@ -1552,6 +1608,7 @@ public:
TaskTree *q = nullptr;
Guard m_guard;
int m_progressValue = 0;
+ int m_asyncCount = 0;
QSet<StorageBase> m_storages;
QHash<StorageBase, StorageHandler> m_storageHandlers;
std::optional<TaskNode> m_root;
@@ -1666,6 +1723,16 @@ static bool isProgressive(RuntimeContainer *container)
return iteration ? iteration->m_isProgressive : true;
}
+void ExecutionContextActivator::activateTaskTree(RuntimeIteration *iteration)
+{
+ activateTaskTree(iteration->m_container);
+}
+
+void ExecutionContextActivator::activateTaskTree(RuntimeContainer *container)
+{
+ s_activeTaskTrees.push_back(container->m_containerNode.m_taskTreePrivate->q);
+}
+
void ExecutionContextActivator::activateContext(RuntimeIteration *iteration)
{
std::optional<Loop> loop = iteration->loop();
@@ -1696,8 +1763,14 @@ void TaskTreePrivate::start()
{
QT_ASSERT(m_root, return);
QT_ASSERT(!m_runtimeRoot, return);
+ m_asyncCount = 0;
m_progressValue = 0;
- emitStartedAndProgress();
+ {
+ GuardLocker locker(m_guard);
+ emit q->started();
+ emit q->asyncCountChanged(m_asyncCount);
+ emit q->progressValueChanged(m_progressValue);
+ }
// TODO: check storage handlers for not existing storages in tree
for (auto it = m_storageHandlers.cbegin(); it != m_storageHandlers.cend(); ++it) {
QT_ASSERT(m_storages.contains(it.key()), qWarning("The registered storage doesn't "
@@ -1705,6 +1778,7 @@ void TaskTreePrivate::start()
}
m_runtimeRoot.reset(new RuntimeTask{*m_root});
start(m_runtimeRoot.get());
+ bumpAsyncCount();
}
void TaskTreePrivate::stop()
@@ -1717,6 +1791,15 @@ void TaskTreePrivate::stop()
emitDone(DoneWith::Cancel);
}
+void TaskTreePrivate::bumpAsyncCount()
+{
+ if (!m_runtimeRoot)
+ return;
+ ++m_asyncCount;
+ GuardLocker locker(m_guard);
+ emit q->asyncCountChanged(m_asyncCount);
+}
+
void TaskTreePrivate::advanceProgress(int byValue)
{
if (byValue == 0)
@@ -1724,18 +1807,6 @@ void TaskTreePrivate::advanceProgress(int byValue)
QT_CHECK(byValue > 0);
QT_CHECK(m_progressValue + byValue <= m_root->taskCount());
m_progressValue += byValue;
- emitProgress();
-}
-
-void TaskTreePrivate::emitStartedAndProgress()
-{
- GuardLocker locker(m_guard);
- emit q->started();
- emit q->progressValueChanged(m_progressValue);
-}
-
-void TaskTreePrivate::emitProgress()
-{
GuardLocker locker(m_guard);
emit q->progressValueChanged(m_progressValue);
}
@@ -2037,10 +2108,12 @@ SetupResult TaskTreePrivate::start(RuntimeTask *node)
node->m_task.release()->deleteLater();
RuntimeIteration *parentIteration = node->m_parentIteration;
parentIteration->deleteChild(node);
- if (parentIteration->m_container->isStarting())
+ if (parentIteration->m_container->isStarting()) {
*unwindAction = toSetupResult(result);
- else
+ } else {
childDone(parentIteration, result);
+ bumpAsyncCount();
+ }
});
node->m_task->start();
@@ -2962,6 +3035,38 @@ DoneWith TaskTree::runBlocking(const Group &recipe, const QFuture<void> &future,
}
/*!
+ Returns the current real count of asynchronous chains of invocations.
+
+ The returned value indicates how many times the control returns to the caller's
+ event loop while the task tree is running. Initially, this value is 0.
+ If the execution of the task tree finishes fully synchronously, this value remains 0.
+ If the task tree contains any asynchronous tasks that are successfully started during
+ a call to start(), this value is bumped to 1 just before the call to start() finishes.
+ Later, when any asynchronous task finishes and any possible continuations are started,
+ this value is bumped again. The bumping continues until the task tree finishes.
+ When the task tree emits the done() signal, the bumping stops.
+ The asyncCountChanged() signal is emitted on every bump of this value.
+
+ \sa asyncCountChanged()
+*/
+int TaskTree::asyncCount() const
+{
+ return d->m_asyncCount;
+}
+
+/*!
+ \fn void TaskTree::asyncCountChanged(int count)
+
+ This signal is emitted when the running task tree is about to return control to the caller's
+ event loop. When the task tree is started, this signal is emitted with \a count value of 0,
+ and emitted later on every asyncCount() value bump with an updated \a count value.
+ Every signal sent (except the initial one with the value of 0) guarantees that the task tree
+ is still running asynchronously after the emission.
+
+ \sa asyncCount()
+*/
+
+/*!
Returns the number of asynchronous tasks contained in the stored recipe.
\note The returned number doesn't include \l {Tasking::Sync} {Sync} tasks.
@@ -3006,7 +3111,7 @@ int TaskTree::taskCount() const
When the task tree is started, this number is set to \c 0.
When the task tree is finished, this number always equals progressMaximum().
- \sa progressMaximum()
+ \sa progressMaximum(), progressValueChanged()
*/
int TaskTree::progressValue() const
{
diff --git a/src/libs/solutions/tasking/tasktree.h b/src/libs/solutions/tasking/tasktree.h
index 7295c47e1e..8ea255303b 100644
--- a/src/libs/solutions/tasking/tasktree.h
+++ b/src/libs/solutions/tasking/tasktree.h
@@ -261,8 +261,6 @@ protected:
static GroupItem groupHandler(const GroupHandler &handler) { return GroupItem({handler}); }
static GroupItem parallelLimit(int limit) { return GroupItem({{}, limit}); }
static GroupItem workflowPolicy(WorkflowPolicy policy) { return GroupItem({{}, {}, policy}); }
- static GroupItem withTimeout(const GroupItem &item, std::chrono::milliseconds timeout,
- const std::function<void()> &handler = {});
// Checks if Function may be invoked with Args and if Function's return type is Result.
template <typename Result, typename Function, typename ...Args,
@@ -286,7 +284,19 @@ private:
TaskHandler m_taskHandler;
};
-class TASKING_EXPORT Group : public GroupItem
+class TASKING_EXPORT ExecutableItem : public GroupItem
+{
+public:
+ ExecutableItem withTimeout(std::chrono::milliseconds timeout,
+ const std::function<void()> &handler = {}) const;
+ ExecutableItem withLog(const QString &logName) const;
+
+protected:
+ ExecutableItem() = default;
+ ExecutableItem(const TaskHandler &handler) : GroupItem(handler) {}
+};
+
+class TASKING_EXPORT Group : public ExecutableItem
{
public:
Group(const QList<GroupItem> &children) { addChildren(children); }
@@ -304,11 +314,6 @@ public:
using GroupItem::parallelLimit; // Default: 1 (sequential). 0 means unlimited (parallel).
using GroupItem::workflowPolicy; // Default: WorkflowPolicy::StopOnError.
- GroupItem withTimeout(std::chrono::milliseconds timeout,
- const std::function<void()> &handler = {}) const {
- return GroupItem::withTimeout(*this, timeout, handler);
- }
-
private:
template <typename Handler>
static GroupSetupHandler wrapGroupSetup(Handler &&handler)
@@ -387,7 +392,7 @@ public:
};
// Synchronous invocation. Similarly to Group - isn't counted as a task inside taskCount()
-class TASKING_EXPORT Sync final : public GroupItem
+class TASKING_EXPORT Sync final : public ExecutableItem
{
public:
template <typename Handler>
@@ -431,7 +436,7 @@ private:
};
template <typename Adapter>
-class CustomTask final : public GroupItem
+class CustomTask final : public ExecutableItem
{
public:
using Task = typename Adapter::TaskType;
@@ -445,16 +450,10 @@ public:
template <typename SetupHandler = TaskSetupHandler, typename DoneHandler = TaskDoneHandler>
CustomTask(SetupHandler &&setup = TaskSetupHandler(), DoneHandler &&done = TaskDoneHandler(),
CallDoneIf callDoneIf = CallDoneIf::SuccessOrError)
- : GroupItem({&createAdapter, wrapSetup(std::forward<SetupHandler>(setup)),
- wrapDone(std::forward<DoneHandler>(done)), callDoneIf})
+ : ExecutableItem({&createAdapter, wrapSetup(std::forward<SetupHandler>(setup)),
+ wrapDone(std::forward<DoneHandler>(done)), callDoneIf})
{}
- GroupItem withTimeout(std::chrono::milliseconds timeout,
- const std::function<void()> &handler = {}) const
- {
- return GroupItem::withTimeout(*this, timeout, handler);
- }
-
private:
static Adapter *createAdapter() { return new Adapter; }
@@ -542,6 +541,7 @@ public:
static DoneWith runBlocking(const Group &recipe, const QFuture<void> &future,
std::chrono::milliseconds timeout = std::chrono::milliseconds::max());
+ int asyncCount() const;
int taskCount() const;
int progressMaximum() const { return taskCount(); }
int progressValue() const; // all finished / skipped / stopped tasks, groups itself excluded
@@ -566,6 +566,7 @@ public:
signals:
void started();
void done(DoneWith result);
+ void asyncCountChanged(int count);
void progressValueChanged(int value); // updated whenever task finished / skipped / stopped
private:
diff --git a/src/libs/solutions/terminal/terminalview.cpp b/src/libs/solutions/terminal/terminalview.cpp
index 08a85d4f11..0cebe6d9b9 100644
--- a/src/libs/solutions/terminal/terminalview.cpp
+++ b/src/libs/solutions/terminal/terminalview.cpp
@@ -1199,6 +1199,9 @@ void TerminalView::mouseReleaseEvent(QMouseEvent *event)
void TerminalView::mouseDoubleClickEvent(QMouseEvent *event)
{
+ if (event->button() != Qt::LeftButton)
+ return;
+
if (d->m_allowMouseTracking) {
d->m_surface->mouseMove(toGridPos(event), event->modifiers());
d->m_surface->mouseButton(event->button(), true, event->modifiers());
diff --git a/src/libs/utils/async.h b/src/libs/utils/async.h
index e1aacb126e..af6fb3fd85 100644
--- a/src/libs/utils/async.h
+++ b/src/libs/utils/async.h
@@ -54,7 +54,7 @@ auto asyncRun(Function &&function, Args &&...args)
template <typename R, typename T>
const QFuture<T> &onResultReady(const QFuture<T> &future, R *receiver, void(R::*member)(const T &))
{
- auto watcher = new QFutureWatcher<T>();
+ auto watcher = new QFutureWatcher<T>(receiver);
QObject::connect(watcher, &QFutureWatcherBase::finished, watcher, &QObject::deleteLater);
QObject::connect(watcher, &QFutureWatcherBase::resultReadyAt, receiver, [=](int index) {
(receiver->*member)(watcher->future().resultAt(index));
@@ -72,7 +72,7 @@ const QFuture<T> &onResultReady(const QFuture<T> &future, R *receiver, void(R::*
template <typename T, typename Function>
const QFuture<T> &onResultReady(const QFuture<T> &future, QObject *guard, Function f)
{
- auto watcher = new QFutureWatcher<T>();
+ auto watcher = new QFutureWatcher<T>(guard);
QObject::connect(watcher, &QFutureWatcherBase::finished, watcher, &QObject::deleteLater);
QObject::connect(watcher, &QFutureWatcherBase::resultReadyAt, guard, [f, watcher](int index) {
f(watcher->future().resultAt(index));
@@ -90,7 +90,7 @@ template<typename R, typename T>
const QFuture<T> &onFinished(const QFuture<T> &future,
R *receiver, void (R::*member)(const QFuture<T> &))
{
- auto watcher = new QFutureWatcher<T>();
+ auto watcher = new QFutureWatcher<T>(receiver);
QObject::connect(watcher, &QFutureWatcherBase::finished, watcher, &QObject::deleteLater);
QObject::connect(watcher, &QFutureWatcherBase::finished, receiver,
[=] { (receiver->*member)(watcher->future()); });
@@ -107,7 +107,7 @@ const QFuture<T> &onFinished(const QFuture<T> &future,
template<typename T, typename Function>
const QFuture<T> &onFinished(const QFuture<T> &future, QObject *guard, Function f)
{
- auto watcher = new QFutureWatcher<T>();
+ auto watcher = new QFutureWatcher<T>(guard);
QObject::connect(watcher, &QFutureWatcherBase::finished, watcher, &QObject::deleteLater);
QObject::connect(watcher, &QFutureWatcherBase::finished, guard, [f, watcher] {
f(watcher->future());
diff --git a/src/libs/utils/devicefileaccess.cpp b/src/libs/utils/devicefileaccess.cpp
index d3a8360136..c2475853e7 100644
--- a/src/libs/utils/devicefileaccess.cpp
+++ b/src/libs/utils/devicefileaccess.cpp
@@ -566,8 +566,8 @@ static bool checkToRefuseRemoveStandardLocationDirectory(const QString &dirPath,
{
if (QStandardPaths::standardLocations(location).contains(dirPath)) {
if (error) {
- *error = Tr::tr("Refusing to remove your %1 directory.").arg(
- QStandardPaths::displayName(location));
+ *error = Tr::tr("Refusing to remove the standard directory \"%1\".")
+ .arg(QStandardPaths::displayName(location));
}
return false;
}
diff --git a/src/libs/utils/macroexpander.cpp b/src/libs/utils/macroexpander.cpp
index f6d3dad362..dd57cd6b5a 100644
--- a/src/libs/utils/macroexpander.cpp
+++ b/src/libs/utils/macroexpander.cpp
@@ -375,7 +375,7 @@ void MacroExpander::registerIntVariable(const QByteArray &variable,
* Convenience function to register several variables with the same \a prefix, that have a file
* as a value. Takes the prefix and registers variables like \c{prefix:FilePath} and
* \c{prefix:Path}, with descriptions that start with the given \a heading.
- * For example \c{registerFileVariables("CurrentDocument", tr("Current Document"))} registers
+ * For example \c{registerFileVariables("CurrentDocument", Tr::tr("Current Document"))} registers
* variables such as \c{CurrentDocument:FilePath} with description
* "Current Document: Full path including file name."
*
diff --git a/src/libs/utils/process.cpp b/src/libs/utils/process.cpp
index 4eacb28986..5bf4451365 100644
--- a/src/libs/utils/process.cpp
+++ b/src/libs/utils/process.cpp
@@ -847,7 +847,9 @@ public:
qint64 m_applicationMainThreadId = 0;
ProcessResultData m_resultData;
- QTextCodec *m_codec = QTextCodec::codecForLocale();
+ QTextCodec *m_stdOutCodec = QTextCodec::codecForLocale();
+ QTextCodec *m_stdErrCodec = QTextCodec::codecForLocale();
+
ProcessResult m_result = ProcessResult::StartFailed;
ChannelBuffer m_stdOut;
ChannelBuffer m_stdErr;
@@ -1102,9 +1104,9 @@ void ProcessPrivate::sendControlSignal(ControlSignal controlSignal)
void ProcessPrivate::clearForRun()
{
m_stdOut.clearForRun();
- m_stdOut.codec = m_codec;
+ m_stdOut.codec = m_stdOutCodec;
m_stdErr.clearForRun();
- m_stdErr.codec = m_codec;
+ m_stdErr.codec = m_stdErrCodec;
m_result = ProcessResult::StartFailed;
m_startTimestamp = {};
m_doneTimestamp = {};
@@ -1663,8 +1665,7 @@ QString Process::exitMessage(const CommandLine &command, ProcessResult result,
case ProcessResult::Canceled:
// TODO: We might want to format it nicely when bigger than 1 second, e.g. 1,324 s.
// Also when it's bigger than 1 minute, 1 hour, etc...
- return Tr::tr("The command \"%1\" was canceled after (%2 ms).")
- .arg(cmd).arg(duration.count());
+ return Tr::tr("The command \"%1\" was canceled after %2 ms.").arg(cmd).arg(duration.count());
}
return {};
}
@@ -1729,13 +1730,13 @@ QByteArray Process::rawStdErr() const
QString Process::stdOut() const
{
QTC_CHECK(d->m_stdOut.keepRawData);
- return d->m_codec->toUnicode(d->m_stdOut.rawData);
+ return d->m_stdOutCodec->toUnicode(d->m_stdOut.rawData);
}
QString Process::stdErr() const
{
QTC_CHECK(d->m_stdErr.keepRawData);
- return d->m_codec->toUnicode(d->m_stdErr.rawData);
+ return d->m_stdErrCodec->toUnicode(d->m_stdErr.rawData);
}
QString Process::cleanedStdOut() const
@@ -1850,7 +1851,20 @@ void ChannelBuffer::handleRest()
void Process::setCodec(QTextCodec *c)
{
QTC_ASSERT(c, return);
- d->m_codec = c;
+ d->m_stdOutCodec = c;
+ d->m_stdErrCodec = c;
+}
+
+void Process::setStdOutCodec(QTextCodec *c)
+{
+ QTC_ASSERT(c, return);
+ d->m_stdOutCodec = c;
+}
+
+void Process::setStdErrCodec(QTextCodec *c)
+{
+ QTC_ASSERT(c, return);
+ d->m_stdErrCodec = c;
}
void Process::setTimeOutMessageBoxEnabled(bool v)
diff --git a/src/libs/utils/process.h b/src/libs/utils/process.h
index d425f76eed..694c1a12a8 100644
--- a/src/libs/utils/process.h
+++ b/src/libs/utils/process.h
@@ -148,8 +148,10 @@ public:
void runBlocking(std::chrono::seconds timeout = std::chrono::seconds(10),
EventLoopMode eventLoopMode = EventLoopMode::Off);
- // TODO: We should specify the purpose of the codec, e.g. setCodecForStandardChannel()
- void setCodec(QTextCodec *c);
+ void setCodec(QTextCodec *c); // for stdOut and stdErr
+ void setStdOutCodec(QTextCodec *c);
+ void setStdErrCodec(QTextCodec *c);
+
void setTimeOutMessageBoxEnabled(bool);
void setStdOutCallback(const TextChannelCallback &callback);
diff --git a/src/plugins/android/androidconfigurations.cpp b/src/plugins/android/androidconfigurations.cpp
index 21a20ff645..fae6c64bbe 100644
--- a/src/plugins/android/androidconfigurations.cpp
+++ b/src/plugins/android/androidconfigurations.cpp
@@ -126,6 +126,15 @@ static QString ndkPackageMarker()
return QLatin1String(Constants::ndkPackageName) + ";";
}
+static QString platformsPackageMarker()
+{
+ return QLatin1String(Constants::platformsPackageName) + ";";
+}
+
+static QString buildToolsPackageMarker()
+{
+ return QLatin1String(Constants::buildToolsPackageName) + ";";
+}
//////////////////////////////////
// AndroidConfig
@@ -951,15 +960,59 @@ bool AndroidConfig::sdkToolsOk() const
return exists && writable && sdkToolsExist;
}
+static QStringList packagesExcludingBuiltWithDefaults(const QStringList &packages)
+{
+ return Utils::filtered(packages, [] (const QString &p) {
+ return !p.startsWith(ndkPackageMarker()) && !p.startsWith(platformsPackageMarker())
+ && !p.startsWith(buildToolsPackageMarker()); });
+}
+
+static QString essentialBuiltWithBuildToolsPackage(int builtWithApiVersion)
+{
+ // For build-tools, to avoid the situation of potentially having the essential packages
+ // invalidated whenever a new minor version is released, check if any version with major
+ // version matching builtWith apiVersion and use it as essential, otherwise use the any
+ // other one that has an minimum major version of builtWith apiVersion.
+ const BuildToolsList buildTools =
+ AndroidConfigurations::sdkManager()->filteredBuildTools(builtWithApiVersion);
+ const BuildToolsList apiBuildTools
+ = Utils::filtered(buildTools, [builtWithApiVersion] (const BuildTools *pkg) {
+ return pkg->revision().majorVersion() == builtWithApiVersion; });
+ const QString installedBuildTool = [apiBuildTools] () -> QString {
+ for (const BuildTools *pkg : apiBuildTools) {
+ if (pkg->state() == AndroidSdkPackage::Installed)
+ return pkg->sdkStylePath();
+ }
+ return {};
+ }();
+
+ if (installedBuildTool.isEmpty()) {
+ if (!apiBuildTools.isEmpty())
+ return apiBuildTools.first()->sdkStylePath();
+ else if (!buildTools.isEmpty())
+ return buildTools.first()->sdkStylePath();
+ // This means there's something wrong with sdkmanager, return a default version anyway
+ else
+ return buildToolsPackageMarker() + QString::number(builtWithApiVersion) + ".0.0";
+ }
+
+ return installedBuildTool;
+}
+
QStringList AndroidConfig::essentialsFromQtVersion(const QtVersion &version) const
{
if (auto androidQtVersion = dynamic_cast<const AndroidQtVersion *>(&version)) {
bool ok;
const AndroidQtVersion::BuiltWith bw = androidQtVersion->builtWith(&ok);
if (ok) {
- const QString ndkPackage = ndkPackageMarker() + bw.ndkVersion.toString();
- return QStringList(ndkPackage)
- + packagesWithoutNdks(m_defaultSdkDepends.essentialPackages);
+ QStringList builtWithPackages;
+ builtWithPackages.append(ndkPackageMarker() + bw.ndkVersion.toString());
+ const QString apiVersion = QString::number(bw.apiVersion);
+ builtWithPackages.append(platformsPackageMarker() + "android-" + apiVersion);
+ builtWithPackages.append(essentialBuiltWithBuildToolsPackage(bw.apiVersion));
+
+ return builtWithPackages + packagesExcludingBuiltWithDefaults(
+ m_defaultSdkDepends.essentialPackages);
}
}
diff --git a/src/plugins/android/androidconstants.h b/src/plugins/android/androidconstants.h
index e2b15e6358..813b6a924c 100644
--- a/src/plugins/android/androidconstants.h
+++ b/src/plugins/android/androidconstants.h
@@ -78,6 +78,8 @@ const Utils::Id AndroidAvdPath = "AndroidAvdPath";
// SDK Tools
const char cmdlineToolsName[] = "cmdline-tools";
const char ndkPackageName[] = "ndk";
+const char platformsPackageName[] = "platforms";
+const char buildToolsPackageName[] = "build-tools";
// For AndroidQtVersion
const char ArmToolsDisplayName[] = "arm";
diff --git a/src/plugins/android/androidsdkmanager.cpp b/src/plugins/android/androidsdkmanager.cpp
index c952ff9097..029cfd8352 100644
--- a/src/plugins/android/androidsdkmanager.cpp
+++ b/src/plugins/android/androidsdkmanager.cpp
@@ -405,7 +405,10 @@ void AndroidSdkManagerPrivate::reloadSdkPackages()
if (m_packageListingSuccessful) {
SdkManagerOutputParser parser(m_allPackages);
parser.parsePackageListing(packageListing);
+ } else {
+ qCWarning(sdkManagerLog) << "Failed parsing packages:" << packageListing;
}
+
emit m_sdkManager.packageReloadFinished();
}
diff --git a/src/plugins/autotest/qtest/datataglocatorfilter.cpp b/src/plugins/autotest/qtest/datataglocatorfilter.cpp
index bb0745d189..e6a436666c 100644
--- a/src/plugins/autotest/qtest/datataglocatorfilter.cpp
+++ b/src/plugins/autotest/qtest/datataglocatorfilter.cpp
@@ -70,7 +70,7 @@ DataTagLocatorFilter::DataTagLocatorFilter()
{
setId("Locate Qt Test data tags");
setDisplayName(Tr::tr("Locate Qt Test data tags"));
- setDescription(Tr::tr("Locates a Qt Test data tag found inside the active project."));
+ setDescription(Tr::tr("Locates Qt Test data tags found inside the active project."));
setDefaultShortcutString("qdt");
setPriority(Medium);
using namespace ProjectExplorer;
diff --git a/src/plugins/autotest/qtest/qttestframework.cpp b/src/plugins/autotest/qtest/qttestframework.cpp
index 009acc81ab..17970e19d7 100644
--- a/src/plugins/autotest/qtest/qttestframework.cpp
+++ b/src/plugins/autotest/qtest/qttestframework.cpp
@@ -73,9 +73,10 @@ QtTestFramework::QtTestFramework()
useXMLOutput.setSettingsKey("UseXMLOutput");
useXMLOutput.setDefaultValue(true);
useXMLOutput.setLabelText(Tr::tr("Use XML output"));
- useXMLOutput.setToolTip(Tr::tr("XML output is recommended, because it avoids parsing issues, "
- "while plain text is more human readable.\n\nWarning: "
- "Plain text misses some information, such as duration."));
+ useXMLOutput.setToolTip("<html>"
+ + Tr::tr("XML output is recommended, because it avoids parsing issues, "
+ "while plain text is more human readable.<p>Warning: "
+ "Plain text misses some information, such as duration."));
verboseBench.setSettingsKey("VerboseBench");
verboseBench.setLabelText(Tr::tr("Verbose benchmarks"));
@@ -98,18 +99,22 @@ QtTestFramework::QtTestFramework()
quickCheckForDerivedTests.setDefaultValue(false);
quickCheckForDerivedTests.setLabelText(Tr::tr("Check for derived Qt Quick tests"));
quickCheckForDerivedTests.setToolTip(
- Tr::tr("Search for Qt Quick tests that are derived from TestCase.\nWarning: Enabling this "
- "feature significantly increases scan time."));
+ "<html>"
+ + Tr::tr(
+ "Search for Qt Quick tests that are derived from TestCase.<p>Warning: Enabling this "
+ "feature significantly increases scan time."));
parseMessages.setSettingsKey("ParseMessages");
parseMessages.setDefaultValue(false);
parseMessages.setLabelText(Tr::tr("Find user-defined locations"));
parseMessages.setToolTip(
- Tr::tr("Parse messages for the pattern \"file://filepath:line\", where \":line\" is "
- "optional, and use this as location information.\n"
- "Warning: If the patterns are used in code, the location information for debug "
- "messages and other messages might improve,\n"
- "at the risk of some incorrect locations and lower performance."));
+ "<html>"
+ + Tr::tr("Parse messages for the following pattern and use it as location information:"
+ "<pre>file://filepath:line</pre>"
+ "where \":line\" is optional."
+ "<p>Warning: If the patterns are used in code, the location information for debug "
+ "messages and other messages might improve,"
+ "at the risk of some incorrect locations and lower performance."));
readSettings();
maxWarnings.setEnabler(&limitWarnings);
diff --git a/src/plugins/axivion/CMakeLists.txt b/src/plugins/axivion/CMakeLists.txt
index a71b984520..561ad680e6 100644
--- a/src/plugins/axivion/CMakeLists.txt
+++ b/src/plugins/axivion/CMakeLists.txt
@@ -6,11 +6,14 @@ add_qtc_plugin(Axivion
axivion.qrc
axivionoutputpane.cpp axivionoutputpane.h
axivionplugin.cpp axivionplugin.h
- axivionprojectsettings.h axivionprojectsettings.cpp
+ axivionprojectsettings.cpp axivionprojectsettings.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
+ dashboard/error.cpp dashboard/error.h
+ dynamiclistmodel.cpp dynamiclistmodel.h
+ issueheaderview.cpp issueheaderview.h
)
diff --git a/src/plugins/axivion/axivion.qbs b/src/plugins/axivion/axivion.qbs
index 7b8034c26c..0e808f6580 100644
--- a/src/plugins/axivion/axivion.qbs
+++ b/src/plugins/axivion/axivion.qbs
@@ -23,8 +23,12 @@ QtcPlugin {
"axivionsettings.cpp",
"axivionsettings.h",
"axiviontr.h",
- "credentialquery.h",
"credentialquery.cpp",
+ "credentialquery.h",
+ "dynamiclistmodel.cpp",
+ "dynamiclistmodel.h",
+ "issueheaderview.cpp",
+ "issueheaderview.h",
]
cpp.includePaths: base.concat(["."]) // needed for the generated stuff below
diff --git a/src/plugins/axivion/axivion.qrc b/src/plugins/axivion/axivion.qrc
index c0d56f8f7b..fa3ad146d3 100644
--- a/src/plugins/axivion/axivion.qrc
+++ b/src/plugins/axivion/axivion.qrc
@@ -14,5 +14,9 @@
<file>images/button-mv@2x.png</file>
<file>images/button-sv.png</file>
<file>images/button-sv@2x.png</file>
+ <file>images/sortAsc.png</file>
+ <file>images/sortAsc@2x.png</file>
+ <file>images/sortDesc.png</file>
+ <file>images/sortDesc@2x.png</file>
</qresource>
</RCC>
diff --git a/src/plugins/axivion/axivionoutputpane.cpp b/src/plugins/axivion/axivionoutputpane.cpp
index 9bd50784f3..a13b63dd3a 100644
--- a/src/plugins/axivion/axivionoutputpane.cpp
+++ b/src/plugins/axivion/axivionoutputpane.cpp
@@ -6,17 +6,21 @@
#include "axivionplugin.h"
#include "axiviontr.h"
#include "dashboard/dto.h"
+#include "issueheaderview.h"
+#include "dynamiclistmodel.h"
#include <coreplugin/editormanager/editormanager.h>
+#include <coreplugin/ioutputpane.h>
#include <projectexplorer/project.h>
#include <projectexplorer/projectmanager.h>
#include <solutions/tasking/tasktreerunner.h>
+#include <utils/algorithm.h>
+#include <utils/layoutbuilder.h>
#include <utils/link.h>
#include <utils/qtcassert.h>
-#include <utils/treemodel.h>
#include <utils/basetreeview.h>
#include <utils/utilsicons.h>
@@ -28,9 +32,7 @@
#include <QLabel>
#include <QPushButton>
#include <QScrollArea>
-#include <QScrollBar>
#include <QStackedWidget>
-#include <QTextBrowser>
#include <QToolButton>
#include <map>
@@ -59,22 +61,24 @@ DashboardWidget::DashboardWidget(QWidget *parent)
: QScrollArea(parent)
{
QWidget *widget = new QWidget(this);
- QVBoxLayout *layout = new QVBoxLayout(widget);
- QFormLayout *projectLayout = new QFormLayout;
m_project = new QLabel(this);
- projectLayout->addRow(Tr::tr("Project:"), m_project);
m_loc = new QLabel(this);
- projectLayout->addRow(Tr::tr("Lines of code:"), m_loc);
m_timestamp = new QLabel(this);
- projectLayout->addRow(Tr::tr("Analysis timestamp:"), m_timestamp);
- layout->addLayout(projectLayout);
- layout->addSpacing(10);
- auto row = new QHBoxLayout;
+
m_gridLayout = new QGridLayout;
- row->addLayout(m_gridLayout);
- row->addStretch(1);
- layout->addLayout(row);
- layout->addStretch(1);
+
+ using namespace Layouting;
+ Column {
+ Form {
+ Tr::tr("Project:"), m_project, br,
+ Tr::tr("Lines of code:"), m_loc, br,
+ Tr::tr("Analysis timestamp:"), m_timestamp
+ },
+ Space(10),
+ Row { m_gridLayout, st },
+ st
+ }.attachTo(widget);
+
setWidget(widget);
setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
setWidgetResizable(true);
@@ -187,32 +191,59 @@ void DashboardWidget::updateUi()
addValuesWidgets(Tr::tr("Total:"), allTotal, allAdded, allRemoved, row);
}
-class IssueTreeItem final : public StaticTreeItem
+struct LinkWithColumns
+{
+ Link link;
+ QList<int> columns;
+};
+
+class IssueListItem final : public ListItem
{
public:
- IssueTreeItem(const QStringList &data, const QStringList &toolTips)
- : StaticTreeItem(data, toolTips)
+ IssueListItem(int row, const QString &id, const QStringList &data, const QStringList &toolTips)
+ : ListItem(row)
+ , m_id(id)
+ , m_data(data)
+ , m_toolTips(toolTips)
{}
- void setLinks(const Links &links) { m_links = links; }
+ void setLinks(const QList<LinkWithColumns> &links) { m_links = links; }
+
+ QVariant data(int column, int role) const
+ {
+ if (role == Qt::DisplayRole && column >= 0 && column < m_data.size())
+ return m_data.at(column);
+ if (role == Qt::ToolTipRole && column >= 0 && column < m_toolTips.size())
+ return m_toolTips.at(column);
+ return {};
+ }
bool setData(int column, const QVariant &value, int role) final
{
- if (role == BaseTreeView::ItemActivatedRole && !m_links.isEmpty()) {
- // TODO for now only simple - just the first..
- Link link = m_links.first();
- Project *project = ProjectManager::startupProject();
- FilePath baseDir = project ? project->projectDirectory() : FilePath{};
- link.targetFilePath = baseDir.resolvePath(link.targetFilePath);
- if (link.targetFilePath.exists())
- EditorManager::openEditorAt(link);
+ if (role == BaseTreeView::ItemActivatedRole) {
+ if (!m_links.isEmpty()) {
+ Link link
+ = Utils::findOr(m_links, m_links.first(), [column](const LinkWithColumns &link) {
+ return link.columns.contains(column);
+ }).link;
+ Project *project = ProjectManager::startupProject();
+ FilePath baseDir = project ? project->projectDirectory() : FilePath{};
+ link.targetFilePath = baseDir.resolvePath(link.targetFilePath);
+ if (link.targetFilePath.exists())
+ EditorManager::openEditorAt(link);
+ }
+ if (!m_id.isEmpty())
+ fetchIssueInfo(m_id);
return true;
}
- return StaticTreeItem::setData(column, value, role);
+ return ListItem::setData(column, value, role);
}
private:
- Links m_links;
+ const QString m_id;
+ QStringList m_data;
+ QStringList m_toolTips;
+ QList<LinkWithColumns> m_links;
};
class IssuesWidget : public QScrollArea
@@ -220,24 +251,23 @@ class IssuesWidget : public QScrollArea
public:
explicit IssuesWidget(QWidget *parent = nullptr);
void updateUi();
- void setTableDto(const Dto::TableInfoDto &dto);
- void addIssues(const Dto::IssueTableDto &dto);
private:
+ void updateTable();
+ void addIssues(const Dto::IssueTableDto &dto, int startRow);
void onSearchParameterChanged();
void updateBasicProjectInfo(std::optional<Dto::ProjectInfoDto> info);
- void updateTableView();
void setFiltersEnabled(bool enabled);
IssueListSearch searchFromUi() const;
+ void fetchTable();
void fetchIssues(const IssueListSearch &search);
- void fetchMoreIssues();
+ void onFetchRequested(int startRow, int limit);
QString m_currentPrefix;
QString m_currentProject;
std::optional<Dto::TableInfoDto> m_currentTableInfo;
QHBoxLayout *m_typesLayout = nullptr;
QButtonGroup *m_typesButtonGroup = nullptr;
- QHBoxLayout *m_filtersLayout = nullptr;
QPushButton *m_addedFilter = nullptr;
QPushButton *m_removedFilter = nullptr;
QComboBox *m_ownerFilter = nullptr;
@@ -246,9 +276,9 @@ private:
QLineEdit *m_pathGlobFilter = nullptr; // FancyLineEdit instead?
QLabel *m_totalRows = nullptr;
BaseTreeView *m_issuesView = nullptr;
- TreeModel<> *m_issuesModel = nullptr;
+ IssueHeaderView *m_headerView = nullptr;
+ DynamicListModel *m_issuesModel = nullptr;
int m_totalRowCount = 0;
- int m_lastRequestedOffset = 0;
QStringList m_userNames;
QStringList m_versionDates;
TaskTreeRunner m_taskTreeRunner;
@@ -258,79 +288,71 @@ IssuesWidget::IssuesWidget(QWidget *parent)
: QScrollArea(parent)
{
QWidget *widget = new QWidget(this);
- QVBoxLayout *layout = new QVBoxLayout(widget);
// row with issue types (-> depending on choice, tables below change)
// and a selectable range (start version, end version)
// row with added/removed and some filters (assignee, path glob, (named filter))
// table, columns depend on chosen issue type
- QHBoxLayout *top = new QHBoxLayout;
- layout->addLayout(top);
m_typesButtonGroup = new QButtonGroup(this);
m_typesButtonGroup->setExclusive(true);
m_typesLayout = new QHBoxLayout;
- top->addLayout(m_typesLayout);
- top->addStretch(1);
+
m_versionStart = new QComboBox(this);
m_versionStart->setMinimumContentsLength(25);
- top->addWidget(m_versionStart);
+ connect(m_versionStart, &QComboBox::activated, this, &IssuesWidget::onSearchParameterChanged);
+
m_versionEnd = new QComboBox(this);
m_versionEnd->setMinimumContentsLength(25);
- connect(m_versionStart, &QComboBox::activated, this, &IssuesWidget::onSearchParameterChanged);
connect(m_versionEnd, &QComboBox::activated, this, &IssuesWidget::onSearchParameterChanged);
- top->addWidget(m_versionEnd);
- top->addStretch(1);
- m_filtersLayout = new QHBoxLayout;
+
m_addedFilter = new QPushButton(this);
m_addedFilter->setIcon(trendIcon(1, 0));
m_addedFilter->setText("0");
m_addedFilter->setCheckable(true);
- m_filtersLayout->addWidget(m_addedFilter);
- m_removedFilter = new QPushButton(this);
- m_removedFilter->setIcon(trendIcon(0, 1));
- m_removedFilter->setText("0");
- m_removedFilter->setCheckable(true);
- m_filtersLayout->addWidget(m_removedFilter);
connect(m_addedFilter, &QPushButton::clicked, this, [this](bool checked) {
if (checked && m_removedFilter->isChecked())
m_removedFilter->setChecked(false);
onSearchParameterChanged();
});
+
+ m_removedFilter = new QPushButton(this);
+ m_removedFilter->setIcon(trendIcon(0, 1));
+ m_removedFilter->setText("0");
+ m_removedFilter->setCheckable(true);
connect(m_removedFilter, &QPushButton::clicked, this, [this](bool checked) {
if (checked && m_addedFilter->isChecked())
m_addedFilter->setChecked(false);
onSearchParameterChanged();
});
- m_filtersLayout->addSpacing(1);
+
m_ownerFilter = new QComboBox(this);
m_ownerFilter->setToolTip(Tr::tr("Owner"));
m_ownerFilter->setMinimumContentsLength(25);
connect(m_ownerFilter, &QComboBox::activated, this, &IssuesWidget::onSearchParameterChanged);
- m_filtersLayout->addWidget(m_ownerFilter);
+
m_pathGlobFilter = new QLineEdit(this);
m_pathGlobFilter->setPlaceholderText(Tr::tr("Path globbing"));
connect(m_pathGlobFilter, &QLineEdit::textEdited, this, &IssuesWidget::onSearchParameterChanged);
- m_filtersLayout->addWidget(m_pathGlobFilter);
- layout->addLayout(m_filtersLayout);
+
m_issuesView = new BaseTreeView(this);
+ m_headerView = new IssueHeaderView(this);
+ connect(m_headerView, &IssueHeaderView::sortTriggered,
+ this, &IssuesWidget::onSearchParameterChanged);
+ m_issuesView->setHeader(m_headerView);
m_issuesView->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
m_issuesView->enableColumnHiding();
- m_issuesModel = new TreeModel(this);
+ m_issuesModel = new DynamicListModel(this);
m_issuesView->setModel(m_issuesModel);
- auto sb = m_issuesView->verticalScrollBar();
- if (QTC_GUARD(sb)) {
- connect(sb, &QAbstractSlider::valueChanged, sb, [this, sb](int value) {
- if (value >= sb->maximum() - 50) {
- if (m_issuesModel->rowCount() < m_totalRowCount)
- fetchMoreIssues();
- }
- });
- }
- layout->addWidget(m_issuesView);
+ connect(m_issuesModel, &DynamicListModel::fetchRequested, this, &IssuesWidget::onFetchRequested);
m_totalRows = new QLabel(Tr::tr("Total rows:"), this);
- QHBoxLayout *bottom = new QHBoxLayout;
- layout->addLayout(bottom);
- bottom->addStretch(1);
- bottom->addWidget(m_totalRows);
+
+ using namespace Layouting;
+ Column {
+ Row { m_typesLayout, st, m_versionStart, m_versionEnd, st },
+ Row { m_addedFilter, m_removedFilter, Space(1), m_ownerFilter, m_pathGlobFilter },
+ m_issuesView,
+ Row { st, m_totalRows }
+ }.attachTo(widget);
+
setWidget(widget);
setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
setWidgetResizable(true);
@@ -355,50 +377,81 @@ void IssuesWidget::updateUi()
if (info.issueKinds.size())
m_currentPrefix = info.issueKinds.front().prefix;
- updateTableView();
+ fetchTable();
}
-void IssuesWidget::setTableDto(const Dto::TableInfoDto &dto)
+static Qt::Alignment alignmentFromString(const QString &str)
{
- m_currentTableInfo.emplace(dto);
+ if (str == "left")
+ return Qt::AlignLeft;
+ if (str == "right")
+ return Qt::AlignRight;
+ if (str == "center")
+ return Qt::AlignHCenter;
+ return Qt::AlignLeft;
+}
+
+void IssuesWidget::updateTable()
+{
+ if (!m_currentTableInfo)
+ return;
- // update issues table layout - for now just simple approach
- TreeModel<> *issuesModel = new TreeModel(this);
QStringList columnHeaders;
QStringList hiddenColumns;
- for (const Dto::ColumnInfoDto &column : dto.columns) {
+ QList<bool> sortableColumns;
+ QList<int> columnWidths;
+ QList<Qt::Alignment> alignments;
+ for (const Dto::ColumnInfoDto &column : m_currentTableInfo->columns) {
columnHeaders << column.header.value_or(column.key);
if (!column.showByDefault)
hiddenColumns << column.key;
+ sortableColumns << column.canSort;
+ columnWidths << column.width;
+ alignments << alignmentFromString(column.alignment);
}
m_addedFilter->setText("0");
m_removedFilter->setText("0");
m_totalRows->setText(Tr::tr("Total rows:"));
- issuesModel->setHeader(columnHeaders);
-
- auto oldModel = m_issuesModel;
- m_issuesModel = issuesModel;
- m_issuesView->setModel(issuesModel);
- delete oldModel;
+ m_issuesModel->clear();
+ m_issuesModel->setHeader(columnHeaders);
+ m_issuesModel->setAlignments(alignments);
+ m_headerView->setSortableColumns(sortableColumns);
+ m_headerView->setColumnWidths(columnWidths);
int counter = 0;
for (const QString &header : std::as_const(columnHeaders))
m_issuesView->setColumnHidden(counter++, hiddenColumns.contains(header));
+ m_headerView->resizeSections(QHeaderView::ResizeToContents);
}
-static Links linksForIssue(const std::map<QString, Dto::Any> &issueRow)
+static QList<LinkWithColumns> linksForIssue(const std::map<QString, Dto::Any> &issueRow,
+ const std::vector<Dto::ColumnInfoDto> &columnInfos)
{
- Links links;
+ QList<LinkWithColumns> links;
auto end = issueRow.end();
- auto findAndAppend = [&links, &issueRow, &end](const QString &path, const QString &line) {
+ auto findColumn = [columnInfos](const QString &columnKey) {
+ int col = 0;
+ for (auto it = columnInfos.cbegin(), end = columnInfos.cend(); it != end; ++it) {
+ if (it->key == columnKey)
+ return col;
+ ++col;
+ }
+ return -1;
+ };
+ auto findAndAppend = [&links, &issueRow, &findColumn, &end](const QString &path,
+ const QString &line) {
+ QList<int> columns;
auto it = issueRow.find(path);
if (it != end) {
Link link{ FilePath::fromUserInput(it->second.getString()) };
+ columns.append(findColumn(it->first));
it = issueRow.find(line);
- if (it != end)
+ if (it != end) {
link.targetLine = it->second.getDouble();
- links.append(link);
+ columns.append(findColumn(it->first));
+ }
+ links.append({link, columns});
}
};
// do these always? or just for their "expected" kind
@@ -411,11 +464,12 @@ static Links linksForIssue(const std::map<QString, Dto::Any> &issueRow)
return links;
}
-void IssuesWidget::addIssues(const Dto::IssueTableDto &dto)
+void IssuesWidget::addIssues(const Dto::IssueTableDto &dto, int startRow)
{
QTC_ASSERT(m_currentTableInfo.has_value(), return);
if (dto.totalRowCount.has_value()) {
m_totalRowCount = dto.totalRowCount.value();
+ m_issuesModel->setExpectedRowCount(m_totalRowCount);
m_totalRows->setText(Tr::tr("Total rows:") + ' ' + QString::number(m_totalRowCount));
}
if (dto.totalAddedCount.has_value())
@@ -425,21 +479,32 @@ void IssuesWidget::addIssues(const Dto::IssueTableDto &dto)
const std::vector<Dto::ColumnInfoDto> &tableColumns = m_currentTableInfo->columns;
const std::vector<std::map<QString, Dto::Any>> &rows = dto.rows;
+ QList<ListItem *> items;
for (const auto &row : rows) {
+ QString id;
QStringList data;
+ QStringList toolTips;
for (const auto &column : tableColumns) {
const auto it = row.find(column.key);
if (it != row.end()) {
QString value = anyToSimpleString(it->second);
- if (column.key == "id")
+ if (column.key == "id") {
value.prepend(m_currentPrefix);
+ id = value;
+ }
+ toolTips << value;
+ if (column.key.toLower().endsWith("path")) {
+ const FilePath fp = FilePath::fromUserInput(value);
+ value = QString("%1 [%2]").arg(fp.fileName(), fp.path());
+ }
data << value;
}
}
- IssueTreeItem *it = new IssueTreeItem(data, data);
- it->setLinks(linksForIssue(row));
- m_issuesModel->rootItem()->appendChild(it);
+ IssueListItem *it = new IssueListItem(startRow++, id, data, toolTips);
+ it->setLinks(linksForIssue(row, tableColumns));
+ items.append(it);
}
+ m_issuesModel->setItems(items);
}
void IssuesWidget::onSearchParameterChanged()
@@ -448,10 +513,9 @@ void IssuesWidget::onSearchParameterChanged()
m_removedFilter->setText("0");
m_totalRows->setText(Tr::tr("Total rows:"));
- m_issuesModel->rootItem()->removeChildren();
+ m_issuesModel->clear();
// new "first" time lookup
m_totalRowCount = 0;
- m_lastRequestedOffset = 0;
IssueListSearch search = searchFromUi();
search.computeTotalRowCount = true;
fetchIssues(search);
@@ -503,7 +567,7 @@ void IssuesWidget::updateBasicProjectInfo(std::optional<Dto::ProjectInfoDto> inf
button->setCheckable(true);
connect(button, &QToolButton::clicked, this, [this, prefix = kind.prefix]{
m_currentPrefix = prefix;
- updateTableView();
+ fetchTable();
});
m_typesButtonGroup->addButton(button, ++buttonId);
m_typesLayout->addWidget(button);
@@ -535,27 +599,6 @@ void IssuesWidget::updateBasicProjectInfo(std::optional<Dto::ProjectInfoDto> inf
m_versionStart->setCurrentIndex(m_versionDates.count() - 1);
}
-void IssuesWidget::updateTableView()
-{
- QTC_ASSERT(!m_currentPrefix.isEmpty(), return);
- // fetch table dto and apply, on done fetch first data for the selected issues
- const auto tableHandler = [this](const Dto::TableInfoDto &dto) { setTableDto(dto); };
- const auto setupHandler = [this](TaskTree *) { m_issuesView->showProgressIndicator(); };
- const auto doneHandler = [this](DoneWith result) {
- if (result == DoneWith::Error) {
- m_issuesView->hideProgressIndicator();
- return;
- }
- // first time lookup... should we cache and maybe represent old data?
- m_totalRowCount = 0;
- m_lastRequestedOffset = 0;
- IssueListSearch search = searchFromUi();
- search.computeTotalRowCount = true;
- fetchIssues(search);
- };
- m_taskTreeRunner.start(tableInfoRecipe(m_currentPrefix, tableHandler), setupHandler, doneHandler);
-}
-
void IssuesWidget::setFiltersEnabled(bool enabled)
{
m_addedFilter->setEnabled(enabled);
@@ -581,143 +624,168 @@ IssueListSearch IssuesWidget::searchFromUi() const
search.state = "added";
else if (m_removedFilter->isChecked())
search.state = "removed";
+ if (int column = m_headerView->currentSortColumn() != -1) {
+ QTC_ASSERT(m_currentTableInfo, return search);
+ QTC_ASSERT((ulong)column < m_currentTableInfo->columns.size(), return search);
+ search.sort = m_currentTableInfo->columns.at(m_headerView->currentSortColumn()).key
+ + (m_headerView->currentSortOrder() == SortOrder::Ascending ? " asc" : " desc");
+ }
+
return search;
}
+void IssuesWidget::fetchTable()
+{
+ QTC_ASSERT(!m_currentPrefix.isEmpty(), return);
+ // fetch table dto and apply, on done fetch first data for the selected issues
+ const auto tableHandler = [this](const Dto::TableInfoDto &dto) {
+ m_currentTableInfo.emplace(dto);
+ };
+ const auto setupHandler = [this](TaskTree *) {
+ m_totalRowCount = 0;
+ m_currentTableInfo.reset();
+ m_issuesView->showProgressIndicator();
+ };
+ const auto doneHandler = [this](DoneWith result) {
+ if (result == DoneWith::Error) {
+ m_issuesView->hideProgressIndicator();
+ return;
+ }
+ // first time lookup... should we cache and maybe represent old data?
+ updateTable();
+ IssueListSearch search = searchFromUi();
+ search.computeTotalRowCount = true;
+ fetchIssues(search);
+ };
+ m_taskTreeRunner.start(tableInfoRecipe(m_currentPrefix, tableHandler), setupHandler, doneHandler);
+}
+
void IssuesWidget::fetchIssues(const IssueListSearch &search)
{
- const auto issuesHandler = [this](const Dto::IssueTableDto &dto) { addIssues(dto); };
+ const auto issuesHandler = [this, startRow = search.offset](const Dto::IssueTableDto &dto) {
+ addIssues(dto, startRow);
+ };
const auto setupHandler = [this](TaskTree *) { m_issuesView->showProgressIndicator(); };
const auto doneHandler = [this](DoneWith) { m_issuesView->hideProgressIndicator(); };
m_taskTreeRunner.start(issueTableRecipe(search, issuesHandler), setupHandler, doneHandler);
}
-void IssuesWidget::fetchMoreIssues()
+void IssuesWidget::onFetchRequested(int startRow, int limit)
{
- if (m_lastRequestedOffset == m_issuesModel->rowCount())
+ if (m_taskTreeRunner.isRunning())
return;
IssueListSearch search = searchFromUi();
- m_lastRequestedOffset = m_issuesModel->rowCount();
- search.offset = m_lastRequestedOffset;
+ search.offset = startRow;
+ search.limit = limit;
fetchIssues(search);
}
-AxivionOutputPane::AxivionOutputPane(QObject *parent)
- : IOutputPane(parent)
+class AxivionOutputPane final : public IOutputPane
{
- setId("Axivion");
- setDisplayName(Tr::tr("Axivion"));
- setPriorityInStatusBar(-50);
-
- m_outputWidget = new QStackedWidget;
- DashboardWidget *dashboardWidget = new DashboardWidget(m_outputWidget);
- m_outputWidget->addWidget(dashboardWidget);
- IssuesWidget *issuesWidget = new IssuesWidget(m_outputWidget);
- m_outputWidget->addWidget(issuesWidget);
- QTextBrowser *browser = new QTextBrowser(m_outputWidget);
- m_outputWidget->addWidget(browser);
-}
-
-AxivionOutputPane::~AxivionOutputPane()
-{
- if (!m_outputWidget->parent())
- delete m_outputWidget;
-}
-
-QWidget *AxivionOutputPane::outputWidget(QWidget *parent)
-{
- if (m_outputWidget)
- m_outputWidget->setParent(parent);
- else
- QTC_CHECK(false);
- return m_outputWidget;
-}
-
-QList<QWidget *> AxivionOutputPane::toolBarWidgets() const
-{
- QList<QWidget *> buttons;
- auto showDashboard = new QToolButton(m_outputWidget);
- showDashboard->setIcon(Icons::HOME_TOOLBAR.icon());
- showDashboard->setToolTip(Tr::tr("Show dashboard"));
- connect(showDashboard, &QToolButton::clicked, this, [this]{
- QTC_ASSERT(m_outputWidget, return);
- m_outputWidget->setCurrentIndex(0);
- });
- buttons.append(showDashboard);
- auto showIssues = new QToolButton(m_outputWidget);
- showIssues->setIcon(Icons::ZOOM_TOOLBAR.icon());
- showIssues->setToolTip(Tr::tr("Search for issues"));
- connect(showIssues, &QToolButton::clicked, this, [this]{
- QTC_ASSERT(m_outputWidget, return);
- m_outputWidget->setCurrentIndex(1);
- if (auto issues = static_cast<IssuesWidget *>(m_outputWidget->widget(1)))
- issues->updateUi();
- });
- buttons.append(showIssues);
- return buttons;
-}
+public:
+ explicit AxivionOutputPane(QObject *parent)
+ : IOutputPane(parent)
+ {
+ setId("Axivion");
+ setDisplayName(Tr::tr("Axivion"));
+ setPriorityInStatusBar(-50);
+
+ m_outputWidget = new QStackedWidget;
+ DashboardWidget *dashboardWidget = new DashboardWidget(m_outputWidget);
+ m_outputWidget->addWidget(dashboardWidget);
+ IssuesWidget *issuesWidget = new IssuesWidget(m_outputWidget);
+ m_outputWidget->addWidget(issuesWidget);
+
+ QPalette pal = m_outputWidget->palette();
+ pal.setColor(QPalette::Window, creatorTheme()->color(Theme::Color::BackgroundColorNormal));
+ m_outputWidget->setPalette(pal);
+
+ m_showDashboard = new QToolButton(m_outputWidget);
+ m_showDashboard->setIcon(Icons::HOME_TOOLBAR.icon());
+ m_showDashboard->setToolTip(Tr::tr("Show dashboard"));
+ m_showDashboard->setCheckable(true);
+ m_showDashboard->setChecked(true);
+ connect(m_showDashboard, &QToolButton::clicked, this, [this] {
+ QTC_ASSERT(m_outputWidget, return);
+ m_outputWidget->setCurrentIndex(0);
+ });
-void AxivionOutputPane::clearContents()
-{
-}
+ m_showIssues = new QToolButton(m_outputWidget);
+ m_showIssues->setIcon(Icons::ZOOM_TOOLBAR.icon());
+ m_showIssues->setToolTip(Tr::tr("Search for issues"));
+ m_showIssues->setCheckable(true);
+ connect(m_showIssues, &QToolButton::clicked, this, [this] {
+ QTC_ASSERT(m_outputWidget, return);
+ m_outputWidget->setCurrentIndex(1);
+ if (auto issues = static_cast<IssuesWidget *>(m_outputWidget->widget(1)))
+ issues->updateUi();
+ });
-void AxivionOutputPane::setFocus()
-{
-}
+ connect(m_outputWidget, &QStackedWidget::currentChanged, this, [this](int idx) {
+ m_showDashboard->setChecked(idx == 0);
+ m_showIssues->setChecked(idx == 1);
+ });
+ }
-bool AxivionOutputPane::hasFocus() const
-{
- return false;
-}
+ ~AxivionOutputPane()
+ {
+ if (!m_outputWidget->parent())
+ delete m_outputWidget;
+ }
-bool AxivionOutputPane::canFocus() const
-{
- return true;
-}
+ QWidget *outputWidget(QWidget *parent) final
+ {
+ if (m_outputWidget)
+ m_outputWidget->setParent(parent);
+ else
+ QTC_CHECK(false);
+ return m_outputWidget;
+ }
-bool AxivionOutputPane::canNavigate() const
-{
- return true;
-}
+ QList<QWidget *> toolBarWidgets() const final
+ {
+ return {m_showDashboard, m_showIssues};
+ }
-bool AxivionOutputPane::canNext() const
-{
- return false;
-}
+ void clearContents() final {}
+ void setFocus() final {}
+ bool hasFocus() const final { return false; }
+ bool canFocus() const final { return true; }
+ bool canNavigate() const final { return true; }
+ bool canNext() const final { return false; }
+ bool canPrevious() const final { return false; }
+ void goToNext() final {}
+ void goToPrev() final {}
+
+ void updateDashboard()
+ {
+ if (auto dashboard = static_cast<DashboardWidget *>(m_outputWidget->widget(0))) {
+ dashboard->updateUi();
+ m_outputWidget->setCurrentIndex(0);
+ if (dashboard->hasProject())
+ flash();
+ }
+ }
-bool AxivionOutputPane::canPrevious() const
-{
- return false;
-}
+private:
+ QStackedWidget *m_outputWidget = nullptr;
+ QToolButton *m_showDashboard = nullptr;
+ QToolButton *m_showIssues = nullptr;
+};
-void AxivionOutputPane::goToNext()
-{
-}
-void AxivionOutputPane::goToPrev()
-{
-}
+static QPointer<AxivionOutputPane> theAxivionOutputPane;
-void AxivionOutputPane::updateDashboard()
+void setupAxivionOutputPane(QObject *guard)
{
- if (auto dashboard = static_cast<DashboardWidget *>(m_outputWidget->widget(0))) {
- dashboard->updateUi();
- m_outputWidget->setCurrentIndex(0);
- if (dashboard->hasProject())
- flash();
- }
+ theAxivionOutputPane = new AxivionOutputPane(guard);
}
-void AxivionOutputPane::updateAndShowRule(const QString &ruleHtml)
+void updateDashboard()
{
- if (auto browser = static_cast<QTextBrowser *>(m_outputWidget->widget(2))) {
- browser->setText(ruleHtml);
- if (!ruleHtml.isEmpty()) {
- m_outputWidget->setCurrentIndex(2);
- popup(IOutputPane::NoModeSwitch);
- }
- }
+ QTC_ASSERT(theAxivionOutputPane, return);
+ theAxivionOutputPane->updateDashboard();
}
} // Axivion::Internal
diff --git a/src/plugins/axivion/axivionoutputpane.h b/src/plugins/axivion/axivionoutputpane.h
index 140d50b723..a13b125c18 100644
--- a/src/plugins/axivion/axivionoutputpane.h
+++ b/src/plugins/axivion/axivionoutputpane.h
@@ -3,38 +3,11 @@
#pragma once
-#include <coreplugin/ioutputpane.h>
-
-QT_BEGIN_NAMESPACE
-class QStackedWidget;
-QT_END_NAMESPACE
+#include <QObject>
namespace Axivion::Internal {
-class AxivionOutputPane : public Core::IOutputPane
-{
- Q_OBJECT
-public:
- explicit AxivionOutputPane(QObject *parent = nullptr);
- ~AxivionOutputPane();
-
- // IOutputPane interface
- QWidget *outputWidget(QWidget *parent) override;
- QList<QWidget *> toolBarWidgets() const override;
- void clearContents() override;
- void setFocus() override;
- bool hasFocus() const override;
- bool canFocus() const override;
- bool canNavigate() const override;
- bool canNext() const override;
- bool canPrevious() const override;
- void goToNext() override;
- void goToPrev() override;
-
- void updateDashboard();
- void updateAndShowRule(const QString &ruleHtml);
-private:
- QStackedWidget *m_outputWidget = nullptr;
-};
+void setupAxivionOutputPane(QObject *guard);
+void updateDashboard();
} // Axivion::Internal
diff --git a/src/plugins/axivion/axivionplugin.cpp b/src/plugins/axivion/axivionplugin.cpp
index 9b333af7c3..c559e2b7d3 100644
--- a/src/plugins/axivion/axivionplugin.cpp
+++ b/src/plugins/axivion/axivionplugin.cpp
@@ -7,13 +7,16 @@
#include "axivionprojectsettings.h"
#include "axivionsettings.h"
#include "axiviontr.h"
+#include "credentialquery.h"
#include "dashboard/dto.h"
#include "dashboard/error.h"
#include <coreplugin/editormanager/documentmodel.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/icore.h>
+#include <coreplugin/inavigationwidgetfactory.h>
#include <coreplugin/messagemanager.h>
+#include <coreplugin/navigationwidget.h>
#include <extensionsystem/iplugin.h>
#include <extensionsystem/pluginmanager.h>
@@ -31,19 +34,26 @@
#include <utils/algorithm.h>
#include <utils/async.h>
+#include <utils/checkablemessagebox.h>
+#include <utils/environment.h>
#include <utils/networkaccessmanager.h>
#include <utils/qtcassert.h>
#include <utils/utilsicons.h>
#include <QAction>
+#include <QDesktopServices>
+#include <QInputDialog>
#include <QMessageBox>
#include <QNetworkAccessManager>
#include <QNetworkReply>
+#include <QTextBrowser>
#include <QTimer>
+#include <QUrlQuery>
#include <memory>
-constexpr char AxivionTextMarkId[] = "AxivionTextMark";
+constexpr char s_axivionTextMarkId[] = "AxivionTextMark";
+constexpr char s_axivionKeychainService[] = "keychain.axivion.qtcreator";
using namespace Core;
using namespace ProjectExplorer;
@@ -96,6 +106,42 @@ QString anyToSimpleString(const Dto::Any &any)
return {};
}
+static QString apiTokenDescription()
+{
+ const QString ua = "Axivion" + QCoreApplication::applicationName() + "Plugin/"
+ + QCoreApplication::applicationVersion();
+ QString user = Utils::qtcEnvironmentVariable("USERNAME");
+ if (user.isEmpty())
+ user = Utils::qtcEnvironmentVariable("USER");
+ return "Automatically created by " + ua + " on " + user + "@" + QSysInfo::machineHostName();
+}
+
+static QString credentialKey()
+{
+ const auto escape = [](const QString &string) {
+ QString escaped = string;
+ return escaped.replace('\\', "\\\\").replace('@', "\\@");
+ };
+ return escape(settings().server.dashboard) + '@' + escape(settings().server.username);
+}
+
+static DashboardInfo toDashboardInfo(const QUrl &source, const Dto::DashboardInfoDto &infoDto)
+{
+ const QVersionNumber versionNumber = infoDto.dashboardVersionNumber
+ ? QVersionNumber::fromString(*infoDto.dashboardVersionNumber) : QVersionNumber();
+
+ QStringList projects;
+ QHash<QString, QUrl> projectUrls;
+
+ if (infoDto.projects) {
+ for (const Dto::ProjectReferenceDto &project : *infoDto.projects) {
+ projects.push_back(project.name);
+ projectUrls.insert(project.name, project.url);
+ }
+ }
+ return {source, versionNumber, projects, projectUrls, infoDto.checkCredentialsUrl};
+}
+
QString IssueListSearch::toQuery() const
{
if (kind.isEmpty())
@@ -118,18 +164,24 @@ QString IssueListSearch::toQuery() const
QString::fromUtf8((QUrl::toPercentEncoding(owner)))));
}
if (!filter_path.isEmpty()) {
- result.append(QString("&filter_path=%1").arg(
+ result.append(QString("&filter_any path=%1").arg(
QString::fromUtf8(QUrl::toPercentEncoding(filter_path))));
}
if (!state.isEmpty())
result.append(QString("&state=%1").arg(state));
if (computeTotalRowCount)
result.append("&computeTotalRowCount=true");
+ if (!sort.isEmpty())
+ result.append(QString("&sort=%1").arg(
+ QString::fromUtf8(QUrl::toPercentEncoding(sort))));
return result;
}
+enum class ServerAccess { Unknown, NoAuthorization, WithAuthorization };
+
class AxivionPluginPrivate : public QObject
{
+ Q_OBJECT
public:
AxivionPluginPrivate();
void handleSslErrors(QNetworkReply *reply, const QList<QSslError> &errors);
@@ -141,9 +193,18 @@ public:
void clearAllMarks();
void handleIssuesForFile(const Dto::FileViewDto &fileView);
void fetchIssueInfo(const QString &id);
+ void setIssueDetails(const QString &issueDetailsHtml);
+ void handleAnchorClicked(const QUrl &url);
+signals:
+ void issueDetailsChanged(const QString &issueDetailsHtml);
+
+public:
+ // TODO: Should be set to Unknown on server address change in settings.
+ ServerAccess m_serverAccess = ServerAccess::Unknown;
+ // TODO: Should be cleared on username change in settings.
+ std::optional<QByteArray> m_apiToken;
NetworkAccessManager m_networkAccessManager;
- AxivionOutputPane m_axivionOutputPane;
std::optional<DashboardInfo> m_dashboardInfo;
std::optional<Dto::ProjectInfoDto> m_currentProjectInfo;
Project *m_project = nullptr;
@@ -158,13 +219,16 @@ static AxivionPluginPrivate *dd = nullptr;
class AxivionTextMark : public TextMark
{
public:
- AxivionTextMark(const FilePath &filePath, const Dto::LineMarkerDto &issue)
- : TextMark(filePath, issue.startLine, {Tr::tr("Axivion"), AxivionTextMarkId})
+ AxivionTextMark(const FilePath &filePath, const Dto::LineMarkerDto &issue,
+ std::optional<Theme::Color> color)
+ : TextMark(filePath, issue.startLine, {"Axivion", s_axivionTextMarkId})
{
const QString markText = issue.description;
const QString id = issue.kind + QString::number(issue.id.value_or(-1));
- setToolTip(id + markText);
+ setToolTip(id + '\n' + markText);
setIcon(iconForIssue(issue.kind));
+ if (color)
+ setColor(*color);
setPriority(TextMark::NormalPriority);
setLineAnnotation(markText);
setActionsProvider([id] {
@@ -247,7 +311,7 @@ void AxivionPluginPrivate::onStartupProjectChanged(Project *project)
m_project = project;
clearAllMarks();
m_currentProjectInfo = {};
- m_axivionOutputPane.updateDashboard();
+ updateDashboard();
if (!m_project)
return;
@@ -259,10 +323,7 @@ void AxivionPluginPrivate::onStartupProjectChanged(Project *project)
static QUrl urlForProject(const QString &projectName)
{
- QString dashboard = settings().server.dashboard;
- if (!dashboard.endsWith(QLatin1Char('/')))
- dashboard += QLatin1Char('/');
- return QUrl(dashboard).resolved(QStringLiteral("api/projects/")).resolved(projectName);
+ return QUrl(settings().server.dashboard).resolved(QString("api/projects/")).resolved(projectName);
}
static constexpr int httpStatusCodeOk = 200;
@@ -271,28 +332,22 @@ constexpr char s_jsonContentType[] = "application/json";
static Group fetchHtmlRecipe(const QUrl &url, const std::function<void(const QByteArray &)> &handler)
{
- struct StorageData
- {
- QByteArray credentials;
- };
-
- const Storage<StorageData> storage;
-
- const auto onCredentialSetup = [storage] {
- storage->credentials = QByteArrayLiteral("AxToken ") + settings().server.token.toUtf8();
- };
+ // TODO: Refactor so that it's a common code with fetchDataRecipe().
+ const auto onQuerySetup = [url](NetworkQuery &query) {
+ if (dd->m_serverAccess == ServerAccess::Unknown)
+ return SetupResult::StopWithError; // TODO: start authorizationRecipe()?
- const auto onQuerySetup = [storage, url](NetworkQuery &query) {
QNetworkRequest request(url);
request.setRawHeader("Accept", s_htmlContentType);
- request.setRawHeader("Authorization", storage->credentials);
+ if (dd->m_serverAccess == ServerAccess::WithAuthorization && dd->m_apiToken)
+ request.setRawHeader("Authorization", "AxToken " + *dd->m_apiToken);
const QByteArray ua = "Axivion" + QCoreApplication::applicationName().toUtf8() +
"Plugin/" + QCoreApplication::applicationVersion().toUtf8();
request.setRawHeader("X-Axivion-User-Agent", ua);
query.setRequest(request);
query.setNetworkAccessManager(&dd->m_networkAccessManager);
+ return SetupResult::Continue;
};
-
const auto onQueryDone = [url, handler](const NetworkQuery &query, DoneWith doneWith) {
QNetworkReply *reply = query.reply();
const int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
@@ -309,36 +364,48 @@ static Group fetchHtmlRecipe(const QUrl &url, const std::function<void(const QBy
}
return DoneResult::Error;
};
-
- const Group recipe {
- storage,
- Sync(onCredentialSetup),
- NetworkQueryTask(onQuerySetup, onQueryDone),
- };
-
- return recipe;
+ return {NetworkQueryTask(onQuerySetup, onQueryDone)};
}
template <typename DtoType>
struct GetDtoStorage
{
- QByteArray credential;
QUrl url;
+ std::optional<QByteArray> credential;
std::optional<DtoType> dtoData;
};
template <typename DtoType>
-static Group getDtoRecipe(const Storage<GetDtoStorage<DtoType>> &dtoStorage)
+struct PostDtoStorage
+{
+ QUrl url;
+ std::optional<QByteArray> credential;
+ QByteArray csrfToken;
+ QByteArray writeData;
+ std::optional<DtoType> dtoData;
+};
+
+template <typename DtoType, template <typename> typename DtoStorageType>
+static Group dtoRecipe(const Storage<DtoStorageType<DtoType>> &dtoStorage)
{
const Storage<QByteArray> storage;
const auto onNetworkQuerySetup = [dtoStorage](NetworkQuery &query) {
QNetworkRequest request(dtoStorage->url);
request.setRawHeader("Accept", s_jsonContentType);
- request.setRawHeader("Authorization", dtoStorage->credential);
+ if (dtoStorage->credential) // Unauthorized access otherwise
+ request.setRawHeader("Authorization", *dtoStorage->credential);
const QByteArray ua = "Axivion" + QCoreApplication::applicationName().toUtf8() +
"Plugin/" + QCoreApplication::applicationVersion().toUtf8();
request.setRawHeader("X-Axivion-User-Agent", ua);
+
+ if constexpr (std::is_same_v<DtoStorageType<DtoType>, PostDtoStorage<DtoType>>) {
+ request.setRawHeader("Content-Type", "application/json");
+ request.setRawHeader("AX-CSRF-Token", dtoStorage->csrfToken);
+ query.setWriteData(dtoStorage->writeData);
+ query.setOperation(NetworkOperation::Post);
+ }
+
query.setRequest(request);
query.setNetworkAccessManager(&dd->m_networkAccessManager);
};
@@ -376,164 +443,220 @@ static Group getDtoRecipe(const Storage<GetDtoStorage<DtoType>> &dtoStorage)
}
return NetworkError(reply->url(), error, reply->errorString());
};
-
- MessageManager::writeFlashing(QStringLiteral("Axivion: %1").arg(getError().message()));
+ MessageManager::writeDisrupting(QString("Axivion: %1").arg(getError().message()));
return DoneResult::Error;
};
- const auto onDeserializeSetup = [storage](Async<DtoType> &task) {
- const auto deserialize = [](QPromise<DtoType> &promise, const QByteArray &input) {
- promise.addResult(DtoType::deserialize(input));
+ const auto onDeserializeSetup = [storage](Async<expected_str<DtoType>> &task) {
+ const auto deserialize = [](QPromise<expected_str<DtoType>> &promise, const QByteArray &input) {
+ promise.addResult(DtoType::deserializeExpected(input));
};
task.setFutureSynchronizer(ExtensionSystem::PluginManager::futureSynchronizer());
task.setConcurrentCallData(deserialize, *storage);
};
- const auto onDeserializeDone = [dtoStorage](const Async<DtoType> &task, DoneWith doneWith) {
- if (doneWith == DoneWith::Success)
- dtoStorage->dtoData = task.future().result();
+ const auto onDeserializeDone = [dtoStorage](const Async<expected_str<DtoType>> &task,
+ DoneWith doneWith) {
+ if (doneWith == DoneWith::Success && task.isResultAvailable()) {
+ const auto result = task.result();
+ if (result) {
+ dtoStorage->dtoData = *result;
+ return DoneResult::Success;
+ }
+ MessageManager::writeFlashing(QString("Axivion: %1").arg(result.error()));
+ } else {
+ MessageManager::writeFlashing(QString("Axivion: %1")
+ .arg(Tr::tr("Unknown Dto structure deserialization error.")));
+ }
+ return DoneResult::Error;
};
- const Group recipe {
+ return {
storage,
NetworkQueryTask(onNetworkQuerySetup, onNetworkQueryDone),
- AsyncTask<DtoType>(onDeserializeSetup, onDeserializeDone)
+ AsyncTask<expected_str<DtoType>>(onDeserializeSetup, onDeserializeDone)
};
- return recipe;
-};
+}
-template <typename DtoType>
-struct PostDtoStorage
+static QString credentialOperationMessage(CredentialOperation operation)
{
- QByteArray credential;
- QUrl url;
- QByteArray csrfToken;
- QByteArray writeData;
- std::optional<DtoType> dtoData;
-};
+ switch (operation) {
+ case CredentialOperation::Get:
+ return Tr::tr("The ApiToken cannot be read in a secure way.");
+ case CredentialOperation::Set:
+ return Tr::tr("The ApiToken cannot be stored in a secure way.");
+ case CredentialOperation::Delete:
+ return Tr::tr("The ApiToken cannot be deleted in a secure way.");
+ }
+ return {};
+}
-template <typename DtoType>
-static Group postDtoRecipe(const Storage<PostDtoStorage<DtoType>> &dtoStorage)
+static void handleCredentialError(const CredentialQuery &credential)
{
- const Storage<QByteArray> storage;
+ const QString keyChainMessage = credential.errorString().isEmpty() ? QString()
+ : QString(" %1").arg(Tr::tr("Key chain message: \"%1\".").arg(credential.errorString()));
+ MessageManager::writeFlashing(QString("Axivion: %1")
+ .arg(credentialOperationMessage(credential.operation()) + keyChainMessage));
+}
- const auto onNetworkQuerySetup = [dtoStorage](NetworkQuery &query) {
- QNetworkRequest request(dtoStorage->url);
- request.setRawHeader("Accept", s_jsonContentType);
- request.setRawHeader("Authorization", dtoStorage->credential);
- const QByteArray ua = "Axivion" + QCoreApplication::applicationName().toUtf8() +
- "Plugin/" + QCoreApplication::applicationVersion().toUtf8();
- request.setRawHeader("X-Axivion-User-Agent", ua);
- request.setRawHeader("AX-CSRF-Token", dtoStorage->csrfToken);
- query.setRequest(request);
- query.setWriteData(dtoStorage->writeData);
- query.setOperation(NetworkOperation::Post);
- query.setNetworkAccessManager(&dd->m_networkAccessManager);
- };
+static Group authorizationRecipe()
+{
+ const Storage<GetDtoStorage<Dto::DashboardInfoDto>> unauthorizedDashboardStorage;
+ const auto onUnauthorizedGroupSetup = [unauthorizedDashboardStorage] {
+ if (dd->m_serverAccess != ServerAccess::NoAuthorization)
+ return SetupResult::StopWithSuccess;
- const auto onNetworkQueryDone = [storage](const NetworkQuery &query, DoneWith doneWith) {
- QNetworkReply *reply = query.reply();
- const QNetworkReply::NetworkError error = reply->error();
- const int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
- const QString contentType = reply->header(QNetworkRequest::ContentTypeHeader)
- .toString()
- .split(';')
- .constFirst()
- .trimmed()
- .toLower();
- if (doneWith == DoneWith::Success && statusCode == httpStatusCodeOk
- && contentType == s_jsonContentType) {
- *storage = reply->readAll();
- return DoneResult::Success;
+ unauthorizedDashboardStorage->url = QUrl(settings().server.dashboard);
+ return SetupResult::Continue;
+ };
+ const auto onUnauthorizedGroupDone = [unauthorizedDashboardStorage] {
+ if (unauthorizedDashboardStorage->dtoData) {
+ dd->m_serverAccess = ServerAccess::NoAuthorization;
+ dd->m_dashboardInfo = toDashboardInfo(settings().server.dashboard,
+ *unauthorizedDashboardStorage->dtoData);
+ } else {
+ dd->m_serverAccess = ServerAccess::WithAuthorization;
}
+ return DoneResult::Success;
+ };
- const auto getError = [&]() -> Error {
- if (contentType == s_jsonContentType) {
- try {
- return DashboardError(reply->url(), statusCode,
- reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString(),
- Dto::ErrorDto::deserialize(reply->readAll()));
- } catch (const Dto::invalid_dto_exception &) {
- // ignore
- }
- }
- if (statusCode != 0) {
- return HttpError(reply->url(), statusCode,
- reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString(),
- QString::fromUtf8(reply->readAll())); // encoding?
- }
- return NetworkError(reply->url(), error, reply->errorString());
- };
+ const auto onCredentialLoopCondition = [](int) {
+ return dd->m_serverAccess == ServerAccess::WithAuthorization && !dd->m_apiToken;
+ };
+ const auto onGetCredentialSetup = [](CredentialQuery &credential) {
+ credential.setOperation(CredentialOperation::Get);
+ credential.setService(s_axivionKeychainService);
+ credential.setKey(credentialKey());
+ };
+ const auto onGetCredentialDone = [](const CredentialQuery &credential, DoneWith result) {
+ if (result == DoneWith::Success)
+ dd->m_apiToken = credential.data();
+ else
+ handleCredentialError(credential);
+ // TODO: In case of an error we are multiplying the ApiTokens on Axivion server for each
+ // Creator run, but at least things should continue to work OK in the current session.
+ return DoneResult::Success;
+ };
- MessageManager::writeFlashing(QStringLiteral("Axivion: %1").arg(getError().message()));
- return DoneResult::Error;
+ const Storage<QString> passwordStorage;
+ const Storage<GetDtoStorage<Dto::DashboardInfoDto>> dashboardStorage;
+ const auto onDashboardGroupSetup = [passwordStorage, dashboardStorage] {
+ if (dd->m_apiToken)
+ return SetupResult::StopWithSuccess;
+
+ bool ok = false;
+ const QString text(Tr::tr("Enter the password for:\nDashboard: %1\nUser: %2")
+ .arg(settings().server.dashboard, settings().server.username));
+ *passwordStorage = QInputDialog::getText(ICore::mainWindow(),
+ Tr::tr("Axivion Server Password"), text, QLineEdit::Password, {}, &ok);
+ if (!ok)
+ return SetupResult::StopWithError;
+
+ const QString credential = settings().server.username + ':' + *passwordStorage;
+ dashboardStorage->credential = "Basic " + credential.toUtf8().toBase64();
+ dashboardStorage->url = QUrl(settings().server.dashboard);
+ return SetupResult::Continue;
};
- const auto onDeserializeSetup = [storage](Async<DtoType> &task) {
- const auto deserialize = [](QPromise<DtoType> &promise, const QByteArray &input) {
- promise.addResult(DtoType::deserialize(input));
- };
- task.setFutureSynchronizer(ExtensionSystem::PluginManager::futureSynchronizer());
- task.setConcurrentCallData(deserialize, *storage);
+ const Storage<PostDtoStorage<Dto::ApiTokenInfoDto>> apiTokenStorage;
+ const auto onApiTokenGroupSetup = [passwordStorage, dashboardStorage, apiTokenStorage] {
+ if (!dashboardStorage->dtoData)
+ return SetupResult::StopWithSuccess;
+
+ dd->m_dashboardInfo = toDashboardInfo(settings().server.dashboard,
+ *dashboardStorage->dtoData);
+
+ const Dto::DashboardInfoDto &dashboardDto = *dashboardStorage->dtoData;
+ if (!dashboardDto.userApiTokenUrl)
+ return SetupResult::StopWithError;
+
+ apiTokenStorage->credential = dashboardStorage->credential;
+ apiTokenStorage->url
+ = QUrl(settings().server.dashboard).resolved(*dashboardDto.userApiTokenUrl);
+ apiTokenStorage->csrfToken = dashboardDto.csrfToken.toUtf8();
+ const Dto::ApiTokenCreationRequestDto requestDto{*passwordStorage, "IdePlugin",
+ apiTokenDescription(), 0};
+ apiTokenStorage->writeData = requestDto.serialize();
+ return SetupResult::Continue;
};
- const auto onDeserializeDone = [dtoStorage](const Async<DtoType> &task, DoneWith doneWith) {
- if (doneWith == DoneWith::Success)
- dtoStorage->dtoData = task.future().result();
+ const auto onSetCredentialSetup = [apiTokenStorage](CredentialQuery &credential) {
+ if (!apiTokenStorage->dtoData || !apiTokenStorage->dtoData->token)
+ return SetupResult::StopWithSuccess;
+
+ dd->m_apiToken = apiTokenStorage->dtoData->token->toUtf8();
+ credential.setOperation(CredentialOperation::Set);
+ credential.setService(s_axivionKeychainService);
+ credential.setKey(credentialKey());
+ credential.setData(*dd->m_apiToken);
+ return SetupResult::Continue;
+ };
+ const auto onSetCredentialDone = [](const CredentialQuery &credential) {
+ handleCredentialError(credential);
+ // TODO: In case of an error we are multiplying the ApiTokens on Axivion server for each
+ // Creator run, but at least things should continue to work OK in the current session.
+ return DoneResult::Success;
};
- const Group recipe {
- storage,
- NetworkQueryTask(onNetworkQuerySetup, onNetworkQueryDone),
- AsyncTask<DtoType>(onDeserializeSetup, onDeserializeDone)
+ return {
+ Group {
+ unauthorizedDashboardStorage,
+ onGroupSetup(onUnauthorizedGroupSetup),
+ dtoRecipe(unauthorizedDashboardStorage),
+ onGroupDone(onUnauthorizedGroupDone)
+ },
+ Group {
+ LoopUntil(onCredentialLoopCondition),
+ CredentialQueryTask(onGetCredentialSetup, onGetCredentialDone),
+ Group {
+ passwordStorage,
+ dashboardStorage,
+ onGroupSetup(onDashboardGroupSetup),
+ Group { // GET DashboardInfoDto
+ finishAllAndSuccess,
+ dtoRecipe(dashboardStorage)
+ },
+ Group { // POST ApiTokenCreationRequestDto, GET ApiTokenInfoDto.
+ apiTokenStorage,
+ onGroupSetup(onApiTokenGroupSetup),
+ dtoRecipe(apiTokenStorage),
+ CredentialQueryTask(onSetCredentialSetup, onSetCredentialDone, CallDoneIf::Error)
+ }
+ }
+ }
};
- return recipe;
-};
+}
template<typename DtoType>
static Group fetchDataRecipe(const QUrl &url, const std::function<void(const DtoType &)> &handler)
{
const Storage<GetDtoStorage<DtoType>> dtoStorage;
- const auto onCredentialSetup = [dtoStorage, url] {
- dtoStorage->credential = QByteArrayLiteral("AxToken ") + settings().server.token.toUtf8();
+ const auto onDtoSetup = [dtoStorage, url] {
+ if (!dd->m_apiToken)
+ return SetupResult::StopWithError;
+
+ dtoStorage->credential = "AxToken " + *dd->m_apiToken;
dtoStorage->url = url;
+ return SetupResult::Continue;
};
-
const auto onDtoDone = [dtoStorage, handler] {
if (dtoStorage->dtoData)
handler(*dtoStorage->dtoData);
};
const Group recipe {
- dtoStorage,
- Sync(onCredentialSetup),
+ authorizationRecipe(),
Group {
- getDtoRecipe(dtoStorage),
+ dtoStorage,
+ onGroupSetup(onDtoSetup),
+ dtoRecipe(dtoStorage),
onGroupDone(onDtoDone)
}
};
-
return recipe;
}
-static DashboardInfo toDashboardInfo(const QUrl &source, const Dto::DashboardInfoDto &infoDto)
-{
- const QVersionNumber versionNumber = infoDto.dashboardVersionNumber
- ? QVersionNumber::fromString(*infoDto.dashboardVersionNumber) : QVersionNumber();
-
- QStringList projects;
- QHash<QString, QUrl> projectUrls;
-
- if (infoDto.projects) {
- for (const Dto::ProjectReferenceDto &project : *infoDto.projects) {
- projects.push_back(project.name);
- projectUrls.insert(project.name, project.url);
- }
- }
- return {source, versionNumber, projects, projectUrls, infoDto.checkCredentialsUrl};
-}
-
Group dashboardInfoRecipe(const DashboardInfoHandler &handler)
{
const auto onSetup = [handler] {
@@ -549,17 +672,15 @@ Group dashboardInfoRecipe(const DashboardInfoHandler &handler)
handler(make_unexpected(QString("Error"))); // TODO: Collect error message in the storage.
};
- const QUrl url(settings().server.dashboard);
-
- const auto resultHandler = [handler, url](const Dto::DashboardInfoDto &data) {
- dd->m_dashboardInfo = toDashboardInfo(url, data);
+ const auto resultHandler = [handler](const Dto::DashboardInfoDto &data) {
+ dd->m_dashboardInfo = toDashboardInfo(settings().server.dashboard, data);
if (handler)
handler(*dd->m_dashboardInfo);
};
const Group root {
onGroupSetup(onSetup), // Stops if cache exists.
- fetchDataRecipe<Dto::DashboardInfoDto>(url, resultHandler),
+ fetchDataRecipe<Dto::DashboardInfoDto>(settings().server.dashboard, resultHandler),
onGroupDone(onDone, CallDoneIf::Error)
};
return root;
@@ -575,7 +696,6 @@ Group issueTableRecipe(const IssueListSearch &search, const IssueTableHandler &h
const QUrl url = urlForProject(dd->m_currentProjectInfo.value().name + '/')
.resolved(QString("issues" + query));
-
return fetchDataRecipe<Dto::IssueTableDto>(url, handler);
}
@@ -594,10 +714,6 @@ Group issueHtmlRecipe(const QString &issueId, const HtmlHandler &handler)
{
QTC_ASSERT(dd->m_currentProjectInfo, return {}); // TODO: Call handler with unexpected?
- QString dashboard = settings().server.dashboard;
- if (!dashboard.endsWith(QLatin1Char('/')))
- dashboard += QLatin1Char('/');
-
const QUrl url = urlForProject(dd->m_currentProjectInfo.value().name + '/')
.resolved(QString("issues/"))
.resolved(QString(issueId + '/'))
@@ -614,21 +730,27 @@ void AxivionPluginPrivate::fetchProjectInfo(const QString &projectName)
clearAllMarks();
if (projectName.isEmpty()) {
m_currentProjectInfo = {};
- m_axivionOutputPane.updateDashboard();
+ updateDashboard();
return;
}
const auto onTaskTreeSetup = [this, projectName](TaskTree &taskTree) {
- if (!m_dashboardInfo)
+ if (!m_dashboardInfo) {
+ MessageManager::writeDisrupting(QString("Axivion: %1")
+ .arg(Tr::tr("Fetching DashboardInfo error.")));
return SetupResult::StopWithError;
+ }
const auto it = m_dashboardInfo->projectUrls.constFind(projectName);
- if (it == m_dashboardInfo->projectUrls.constEnd())
+ if (it == m_dashboardInfo->projectUrls.constEnd()) {
+ MessageManager::writeDisrupting(QString("Axivion: %1")
+ .arg(Tr::tr("The DashboardInfo doesn't contain project \"%1\".").arg(projectName)));
return SetupResult::StopWithError;
+ }
const auto handler = [this](const Dto::ProjectInfoDto &data) {
m_currentProjectInfo = data;
- m_axivionOutputPane.updateDashboard();
+ updateDashboard();
handleOpenedDocs();
};
@@ -661,12 +783,19 @@ void AxivionPluginPrivate::fetchIssueInfo(const QString &id)
const int idx = htmlText.indexOf("<div class=\"ax-issuedetails-table-container\">");
if (idx >= 0)
fixedHtml = "<html><body>" + htmlText.mid(idx);
- dd->m_axivionOutputPane.updateAndShowRule(QString::fromUtf8(fixedHtml));
+
+ NavigationWidget::activateSubWidget("Axivion.Issue", Side::Right);
+ dd->setIssueDetails(QString::fromUtf8(fixedHtml));
};
m_issueInfoRunner.start(issueHtmlRecipe(id, ruleHandler));
}
+void AxivionPluginPrivate::setIssueDetails(const QString &issueDetailsHtml)
+{
+ emit issueDetailsChanged(issueDetailsHtml);
+}
+
void AxivionPluginPrivate::handleOpenedDocs()
{
const QList<IDocument *> openDocuments = DocumentModel::openedDocuments();
@@ -687,7 +816,8 @@ void AxivionPluginPrivate::onDocumentOpened(IDocument *doc)
return;
const FilePath filePath = doc->filePath().relativeChildPath(m_project->projectDirectory());
- QTC_ASSERT(!filePath.isEmpty(), return);
+ if (filePath.isEmpty())
+ return; // Empty is fine
const auto handler = [this](const Dto::FileViewDto &data) {
if (data.lineMarkers.empty())
@@ -718,7 +848,7 @@ void AxivionPluginPrivate::onDocumentClosed(IDocument *doc)
const TextMarks &marks = document->marks();
for (TextMark *mark : marks) {
- if (mark->category().id == AxivionTextMarkId)
+ if (mark->category().id == s_axivionTextMarkId)
delete mark;
}
}
@@ -733,13 +863,74 @@ void AxivionPluginPrivate::handleIssuesForFile(const Dto::FileViewDto &fileView)
return;
const FilePath filePath = project->projectDirectory().pathAppended(fileView.fileName);
-
+ std::optional<Theme::Color> color = std::nullopt;
+ if (settings().highlightMarks())
+ color.emplace(Theme::Color(Theme::Bookmarks_TextMarkColor)); // FIXME!
for (const Dto::LineMarkerDto &marker : std::as_const(fileView.lineMarkers)) {
// FIXME the line location can be wrong (even the whole issue could be wrong)
// depending on whether this line has been changed since the last axivion run and the
// current state of the file - some magic has to happen here
- new AxivionTextMark(filePath, marker);
+ new AxivionTextMark(filePath, marker, color);
+ }
+}
+
+void AxivionPluginPrivate::handleAnchorClicked(const QUrl &url)
+{
+ QTC_ASSERT(dd, return);
+ QTC_ASSERT(dd->m_project, return);
+ if (!url.scheme().isEmpty()) {
+ const QString detail = Tr::tr("The activated link appears to be external.\n"
+ "Do you want to open \"%1\" with its default application?")
+ .arg(url.toString());
+ const QMessageBox::StandardButton pressed
+ = CheckableMessageBox::question(Core::ICore::dialogParent(),
+ Tr::tr("Open External Links"),
+ detail,
+ Key("AxivionOpenExternalLinks"));
+ if (pressed == QMessageBox::Yes)
+ QDesktopServices::openUrl(url);
+ return;
+ }
+ const QUrlQuery query(url);
+ if (query.isEmpty())
+ return;
+ Link link;
+ if (const QString path = query.queryItemValue("filename", QUrl::FullyDecoded); !path.isEmpty())
+ link.targetFilePath = m_project->projectDirectory().pathAppended(path);
+ if (const QString line = query.queryItemValue("line"); !line.isEmpty())
+ link.targetLine = line.toInt();
+ // column entry is wrong - so, ignore it
+ if (link.hasValidTarget() && link.targetFilePath.exists())
+ EditorManager::openEditorAt(link);
+}
+
+class AxivionIssueWidgetFactory final : public INavigationWidgetFactory
+{
+public:
+ AxivionIssueWidgetFactory()
+ {
+ setDisplayName(Tr::tr("Axivion"));
+ setId("Axivion.Issue");
+ setPriority(555);
}
+
+ NavigationView createWidget() final
+ {
+ QTC_ASSERT(dd, return {});
+ QTextBrowser *browser = new QTextBrowser;
+ browser->setOpenLinks(false);
+ NavigationView view;
+ view.widget = browser;
+ connect(dd, &AxivionPluginPrivate::issueDetailsChanged, browser, &QTextBrowser::setHtml);
+ connect(browser, &QTextBrowser::anchorClicked,
+ dd, &AxivionPluginPrivate::handleAnchorClicked);
+ return view;
+ }
+};
+
+void setupAxivionIssueWidgetFactory()
+{
+ static AxivionIssueWidgetFactory issueWidgetFactory;
}
class AxivionPlugin final : public ExtensionSystem::IPlugin
@@ -756,9 +947,12 @@ class AxivionPlugin final : public ExtensionSystem::IPlugin
void initialize() final
{
+ setupAxivionOutputPane(this);
+
dd = new AxivionPluginPrivate;
AxivionProjectSettings::setupProjectPanel();
+ setupAxivionIssueWidgetFactory();
connect(ProjectManager::instance(), &ProjectManager::startupProjectChanged,
dd, &AxivionPluginPrivate::onStartupProjectChanged);
@@ -769,6 +963,12 @@ class AxivionPlugin final : public ExtensionSystem::IPlugin
}
};
+void fetchIssueInfo(const QString &id)
+{
+ QTC_ASSERT(dd, return);
+ dd->fetchIssueInfo(id);
+}
+
} // Axivion::Internal
#include "axivionplugin.moc"
diff --git a/src/plugins/axivion/axivionplugin.h b/src/plugins/axivion/axivionplugin.h
index 1d5245a503..c60aad6e9e 100644
--- a/src/plugins/axivion/axivionplugin.h
+++ b/src/plugins/axivion/axivionplugin.h
@@ -31,6 +31,7 @@ struct IssueListSearch
QString versionEnd;
QString owner;
QString filter_path;
+ QString sort;
int offset = 0;
int limit = 150;
bool computeTotalRowCount = false;
@@ -72,6 +73,7 @@ bool handleCertificateIssue();
QIcon iconForIssue(const QString &prefix);
QString anyToSimpleString(const Dto::Any &any);
+void fetchIssueInfo(const QString &id);
} // Axivion::Internal
diff --git a/src/plugins/axivion/axivionprojectsettings.cpp b/src/plugins/axivion/axivionprojectsettings.cpp
index 14d47eca53..8cd63ba7ac 100644
--- a/src/plugins/axivion/axivionprojectsettings.cpp
+++ b/src/plugins/axivion/axivionprojectsettings.cpp
@@ -14,6 +14,7 @@
#include <solutions/tasking/tasktreerunner.h>
#include <utils/infolabel.h>
+#include <utils/layoutbuilder.h>
#include <utils/qtcassert.h>
#include <QPushButton>
@@ -117,34 +118,33 @@ AxivionProjectSettingsWidget::AxivionProjectSettingsWidget(Project *project)
setUseGlobalSettingsCheckBoxVisible(false);
setUseGlobalSettingsLabelVisible(true);
setGlobalSettingsId("Axivion.Settings.General"); // FIXME move id to constants
- // setup ui
- auto verticalLayout = new QVBoxLayout(this);
- verticalLayout->setContentsMargins(0, 0, 0, 0);
m_linkedProject = new QLabel(this);
- verticalLayout->addWidget(m_linkedProject);
m_dashboardProjects = new QTreeWidget(this);
m_dashboardProjects->setHeaderHidden(true);
m_dashboardProjects->setRootIsDecorated(false);
- verticalLayout->addWidget(new QLabel(Tr::tr("Dashboard projects:")));
- verticalLayout->addWidget(m_dashboardProjects);
m_infoLabel = new InfoLabel(this);
m_infoLabel->setVisible(false);
- verticalLayout->addWidget(m_infoLabel);
- auto horizontalLayout = new QHBoxLayout;
- horizontalLayout->setContentsMargins(0, 0, 0, 0);
m_fetchProjects = new QPushButton(Tr::tr("Fetch Projects"));
- horizontalLayout->addWidget(m_fetchProjects);
+
m_link = new QPushButton(Tr::tr("Link Project"));
m_link->setEnabled(false);
- horizontalLayout->addWidget(m_link);
+
m_unlink = new QPushButton(Tr::tr("Unlink Project"));
m_unlink->setEnabled(false);
- horizontalLayout->addWidget(m_unlink);
- verticalLayout->addLayout(horizontalLayout);
+
+ using namespace Layouting;
+ Column {
+ noMargin,
+ m_linkedProject,
+ Tr::tr("Dashboard projects:"),
+ m_dashboardProjects,
+ m_infoLabel,
+ Row { m_fetchProjects, m_link, m_unlink, st }
+ }.attachTo(this);
connect(m_dashboardProjects, &QTreeWidget::itemSelectionChanged,
this, &AxivionProjectSettingsWidget::updateEnabledStates);
@@ -220,8 +220,7 @@ void AxivionProjectSettingsWidget::updateUi()
void AxivionProjectSettingsWidget::updateEnabledStates()
{
- const bool hasDashboardSettings = !settings().server.dashboard.isEmpty()
- && !settings().server.token.isEmpty();
+ const bool hasDashboardSettings = !settings().server.dashboard.isEmpty();
const bool linked = !m_projectSettings->dashboardProjectName().isEmpty();
const bool linkable = m_dashboardProjects->topLevelItemCount()
&& !m_dashboardProjects->selectedItems().isEmpty();
diff --git a/src/plugins/axivion/axivionsettings.cpp b/src/plugins/axivion/axivionsettings.cpp
index f742f0c562..9b24fa51f0 100644
--- a/src/plugins/axivion/axivionsettings.cpp
+++ b/src/plugins/axivion/axivionsettings.cpp
@@ -10,6 +10,7 @@
#include <utils/id.h>
#include <utils/layoutbuilder.h>
+#include <utils/stringutils.h>
#include <QDialog>
#include <QDialogButtonBox>
@@ -27,8 +28,7 @@ namespace Axivion::Internal {
bool AxivionServer::operator==(const AxivionServer &other) const
{
- return id == other.id && dashboard == other.dashboard && username == other.username
- && description == other.description && token == other.token;
+ return id == other.id && dashboard == other.dashboard && username == other.username;
}
bool AxivionServer::operator!=(const AxivionServer &other) const
@@ -42,11 +42,15 @@ QJsonObject AxivionServer::toJson() const
result.insert("id", id.toString());
result.insert("dashboard", dashboard);
result.insert("username", username);
- result.insert("description", description);
- result.insert("token", token);
return result;
}
+static QString fixUrl(const QString &url)
+{
+ const QString trimmed = Utils::trimBack(url, ' ');
+ return trimmed.endsWith('/') ? trimmed : trimmed + '/';
+}
+
AxivionServer AxivionServer::fromJson(const QJsonObject &json)
{
const AxivionServer invalidServer;
@@ -59,14 +63,7 @@ AxivionServer AxivionServer::fromJson(const QJsonObject &json)
const QJsonValue username = json.value("username");
if (username == QJsonValue::Undefined)
return invalidServer;
- const QJsonValue description = json.value("description");
- if (description == QJsonValue::Undefined)
- return invalidServer;
- const QJsonValue token = json.value("token");
- if (token == QJsonValue::Undefined)
- return invalidServer;
- return {Id::fromString(id.toString()), dashboard.toString(), username.toString(),
- description.toString(), token.toString()};
+ return {Id::fromString(id.toString()), fixUrl(dashboard.toString()), username.toString()};
}
static FilePath tokensFilePath()
@@ -109,6 +106,10 @@ AxivionSettings::AxivionSettings()
{
setSettingsGroup("Axivion");
+ highlightMarks.setSettingsKey("HighlightMarks");
+ highlightMarks.setLabelText(Tr::tr("Highlight marks"));
+ highlightMarks.setToolTip(Tr::tr("Marks issues on the scroll bar."));
+ highlightMarks.setDefaultValue(false);
AspectContainer::readSettings();
server = readTokenFile(tokensFilePath());
@@ -161,8 +162,6 @@ private:
Id m_id;
StringAspect m_dashboardUrl;
StringAspect m_username;
- StringAspect m_description;
- StringAspect m_token;
BoolAspect m_valid;
};
@@ -181,23 +180,12 @@ DashboardSettingsWidget::DashboardSettingsWidget(Mode mode, QWidget *parent, QPu
m_username.setDisplayStyle(labelStyle);
m_username.setPlaceHolderText(Tr::tr("User name"));
- m_description.setLabelText(Tr::tr("Description:"));
- m_description.setDisplayStyle(labelStyle);
- m_description.setPlaceHolderText(Tr::tr("Non-empty description"));
-
- m_token.setLabelText(Tr::tr("Access token:"));
- m_token.setDisplayStyle(labelStyle);
- m_token.setPlaceHolderText(Tr::tr("IDE Access Token"));
- m_token.setVisible(mode == Edit);
-
using namespace Layouting;
Form {
m_dashboardUrl, br,
m_username, br,
- m_description, br,
- m_token, br,
- mode == Edit ? normalMargin : noMargin
+ noMargin
}.attachTo(this);
if (mode == Edit) {
@@ -208,8 +196,6 @@ DashboardSettingsWidget::DashboardSettingsWidget(Mode mode, QWidget *parent, QPu
};
connect(&m_dashboardUrl, &BaseAspect::changed, this, checkValidity);
connect(&m_username, &BaseAspect::changed, this, checkValidity);
- connect(&m_description, &BaseAspect::changed, this, checkValidity);
- connect(&m_token, &BaseAspect::changed, this, checkValidity);
}
}
@@ -220,10 +206,8 @@ AxivionServer DashboardSettingsWidget::dashboardServer() const
result.id = m_id;
else
result.id = m_mode == Edit ? Id::fromName(QUuid::createUuid().toByteArray()) : m_id;
- result.dashboard = m_dashboardUrl();
+ result.dashboard = fixUrl(m_dashboardUrl());
result.username = m_username();
- result.description = m_description();
- result.token = m_token();
return result;
}
@@ -232,13 +216,11 @@ void DashboardSettingsWidget::setDashboardServer(const AxivionServer &server)
m_id = server.id;
m_dashboardUrl.setValue(server.dashboard);
m_username.setValue(server.username);
- m_description.setValue(server.description);
- m_token.setValue(server.token);
}
bool DashboardSettingsWidget::isValid() const
{
- return !m_token().isEmpty() && !m_description().isEmpty() && isUrlValid(m_dashboardUrl());
+ return isUrlValid(m_dashboardUrl());
}
class AxivionSettingsWidget : public IOptionsPageWidget
@@ -262,10 +244,15 @@ AxivionSettingsWidget::AxivionSettingsWidget()
m_dashboardDisplay = new DashboardSettingsWidget(DashboardSettingsWidget::Display, this);
m_dashboardDisplay->setDashboardServer(settings().server);
m_edit = new QPushButton(Tr::tr("Edit..."), this);
- Row {
- Form {
- m_dashboardDisplay, br,
- }, Column { m_edit, st }
+ Column {
+ Row {
+ Form {
+ m_dashboardDisplay, br
+ }, st,
+ Column { m_edit },
+ },
+ Space(10), br,
+ Row { settings().highlightMarks }, st
}.attachTo(this);
connect(m_edit, &QPushButton::clicked, this, &AxivionSettingsWidget::showEditServerDialog);
diff --git a/src/plugins/axivion/axivionsettings.h b/src/plugins/axivion/axivionsettings.h
index 00a9384381..257b4056c5 100644
--- a/src/plugins/axivion/axivionsettings.h
+++ b/src/plugins/axivion/axivionsettings.h
@@ -26,8 +26,6 @@ public:
Utils::Id id;
QString dashboard;
QString username;
- QString description;
- QString token;
bool validateCert = true;
};
@@ -40,6 +38,7 @@ public:
void toSettings() const;
AxivionServer server; // shall we have more than one?
+ Utils::BoolAspect highlightMarks{this};
};
AxivionSettings &settings();
diff --git a/src/plugins/axivion/axiviontr.h b/src/plugins/axivion/axiviontr.h
index 1f3475cb45..48798aaa2a 100644
--- a/src/plugins/axivion/axiviontr.h
+++ b/src/plugins/axivion/axiviontr.h
@@ -9,7 +9,7 @@ namespace Axivion {
struct Tr
{
- Q_DECLARE_TR_FUNCTIONS(Axivion)
+ Q_DECLARE_TR_FUNCTIONS(QtC::Axivion)
};
} // Axivion
diff --git a/src/plugins/axivion/credentialquery.cpp b/src/plugins/axivion/credentialquery.cpp
index 7393845819..14aabc3958 100644
--- a/src/plugins/axivion/credentialquery.cpp
+++ b/src/plugins/axivion/credentialquery.cpp
@@ -24,7 +24,8 @@ void CredentialQueryTaskAdapter::start()
}
case CredentialOperation::Set: {
WritePasswordJob *writer = new WritePasswordJob(task()->m_service);
- writer->setBinaryData(task()->m_data);
+ if (task()->m_data)
+ writer->setBinaryData(*task()->m_data);
job = writer;
break;
}
@@ -38,11 +39,12 @@ void CredentialQueryTaskAdapter::start()
m_guard.reset(job);
connect(job, &Job::finished, this, [this, reader](Job *job) {
- if (job->error() != NoError)
+ const bool success = job->error() == NoError || job->error() == EntryNotFound;
+ if (!success)
task()->m_errorString = job->errorString();
- else if (reader)
+ else if (reader && job->error() == NoError)
task()->m_data = reader->binaryData();
- emit done(toDoneResult(job->error() == NoError));
+ emit done(toDoneResult(success));
m_guard.release()->deleteLater();
});
job->start();
diff --git a/src/plugins/axivion/credentialquery.h b/src/plugins/axivion/credentialquery.h
index 6440cd5104..b5ea338c3b 100644
--- a/src/plugins/axivion/credentialquery.h
+++ b/src/plugins/axivion/credentialquery.h
@@ -17,14 +17,15 @@ public:
void setKey(const QString &key) { m_key = key; }
void setData(const QByteArray &data) { m_data = data; }
- QByteArray data() const { return m_data; }
+ CredentialOperation operation() const { return m_operation; }
+ std::optional<QByteArray> data() const { return m_data; }
QString errorString() const { return m_errorString; }
private:
CredentialOperation m_operation = CredentialOperation::Get;
QString m_service;
QString m_key;
- QByteArray m_data; // Used for input when Set and for output when Get.
+ std::optional<QByteArray> m_data; // Used for input when Set and for output when Get.
QString m_errorString;
friend class CredentialQueryTaskAdapter;
};
diff --git a/src/plugins/axivion/dashboard/dto.cpp b/src/plugins/axivion/dashboard/dto.cpp
index 11494e67ae..747ea2d03d 100644
--- a/src/plugins/axivion/dashboard/dto.cpp
+++ b/src/plugins/axivion/dashboard/dto.cpp
@@ -77,7 +77,8 @@ namespace Axivion::Internal::Dto {
// throws Axivion::Internal::Dto::invalid_dto_exception
template<typename T>
- [[noreturn]] static void throw_json_type_conversion(QJsonValue::Type type) {
+ [[noreturn]] static void throw_json_type_conversion(QJsonValue::Type type)
+ {
throw_invalid_dto_exception<T>(concat({
"Error parsing JSON: Cannot convert type ",
to_std_string(type)
@@ -86,7 +87,8 @@ namespace Axivion::Internal::Dto {
// throws Axivion::Internal::Dto::invalid_dto_exception
template<typename T, typename V>
- [[noreturn]] static void throw_json_value_conversion(const V &raw_value) {
+ [[noreturn]] static void throw_json_value_conversion(const V &raw_value)
+ {
throw_invalid_dto_exception<T>(concat({
"Error parsing JSON: Cannot convert raw value ",
to_std_string(raw_value)
@@ -127,6 +129,26 @@ namespace Axivion::Internal::Dto {
return de_serializer<T>::deserialize(json);
}
+ template<typename T>
+ static Utils::expected_str<T> deserializeExp(const QByteArray &json)
+ {
+ try {
+ return T::deserialize(json);
+ } catch (const Dto::invalid_dto_exception &e) {
+ return Utils::make_unexpected(QString::fromUtf8(e.what()));
+ }
+ }
+
+ template<typename M, typename R = std::invoke_result_t<decltype(&M::strToEnum), QAnyStringView>>
+ static std::optional<R> strToOptionalEn(QAnyStringView str)
+ {
+ try {
+ return M::strToEnum(str);
+ } catch (const std::range_error &) {
+ return std::nullopt;
+ }
+ }
+
// throws Axivion::Internal::Dto::invalid_dto_exception
template<typename T>
static T deserialize_bytes(const QByteArray &json)
@@ -158,6 +180,7 @@ namespace Axivion::Internal::Dto {
return de_serializer<T>::serialize(value);
}
+ // throws std::domain_error
template<typename T>
static QByteArray serialize_bytes(const T &value)
{
@@ -522,7 +545,8 @@ namespace Axivion::Internal::Dto {
}));
}
- static QJsonValue serialize(const Any &value) {
+ static QJsonValue serialize(const Any &value)
+ {
if (value.isNull())
return serialize_json(nullptr);
if (value.isString())
@@ -548,6 +572,11 @@ namespace Axivion::Internal::Dto {
return deserialize_bytes<Any>(json);
}
+ Utils::expected_str<Any> Any::deserializeExpected(const QByteArray &json)
+ {
+ return deserializeExp<Any>(json);
+ }
+
Any::Any() {}
Any::Any(QString value) : data(std::move(value)) {}
@@ -647,10 +676,10 @@ namespace Axivion::Internal::Dto {
// version
- constexpr std::array<qint32, 4> ApiVersion::number{7,7,2,13780};
- const QLatin1String ApiVersion::string{"7.7.2.13780"};
- const QLatin1String ApiVersion::name{"7.7.2"};
- const QLatin1String ApiVersion::timestamp{"2024-01-10 07:39:35 +00:00"};
+ constexpr std::array<qint32, 4> ApiVersion::number{7,7,3,3857};
+ const QLatin1String ApiVersion::string{"7.7.3.13857"};
+ const QLatin1String ApiVersion::name{"7.7.3"};
+ const QLatin1String ApiVersion::timestamp{"2024-02-07 09:28:43 +00:00"};
// AnalyzedFileDto
@@ -663,7 +692,8 @@ namespace Axivion::Internal::Dto {
{
public:
// throws Axivion::Internal::Dto::invalid_dto_exception
- static AnalyzedFileDto deserialize(const QJsonValue &json) {
+ static AnalyzedFileDto deserialize(const QJsonValue &json)
+ {
const QJsonObject jo = toJsonObject<AnalyzedFileDto>(json);
return {
deserialize_field<QString>(jo, analyzedFileKeyPath),
@@ -672,7 +702,8 @@ namespace Axivion::Internal::Dto {
};
}
- static QJsonValue serialize(const AnalyzedFileDto &value) {
+ static QJsonValue serialize(const AnalyzedFileDto &value)
+ {
QJsonObject jo;
serialize_field(jo, analyzedFileKeyPath, value.path);
serialize_field(jo, analyzedFileKeyIsSystemHeader, value.isSystemHeader);
@@ -690,6 +721,11 @@ namespace Axivion::Internal::Dto {
return deserialize_bytes<AnalyzedFileDto>(json);
}
+ Utils::expected_str<AnalyzedFileDto> AnalyzedFileDto::deserializeExpected(const QByteArray &json)
+ {
+ return deserializeExp<AnalyzedFileDto>(json);
+ }
+
AnalyzedFileDto::AnalyzedFileDto(
QString path,
std::optional<bool> isSystemHeader,
@@ -700,7 +736,6 @@ namespace Axivion::Internal::Dto {
languageName(std::move(languageName))
{ }
- // throws Axivion::Internal::Dto::invalid_dto_exception
QByteArray AnalyzedFileDto::serialize() const
{
return serialize_bytes(*this);
@@ -740,6 +775,11 @@ namespace Axivion::Internal::Dto {
throw std::range_error(concat({ "Unknown ApiTokenType str: ", to_std_string(str) }));
}
+ std::optional<ApiTokenType> ApiTokenTypeMeta::strToOptionalEnum(QAnyStringView str)
+ {
+ return strToOptionalEn<ApiTokenTypeMeta>(str);
+ }
+
QLatin1String ApiTokenTypeMeta::enumToStr(ApiTokenType e)
{
switch (e)
@@ -772,7 +812,8 @@ namespace Axivion::Internal::Dto {
{
public:
// throws Axivion::Internal::Dto::invalid_dto_exception
- static ChangePasswordFormDto deserialize(const QJsonValue &json) {
+ static ChangePasswordFormDto deserialize(const QJsonValue &json)
+ {
const QJsonObject jo = toJsonObject<ChangePasswordFormDto>(json);
return {
deserialize_field<QString>(jo, changePasswordFormKeyCurrentPassword),
@@ -780,7 +821,8 @@ namespace Axivion::Internal::Dto {
};
}
- static QJsonValue serialize(const ChangePasswordFormDto &value) {
+ static QJsonValue serialize(const ChangePasswordFormDto &value)
+ {
QJsonObject jo;
serialize_field(jo, changePasswordFormKeyCurrentPassword, value.currentPassword);
serialize_field(jo, changePasswordFormKeyNewPassword, value.newPassword);
@@ -797,6 +839,11 @@ namespace Axivion::Internal::Dto {
return deserialize_bytes<ChangePasswordFormDto>(json);
}
+ Utils::expected_str<ChangePasswordFormDto> ChangePasswordFormDto::deserializeExpected(const QByteArray &json)
+ {
+ return deserializeExp<ChangePasswordFormDto>(json);
+ }
+
ChangePasswordFormDto::ChangePasswordFormDto(
QString currentPassword,
QString newPassword
@@ -805,7 +852,6 @@ namespace Axivion::Internal::Dto {
newPassword(std::move(newPassword))
{ }
- // throws Axivion::Internal::Dto::invalid_dto_exception
QByteArray ChangePasswordFormDto::serialize() const
{
return serialize_bytes(*this);
@@ -860,6 +906,11 @@ namespace Axivion::Internal::Dto {
throw std::range_error(concat({ "Unknown ColumnType str: ", to_std_string(str) }));
}
+ std::optional<ColumnType> ColumnTypeMeta::strToOptionalEnum(QAnyStringView str)
+ {
+ return strToOptionalEn<ColumnTypeMeta>(str);
+ }
+
QLatin1String ColumnTypeMeta::enumToStr(ColumnType e)
{
switch (e)
@@ -899,7 +950,8 @@ namespace Axivion::Internal::Dto {
{
public:
// throws Axivion::Internal::Dto::invalid_dto_exception
- static ColumnTypeOptionDto deserialize(const QJsonValue &json) {
+ static ColumnTypeOptionDto deserialize(const QJsonValue &json)
+ {
const QJsonObject jo = toJsonObject<ColumnTypeOptionDto>(json);
return {
deserialize_field<QString>(jo, columnTypeOptionKeyKey),
@@ -908,7 +960,8 @@ namespace Axivion::Internal::Dto {
};
}
- static QJsonValue serialize(const ColumnTypeOptionDto &value) {
+ static QJsonValue serialize(const ColumnTypeOptionDto &value)
+ {
QJsonObject jo;
serialize_field(jo, columnTypeOptionKeyKey, value.key);
serialize_field(jo, columnTypeOptionKeyDisplayName, value.displayName);
@@ -926,6 +979,11 @@ namespace Axivion::Internal::Dto {
return deserialize_bytes<ColumnTypeOptionDto>(json);
}
+ Utils::expected_str<ColumnTypeOptionDto> ColumnTypeOptionDto::deserializeExpected(const QByteArray &json)
+ {
+ return deserializeExp<ColumnTypeOptionDto>(json);
+ }
+
ColumnTypeOptionDto::ColumnTypeOptionDto(
QString key,
std::optional<QString> displayName,
@@ -936,7 +994,6 @@ namespace Axivion::Internal::Dto {
displayColor(std::move(displayColor))
{ }
- // throws Axivion::Internal::Dto::invalid_dto_exception
QByteArray ColumnTypeOptionDto::serialize() const
{
return serialize_bytes(*this);
@@ -951,14 +1008,16 @@ namespace Axivion::Internal::Dto {
{
public:
// throws Axivion::Internal::Dto::invalid_dto_exception
- static CommentRequestDto deserialize(const QJsonValue &json) {
+ static CommentRequestDto deserialize(const QJsonValue &json)
+ {
const QJsonObject jo = toJsonObject<CommentRequestDto>(json);
return {
deserialize_field<QString>(jo, commentRequestKeyText)
};
}
- static QJsonValue serialize(const CommentRequestDto &value) {
+ static QJsonValue serialize(const CommentRequestDto &value)
+ {
QJsonObject jo;
serialize_field(jo, commentRequestKeyText, value.text);
return { jo };
@@ -974,13 +1033,17 @@ namespace Axivion::Internal::Dto {
return deserialize_bytes<CommentRequestDto>(json);
}
+ Utils::expected_str<CommentRequestDto> CommentRequestDto::deserializeExpected(const QByteArray &json)
+ {
+ return deserializeExp<CommentRequestDto>(json);
+ }
+
CommentRequestDto::CommentRequestDto(
QString text
) :
text(std::move(text))
{ }
- // throws Axivion::Internal::Dto::invalid_dto_exception
QByteArray CommentRequestDto::serialize() const
{
return serialize_bytes(*this);
@@ -995,14 +1058,16 @@ namespace Axivion::Internal::Dto {
{
public:
// throws Axivion::Internal::Dto::invalid_dto_exception
- static CsrfTokenDto deserialize(const QJsonValue &json) {
+ static CsrfTokenDto deserialize(const QJsonValue &json)
+ {
const QJsonObject jo = toJsonObject<CsrfTokenDto>(json);
return {
deserialize_field<QString>(jo, csrfTokenKeyCsrfToken)
};
}
- static QJsonValue serialize(const CsrfTokenDto &value) {
+ static QJsonValue serialize(const CsrfTokenDto &value)
+ {
QJsonObject jo;
serialize_field(jo, csrfTokenKeyCsrfToken, value.csrfToken);
return { jo };
@@ -1018,13 +1083,17 @@ namespace Axivion::Internal::Dto {
return deserialize_bytes<CsrfTokenDto>(json);
}
+ Utils::expected_str<CsrfTokenDto> CsrfTokenDto::deserializeExpected(const QByteArray &json)
+ {
+ return deserializeExp<CsrfTokenDto>(json);
+ }
+
CsrfTokenDto::CsrfTokenDto(
QString csrfToken
) :
csrfToken(std::move(csrfToken))
{ }
- // throws Axivion::Internal::Dto::invalid_dto_exception
QByteArray CsrfTokenDto::serialize() const
{
return serialize_bytes(*this);
@@ -1043,7 +1112,8 @@ namespace Axivion::Internal::Dto {
{
public:
// throws Axivion::Internal::Dto::invalid_dto_exception
- static EntityDto deserialize(const QJsonValue &json) {
+ static EntityDto deserialize(const QJsonValue &json)
+ {
const QJsonObject jo = toJsonObject<EntityDto>(json);
return {
deserialize_field<QString>(jo, entityKeyId),
@@ -1054,7 +1124,8 @@ namespace Axivion::Internal::Dto {
};
}
- static QJsonValue serialize(const EntityDto &value) {
+ static QJsonValue serialize(const EntityDto &value)
+ {
QJsonObject jo;
serialize_field(jo, entityKeyId, value.id);
serialize_field(jo, entityKeyName, value.name);
@@ -1074,6 +1145,11 @@ namespace Axivion::Internal::Dto {
return deserialize_bytes<EntityDto>(json);
}
+ Utils::expected_str<EntityDto> EntityDto::deserializeExpected(const QByteArray &json)
+ {
+ return deserializeExp<EntityDto>(json);
+ }
+
EntityDto::EntityDto(
QString id,
QString name,
@@ -1088,7 +1164,6 @@ namespace Axivion::Internal::Dto {
line(std::move(line))
{ }
- // throws Axivion::Internal::Dto::invalid_dto_exception
QByteArray EntityDto::serialize() const
{
return serialize_bytes(*this);
@@ -1111,7 +1186,8 @@ namespace Axivion::Internal::Dto {
{
public:
// throws Axivion::Internal::Dto::invalid_dto_exception
- static ErrorDto deserialize(const QJsonValue &json) {
+ static ErrorDto deserialize(const QJsonValue &json)
+ {
const QJsonObject jo = toJsonObject<ErrorDto>(json);
return {
deserialize_field<std::optional<QString>>(jo, errorKeyDashboardVersionNumber),
@@ -1126,7 +1202,8 @@ namespace Axivion::Internal::Dto {
};
}
- static QJsonValue serialize(const ErrorDto &value) {
+ static QJsonValue serialize(const ErrorDto &value)
+ {
QJsonObject jo;
serialize_field(jo, errorKeyDashboardVersionNumber, value.dashboardVersionNumber);
serialize_field(jo, errorKeyType, value.type);
@@ -1150,6 +1227,11 @@ namespace Axivion::Internal::Dto {
return deserialize_bytes<ErrorDto>(json);
}
+ Utils::expected_str<ErrorDto> ErrorDto::deserializeExpected(const QByteArray &json)
+ {
+ return deserializeExp<ErrorDto>(json);
+ }
+
ErrorDto::ErrorDto(
std::optional<QString> dashboardVersionNumber,
QString type,
@@ -1172,7 +1254,6 @@ namespace Axivion::Internal::Dto {
data(std::move(data))
{ }
- // throws Axivion::Internal::Dto::invalid_dto_exception
QByteArray ErrorDto::serialize() const
{
return serialize_bytes(*this);
@@ -1193,7 +1274,8 @@ namespace Axivion::Internal::Dto {
{
public:
// throws Axivion::Internal::Dto::invalid_dto_exception
- static IssueCommentDto deserialize(const QJsonValue &json) {
+ static IssueCommentDto deserialize(const QJsonValue &json)
+ {
const QJsonObject jo = toJsonObject<IssueCommentDto>(json);
return {
deserialize_field<QString>(jo, issueCommentKeyUsername),
@@ -1206,7 +1288,8 @@ namespace Axivion::Internal::Dto {
};
}
- static QJsonValue serialize(const IssueCommentDto &value) {
+ static QJsonValue serialize(const IssueCommentDto &value)
+ {
QJsonObject jo;
serialize_field(jo, issueCommentKeyUsername, value.username);
serialize_field(jo, issueCommentKeyUserDisplayName, value.userDisplayName);
@@ -1228,6 +1311,11 @@ namespace Axivion::Internal::Dto {
return deserialize_bytes<IssueCommentDto>(json);
}
+ Utils::expected_str<IssueCommentDto> IssueCommentDto::deserializeExpected(const QByteArray &json)
+ {
+ return deserializeExp<IssueCommentDto>(json);
+ }
+
IssueCommentDto::IssueCommentDto(
QString username,
QString userDisplayName,
@@ -1246,7 +1334,6 @@ namespace Axivion::Internal::Dto {
commentDeletionId(std::move(commentDeletionId))
{ }
- // throws Axivion::Internal::Dto::invalid_dto_exception
QByteArray IssueCommentDto::serialize() const
{
return serialize_bytes(*this);
@@ -1291,6 +1378,11 @@ namespace Axivion::Internal::Dto {
throw std::range_error(concat({ "Unknown IssueKind str: ", to_std_string(str) }));
}
+ std::optional<IssueKind> IssueKindMeta::strToOptionalEnum(QAnyStringView str)
+ {
+ return strToOptionalEn<IssueKindMeta>(str);
+ }
+
QLatin1String IssueKindMeta::enumToStr(IssueKind e)
{
switch (e)
@@ -1359,6 +1451,11 @@ namespace Axivion::Internal::Dto {
throw std::range_error(concat({ "Unknown IssueKindForNamedFilterCreation str: ", to_std_string(str) }));
}
+ std::optional<IssueKindForNamedFilterCreation> IssueKindForNamedFilterCreationMeta::strToOptionalEnum(QAnyStringView str)
+ {
+ return strToOptionalEn<IssueKindForNamedFilterCreationMeta>(str);
+ }
+
QLatin1String IssueKindForNamedFilterCreationMeta::enumToStr(IssueKindForNamedFilterCreation e)
{
switch (e)
@@ -1400,7 +1497,8 @@ namespace Axivion::Internal::Dto {
{
public:
// throws Axivion::Internal::Dto::invalid_dto_exception
- static IssueSourceLocationDto deserialize(const QJsonValue &json) {
+ static IssueSourceLocationDto deserialize(const QJsonValue &json)
+ {
const QJsonObject jo = toJsonObject<IssueSourceLocationDto>(json);
return {
deserialize_field<QString>(jo, issueSourceLocationKeyFileName),
@@ -1413,7 +1511,8 @@ namespace Axivion::Internal::Dto {
};
}
- static QJsonValue serialize(const IssueSourceLocationDto &value) {
+ static QJsonValue serialize(const IssueSourceLocationDto &value)
+ {
QJsonObject jo;
serialize_field(jo, issueSourceLocationKeyFileName, value.fileName);
serialize_field(jo, issueSourceLocationKeyRole, value.role);
@@ -1435,6 +1534,11 @@ namespace Axivion::Internal::Dto {
return deserialize_bytes<IssueSourceLocationDto>(json);
}
+ Utils::expected_str<IssueSourceLocationDto> IssueSourceLocationDto::deserializeExpected(const QByteArray &json)
+ {
+ return deserializeExp<IssueSourceLocationDto>(json);
+ }
+
IssueSourceLocationDto::IssueSourceLocationDto(
QString fileName,
std::optional<QString> role,
@@ -1453,7 +1557,6 @@ namespace Axivion::Internal::Dto {
endColumn(std::move(endColumn))
{ }
- // throws Axivion::Internal::Dto::invalid_dto_exception
QByteArray IssueSourceLocationDto::serialize() const
{
return serialize_bytes(*this);
@@ -1469,7 +1572,8 @@ namespace Axivion::Internal::Dto {
{
public:
// throws Axivion::Internal::Dto::invalid_dto_exception
- static IssueTagDto deserialize(const QJsonValue &json) {
+ static IssueTagDto deserialize(const QJsonValue &json)
+ {
const QJsonObject jo = toJsonObject<IssueTagDto>(json);
return {
deserialize_field<QString>(jo, issueTagKeyTag),
@@ -1477,7 +1581,8 @@ namespace Axivion::Internal::Dto {
};
}
- static QJsonValue serialize(const IssueTagDto &value) {
+ static QJsonValue serialize(const IssueTagDto &value)
+ {
QJsonObject jo;
serialize_field(jo, issueTagKeyTag, value.tag);
serialize_field(jo, issueTagKeyColor, value.color);
@@ -1494,6 +1599,11 @@ namespace Axivion::Internal::Dto {
return deserialize_bytes<IssueTagDto>(json);
}
+ Utils::expected_str<IssueTagDto> IssueTagDto::deserializeExpected(const QByteArray &json)
+ {
+ return deserializeExp<IssueTagDto>(json);
+ }
+
IssueTagDto::IssueTagDto(
QString tag,
QString color
@@ -1502,7 +1612,6 @@ namespace Axivion::Internal::Dto {
color(std::move(color))
{ }
- // throws Axivion::Internal::Dto::invalid_dto_exception
QByteArray IssueTagDto::serialize() const
{
return serialize_bytes(*this);
@@ -1522,7 +1631,8 @@ namespace Axivion::Internal::Dto {
{
public:
// throws Axivion::Internal::Dto::invalid_dto_exception
- static IssueTagTypeDto deserialize(const QJsonValue &json) {
+ static IssueTagTypeDto deserialize(const QJsonValue &json)
+ {
const QJsonObject jo = toJsonObject<IssueTagTypeDto>(json);
return {
deserialize_field<QString>(jo, issueTagTypeKeyId),
@@ -1534,7 +1644,8 @@ namespace Axivion::Internal::Dto {
};
}
- static QJsonValue serialize(const IssueTagTypeDto &value) {
+ static QJsonValue serialize(const IssueTagTypeDto &value)
+ {
QJsonObject jo;
serialize_field(jo, issueTagTypeKeyId, value.id);
serialize_field(jo, issueTagTypeKeyText, value.text);
@@ -1555,6 +1666,11 @@ namespace Axivion::Internal::Dto {
return deserialize_bytes<IssueTagTypeDto>(json);
}
+ Utils::expected_str<IssueTagTypeDto> IssueTagTypeDto::deserializeExpected(const QByteArray &json)
+ {
+ return deserializeExp<IssueTagTypeDto>(json);
+ }
+
IssueTagTypeDto::IssueTagTypeDto(
QString id,
std::optional<QString> text,
@@ -1571,7 +1687,6 @@ namespace Axivion::Internal::Dto {
selected(std::move(selected))
{ }
- // throws Axivion::Internal::Dto::invalid_dto_exception
QByteArray IssueTagTypeDto::serialize() const
{
return serialize_bytes(*this);
@@ -1611,6 +1726,11 @@ namespace Axivion::Internal::Dto {
throw std::range_error(concat({ "Unknown MessageSeverity str: ", to_std_string(str) }));
}
+ std::optional<MessageSeverity> MessageSeverityMeta::strToOptionalEnum(QAnyStringView str)
+ {
+ return strToOptionalEn<MessageSeverityMeta>(str);
+ }
+
QLatin1String MessageSeverityMeta::enumToStr(MessageSeverity e)
{
switch (e)
@@ -1645,7 +1765,8 @@ namespace Axivion::Internal::Dto {
{
public:
// throws Axivion::Internal::Dto::invalid_dto_exception
- static MetricDto deserialize(const QJsonValue &json) {
+ static MetricDto deserialize(const QJsonValue &json)
+ {
const QJsonObject jo = toJsonObject<MetricDto>(json);
return {
deserialize_field<QString>(jo, metricKeyName),
@@ -1655,7 +1776,8 @@ namespace Axivion::Internal::Dto {
};
}
- static QJsonValue serialize(const MetricDto &value) {
+ static QJsonValue serialize(const MetricDto &value)
+ {
QJsonObject jo;
serialize_field(jo, metricKeyName, value.name);
serialize_field(jo, metricKeyDisplayName, value.displayName);
@@ -1674,6 +1796,11 @@ namespace Axivion::Internal::Dto {
return deserialize_bytes<MetricDto>(json);
}
+ Utils::expected_str<MetricDto> MetricDto::deserializeExpected(const QByteArray &json)
+ {
+ return deserializeExp<MetricDto>(json);
+ }
+
MetricDto::MetricDto(
QString name,
QString displayName,
@@ -1686,7 +1813,6 @@ namespace Axivion::Internal::Dto {
maxValue(std::move(maxValue))
{ }
- // throws Axivion::Internal::Dto::invalid_dto_exception
QByteArray MetricDto::serialize() const
{
return serialize_bytes(*this);
@@ -1707,7 +1833,8 @@ namespace Axivion::Internal::Dto {
{
public:
// throws Axivion::Internal::Dto::invalid_dto_exception
- static MetricValueTableRowDto deserialize(const QJsonValue &json) {
+ static MetricValueTableRowDto deserialize(const QJsonValue &json)
+ {
const QJsonObject jo = toJsonObject<MetricValueTableRowDto>(json);
return {
deserialize_field<QString>(jo, metricValueTableRowKeyMetric),
@@ -1720,7 +1847,8 @@ namespace Axivion::Internal::Dto {
};
}
- static QJsonValue serialize(const MetricValueTableRowDto &value) {
+ static QJsonValue serialize(const MetricValueTableRowDto &value)
+ {
QJsonObject jo;
serialize_field(jo, metricValueTableRowKeyMetric, value.metric);
serialize_field(jo, metricValueTableRowKeyPath, value.path);
@@ -1742,6 +1870,11 @@ namespace Axivion::Internal::Dto {
return deserialize_bytes<MetricValueTableRowDto>(json);
}
+ Utils::expected_str<MetricValueTableRowDto> MetricValueTableRowDto::deserializeExpected(const QByteArray &json)
+ {
+ return deserializeExp<MetricValueTableRowDto>(json);
+ }
+
MetricValueTableRowDto::MetricValueTableRowDto(
QString metric,
std::optional<QString> path,
@@ -1760,7 +1893,6 @@ namespace Axivion::Internal::Dto {
entityId(std::move(entityId))
{ }
- // throws Axivion::Internal::Dto::invalid_dto_exception
QByteArray MetricValueTableRowDto::serialize() const
{
return serialize_bytes(*this);
@@ -1790,6 +1922,11 @@ namespace Axivion::Internal::Dto {
throw std::range_error(concat({ "Unknown NamedFilterType str: ", to_std_string(str) }));
}
+ std::optional<NamedFilterType> NamedFilterTypeMeta::strToOptionalEnum(QAnyStringView str)
+ {
+ return strToOptionalEn<NamedFilterTypeMeta>(str);
+ }
+
QLatin1String NamedFilterTypeMeta::enumToStr(NamedFilterType e)
{
switch (e)
@@ -1817,14 +1954,16 @@ namespace Axivion::Internal::Dto {
{
public:
// throws Axivion::Internal::Dto::invalid_dto_exception
- static NamedFilterVisibilityDto deserialize(const QJsonValue &json) {
+ static NamedFilterVisibilityDto deserialize(const QJsonValue &json)
+ {
const QJsonObject jo = toJsonObject<NamedFilterVisibilityDto>(json);
return {
deserialize_field<std::optional<std::vector<QString>>>(jo, namedFilterVisibilityKeyGroups)
};
}
- static QJsonValue serialize(const NamedFilterVisibilityDto &value) {
+ static QJsonValue serialize(const NamedFilterVisibilityDto &value)
+ {
QJsonObject jo;
serialize_field(jo, namedFilterVisibilityKeyGroups, value.groups);
return { jo };
@@ -1840,13 +1979,17 @@ namespace Axivion::Internal::Dto {
return deserialize_bytes<NamedFilterVisibilityDto>(json);
}
+ Utils::expected_str<NamedFilterVisibilityDto> NamedFilterVisibilityDto::deserializeExpected(const QByteArray &json)
+ {
+ return deserializeExp<NamedFilterVisibilityDto>(json);
+ }
+
NamedFilterVisibilityDto::NamedFilterVisibilityDto(
std::optional<std::vector<QString>> groups
) :
groups(std::move(groups))
{ }
- // throws Axivion::Internal::Dto::invalid_dto_exception
QByteArray NamedFilterVisibilityDto::serialize() const
{
return serialize_bytes(*this);
@@ -1862,7 +2005,8 @@ namespace Axivion::Internal::Dto {
{
public:
// throws Axivion::Internal::Dto::invalid_dto_exception
- static ProjectReferenceDto deserialize(const QJsonValue &json) {
+ static ProjectReferenceDto deserialize(const QJsonValue &json)
+ {
const QJsonObject jo = toJsonObject<ProjectReferenceDto>(json);
return {
deserialize_field<QString>(jo, projectReferenceKeyName),
@@ -1870,7 +2014,8 @@ namespace Axivion::Internal::Dto {
};
}
- static QJsonValue serialize(const ProjectReferenceDto &value) {
+ static QJsonValue serialize(const ProjectReferenceDto &value)
+ {
QJsonObject jo;
serialize_field(jo, projectReferenceKeyName, value.name);
serialize_field(jo, projectReferenceKeyUrl, value.url);
@@ -1887,6 +2032,11 @@ namespace Axivion::Internal::Dto {
return deserialize_bytes<ProjectReferenceDto>(json);
}
+ Utils::expected_str<ProjectReferenceDto> ProjectReferenceDto::deserializeExpected(const QByteArray &json)
+ {
+ return deserializeExp<ProjectReferenceDto>(json);
+ }
+
ProjectReferenceDto::ProjectReferenceDto(
QString name,
QString url
@@ -1895,7 +2045,6 @@ namespace Axivion::Internal::Dto {
url(std::move(url))
{ }
- // throws Axivion::Internal::Dto::invalid_dto_exception
QByteArray ProjectReferenceDto::serialize() const
{
return serialize_bytes(*this);
@@ -1912,7 +2061,8 @@ namespace Axivion::Internal::Dto {
{
public:
// throws Axivion::Internal::Dto::invalid_dto_exception
- static RuleDto deserialize(const QJsonValue &json) {
+ static RuleDto deserialize(const QJsonValue &json)
+ {
const QJsonObject jo = toJsonObject<RuleDto>(json);
return {
deserialize_field<QString>(jo, ruleKeyName),
@@ -1921,7 +2071,8 @@ namespace Axivion::Internal::Dto {
};
}
- static QJsonValue serialize(const RuleDto &value) {
+ static QJsonValue serialize(const RuleDto &value)
+ {
QJsonObject jo;
serialize_field(jo, ruleKeyName, value.name);
serialize_field(jo, ruleKeyOriginal_name, value.original_name);
@@ -1939,6 +2090,11 @@ namespace Axivion::Internal::Dto {
return deserialize_bytes<RuleDto>(json);
}
+ Utils::expected_str<RuleDto> RuleDto::deserializeExpected(const QByteArray &json)
+ {
+ return deserializeExp<RuleDto>(json);
+ }
+
RuleDto::RuleDto(
QString name,
QString original_name,
@@ -1949,7 +2105,6 @@ namespace Axivion::Internal::Dto {
disabled(std::move(disabled))
{ }
- // throws Axivion::Internal::Dto::invalid_dto_exception
QByteArray RuleDto::serialize() const
{
return serialize_bytes(*this);
@@ -1974,6 +2129,11 @@ namespace Axivion::Internal::Dto {
throw std::range_error(concat({ "Unknown SortDirection str: ", to_std_string(str) }));
}
+ std::optional<SortDirection> SortDirectionMeta::strToOptionalEnum(QAnyStringView str)
+ {
+ return strToOptionalEn<SortDirectionMeta>(str);
+ }
+
QLatin1String SortDirectionMeta::enumToStr(SortDirection e)
{
switch (e)
@@ -2014,6 +2174,11 @@ namespace Axivion::Internal::Dto {
throw std::range_error(concat({ "Unknown TableCellAlignment str: ", to_std_string(str) }));
}
+ std::optional<TableCellAlignment> TableCellAlignmentMeta::strToOptionalEnum(QAnyStringView str)
+ {
+ return strToOptionalEn<TableCellAlignmentMeta>(str);
+ }
+
QLatin1String TableCellAlignmentMeta::enumToStr(TableCellAlignment e)
{
switch (e)
@@ -2043,7 +2208,8 @@ namespace Axivion::Internal::Dto {
{
public:
// throws Axivion::Internal::Dto::invalid_dto_exception
- static ToolsVersionDto deserialize(const QJsonValue &json) {
+ static ToolsVersionDto deserialize(const QJsonValue &json)
+ {
const QJsonObject jo = toJsonObject<ToolsVersionDto>(json);
return {
deserialize_field<QString>(jo, toolsVersionKeyName),
@@ -2052,7 +2218,8 @@ namespace Axivion::Internal::Dto {
};
}
- static QJsonValue serialize(const ToolsVersionDto &value) {
+ static QJsonValue serialize(const ToolsVersionDto &value)
+ {
QJsonObject jo;
serialize_field(jo, toolsVersionKeyName, value.name);
serialize_field(jo, toolsVersionKeyNumber, value.number);
@@ -2070,6 +2237,11 @@ namespace Axivion::Internal::Dto {
return deserialize_bytes<ToolsVersionDto>(json);
}
+ Utils::expected_str<ToolsVersionDto> ToolsVersionDto::deserializeExpected(const QByteArray &json)
+ {
+ return deserializeExp<ToolsVersionDto>(json);
+ }
+
ToolsVersionDto::ToolsVersionDto(
QString name,
QString number,
@@ -2080,7 +2252,6 @@ namespace Axivion::Internal::Dto {
buildDate(std::move(buildDate))
{ }
- // throws Axivion::Internal::Dto::invalid_dto_exception
QByteArray ToolsVersionDto::serialize() const
{
return serialize_bytes(*this);
@@ -2110,6 +2281,11 @@ namespace Axivion::Internal::Dto {
throw std::range_error(concat({ "Unknown UserRefType str: ", to_std_string(str) }));
}
+ std::optional<UserRefType> UserRefTypeMeta::strToOptionalEnum(QAnyStringView str)
+ {
+ return strToOptionalEn<UserRefTypeMeta>(str);
+ }
+
QLatin1String UserRefTypeMeta::enumToStr(UserRefType e)
{
switch (e)
@@ -2139,7 +2315,8 @@ namespace Axivion::Internal::Dto {
{
public:
// throws Axivion::Internal::Dto::invalid_dto_exception
- static VersionKindCountDto deserialize(const QJsonValue &json) {
+ static VersionKindCountDto deserialize(const QJsonValue &json)
+ {
const QJsonObject jo = toJsonObject<VersionKindCountDto>(json);
return {
deserialize_field<qint32>(jo, versionKindCountKeyTotal),
@@ -2148,7 +2325,8 @@ namespace Axivion::Internal::Dto {
};
}
- static QJsonValue serialize(const VersionKindCountDto &value) {
+ static QJsonValue serialize(const VersionKindCountDto &value)
+ {
QJsonObject jo;
serialize_field(jo, versionKindCountKeyTotal, value.Total);
serialize_field(jo, versionKindCountKeyAdded, value.Added);
@@ -2166,6 +2344,11 @@ namespace Axivion::Internal::Dto {
return deserialize_bytes<VersionKindCountDto>(json);
}
+ Utils::expected_str<VersionKindCountDto> VersionKindCountDto::deserializeExpected(const QByteArray &json)
+ {
+ return deserializeExp<VersionKindCountDto>(json);
+ }
+
VersionKindCountDto::VersionKindCountDto(
qint32 Total,
qint32 Added,
@@ -2176,7 +2359,6 @@ namespace Axivion::Internal::Dto {
Removed(std::move(Removed))
{ }
- // throws Axivion::Internal::Dto::invalid_dto_exception
QByteArray VersionKindCountDto::serialize() const
{
return serialize_bytes(*this);
@@ -2199,7 +2381,8 @@ namespace Axivion::Internal::Dto {
{
public:
// throws Axivion::Internal::Dto::invalid_dto_exception
- static AnalysisVersionDto deserialize(const QJsonValue &json) {
+ static AnalysisVersionDto deserialize(const QJsonValue &json)
+ {
const QJsonObject jo = toJsonObject<AnalysisVersionDto>(json);
return {
deserialize_field<QString>(jo, analysisVersionKeyDate),
@@ -2214,7 +2397,8 @@ namespace Axivion::Internal::Dto {
};
}
- static QJsonValue serialize(const AnalysisVersionDto &value) {
+ static QJsonValue serialize(const AnalysisVersionDto &value)
+ {
QJsonObject jo;
serialize_field(jo, analysisVersionKeyDate, value.date);
serialize_field(jo, analysisVersionKeyLabel, value.label);
@@ -2238,6 +2422,11 @@ namespace Axivion::Internal::Dto {
return deserialize_bytes<AnalysisVersionDto>(json);
}
+ Utils::expected_str<AnalysisVersionDto> AnalysisVersionDto::deserializeExpected(const QByteArray &json)
+ {
+ return deserializeExp<AnalysisVersionDto>(json);
+ }
+
AnalysisVersionDto::AnalysisVersionDto(
QString date,
std::optional<QString> label,
@@ -2260,7 +2449,6 @@ namespace Axivion::Internal::Dto {
cloneRatio(std::move(cloneRatio))
{ }
- // throws Axivion::Internal::Dto::invalid_dto_exception
QByteArray AnalysisVersionDto::serialize() const
{
return serialize_bytes(*this);
@@ -2278,7 +2466,8 @@ namespace Axivion::Internal::Dto {
{
public:
// throws Axivion::Internal::Dto::invalid_dto_exception
- static ApiTokenCreationRequestDto deserialize(const QJsonValue &json) {
+ static ApiTokenCreationRequestDto deserialize(const QJsonValue &json)
+ {
const QJsonObject jo = toJsonObject<ApiTokenCreationRequestDto>(json);
return {
deserialize_field<QString>(jo, apiTokenCreationRequestKeyPassword),
@@ -2288,7 +2477,8 @@ namespace Axivion::Internal::Dto {
};
}
- static QJsonValue serialize(const ApiTokenCreationRequestDto &value) {
+ static QJsonValue serialize(const ApiTokenCreationRequestDto &value)
+ {
QJsonObject jo;
serialize_field(jo, apiTokenCreationRequestKeyPassword, value.password);
serialize_field(jo, apiTokenCreationRequestKeyType, value.type);
@@ -2307,6 +2497,11 @@ namespace Axivion::Internal::Dto {
return deserialize_bytes<ApiTokenCreationRequestDto>(json);
}
+ Utils::expected_str<ApiTokenCreationRequestDto> ApiTokenCreationRequestDto::deserializeExpected(const QByteArray &json)
+ {
+ return deserializeExp<ApiTokenCreationRequestDto>(json);
+ }
+
ApiTokenCreationRequestDto::ApiTokenCreationRequestDto(
QString password,
QString type,
@@ -2351,7 +2546,6 @@ namespace Axivion::Internal::Dto {
type = ApiTokenTypeMeta::enumToStr(newValue);
}
- // throws Axivion::Internal::Dto::invalid_dto_exception
QByteArray ApiTokenCreationRequestDto::serialize() const
{
return serialize_bytes(*this);
@@ -2378,7 +2572,8 @@ namespace Axivion::Internal::Dto {
{
public:
// throws Axivion::Internal::Dto::invalid_dto_exception
- static ApiTokenInfoDto deserialize(const QJsonValue &json) {
+ static ApiTokenInfoDto deserialize(const QJsonValue &json)
+ {
const QJsonObject jo = toJsonObject<ApiTokenInfoDto>(json);
return {
deserialize_field<QString>(jo, apiTokenInfoKeyId),
@@ -2397,7 +2592,8 @@ namespace Axivion::Internal::Dto {
};
}
- static QJsonValue serialize(const ApiTokenInfoDto &value) {
+ static QJsonValue serialize(const ApiTokenInfoDto &value)
+ {
QJsonObject jo;
serialize_field(jo, apiTokenInfoKeyId, value.id);
serialize_field(jo, apiTokenInfoKeyUrl, value.url);
@@ -2425,6 +2621,11 @@ namespace Axivion::Internal::Dto {
return deserialize_bytes<ApiTokenInfoDto>(json);
}
+ Utils::expected_str<ApiTokenInfoDto> ApiTokenInfoDto::deserializeExpected(const QByteArray &json)
+ {
+ return deserializeExp<ApiTokenInfoDto>(json);
+ }
+
ApiTokenInfoDto::ApiTokenInfoDto(
QString id,
QString url,
@@ -2505,7 +2706,6 @@ namespace Axivion::Internal::Dto {
type = ApiTokenTypeMeta::enumToStr(newValue);
}
- // throws Axivion::Internal::Dto::invalid_dto_exception
QByteArray ApiTokenInfoDto::serialize() const
{
return serialize_bytes(*this);
@@ -2529,7 +2729,8 @@ namespace Axivion::Internal::Dto {
{
public:
// throws Axivion::Internal::Dto::invalid_dto_exception
- static ColumnInfoDto deserialize(const QJsonValue &json) {
+ static ColumnInfoDto deserialize(const QJsonValue &json)
+ {
const QJsonObject jo = toJsonObject<ColumnInfoDto>(json);
return {
deserialize_field<QString>(jo, columnInfoKeyKey),
@@ -2545,7 +2746,8 @@ namespace Axivion::Internal::Dto {
};
}
- static QJsonValue serialize(const ColumnInfoDto &value) {
+ static QJsonValue serialize(const ColumnInfoDto &value)
+ {
QJsonObject jo;
serialize_field(jo, columnInfoKeyKey, value.key);
serialize_field(jo, columnInfoKeyHeader, value.header);
@@ -2570,6 +2772,11 @@ namespace Axivion::Internal::Dto {
return deserialize_bytes<ColumnInfoDto>(json);
}
+ Utils::expected_str<ColumnInfoDto> ColumnInfoDto::deserializeExpected(const QByteArray &json)
+ {
+ return deserializeExp<ColumnInfoDto>(json);
+ }
+
ColumnInfoDto::ColumnInfoDto(
QString key,
std::optional<QString> header,
@@ -2658,7 +2865,6 @@ namespace Axivion::Internal::Dto {
type = ColumnTypeMeta::enumToStr(newValue);
}
- // throws Axivion::Internal::Dto::invalid_dto_exception
QByteArray ColumnInfoDto::serialize() const
{
return serialize_bytes(*this);
@@ -2687,7 +2893,8 @@ namespace Axivion::Internal::Dto {
{
public:
// throws Axivion::Internal::Dto::invalid_dto_exception
- static DashboardInfoDto deserialize(const QJsonValue &json) {
+ static DashboardInfoDto deserialize(const QJsonValue &json)
+ {
const QJsonObject jo = toJsonObject<DashboardInfoDto>(json);
return {
deserialize_field<std::optional<QString>>(jo, dashboardInfoKeyMainUrl),
@@ -2708,7 +2915,8 @@ namespace Axivion::Internal::Dto {
};
}
- static QJsonValue serialize(const DashboardInfoDto &value) {
+ static QJsonValue serialize(const DashboardInfoDto &value)
+ {
QJsonObject jo;
serialize_field(jo, dashboardInfoKeyMainUrl, value.mainUrl);
serialize_field(jo, dashboardInfoKeyDashboardVersion, value.dashboardVersion);
@@ -2738,6 +2946,11 @@ namespace Axivion::Internal::Dto {
return deserialize_bytes<DashboardInfoDto>(json);
}
+ Utils::expected_str<DashboardInfoDto> DashboardInfoDto::deserializeExpected(const QByteArray &json)
+ {
+ return deserializeExp<DashboardInfoDto>(json);
+ }
+
DashboardInfoDto::DashboardInfoDto(
std::optional<QString> mainUrl,
QString dashboardVersion,
@@ -2772,7 +2985,6 @@ namespace Axivion::Internal::Dto {
csrfTokenUrl(std::move(csrfTokenUrl))
{ }
- // throws Axivion::Internal::Dto::invalid_dto_exception
QByteArray DashboardInfoDto::serialize() const
{
return serialize_bytes(*this);
@@ -2787,14 +2999,16 @@ namespace Axivion::Internal::Dto {
{
public:
// throws Axivion::Internal::Dto::invalid_dto_exception
- static IssueCommentListDto deserialize(const QJsonValue &json) {
+ static IssueCommentListDto deserialize(const QJsonValue &json)
+ {
const QJsonObject jo = toJsonObject<IssueCommentListDto>(json);
return {
deserialize_field<std::vector<IssueCommentDto>>(jo, issueCommentListKeyComments)
};
}
- static QJsonValue serialize(const IssueCommentListDto &value) {
+ static QJsonValue serialize(const IssueCommentListDto &value)
+ {
QJsonObject jo;
serialize_field(jo, issueCommentListKeyComments, value.comments);
return { jo };
@@ -2810,13 +3024,17 @@ namespace Axivion::Internal::Dto {
return deserialize_bytes<IssueCommentListDto>(json);
}
+ Utils::expected_str<IssueCommentListDto> IssueCommentListDto::deserializeExpected(const QByteArray &json)
+ {
+ return deserializeExp<IssueCommentListDto>(json);
+ }
+
IssueCommentListDto::IssueCommentListDto(
std::vector<IssueCommentDto> comments
) :
comments(std::move(comments))
{ }
- // throws Axivion::Internal::Dto::invalid_dto_exception
QByteArray IssueCommentListDto::serialize() const
{
return serialize_bytes(*this);
@@ -2833,7 +3051,8 @@ namespace Axivion::Internal::Dto {
{
public:
// throws Axivion::Internal::Dto::invalid_dto_exception
- static IssueKindInfoDto deserialize(const QJsonValue &json) {
+ static IssueKindInfoDto deserialize(const QJsonValue &json)
+ {
const QJsonObject jo = toJsonObject<IssueKindInfoDto>(json);
return {
deserialize_field<QString>(jo, issueKindInfoKeyPrefix),
@@ -2842,7 +3061,8 @@ namespace Axivion::Internal::Dto {
};
}
- static QJsonValue serialize(const IssueKindInfoDto &value) {
+ static QJsonValue serialize(const IssueKindInfoDto &value)
+ {
QJsonObject jo;
serialize_field(jo, issueKindInfoKeyPrefix, value.prefix);
serialize_field(jo, issueKindInfoKeyNiceSingularName, value.niceSingularName);
@@ -2860,6 +3080,11 @@ namespace Axivion::Internal::Dto {
return deserialize_bytes<IssueKindInfoDto>(json);
}
+ Utils::expected_str<IssueKindInfoDto> IssueKindInfoDto::deserializeExpected(const QByteArray &json)
+ {
+ return deserializeExp<IssueKindInfoDto>(json);
+ }
+
IssueKindInfoDto::IssueKindInfoDto(
QString prefix,
QString niceSingularName,
@@ -2900,7 +3125,6 @@ namespace Axivion::Internal::Dto {
prefix = IssueKindMeta::enumToStr(newValue);
}
- // throws Axivion::Internal::Dto::invalid_dto_exception
QByteArray IssueKindInfoDto::serialize() const
{
return serialize_bytes(*this);
@@ -2915,14 +3139,16 @@ namespace Axivion::Internal::Dto {
{
public:
// throws Axivion::Internal::Dto::invalid_dto_exception
- static IssueTagTypeListDto deserialize(const QJsonValue &json) {
+ static IssueTagTypeListDto deserialize(const QJsonValue &json)
+ {
const QJsonObject jo = toJsonObject<IssueTagTypeListDto>(json);
return {
deserialize_field<std::vector<IssueTagTypeDto>>(jo, issueTagTypeListKeyTags)
};
}
- static QJsonValue serialize(const IssueTagTypeListDto &value) {
+ static QJsonValue serialize(const IssueTagTypeListDto &value)
+ {
QJsonObject jo;
serialize_field(jo, issueTagTypeListKeyTags, value.tags);
return { jo };
@@ -2938,13 +3164,17 @@ namespace Axivion::Internal::Dto {
return deserialize_bytes<IssueTagTypeListDto>(json);
}
+ Utils::expected_str<IssueTagTypeListDto> IssueTagTypeListDto::deserializeExpected(const QByteArray &json)
+ {
+ return deserializeExp<IssueTagTypeListDto>(json);
+ }
+
IssueTagTypeListDto::IssueTagTypeListDto(
std::vector<IssueTagTypeDto> tags
) :
tags(std::move(tags))
{ }
- // throws Axivion::Internal::Dto::invalid_dto_exception
QByteArray IssueTagTypeListDto::serialize() const
{
return serialize_bytes(*this);
@@ -2967,7 +3197,8 @@ namespace Axivion::Internal::Dto {
{
public:
// throws Axivion::Internal::Dto::invalid_dto_exception
- static LineMarkerDto deserialize(const QJsonValue &json) {
+ static LineMarkerDto deserialize(const QJsonValue &json)
+ {
const QJsonObject jo = toJsonObject<LineMarkerDto>(json);
return {
deserialize_field<QString>(jo, lineMarkerKeyKind),
@@ -2982,7 +3213,8 @@ namespace Axivion::Internal::Dto {
};
}
- static QJsonValue serialize(const LineMarkerDto &value) {
+ static QJsonValue serialize(const LineMarkerDto &value)
+ {
QJsonObject jo;
serialize_field(jo, lineMarkerKeyKind, value.kind);
serialize_field(jo, lineMarkerKeyId, value.id);
@@ -3006,6 +3238,11 @@ namespace Axivion::Internal::Dto {
return deserialize_bytes<LineMarkerDto>(json);
}
+ Utils::expected_str<LineMarkerDto> LineMarkerDto::deserializeExpected(const QByteArray &json)
+ {
+ return deserializeExp<LineMarkerDto>(json);
+ }
+
LineMarkerDto::LineMarkerDto(
QString kind,
std::optional<qint64> id,
@@ -3070,7 +3307,6 @@ namespace Axivion::Internal::Dto {
kind = IssueKindMeta::enumToStr(newValue);
}
- // throws Axivion::Internal::Dto::invalid_dto_exception
QByteArray LineMarkerDto::serialize() const
{
return serialize_bytes(*this);
@@ -3086,7 +3322,8 @@ namespace Axivion::Internal::Dto {
{
public:
// throws Axivion::Internal::Dto::invalid_dto_exception
- static RepositoryUpdateMessageDto deserialize(const QJsonValue &json) {
+ static RepositoryUpdateMessageDto deserialize(const QJsonValue &json)
+ {
const QJsonObject jo = toJsonObject<RepositoryUpdateMessageDto>(json);
return {
deserialize_field<QString>(jo, repositoryUpdateMessageKeySeverity),
@@ -3094,7 +3331,8 @@ namespace Axivion::Internal::Dto {
};
}
- static QJsonValue serialize(const RepositoryUpdateMessageDto &value) {
+ static QJsonValue serialize(const RepositoryUpdateMessageDto &value)
+ {
QJsonObject jo;
serialize_field(jo, repositoryUpdateMessageKeySeverity, value.severity);
serialize_field(jo, repositoryUpdateMessageKeyMessage, value.message);
@@ -3111,6 +3349,11 @@ namespace Axivion::Internal::Dto {
return deserialize_bytes<RepositoryUpdateMessageDto>(json);
}
+ Utils::expected_str<RepositoryUpdateMessageDto> RepositoryUpdateMessageDto::deserializeExpected(const QByteArray &json)
+ {
+ return deserializeExp<RepositoryUpdateMessageDto>(json);
+ }
+
RepositoryUpdateMessageDto::RepositoryUpdateMessageDto(
QString severity,
QString message
@@ -3147,7 +3390,6 @@ namespace Axivion::Internal::Dto {
severity = MessageSeverityMeta::enumToStr(newValue);
}
- // throws Axivion::Internal::Dto::invalid_dto_exception
QByteArray RepositoryUpdateMessageDto::serialize() const
{
return serialize_bytes(*this);
@@ -3162,14 +3404,16 @@ namespace Axivion::Internal::Dto {
{
public:
// throws Axivion::Internal::Dto::invalid_dto_exception
- static RuleListDto deserialize(const QJsonValue &json) {
+ static RuleListDto deserialize(const QJsonValue &json)
+ {
const QJsonObject jo = toJsonObject<RuleListDto>(json);
return {
deserialize_field<std::vector<RuleDto>>(jo, ruleListKeyRules)
};
}
- static QJsonValue serialize(const RuleListDto &value) {
+ static QJsonValue serialize(const RuleListDto &value)
+ {
QJsonObject jo;
serialize_field(jo, ruleListKeyRules, value.rules);
return { jo };
@@ -3185,13 +3429,17 @@ namespace Axivion::Internal::Dto {
return deserialize_bytes<RuleListDto>(json);
}
+ Utils::expected_str<RuleListDto> RuleListDto::deserializeExpected(const QByteArray &json)
+ {
+ return deserializeExp<RuleListDto>(json);
+ }
+
RuleListDto::RuleListDto(
std::vector<RuleDto> rules
) :
rules(std::move(rules))
{ }
- // throws Axivion::Internal::Dto::invalid_dto_exception
QByteArray RuleListDto::serialize() const
{
return serialize_bytes(*this);
@@ -3207,7 +3455,8 @@ namespace Axivion::Internal::Dto {
{
public:
// throws Axivion::Internal::Dto::invalid_dto_exception
- static SortInfoDto deserialize(const QJsonValue &json) {
+ static SortInfoDto deserialize(const QJsonValue &json)
+ {
const QJsonObject jo = toJsonObject<SortInfoDto>(json);
return {
deserialize_field<QString>(jo, sortInfoKeyKey),
@@ -3215,7 +3464,8 @@ namespace Axivion::Internal::Dto {
};
}
- static QJsonValue serialize(const SortInfoDto &value) {
+ static QJsonValue serialize(const SortInfoDto &value)
+ {
QJsonObject jo;
serialize_field(jo, sortInfoKeyKey, value.key);
serialize_field(jo, sortInfoKeyDirection, value.direction);
@@ -3232,6 +3482,11 @@ namespace Axivion::Internal::Dto {
return deserialize_bytes<SortInfoDto>(json);
}
+ Utils::expected_str<SortInfoDto> SortInfoDto::deserializeExpected(const QByteArray &json)
+ {
+ return deserializeExp<SortInfoDto>(json);
+ }
+
SortInfoDto::SortInfoDto(
QString key,
QString direction
@@ -3268,7 +3523,6 @@ namespace Axivion::Internal::Dto {
direction = SortDirectionMeta::enumToStr(newValue);
}
- // throws Axivion::Internal::Dto::invalid_dto_exception
QByteArray SortInfoDto::serialize() const
{
return serialize_bytes(*this);
@@ -3286,7 +3540,8 @@ namespace Axivion::Internal::Dto {
{
public:
// throws Axivion::Internal::Dto::invalid_dto_exception
- static UserRefDto deserialize(const QJsonValue &json) {
+ static UserRefDto deserialize(const QJsonValue &json)
+ {
const QJsonObject jo = toJsonObject<UserRefDto>(json);
return {
deserialize_field<QString>(jo, userRefKeyName),
@@ -3296,7 +3551,8 @@ namespace Axivion::Internal::Dto {
};
}
- static QJsonValue serialize(const UserRefDto &value) {
+ static QJsonValue serialize(const UserRefDto &value)
+ {
QJsonObject jo;
serialize_field(jo, userRefKeyName, value.name);
serialize_field(jo, userRefKeyDisplayName, value.displayName);
@@ -3315,6 +3571,11 @@ namespace Axivion::Internal::Dto {
return deserialize_bytes<UserRefDto>(json);
}
+ Utils::expected_str<UserRefDto> UserRefDto::deserializeExpected(const QByteArray &json)
+ {
+ return deserializeExp<UserRefDto>(json);
+ }
+
UserRefDto::UserRefDto(
QString name,
QString displayName,
@@ -3361,7 +3622,6 @@ namespace Axivion::Internal::Dto {
type = UserRefTypeMeta::enumToStr(newValue);
}
- // throws Axivion::Internal::Dto::invalid_dto_exception
QByteArray UserRefDto::serialize() const
{
return serialize_bytes(*this);
@@ -3377,7 +3637,8 @@ namespace Axivion::Internal::Dto {
{
public:
// throws Axivion::Internal::Dto::invalid_dto_exception
- static AnalyzedFileListDto deserialize(const QJsonValue &json) {
+ static AnalyzedFileListDto deserialize(const QJsonValue &json)
+ {
const QJsonObject jo = toJsonObject<AnalyzedFileListDto>(json);
return {
deserialize_field<AnalysisVersionDto>(jo, analyzedFileListKeyVersion),
@@ -3385,7 +3646,8 @@ namespace Axivion::Internal::Dto {
};
}
- static QJsonValue serialize(const AnalyzedFileListDto &value) {
+ static QJsonValue serialize(const AnalyzedFileListDto &value)
+ {
QJsonObject jo;
serialize_field(jo, analyzedFileListKeyVersion, value.version);
serialize_field(jo, analyzedFileListKeyRows, value.rows);
@@ -3402,6 +3664,11 @@ namespace Axivion::Internal::Dto {
return deserialize_bytes<AnalyzedFileListDto>(json);
}
+ Utils::expected_str<AnalyzedFileListDto> AnalyzedFileListDto::deserializeExpected(const QByteArray &json)
+ {
+ return deserializeExp<AnalyzedFileListDto>(json);
+ }
+
AnalyzedFileListDto::AnalyzedFileListDto(
AnalysisVersionDto version,
std::vector<AnalyzedFileDto> rows
@@ -3410,7 +3677,6 @@ namespace Axivion::Internal::Dto {
rows(std::move(rows))
{ }
- // throws Axivion::Internal::Dto::invalid_dto_exception
QByteArray AnalyzedFileListDto::serialize() const
{
return serialize_bytes(*this);
@@ -3426,7 +3692,8 @@ namespace Axivion::Internal::Dto {
{
public:
// throws Axivion::Internal::Dto::invalid_dto_exception
- static EntityListDto deserialize(const QJsonValue &json) {
+ static EntityListDto deserialize(const QJsonValue &json)
+ {
const QJsonObject jo = toJsonObject<EntityListDto>(json);
return {
deserialize_field<std::optional<AnalysisVersionDto>>(jo, entityListKeyVersion),
@@ -3434,7 +3701,8 @@ namespace Axivion::Internal::Dto {
};
}
- static QJsonValue serialize(const EntityListDto &value) {
+ static QJsonValue serialize(const EntityListDto &value)
+ {
QJsonObject jo;
serialize_field(jo, entityListKeyVersion, value.version);
serialize_field(jo, entityListKeyEntities, value.entities);
@@ -3451,6 +3719,11 @@ namespace Axivion::Internal::Dto {
return deserialize_bytes<EntityListDto>(json);
}
+ Utils::expected_str<EntityListDto> EntityListDto::deserializeExpected(const QByteArray &json)
+ {
+ return deserializeExp<EntityListDto>(json);
+ }
+
EntityListDto::EntityListDto(
std::optional<AnalysisVersionDto> version,
std::vector<EntityDto> entities
@@ -3459,7 +3732,6 @@ namespace Axivion::Internal::Dto {
entities(std::move(entities))
{ }
- // throws Axivion::Internal::Dto::invalid_dto_exception
QByteArray EntityListDto::serialize() const
{
return serialize_bytes(*this);
@@ -3477,7 +3749,8 @@ namespace Axivion::Internal::Dto {
{
public:
// throws Axivion::Internal::Dto::invalid_dto_exception
- static FileViewDto deserialize(const QJsonValue &json) {
+ static FileViewDto deserialize(const QJsonValue &json)
+ {
const QJsonObject jo = toJsonObject<FileViewDto>(json);
return {
deserialize_field<QString>(jo, fileViewKeyFileName),
@@ -3487,7 +3760,8 @@ namespace Axivion::Internal::Dto {
};
}
- static QJsonValue serialize(const FileViewDto &value) {
+ static QJsonValue serialize(const FileViewDto &value)
+ {
QJsonObject jo;
serialize_field(jo, fileViewKeyFileName, value.fileName);
serialize_field(jo, fileViewKeyVersion, value.version);
@@ -3506,6 +3780,11 @@ namespace Axivion::Internal::Dto {
return deserialize_bytes<FileViewDto>(json);
}
+ Utils::expected_str<FileViewDto> FileViewDto::deserializeExpected(const QByteArray &json)
+ {
+ return deserializeExp<FileViewDto>(json);
+ }
+
FileViewDto::FileViewDto(
QString fileName,
std::optional<QString> version,
@@ -3518,7 +3797,6 @@ namespace Axivion::Internal::Dto {
lineMarkers(std::move(lineMarkers))
{ }
- // throws Axivion::Internal::Dto::invalid_dto_exception
QByteArray FileViewDto::serialize() const
{
return serialize_bytes(*this);
@@ -3539,7 +3817,8 @@ namespace Axivion::Internal::Dto {
{
public:
// throws Axivion::Internal::Dto::invalid_dto_exception
- static IssueDto deserialize(const QJsonValue &json) {
+ static IssueDto deserialize(const QJsonValue &json)
+ {
const QJsonObject jo = toJsonObject<IssueDto>(json);
return {
deserialize_field<QString>(jo, issueKeyKind),
@@ -3552,7 +3831,8 @@ namespace Axivion::Internal::Dto {
};
}
- static QJsonValue serialize(const IssueDto &value) {
+ static QJsonValue serialize(const IssueDto &value)
+ {
QJsonObject jo;
serialize_field(jo, issueKeyKind, value.kind);
serialize_field(jo, issueKeyId, value.id);
@@ -3574,6 +3854,11 @@ namespace Axivion::Internal::Dto {
return deserialize_bytes<IssueDto>(json);
}
+ Utils::expected_str<IssueDto> IssueDto::deserializeExpected(const QByteArray &json)
+ {
+ return deserializeExp<IssueDto>(json);
+ }
+
IssueDto::IssueDto(
QString kind,
qint64 id,
@@ -3630,7 +3915,6 @@ namespace Axivion::Internal::Dto {
kind = IssueKindMeta::enumToStr(newValue);
}
- // throws Axivion::Internal::Dto::invalid_dto_exception
QByteArray IssueDto::serialize() const
{
return serialize_bytes(*this);
@@ -3652,7 +3936,8 @@ namespace Axivion::Internal::Dto {
{
public:
// throws Axivion::Internal::Dto::invalid_dto_exception
- static IssueTableDto deserialize(const QJsonValue &json) {
+ static IssueTableDto deserialize(const QJsonValue &json)
+ {
const QJsonObject jo = toJsonObject<IssueTableDto>(json);
return {
deserialize_field<std::optional<AnalysisVersionDto>>(jo, issueTableKeyStartVersion),
@@ -3666,7 +3951,8 @@ namespace Axivion::Internal::Dto {
};
}
- static QJsonValue serialize(const IssueTableDto &value) {
+ static QJsonValue serialize(const IssueTableDto &value)
+ {
QJsonObject jo;
serialize_field(jo, issueTableKeyStartVersion, value.startVersion);
serialize_field(jo, issueTableKeyEndVersion, value.endVersion);
@@ -3689,6 +3975,11 @@ namespace Axivion::Internal::Dto {
return deserialize_bytes<IssueTableDto>(json);
}
+ Utils::expected_str<IssueTableDto> IssueTableDto::deserializeExpected(const QByteArray &json)
+ {
+ return deserializeExp<IssueTableDto>(json);
+ }
+
IssueTableDto::IssueTableDto(
std::optional<AnalysisVersionDto> startVersion,
AnalysisVersionDto endVersion,
@@ -3709,7 +4000,6 @@ namespace Axivion::Internal::Dto {
totalRemovedCount(std::move(totalRemovedCount))
{ }
- // throws Axivion::Internal::Dto::invalid_dto_exception
QByteArray IssueTableDto::serialize() const
{
return serialize_bytes(*this);
@@ -3725,7 +4015,8 @@ namespace Axivion::Internal::Dto {
{
public:
// throws Axivion::Internal::Dto::invalid_dto_exception
- static MetricListDto deserialize(const QJsonValue &json) {
+ static MetricListDto deserialize(const QJsonValue &json)
+ {
const QJsonObject jo = toJsonObject<MetricListDto>(json);
return {
deserialize_field<std::optional<AnalysisVersionDto>>(jo, metricListKeyVersion),
@@ -3733,7 +4024,8 @@ namespace Axivion::Internal::Dto {
};
}
- static QJsonValue serialize(const MetricListDto &value) {
+ static QJsonValue serialize(const MetricListDto &value)
+ {
QJsonObject jo;
serialize_field(jo, metricListKeyVersion, value.version);
serialize_field(jo, metricListKeyMetrics, value.metrics);
@@ -3750,6 +4042,11 @@ namespace Axivion::Internal::Dto {
return deserialize_bytes<MetricListDto>(json);
}
+ Utils::expected_str<MetricListDto> MetricListDto::deserializeExpected(const QByteArray &json)
+ {
+ return deserializeExp<MetricListDto>(json);
+ }
+
MetricListDto::MetricListDto(
std::optional<AnalysisVersionDto> version,
std::vector<MetricDto> metrics
@@ -3758,7 +4055,6 @@ namespace Axivion::Internal::Dto {
metrics(std::move(metrics))
{ }
- // throws Axivion::Internal::Dto::invalid_dto_exception
QByteArray MetricListDto::serialize() const
{
return serialize_bytes(*this);
@@ -3777,7 +4073,8 @@ namespace Axivion::Internal::Dto {
{
public:
// throws Axivion::Internal::Dto::invalid_dto_exception
- static MetricValueRangeDto deserialize(const QJsonValue &json) {
+ static MetricValueRangeDto deserialize(const QJsonValue &json)
+ {
const QJsonObject jo = toJsonObject<MetricValueRangeDto>(json);
return {
deserialize_field<AnalysisVersionDto>(jo, metricValueRangeKeyStartVersion),
@@ -3788,7 +4085,8 @@ namespace Axivion::Internal::Dto {
};
}
- static QJsonValue serialize(const MetricValueRangeDto &value) {
+ static QJsonValue serialize(const MetricValueRangeDto &value)
+ {
QJsonObject jo;
serialize_field(jo, metricValueRangeKeyStartVersion, value.startVersion);
serialize_field(jo, metricValueRangeKeyEndVersion, value.endVersion);
@@ -3808,6 +4106,11 @@ namespace Axivion::Internal::Dto {
return deserialize_bytes<MetricValueRangeDto>(json);
}
+ Utils::expected_str<MetricValueRangeDto> MetricValueRangeDto::deserializeExpected(const QByteArray &json)
+ {
+ return deserializeExp<MetricValueRangeDto>(json);
+ }
+
MetricValueRangeDto::MetricValueRangeDto(
AnalysisVersionDto startVersion,
AnalysisVersionDto endVersion,
@@ -3822,7 +4125,6 @@ namespace Axivion::Internal::Dto {
values(std::move(values))
{ }
- // throws Axivion::Internal::Dto::invalid_dto_exception
QByteArray MetricValueRangeDto::serialize() const
{
return serialize_bytes(*this);
@@ -3838,7 +4140,8 @@ namespace Axivion::Internal::Dto {
{
public:
// throws Axivion::Internal::Dto::invalid_dto_exception
- static MetricValueTableDto deserialize(const QJsonValue &json) {
+ static MetricValueTableDto deserialize(const QJsonValue &json)
+ {
const QJsonObject jo = toJsonObject<MetricValueTableDto>(json);
return {
deserialize_field<std::vector<ColumnInfoDto>>(jo, metricValueTableKeyColumns),
@@ -3846,7 +4149,8 @@ namespace Axivion::Internal::Dto {
};
}
- static QJsonValue serialize(const MetricValueTableDto &value) {
+ static QJsonValue serialize(const MetricValueTableDto &value)
+ {
QJsonObject jo;
serialize_field(jo, metricValueTableKeyColumns, value.columns);
serialize_field(jo, metricValueTableKeyRows, value.rows);
@@ -3863,6 +4167,11 @@ namespace Axivion::Internal::Dto {
return deserialize_bytes<MetricValueTableDto>(json);
}
+ Utils::expected_str<MetricValueTableDto> MetricValueTableDto::deserializeExpected(const QByteArray &json)
+ {
+ return deserializeExp<MetricValueTableDto>(json);
+ }
+
MetricValueTableDto::MetricValueTableDto(
std::vector<ColumnInfoDto> columns,
std::vector<MetricValueTableRowDto> rows
@@ -3871,7 +4180,6 @@ namespace Axivion::Internal::Dto {
rows(std::move(rows))
{ }
- // throws Axivion::Internal::Dto::invalid_dto_exception
QByteArray MetricValueTableDto::serialize() const
{
return serialize_bytes(*this);
@@ -3890,7 +4198,8 @@ namespace Axivion::Internal::Dto {
{
public:
// throws Axivion::Internal::Dto::invalid_dto_exception
- static NamedFilterCreateDto deserialize(const QJsonValue &json) {
+ static NamedFilterCreateDto deserialize(const QJsonValue &json)
+ {
const QJsonObject jo = toJsonObject<NamedFilterCreateDto>(json);
return {
deserialize_field<QString>(jo, namedFilterCreateKeyDisplayName),
@@ -3901,7 +4210,8 @@ namespace Axivion::Internal::Dto {
};
}
- static QJsonValue serialize(const NamedFilterCreateDto &value) {
+ static QJsonValue serialize(const NamedFilterCreateDto &value)
+ {
QJsonObject jo;
serialize_field(jo, namedFilterCreateKeyDisplayName, value.displayName);
serialize_field(jo, namedFilterCreateKeyKind, value.kind);
@@ -3921,6 +4231,11 @@ namespace Axivion::Internal::Dto {
return deserialize_bytes<NamedFilterCreateDto>(json);
}
+ Utils::expected_str<NamedFilterCreateDto> NamedFilterCreateDto::deserializeExpected(const QByteArray &json)
+ {
+ return deserializeExp<NamedFilterCreateDto>(json);
+ }
+
NamedFilterCreateDto::NamedFilterCreateDto(
QString displayName,
QString kind,
@@ -3969,7 +4284,6 @@ namespace Axivion::Internal::Dto {
kind = IssueKindForNamedFilterCreationMeta::enumToStr(newValue);
}
- // throws Axivion::Internal::Dto::invalid_dto_exception
QByteArray NamedFilterCreateDto::serialize() const
{
return serialize_bytes(*this);
@@ -3994,7 +4308,8 @@ namespace Axivion::Internal::Dto {
{
public:
// throws Axivion::Internal::Dto::invalid_dto_exception
- static NamedFilterInfoDto deserialize(const QJsonValue &json) {
+ static NamedFilterInfoDto deserialize(const QJsonValue &json)
+ {
const QJsonObject jo = toJsonObject<NamedFilterInfoDto>(json);
return {
deserialize_field<QString>(jo, namedFilterInfoKeyKey),
@@ -4011,7 +4326,8 @@ namespace Axivion::Internal::Dto {
};
}
- static QJsonValue serialize(const NamedFilterInfoDto &value) {
+ static QJsonValue serialize(const NamedFilterInfoDto &value)
+ {
QJsonObject jo;
serialize_field(jo, namedFilterInfoKeyKey, value.key);
serialize_field(jo, namedFilterInfoKeyDisplayName, value.displayName);
@@ -4037,6 +4353,11 @@ namespace Axivion::Internal::Dto {
return deserialize_bytes<NamedFilterInfoDto>(json);
}
+ Utils::expected_str<NamedFilterInfoDto> NamedFilterInfoDto::deserializeExpected(const QByteArray &json)
+ {
+ return deserializeExp<NamedFilterInfoDto>(json);
+ }
+
NamedFilterInfoDto::NamedFilterInfoDto(
QString key,
QString displayName,
@@ -4111,7 +4432,6 @@ namespace Axivion::Internal::Dto {
type = NamedFilterTypeMeta::enumToStr(newValue);
}
- // throws Axivion::Internal::Dto::invalid_dto_exception
QByteArray NamedFilterInfoDto::serialize() const
{
return serialize_bytes(*this);
@@ -4129,7 +4449,8 @@ namespace Axivion::Internal::Dto {
{
public:
// throws Axivion::Internal::Dto::invalid_dto_exception
- static NamedFilterUpdateDto deserialize(const QJsonValue &json) {
+ static NamedFilterUpdateDto deserialize(const QJsonValue &json)
+ {
const QJsonObject jo = toJsonObject<NamedFilterUpdateDto>(json);
return {
deserialize_field<std::optional<QString>>(jo, namedFilterUpdateKeyName),
@@ -4139,7 +4460,8 @@ namespace Axivion::Internal::Dto {
};
}
- static QJsonValue serialize(const NamedFilterUpdateDto &value) {
+ static QJsonValue serialize(const NamedFilterUpdateDto &value)
+ {
QJsonObject jo;
serialize_field(jo, namedFilterUpdateKeyName, value.name);
serialize_field(jo, namedFilterUpdateKeyFilters, value.filters);
@@ -4158,6 +4480,11 @@ namespace Axivion::Internal::Dto {
return deserialize_bytes<NamedFilterUpdateDto>(json);
}
+ Utils::expected_str<NamedFilterUpdateDto> NamedFilterUpdateDto::deserializeExpected(const QByteArray &json)
+ {
+ return deserializeExp<NamedFilterUpdateDto>(json);
+ }
+
NamedFilterUpdateDto::NamedFilterUpdateDto(
std::optional<QString> name,
std::optional<std::map<QString, QString>> filters,
@@ -4170,7 +4497,6 @@ namespace Axivion::Internal::Dto {
visibility(std::move(visibility))
{ }
- // throws Axivion::Internal::Dto::invalid_dto_exception
QByteArray NamedFilterUpdateDto::serialize() const
{
return serialize_bytes(*this);
@@ -4191,7 +4517,8 @@ namespace Axivion::Internal::Dto {
{
public:
// throws Axivion::Internal::Dto::invalid_dto_exception
- static ProjectInfoDto deserialize(const QJsonValue &json) {
+ static ProjectInfoDto deserialize(const QJsonValue &json)
+ {
const QJsonObject jo = toJsonObject<ProjectInfoDto>(json);
return {
deserialize_field<QString>(jo, projectInfoKeyName),
@@ -4204,7 +4531,8 @@ namespace Axivion::Internal::Dto {
};
}
- static QJsonValue serialize(const ProjectInfoDto &value) {
+ static QJsonValue serialize(const ProjectInfoDto &value)
+ {
QJsonObject jo;
serialize_field(jo, projectInfoKeyName, value.name);
serialize_field(jo, projectInfoKeyIssueFilterHelp, value.issueFilterHelp);
@@ -4226,6 +4554,11 @@ namespace Axivion::Internal::Dto {
return deserialize_bytes<ProjectInfoDto>(json);
}
+ Utils::expected_str<ProjectInfoDto> ProjectInfoDto::deserializeExpected(const QByteArray &json)
+ {
+ return deserializeExp<ProjectInfoDto>(json);
+ }
+
ProjectInfoDto::ProjectInfoDto(
QString name,
std::optional<QString> issueFilterHelp,
@@ -4244,7 +4577,6 @@ namespace Axivion::Internal::Dto {
hasHiddenIssues(std::move(hasHiddenIssues))
{ }
- // throws Axivion::Internal::Dto::invalid_dto_exception
QByteArray ProjectInfoDto::serialize() const
{
return serialize_bytes(*this);
@@ -4261,7 +4593,8 @@ namespace Axivion::Internal::Dto {
{
public:
// throws Axivion::Internal::Dto::invalid_dto_exception
- static RepositoryUpdateResponseDto deserialize(const QJsonValue &json) {
+ static RepositoryUpdateResponseDto deserialize(const QJsonValue &json)
+ {
const QJsonObject jo = toJsonObject<RepositoryUpdateResponseDto>(json);
return {
deserialize_field<std::vector<RepositoryUpdateMessageDto>>(jo, repositoryUpdateResponseKeyMessages),
@@ -4270,7 +4603,8 @@ namespace Axivion::Internal::Dto {
};
}
- static QJsonValue serialize(const RepositoryUpdateResponseDto &value) {
+ static QJsonValue serialize(const RepositoryUpdateResponseDto &value)
+ {
QJsonObject jo;
serialize_field(jo, repositoryUpdateResponseKeyMessages, value.messages);
serialize_field(jo, repositoryUpdateResponseKeyHasErrors, value.hasErrors);
@@ -4288,6 +4622,11 @@ namespace Axivion::Internal::Dto {
return deserialize_bytes<RepositoryUpdateResponseDto>(json);
}
+ Utils::expected_str<RepositoryUpdateResponseDto> RepositoryUpdateResponseDto::deserializeExpected(const QByteArray &json)
+ {
+ return deserializeExp<RepositoryUpdateResponseDto>(json);
+ }
+
RepositoryUpdateResponseDto::RepositoryUpdateResponseDto(
std::vector<RepositoryUpdateMessageDto> messages,
bool hasErrors,
@@ -4298,7 +4637,6 @@ namespace Axivion::Internal::Dto {
hasWarnings(std::move(hasWarnings))
{ }
- // throws Axivion::Internal::Dto::invalid_dto_exception
QByteArray RepositoryUpdateResponseDto::serialize() const
{
return serialize_bytes(*this);
@@ -4318,7 +4656,8 @@ namespace Axivion::Internal::Dto {
{
public:
// throws Axivion::Internal::Dto::invalid_dto_exception
- static TableInfoDto deserialize(const QJsonValue &json) {
+ static TableInfoDto deserialize(const QJsonValue &json)
+ {
const QJsonObject jo = toJsonObject<TableInfoDto>(json);
return {
deserialize_field<QString>(jo, tableInfoKeyTableDataUri),
@@ -4330,7 +4669,8 @@ namespace Axivion::Internal::Dto {
};
}
- static QJsonValue serialize(const TableInfoDto &value) {
+ static QJsonValue serialize(const TableInfoDto &value)
+ {
QJsonObject jo;
serialize_field(jo, tableInfoKeyTableDataUri, value.tableDataUri);
serialize_field(jo, tableInfoKeyIssueBaseViewUri, value.issueBaseViewUri);
@@ -4351,6 +4691,11 @@ namespace Axivion::Internal::Dto {
return deserialize_bytes<TableInfoDto>(json);
}
+ Utils::expected_str<TableInfoDto> TableInfoDto::deserializeExpected(const QByteArray &json)
+ {
+ return deserializeExp<TableInfoDto>(json);
+ }
+
TableInfoDto::TableInfoDto(
QString tableDataUri,
std::optional<QString> issueBaseViewUri,
@@ -4367,7 +4712,6 @@ namespace Axivion::Internal::Dto {
axivionDefaultFilter(std::move(axivionDefaultFilter))
{ }
- // throws Axivion::Internal::Dto::invalid_dto_exception
QByteArray TableInfoDto::serialize() const
{
return serialize_bytes(*this);
diff --git a/src/plugins/axivion/dashboard/dto.h b/src/plugins/axivion/dashboard/dto.h
index fea5ab4ee1..4543df7d54 100644
--- a/src/plugins/axivion/dashboard/dto.h
+++ b/src/plugins/axivion/dashboard/dto.h
@@ -14,6 +14,8 @@
* <AxivionSuiteRepo>/projects/libs/dashboard_cpp_api/generator/generate_dashboard_cpp_api.py
*/
+#include <utils/expected.h>
+
#include <QAnyStringView>
#include <QByteArray>
#include <QHashFunctions>
@@ -70,6 +72,8 @@ namespace Axivion::Internal::Dto
// Throws Axivion::Internal::Dto::invalid_dto_exception
static Any deserialize(const QByteArray &json);
+ static Utils::expected_str<Any> deserializeExpected(const QByteArray &json);
+
Any();
Any(QString value);
@@ -171,6 +175,8 @@ namespace Axivion::Internal::Dto
// Throws Axivion::Internal::Dto::invalid_dto_exception
static AnalyzedFileDto deserialize(const QByteArray &json);
+ static Utils::expected_str<AnalyzedFileDto> deserializeExpected(const QByteArray &json);
+
AnalyzedFileDto(
QString path,
std::optional<bool> isSystemHeader,
@@ -219,6 +225,8 @@ namespace Axivion::Internal::Dto
// Throws std::range_error
static ApiTokenType strToEnum(QAnyStringView str);
+ static std::optional<ApiTokenType> strToOptionalEnum(QAnyStringView str);
+
static QLatin1String enumToStr(ApiTokenType e);
ApiTokenTypeMeta() = delete;
@@ -245,6 +253,8 @@ namespace Axivion::Internal::Dto
// Throws Axivion::Internal::Dto::invalid_dto_exception
static ChangePasswordFormDto deserialize(const QByteArray &json);
+ static Utils::expected_str<ChangePasswordFormDto> deserializeExpected(const QByteArray &json);
+
ChangePasswordFormDto(
QString currentPassword,
QString newPassword
@@ -295,6 +305,8 @@ namespace Axivion::Internal::Dto
// Throws std::range_error
static ColumnType strToEnum(QAnyStringView str);
+ static std::optional<ColumnType> strToOptionalEnum(QAnyStringView str);
+
static QLatin1String enumToStr(ColumnType e);
ColumnTypeMeta() = delete;
@@ -332,6 +344,8 @@ namespace Axivion::Internal::Dto
// Throws Axivion::Internal::Dto::invalid_dto_exception
static ColumnTypeOptionDto deserialize(const QByteArray &json);
+ static Utils::expected_str<ColumnTypeOptionDto> deserializeExpected(const QByteArray &json);
+
ColumnTypeOptionDto(
QString key,
std::optional<QString> displayName,
@@ -356,6 +370,8 @@ namespace Axivion::Internal::Dto
// Throws Axivion::Internal::Dto::invalid_dto_exception
static CommentRequestDto deserialize(const QByteArray &json);
+ static Utils::expected_str<CommentRequestDto> deserializeExpected(const QByteArray &json);
+
CommentRequestDto(
QString text
);
@@ -384,6 +400,8 @@ namespace Axivion::Internal::Dto
// Throws Axivion::Internal::Dto::invalid_dto_exception
static CsrfTokenDto deserialize(const QByteArray &json);
+ static Utils::expected_str<CsrfTokenDto> deserializeExpected(const QByteArray &json);
+
CsrfTokenDto(
QString csrfToken
);
@@ -427,6 +445,8 @@ namespace Axivion::Internal::Dto
// Throws Axivion::Internal::Dto::invalid_dto_exception
static EntityDto deserialize(const QByteArray &json);
+ static Utils::expected_str<EntityDto> deserializeExpected(const QByteArray &json);
+
EntityDto(
QString id,
QString name,
@@ -544,6 +564,8 @@ namespace Axivion::Internal::Dto
// Throws Axivion::Internal::Dto::invalid_dto_exception
static ErrorDto deserialize(const QByteArray &json);
+ static Utils::expected_str<ErrorDto> deserializeExpected(const QByteArray &json);
+
ErrorDto(
std::optional<QString> dashboardVersionNumber,
QString type,
@@ -613,6 +635,8 @@ namespace Axivion::Internal::Dto
// Throws Axivion::Internal::Dto::invalid_dto_exception
static IssueCommentDto deserialize(const QByteArray &json);
+ static Utils::expected_str<IssueCommentDto> deserializeExpected(const QByteArray &json);
+
IssueCommentDto(
QString username,
QString userDisplayName,
@@ -654,6 +678,8 @@ namespace Axivion::Internal::Dto
// Throws std::range_error
static IssueKind strToEnum(QAnyStringView str);
+ static std::optional<IssueKind> strToOptionalEnum(QAnyStringView str);
+
static QLatin1String enumToStr(IssueKind e);
IssueKindMeta() = delete;
@@ -690,6 +716,8 @@ namespace Axivion::Internal::Dto
// Throws std::range_error
static IssueKindForNamedFilterCreation strToEnum(QAnyStringView str);
+ static std::optional<IssueKindForNamedFilterCreation> strToOptionalEnum(QAnyStringView str);
+
static QLatin1String enumToStr(IssueKindForNamedFilterCreation e);
IssueKindForNamedFilterCreationMeta() = delete;
@@ -759,6 +787,8 @@ namespace Axivion::Internal::Dto
// Throws Axivion::Internal::Dto::invalid_dto_exception
static IssueSourceLocationDto deserialize(const QByteArray &json);
+ static Utils::expected_str<IssueSourceLocationDto> deserializeExpected(const QByteArray &json);
+
IssueSourceLocationDto(
QString fileName,
std::optional<QString> role,
@@ -795,6 +825,8 @@ namespace Axivion::Internal::Dto
// Throws Axivion::Internal::Dto::invalid_dto_exception
static IssueTagDto deserialize(const QByteArray &json);
+ static Utils::expected_str<IssueTagDto> deserializeExpected(const QByteArray &json);
+
IssueTagDto(
QString tag,
QString color
@@ -851,6 +883,8 @@ namespace Axivion::Internal::Dto
// Throws Axivion::Internal::Dto::invalid_dto_exception
static IssueTagTypeDto deserialize(const QByteArray &json);
+ static Utils::expected_str<IssueTagTypeDto> deserializeExpected(const QByteArray &json);
+
IssueTagTypeDto(
QString id,
std::optional<QString> text,
@@ -893,6 +927,8 @@ namespace Axivion::Internal::Dto
// Throws std::range_error
static MessageSeverity strToEnum(QAnyStringView str);
+ static std::optional<MessageSeverity> strToOptionalEnum(QAnyStringView str);
+
static QLatin1String enumToStr(MessageSeverity e);
MessageSeverityMeta() = delete;
@@ -937,6 +973,8 @@ namespace Axivion::Internal::Dto
// Throws Axivion::Internal::Dto::invalid_dto_exception
static MetricDto deserialize(const QByteArray &json);
+ static Utils::expected_str<MetricDto> deserializeExpected(const QByteArray &json);
+
MetricDto(
QString name,
QString displayName,
@@ -996,6 +1034,8 @@ namespace Axivion::Internal::Dto
// Throws Axivion::Internal::Dto::invalid_dto_exception
static MetricValueTableRowDto deserialize(const QByteArray &json);
+ static Utils::expected_str<MetricValueTableRowDto> deserializeExpected(const QByteArray &json);
+
MetricValueTableRowDto(
QString metric,
std::optional<QString> path,
@@ -1033,6 +1073,8 @@ namespace Axivion::Internal::Dto
// Throws std::range_error
static NamedFilterType strToEnum(QAnyStringView str);
+ static std::optional<NamedFilterType> strToOptionalEnum(QAnyStringView str);
+
static QLatin1String enumToStr(NamedFilterType e);
NamedFilterTypeMeta() = delete;
@@ -1062,6 +1104,8 @@ namespace Axivion::Internal::Dto
// Throws Axivion::Internal::Dto::invalid_dto_exception
static NamedFilterVisibilityDto deserialize(const QByteArray &json);
+ static Utils::expected_str<NamedFilterVisibilityDto> deserializeExpected(const QByteArray &json);
+
NamedFilterVisibilityDto(
std::optional<std::vector<QString>> groups
);
@@ -1089,6 +1133,8 @@ namespace Axivion::Internal::Dto
// Throws Axivion::Internal::Dto::invalid_dto_exception
static ProjectReferenceDto deserialize(const QByteArray &json);
+ static Utils::expected_str<ProjectReferenceDto> deserializeExpected(const QByteArray &json);
+
ProjectReferenceDto(
QString name,
QString url
@@ -1127,6 +1173,8 @@ namespace Axivion::Internal::Dto
// Throws Axivion::Internal::Dto::invalid_dto_exception
static RuleDto deserialize(const QByteArray &json);
+ static Utils::expected_str<RuleDto> deserializeExpected(const QByteArray &json);
+
RuleDto(
QString name,
QString original_name,
@@ -1157,6 +1205,8 @@ namespace Axivion::Internal::Dto
// Throws std::range_error
static SortDirection strToEnum(QAnyStringView str);
+ static std::optional<SortDirection> strToOptionalEnum(QAnyStringView str);
+
static QLatin1String enumToStr(SortDirection e);
SortDirectionMeta() = delete;
@@ -1187,6 +1237,8 @@ namespace Axivion::Internal::Dto
// Throws std::range_error
static TableCellAlignment strToEnum(QAnyStringView str);
+ static std::optional<TableCellAlignment> strToOptionalEnum(QAnyStringView str);
+
static QLatin1String enumToStr(TableCellAlignment e);
TableCellAlignmentMeta() = delete;
@@ -1218,6 +1270,8 @@ namespace Axivion::Internal::Dto
// Throws Axivion::Internal::Dto::invalid_dto_exception
static ToolsVersionDto deserialize(const QByteArray &json);
+ static Utils::expected_str<ToolsVersionDto> deserializeExpected(const QByteArray &json);
+
ToolsVersionDto(
QString name,
QString number,
@@ -1253,6 +1307,8 @@ namespace Axivion::Internal::Dto
// Throws std::range_error
static UserRefType strToEnum(QAnyStringView str);
+ static std::optional<UserRefType> strToOptionalEnum(QAnyStringView str);
+
static QLatin1String enumToStr(UserRefType e);
UserRefTypeMeta() = delete;
@@ -1284,6 +1340,8 @@ namespace Axivion::Internal::Dto
// Throws Axivion::Internal::Dto::invalid_dto_exception
static VersionKindCountDto deserialize(const QByteArray &json);
+ static Utils::expected_str<VersionKindCountDto> deserializeExpected(const QByteArray &json);
+
VersionKindCountDto(
qint32 Total,
qint32 Added,
@@ -1392,6 +1450,8 @@ namespace Axivion::Internal::Dto
// Throws Axivion::Internal::Dto::invalid_dto_exception
static AnalysisVersionDto deserialize(const QByteArray &json);
+ static Utils::expected_str<AnalysisVersionDto> deserializeExpected(const QByteArray &json);
+
AnalysisVersionDto(
QString date,
std::optional<QString> label,
@@ -1450,6 +1510,8 @@ namespace Axivion::Internal::Dto
// Throws Axivion::Internal::Dto::invalid_dto_exception
static ApiTokenCreationRequestDto deserialize(const QByteArray &json);
+ static Utils::expected_str<ApiTokenCreationRequestDto> deserializeExpected(const QByteArray &json);
+
ApiTokenCreationRequestDto(
QString password,
QString type,
@@ -1568,6 +1630,8 @@ namespace Axivion::Internal::Dto
// Throws Axivion::Internal::Dto::invalid_dto_exception
static ApiTokenInfoDto deserialize(const QByteArray &json);
+ static Utils::expected_str<ApiTokenInfoDto> deserializeExpected(const QByteArray &json);
+
ApiTokenInfoDto(
QString id,
QString url,
@@ -1693,6 +1757,8 @@ namespace Axivion::Internal::Dto
// Throws Axivion::Internal::Dto::invalid_dto_exception
static ColumnInfoDto deserialize(const QByteArray &json);
+ static Utils::expected_str<ColumnInfoDto> deserializeExpected(const QByteArray &json);
+
ColumnInfoDto(
QString key,
std::optional<QString> header,
@@ -1726,7 +1792,7 @@ namespace Axivion::Internal::Dto
void setAlignmentEnum(TableCellAlignment newValue);
- // Throws std::range_error
+ // Throws std::range_error
ColumnType getTypeEnum() const;
std::optional<ColumnType> getOptionalTypeEnum() const;
@@ -1859,6 +1925,8 @@ namespace Axivion::Internal::Dto
// Throws Axivion::Internal::Dto::invalid_dto_exception
static DashboardInfoDto deserialize(const QByteArray &json);
+ static Utils::expected_str<DashboardInfoDto> deserializeExpected(const QByteArray &json);
+
DashboardInfoDto(
std::optional<QString> mainUrl,
QString dashboardVersion,
@@ -1895,6 +1963,8 @@ namespace Axivion::Internal::Dto
// Throws Axivion::Internal::Dto::invalid_dto_exception
static IssueCommentListDto deserialize(const QByteArray &json);
+ static Utils::expected_str<IssueCommentListDto> deserializeExpected(const QByteArray &json);
+
IssueCommentListDto(
std::vector<IssueCommentDto> comments
);
@@ -1929,6 +1999,8 @@ namespace Axivion::Internal::Dto
// Throws Axivion::Internal::Dto::invalid_dto_exception
static IssueKindInfoDto deserialize(const QByteArray &json);
+ static Utils::expected_str<IssueKindInfoDto> deserializeExpected(const QByteArray &json);
+
IssueKindInfoDto(
QString prefix,
QString niceSingularName,
@@ -1966,6 +2038,8 @@ namespace Axivion::Internal::Dto
// Throws Axivion::Internal::Dto::invalid_dto_exception
static IssueTagTypeListDto deserialize(const QByteArray &json);
+ static Utils::expected_str<IssueTagTypeListDto> deserializeExpected(const QByteArray &json);
+
IssueTagTypeListDto(
std::vector<IssueTagTypeDto> tags
);
@@ -2056,6 +2130,8 @@ namespace Axivion::Internal::Dto
// Throws Axivion::Internal::Dto::invalid_dto_exception
static LineMarkerDto deserialize(const QByteArray &json);
+ static Utils::expected_str<LineMarkerDto> deserializeExpected(const QByteArray &json);
+
LineMarkerDto(
QString kind,
std::optional<qint64> id,
@@ -2115,6 +2191,8 @@ namespace Axivion::Internal::Dto
// Throws Axivion::Internal::Dto::invalid_dto_exception
static RepositoryUpdateMessageDto deserialize(const QByteArray &json);
+ static Utils::expected_str<RepositoryUpdateMessageDto> deserializeExpected(const QByteArray &json);
+
RepositoryUpdateMessageDto(
QString severity,
QString message
@@ -2150,6 +2228,8 @@ namespace Axivion::Internal::Dto
// Throws Axivion::Internal::Dto::invalid_dto_exception
static RuleListDto deserialize(const QByteArray &json);
+ static Utils::expected_str<RuleListDto> deserializeExpected(const QByteArray &json);
+
RuleListDto(
std::vector<RuleDto> rules
);
@@ -2179,6 +2259,8 @@ namespace Axivion::Internal::Dto
// Throws Axivion::Internal::Dto::invalid_dto_exception
static SortInfoDto deserialize(const QByteArray &json);
+ static Utils::expected_str<SortInfoDto> deserializeExpected(const QByteArray &json);
+
SortInfoDto(
QString key,
QString direction
@@ -2235,6 +2317,8 @@ namespace Axivion::Internal::Dto
// Throws Axivion::Internal::Dto::invalid_dto_exception
static UserRefDto deserialize(const QByteArray &json);
+ static Utils::expected_str<UserRefDto> deserializeExpected(const QByteArray &json);
+
UserRefDto(
QString name,
QString displayName,
@@ -2279,6 +2363,8 @@ namespace Axivion::Internal::Dto
// Throws Axivion::Internal::Dto::invalid_dto_exception
static AnalyzedFileListDto deserialize(const QByteArray &json);
+ static Utils::expected_str<AnalyzedFileListDto> deserializeExpected(const QByteArray &json);
+
AnalyzedFileListDto(
AnalysisVersionDto version,
std::vector<AnalyzedFileDto> rows
@@ -2307,6 +2393,8 @@ namespace Axivion::Internal::Dto
// Throws Axivion::Internal::Dto::invalid_dto_exception
static EntityListDto deserialize(const QByteArray &json);
+ static Utils::expected_str<EntityListDto> deserializeExpected(const QByteArray &json);
+
EntityListDto(
std::optional<AnalysisVersionDto> version,
std::vector<EntityDto> entities
@@ -2355,6 +2443,8 @@ namespace Axivion::Internal::Dto
// Throws Axivion::Internal::Dto::invalid_dto_exception
static FileViewDto deserialize(const QByteArray &json);
+ static Utils::expected_str<FileViewDto> deserializeExpected(const QByteArray &json);
+
FileViewDto(
QString fileName,
std::optional<QString> version,
@@ -2418,6 +2508,8 @@ namespace Axivion::Internal::Dto
// Throws Axivion::Internal::Dto::invalid_dto_exception
static IssueDto deserialize(const QByteArray &json);
+ static Utils::expected_str<IssueDto> deserializeExpected(const QByteArray &json);
+
IssueDto(
QString kind,
qint64 id,
@@ -2532,6 +2624,8 @@ namespace Axivion::Internal::Dto
// Throws Axivion::Internal::Dto::invalid_dto_exception
static IssueTableDto deserialize(const QByteArray &json);
+ static Utils::expected_str<IssueTableDto> deserializeExpected(const QByteArray &json);
+
IssueTableDto(
std::optional<AnalysisVersionDto> startVersion,
AnalysisVersionDto endVersion,
@@ -2566,6 +2660,8 @@ namespace Axivion::Internal::Dto
// Throws Axivion::Internal::Dto::invalid_dto_exception
static MetricListDto deserialize(const QByteArray &json);
+ static Utils::expected_str<MetricListDto> deserializeExpected(const QByteArray &json);
+
MetricListDto(
std::optional<AnalysisVersionDto> version,
std::vector<MetricDto> metrics
@@ -2617,6 +2713,8 @@ namespace Axivion::Internal::Dto
// Throws Axivion::Internal::Dto::invalid_dto_exception
static MetricValueRangeDto deserialize(const QByteArray &json);
+ static Utils::expected_str<MetricValueRangeDto> deserializeExpected(const QByteArray &json);
+
MetricValueRangeDto(
AnalysisVersionDto startVersion,
AnalysisVersionDto endVersion,
@@ -2650,6 +2748,8 @@ namespace Axivion::Internal::Dto
// Throws Axivion::Internal::Dto::invalid_dto_exception
static MetricValueTableDto deserialize(const QByteArray &json);
+ static Utils::expected_str<MetricValueTableDto> deserializeExpected(const QByteArray &json);
+
MetricValueTableDto(
std::vector<ColumnInfoDto> columns,
std::vector<MetricValueTableRowDto> rows
@@ -2712,6 +2812,8 @@ namespace Axivion::Internal::Dto
// Throws Axivion::Internal::Dto::invalid_dto_exception
static NamedFilterCreateDto deserialize(const QByteArray &json);
+ static Utils::expected_str<NamedFilterCreateDto> deserializeExpected(const QByteArray &json);
+
NamedFilterCreateDto(
QString displayName,
QString kind,
@@ -2834,6 +2936,8 @@ namespace Axivion::Internal::Dto
// Throws Axivion::Internal::Dto::invalid_dto_exception
static NamedFilterInfoDto deserialize(const QByteArray &json);
+ static Utils::expected_str<NamedFilterInfoDto> deserializeExpected(const QByteArray &json);
+
NamedFilterInfoDto(
QString key,
QString displayName,
@@ -2924,6 +3028,8 @@ namespace Axivion::Internal::Dto
// Throws Axivion::Internal::Dto::invalid_dto_exception
static NamedFilterUpdateDto deserialize(const QByteArray &json);
+ static Utils::expected_str<NamedFilterUpdateDto> deserializeExpected(const QByteArray &json);
+
NamedFilterUpdateDto(
std::optional<QString> name,
std::optional<std::map<QString, QString>> filters,
@@ -2983,6 +3089,8 @@ namespace Axivion::Internal::Dto
// Throws Axivion::Internal::Dto::invalid_dto_exception
static ProjectInfoDto deserialize(const QByteArray &json);
+ static Utils::expected_str<ProjectInfoDto> deserializeExpected(const QByteArray &json);
+
ProjectInfoDto(
QString name,
std::optional<QString> issueFilterHelp,
@@ -3024,6 +3132,8 @@ namespace Axivion::Internal::Dto
// Throws Axivion::Internal::Dto::invalid_dto_exception
static RepositoryUpdateResponseDto deserialize(const QByteArray &json);
+ static Utils::expected_str<RepositoryUpdateResponseDto> deserializeExpected(const QByteArray &json);
+
RepositoryUpdateResponseDto(
std::vector<RepositoryUpdateMessageDto> messages,
bool hasErrors,
@@ -3091,6 +3201,8 @@ namespace Axivion::Internal::Dto
// Throws Axivion::Internal::Dto::invalid_dto_exception
static TableInfoDto deserialize(const QByteArray &json);
+ static Utils::expected_str<TableInfoDto> deserializeExpected(const QByteArray &json);
+
TableInfoDto(
QString tableDataUri,
std::optional<QString> issueBaseViewUri,
diff --git a/src/plugins/axivion/dynamiclistmodel.cpp b/src/plugins/axivion/dynamiclistmodel.cpp
new file mode 100644
index 0000000000..70abe087bd
--- /dev/null
+++ b/src/plugins/axivion/dynamiclistmodel.cpp
@@ -0,0 +1,194 @@
+// 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 "dynamiclistmodel.h"
+
+#include "axiviontr.h"
+
+#include <utils/qtcassert.h>
+#include <utils/theme/theme.h>
+
+namespace Axivion::Internal {
+
+constexpr int pageSize = 150;
+
+DynamicListModel::DynamicListModel(QObject *parent)
+ : QAbstractItemModel(parent)
+{
+ m_fetchMoreTimer.setSingleShot(true);
+ m_fetchMoreTimer.setInterval(50);
+ connect(&m_fetchMoreTimer, &QTimer::timeout, this, &DynamicListModel::fetchNow);
+}
+
+DynamicListModel::~DynamicListModel()
+{
+ clear();
+}
+
+QModelIndex DynamicListModel::index(int row, int column, const QModelIndex &parent) const
+{
+ if (parent.isValid())
+ return {};
+ if (row < m_expectedRowCount.value_or(m_children.size())) {
+ auto it = m_children.constFind(row);
+ return createIndex(row, column, it != m_children.constEnd() ? it.value() : nullptr);
+ }
+ return {};
+}
+
+QModelIndex DynamicListModel::parent(const QModelIndex &/*child*/) const
+{
+ return {};
+}
+
+int DynamicListModel::rowCount(const QModelIndex &parent) const
+{
+ if (parent.isValid()) // for simplicity only single level
+ return 0;
+
+ return m_expectedRowCount.value_or(m_children.size());
+}
+
+int DynamicListModel::columnCount(const QModelIndex &/*parent*/) const
+{
+ return m_columnCount;
+}
+
+QVariant DynamicListModel::data(const QModelIndex &index, int role) const
+{
+ const int row = index.row();
+ if (!index.isValid() || row < 0 || row > m_expectedRowCount.value_or(m_children.size()))
+ return {};
+
+ auto item = m_children.constFind(row);
+ if (item != m_children.cend()) {
+ if (role == Qt::TextAlignmentRole) {
+ if (!m_alignments.isEmpty() && index.column() < m_alignments.size())
+ return QVariant::fromValue(m_alignments.at(index.column()));
+ }
+ return item.value()->data(index.column(), role);
+ }
+
+ if ((row < m_lastFetch || row > m_lastFetchEnd) && (row < m_fetchStart || row > m_fetchEnd))
+ const_cast<DynamicListModel *>(this)->onNeedFetch(row);
+ if (role == Qt::DisplayRole && index.column() == 0)
+ return Tr::tr("Fetching..."); // TODO improve/customize?
+ if (role == Qt::ForegroundRole && index.column() == 0)
+ return Utils::creatorTheme()->color(Utils::Theme::TextColorDisabled);
+ return {};
+}
+
+bool DynamicListModel::setData(const QModelIndex &index, const QVariant &value, int role)
+{
+ auto found = m_children.constFind(index.row());
+ if (found == m_children.constEnd())
+ return false;
+ return found.value()->setData(index.column(), value, role);
+}
+
+QVariant DynamicListModel::headerData(int section, Qt::Orientation orientation, int role) const
+{
+ if (orientation == Qt::Horizontal && role == Qt::DisplayRole && section < m_header.size())
+ return m_header.at(section);
+ return {};
+}
+
+void DynamicListModel::setItems(const QList<ListItem *> &items)
+{
+ m_lastFetchEnd = -1; // FIXME wrong.. better a callback? - should happen for failed requests too
+ // for simplicity we assume an ordered list and no non-existing items between first and last
+ if (items.isEmpty())
+ return;
+ // to keep it simple here, we expect the expectedRowCount to be set *before* adding items
+ QTC_ASSERT(m_expectedRowCount, setExpectedRowCount(items.size()));
+ if (int lastRow = items.last()->row; lastRow > *m_expectedRowCount)
+ m_expectedRowCount.emplace(lastRow);
+
+ emit layoutAboutToBeChanged();
+ auto end = m_children.end();
+ for (ListItem *it : items) {
+ auto found = m_children.find(it->row); // check for old data to be removed
+ ListItem *old = nullptr;
+ if (found != end)
+ old = found.value();
+ m_children.insert(it->row, it);
+ delete old;
+ }
+ emit dataChanged(indexForItem(items.first()), indexForItem(items.last()));
+ emit layoutChanged();
+}
+
+void DynamicListModel::clear()
+{
+ beginResetModel();
+ qDeleteAll(m_children);
+ m_children.clear();
+ m_expectedRowCount.reset();
+ endResetModel();
+}
+
+void DynamicListModel::setExpectedRowCount(int expected)
+{
+ QTC_ASSERT(expected >= m_children.size(), return);
+ if (expected == m_children.size())
+ return;
+ beginInsertRows({}, m_children.size(), expected);
+ m_expectedRowCount.emplace(expected);
+ endInsertRows();
+}
+
+void DynamicListModel::setHeader(const QStringList &header)
+{
+ m_header = header;
+ m_columnCount = m_header.size();
+}
+
+void DynamicListModel::setAlignments(const QList<Qt::Alignment> &alignments)
+{
+ m_alignments = alignments;
+}
+
+QModelIndex DynamicListModel::indexForItem(const ListItem *item) const
+{
+ QTC_ASSERT(item, return {});
+ auto found = m_children.constFind(item->row);
+ if (found == m_children.cend())
+ return {};
+ QTC_ASSERT(found.value() == item, return {});
+ return createIndex(item->row, 0, item);
+}
+
+void DynamicListModel::onNeedFetch(int row)
+{
+ m_fetchStart = row;
+ m_fetchEnd = row + pageSize;
+ if (m_fetchStart < 0)
+ return;
+ m_fetchMoreTimer.start();
+}
+
+void DynamicListModel::fetchNow()
+{
+ const int old = m_lastFetch;
+ m_lastFetch = m_fetchStart; // we need the "original" fetch request to avoid endless loop
+ m_lastFetchEnd = m_fetchStart + pageSize;
+
+ if (old != -1) {
+ const int diff = old - m_fetchStart;
+ if (0 < diff && diff < pageSize) {
+ m_fetchStart = qMax(old - pageSize, 0);
+ } else if (0 > diff && diff > -pageSize) {
+ m_fetchStart = old + pageSize;
+ if (m_expectedRowCount && m_fetchStart > *m_expectedRowCount)
+ m_fetchStart = *m_expectedRowCount;
+ }
+ }
+
+ QTC_CHECK(m_expectedRowCount ? m_fetchStart <= *m_expectedRowCount
+ : m_fetchStart >= m_children.size());
+ emit fetchRequested(m_fetchStart, pageSize);
+ m_fetchStart = -1;
+ m_fetchEnd = -1;
+}
+
+} // namespace Axivion::Internal
diff --git a/src/plugins/axivion/dynamiclistmodel.h b/src/plugins/axivion/dynamiclistmodel.h
new file mode 100644
index 0000000000..d60f9f1615
--- /dev/null
+++ b/src/plugins/axivion/dynamiclistmodel.h
@@ -0,0 +1,69 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#pragma once
+
+#include <QAbstractItemModel>
+#include <QHash>
+#include <QTimer>
+#include <QVariant>
+
+#include <optional>
+
+namespace Axivion::Internal {
+
+class ListItem
+{
+public:
+ explicit ListItem(int row) : row(row) {}
+ virtual ~ListItem() = default;
+ virtual bool setData(int /*column*/, const QVariant &/*value*/, int /*role*/) { return false; }
+ virtual QVariant data(int /*column*/, int /*role*/) const { return {}; }
+
+ const int row;
+};
+
+class DynamicListModel : public QAbstractItemModel
+{
+ Q_OBJECT
+public:
+ explicit DynamicListModel(QObject *parent = nullptr);
+ ~DynamicListModel();
+
+ QModelIndex index(int row, int column, const QModelIndex &parent) const override;
+ QModelIndex parent(const QModelIndex &child) const override;
+ int rowCount(const QModelIndex &parent = QModelIndex()) const override;
+ int columnCount(const QModelIndex &parent) const override;
+ QVariant data(const QModelIndex &index, int role) const override;
+ bool setData(const QModelIndex&, const QVariant &value, int role) override;
+ QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
+
+ void setItems(const QList<ListItem *> &items);
+ void clear();
+
+ void setExpectedRowCount(int expected);
+ void setHeader(const QStringList &header);
+ void setAlignments(const QList<Qt::Alignment> &alignments);
+
+ QModelIndex indexForItem(const ListItem *item) const;
+
+signals:
+ void fetchRequested(int startRow, int limit);
+
+private:
+ void onNeedFetch(int row);
+ void fetchNow();
+
+ QHash<int, ListItem *> m_children;
+ QStringList m_header;
+ QList<Qt::Alignment> m_alignments;
+ QTimer m_fetchMoreTimer;
+ std::optional<int> m_expectedRowCount = {};
+ int m_fetchStart = -1;
+ int m_fetchEnd = -1;
+ int m_lastFetch = -1;
+ int m_lastFetchEnd = -1;
+ int m_columnCount = 0;
+};
+
+} // namespace Axivion::Internal
diff --git a/src/plugins/axivion/images/sortAsc.png b/src/plugins/axivion/images/sortAsc.png
new file mode 100644
index 0000000000..c907297279
--- /dev/null
+++ b/src/plugins/axivion/images/sortAsc.png
Binary files differ
diff --git a/src/plugins/axivion/images/sortAsc@2x.png b/src/plugins/axivion/images/sortAsc@2x.png
new file mode 100644
index 0000000000..b99d922b32
--- /dev/null
+++ b/src/plugins/axivion/images/sortAsc@2x.png
Binary files differ
diff --git a/src/plugins/axivion/images/sortDesc.png b/src/plugins/axivion/images/sortDesc.png
new file mode 100644
index 0000000000..a92d018d4e
--- /dev/null
+++ b/src/plugins/axivion/images/sortDesc.png
Binary files differ
diff --git a/src/plugins/axivion/images/sortDesc@2x.png b/src/plugins/axivion/images/sortDesc@2x.png
new file mode 100644
index 0000000000..9991ff2955
--- /dev/null
+++ b/src/plugins/axivion/images/sortDesc@2x.png
Binary files differ
diff --git a/src/plugins/axivion/issueheaderview.cpp b/src/plugins/axivion/issueheaderview.cpp
new file mode 100644
index 0000000000..3f8efd86c6
--- /dev/null
+++ b/src/plugins/axivion/issueheaderview.cpp
@@ -0,0 +1,141 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#include "issueheaderview.h"
+
+#include <utils/icon.h>
+
+#include <QMouseEvent>
+#include <QPainter>
+
+namespace Axivion::Internal {
+
+constexpr int ICON_SIZE = 16;
+
+static QIcon iconForSorted(SortOrder order)
+{
+ const Utils::Icon UNSORTED(
+ {{":/axivion/images/sortAsc.png", Utils::Theme::IconsDisabledColor},
+ {":/axivion/images/sortDesc.png", Utils::Theme::IconsDisabledColor}});
+ const Utils::Icon SORT_ASC(
+ {{":/axivion/images/sortAsc.png", Utils::Theme::PaletteText},
+ {":/axivion/images/sortDesc.png", Utils::Theme::IconsDisabledColor}});
+ const Utils::Icon SORT_DESC(
+ {{":/axivion/images/sortAsc.png", Utils::Theme::IconsDisabledColor},
+ {":/axivion/images/sortDesc.png", Utils::Theme::PaletteText}});
+ static const QIcon unsorted = UNSORTED.icon();
+ static const QIcon sortedAsc = SORT_ASC.icon();
+ static const QIcon sortedDesc = SORT_DESC.icon();
+
+ switch (order) {
+ case SortOrder::None:
+ return unsorted;
+ case SortOrder::Ascending:
+ return sortedAsc;
+ case SortOrder::Descending:
+ return sortedDesc;
+ }
+ return {};
+}
+
+void IssueHeaderView::setSortableColumns(const QList<bool> &sortable)
+{
+ m_sortableColumns = sortable;
+ int oldIndex = m_currentSortIndex;
+ m_currentSortIndex = -1;
+ m_currentSortOrder = SortOrder::None;
+ if (oldIndex != -1)
+ headerDataChanged(Qt::Horizontal, oldIndex, oldIndex);
+}
+
+int IssueHeaderView::currentSortColumn() const
+{
+ return m_currentSortOrder == SortOrder::None ? -1 : m_currentSortIndex;
+}
+
+void IssueHeaderView::mousePressEvent(QMouseEvent *event)
+{
+ if (event->button() == Qt::LeftButton) {
+ const QPoint position = event->position().toPoint();
+ const int y = position.y();
+ if (y > 1 && y < height() - 2) { // TODO improve
+ const int pos = position.x();
+ const int logical = logicalIndexAt(pos);
+ const int end = sectionViewportPosition(logical) + sectionSize(logical);
+ const int start = end - ICON_SIZE - 2;
+ m_maybeToggleSort = start < pos && end > pos;
+ }
+ }
+ QHeaderView::mousePressEvent(event);
+}
+
+void IssueHeaderView::mouseReleaseEvent(QMouseEvent *event)
+{
+ bool dontSkip = !m_dragging && m_maybeToggleSort;
+ m_dragging = false;
+ m_maybeToggleSort = false;
+
+ if (dontSkip) {
+ const QPoint position = event->position().toPoint();
+ const int y = position.y();
+ const int logical = logicalIndexAt(position.x());
+ if (logical > -1 && logical < m_sortableColumns.size()) {
+ if (m_sortableColumns.at(logical)) { // ignore non-sortable
+ if (y < height() / 2) // TODO improve
+ onToggleSort(logical, SortOrder::Ascending);
+ else
+ onToggleSort(logical, SortOrder::Descending);
+ }
+ }
+ }
+ QHeaderView::mouseReleaseEvent(event);
+}
+
+void IssueHeaderView::mouseMoveEvent(QMouseEvent *event)
+{
+ if (event->button() == Qt::LeftButton)
+ m_dragging = true;
+ QHeaderView::mouseMoveEvent(event);
+}
+
+void IssueHeaderView::onToggleSort(int index, SortOrder order)
+{
+ if (m_currentSortIndex == index)
+ m_currentSortOrder = (order == m_currentSortOrder) ? SortOrder::None : order;
+ else
+ m_currentSortOrder = order;
+
+ int oldIndex = m_currentSortIndex;
+ m_currentSortIndex = index;
+ if (oldIndex != -1)
+ headerDataChanged(Qt::Horizontal, oldIndex, oldIndex);
+ headerDataChanged(Qt::Horizontal, index, index);
+ emit sortTriggered();
+}
+
+QSize IssueHeaderView::sectionSizeFromContents(int logicalIndex) const
+{
+ const QSize oldSize = QHeaderView::sectionSizeFromContents(logicalIndex);
+ const QSize newSize = logicalIndex < m_columnWidths.size()
+ ? QSize(qMax(m_columnWidths.at(logicalIndex), oldSize.width()), oldSize.height()) : oldSize;
+ // add icon size and margin (2)
+ return QSize{newSize.width() + ICON_SIZE + 2, qMax(newSize.height(), ICON_SIZE)};
+}
+
+void IssueHeaderView::paintSection(QPainter *painter, const QRect &rect, int logicalIndex) const
+{
+ painter->save();
+ QHeaderView::paintSection(painter, rect, logicalIndex);
+ painter->restore();
+ if (logicalIndex < 0 || logicalIndex >= m_sortableColumns.size())
+ return;
+ if (!m_sortableColumns.at(logicalIndex))
+ return;
+
+ const QIcon icon = iconForSorted(logicalIndex == m_currentSortIndex ? m_currentSortOrder : SortOrder::None);
+ const int offset = qMax((rect.height() - ICON_SIZE), 0) / 2;
+ const QRect iconRect(rect.left() + rect.width() - ICON_SIZE - 2, offset, ICON_SIZE, ICON_SIZE);
+ icon.paint(painter, iconRect);
+}
+
+} // namespace Axivion::Internal
diff --git a/src/plugins/axivion/issueheaderview.h b/src/plugins/axivion/issueheaderview.h
new file mode 100644
index 0000000000..1fbbd9b76f
--- /dev/null
+++ b/src/plugins/axivion/issueheaderview.h
@@ -0,0 +1,44 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#pragma once
+
+#include <QHeaderView>
+#include <QList>
+
+namespace Axivion::Internal {
+
+enum class SortOrder { None, Ascending, Descending };
+
+class IssueHeaderView : public QHeaderView
+{
+ Q_OBJECT
+public:
+ explicit IssueHeaderView(QWidget *parent = nullptr) : QHeaderView(Qt::Horizontal, parent) {}
+ void setSortableColumns(const QList<bool> &sortable);
+ void setColumnWidths(const QList<int> &widths) { m_columnWidths = widths; }
+
+ SortOrder currentSortOrder() const { return m_currentSortOrder; }
+ int currentSortColumn() const;
+
+signals:
+ void sortTriggered();
+
+protected:
+ void paintSection(QPainter *painter, const QRect &rect, int logicalIndex) const override;
+ QSize sectionSizeFromContents(int logicalIndex) const override;
+ void mousePressEvent(QMouseEvent *event) override;
+ void mouseReleaseEvent(QMouseEvent *event) override;
+ void mouseMoveEvent(QMouseEvent *event) override;
+
+private:
+ void onToggleSort(int index, SortOrder order);
+ bool m_dragging = false;
+ bool m_maybeToggleSort = false;
+ int m_currentSortIndex = -1;
+ SortOrder m_currentSortOrder = SortOrder::None;
+ QList<bool> m_sortableColumns;
+ QList<int> m_columnWidths;
+};
+
+} // namespace Axivion::Internal
diff --git a/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp b/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp
index ddb928f5e9..c034ad82f6 100644
--- a/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp
+++ b/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp
@@ -294,10 +294,7 @@ ClangModelManagerSupport::ClangModelManagerSupport()
new ClangdQuickFixFactory(); // memory managed by CppEditor::g_cppQuickFixFactories
}
-ClangModelManagerSupport::~ClangModelManagerSupport()
-{
- m_generatorSynchronizer.waitForFinished();
-}
+ClangModelManagerSupport::~ClangModelManagerSupport() = default;
void ClangModelManagerSupport::followSymbol(const CursorInEditor &data,
const LinkHandler &processLinkCallback,
diff --git a/src/plugins/clangcodemodel/clangmodelmanagersupport.h b/src/plugins/clangcodemodel/clangmodelmanagersupport.h
index 839e71deb6..f1cb849202 100644
--- a/src/plugins/clangcodemodel/clangmodelmanagersupport.h
+++ b/src/plugins/clangcodemodel/clangmodelmanagersupport.h
@@ -94,10 +94,10 @@ private:
void scheduleClientRestart(ClangdClient *client);
static ClangdClient *clientWithProject(const ProjectExplorer::Project *project);
- Utils::FutureSynchronizer m_generatorSynchronizer;
QList<QPointer<ClangdClient>> m_clientsToRestart;
QTimer * const m_clientRestartTimer;
QHash<Utils::FilePath, QString> m_potentialShadowDocuments;
+ Utils::FutureSynchronizer m_generatorSynchronizer; // Keep me last
};
} // namespace Internal
diff --git a/src/plugins/cmakeprojectmanager/cmakeproject.cpp b/src/plugins/cmakeprojectmanager/cmakeproject.cpp
index 7318c7a791..25352f0b5d 100644
--- a/src/plugins/cmakeprojectmanager/cmakeproject.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakeproject.cpp
@@ -7,6 +7,7 @@
#include "cmakeprojectconstants.h"
#include "cmakeprojectimporter.h"
#include "cmakeprojectmanagertr.h"
+#include "presetsmacros.h"
#include <coreplugin/icontext.h>
#include <projectexplorer/buildconfiguration.h>
@@ -301,6 +302,18 @@ void CMakeProject::readPresets()
m_presetsData = combinePresets(cmakePresetsData, cmakeUserPresetsData);
setupBuildPresets(m_presetsData);
+
+ for (const auto &configPreset : m_presetsData.configurePresets) {
+ if (configPreset.hidden.value())
+ continue;
+
+ if (configPreset.condition) {
+ if (!CMakePresets::Macros::evaluatePresetCondition(configPreset, projectFilePath()))
+ continue;
+ }
+ m_presetsData.havePresets = true;
+ break;
+ }
}
bool CMakeProject::setupTarget(Target *t)
diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectimporter.cpp b/src/plugins/cmakeprojectmanager/cmakeprojectimporter.cpp
index 450d154010..52ed82f8d7 100644
--- a/src/plugins/cmakeprojectmanager/cmakeprojectimporter.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakeprojectimporter.cpp
@@ -201,8 +201,6 @@ FilePaths CMakeProjectImporter::presetCandidates()
}
}
- m_hasCMakePresets = !candidates.isEmpty();
-
return candidates;
}
@@ -223,7 +221,7 @@ Target *CMakeProjectImporter::preferredTarget(const QList<Target *> &possibleTar
bool CMakeProjectImporter::filter(ProjectExplorer::Kit *k) const
{
- if (!m_hasCMakePresets)
+ if (!m_project->presetsData().havePresets)
return true;
const auto presetConfigItem = CMakeConfigurationKitAspect::cmakePresetConfigItem(k);
diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectimporter.h b/src/plugins/cmakeprojectmanager/cmakeprojectimporter.h
index 82e1835ba7..63c2403f4b 100644
--- a/src/plugins/cmakeprojectmanager/cmakeprojectimporter.h
+++ b/src/plugins/cmakeprojectmanager/cmakeprojectimporter.h
@@ -49,7 +49,6 @@ private:
const CMakeProject *m_project;
Utils::TemporaryDirectory m_presetsTempDir;
- bool m_hasCMakePresets = false;
};
#ifdef WITH_TESTS
diff --git a/src/plugins/cmakeprojectmanager/cmakespecificsettings.cpp b/src/plugins/cmakeprojectmanager/cmakespecificsettings.cpp
index d814ee8135..28668b3567 100644
--- a/src/plugins/cmakeprojectmanager/cmakespecificsettings.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakespecificsettings.cpp
@@ -93,16 +93,16 @@ CMakeSpecificSettings::CMakeSpecificSettings()
"UseJunctionsForSourceAndBuildDirectories");
useJunctionsForSourceAndBuildDirectories.setDefaultValue(false);
useJunctionsForSourceAndBuildDirectories.setLabelText(::CMakeProjectManager::Tr::tr(
- "Use Junctions for CMake configuration and build operations"));
+ "Use junctions for CMake configuration and build operations"));
useJunctionsForSourceAndBuildDirectories.setVisible(Utils::HostOsInfo().isWindowsHost());
useJunctionsForSourceAndBuildDirectories.setToolTip(::CMakeProjectManager::Tr::tr(
- "Create and use junctions for the source and build directories. This helps to overcome "
+ "Create and use junctions for the source and build directories to overcome "
"issues with long paths on Windows.<br><br>"
- "They are stored under <tt>C:\\ProgramData\\QtCreator\\Links</tt> (overridable via "
- "<tt>QTC_CMAKE_JUNCTIONS_DIR</tt> environment variable).<br><br>"
- "With <tt>QTC_CMAKE_JUNCTIONS_HASH_LENGTH</tt> the MD5 hash key length can be shortened "
+ "Junctions are stored under <tt>C:\\ProgramData\\QtCreator\\Links</tt> (overridable via "
+ "the <tt>QTC_CMAKE_JUNCTIONS_DIR</tt> environment variable).<br><br>"
+ "With <tt>QTC_CMAKE_JUNCTIONS_HASH_LENGTH</tt>, you can shorten the MD5 hash key length "
"to a value smaller than the default length value of 32.<br><br>"
- "They are used for CMake configure, build and install operations."));
+ "Junctions are used for CMake configure, build and install operations."));
readSettings();
}
diff --git a/src/plugins/cmakeprojectmanager/cmaketoolmanager.cpp b/src/plugins/cmakeprojectmanager/cmaketoolmanager.cpp
index 16473a6e79..e20c3c58eb 100644
--- a/src/plugins/cmakeprojectmanager/cmaketoolmanager.cpp
+++ b/src/plugins/cmakeprojectmanager/cmaketoolmanager.cpp
@@ -16,6 +16,7 @@
#include <coreplugin/icore.h>
#include <projectexplorer/buildsystem.h>
+#include <projectexplorer/projectmanager.h>
#include <projectexplorer/projecttree.h>
#include <projectexplorer/target.h>
@@ -69,6 +70,7 @@ typedef struct _REPARSE_DATA_BUFFER {
#endif
using namespace Core;
+using namespace ProjectExplorer;
using namespace Utils;
namespace CMakeProjectManager {
@@ -451,8 +453,19 @@ FilePath CMakeToolManager::mappedFilePath(const FilePath &path)
if (path.needsDevice())
return path;
- Internal::settings();
- if (!Internal::settings().useJunctionsForSourceAndBuildDirectories())
+ auto project = ProjectManager::startupProject();
+ auto environment = Environment::systemEnvironment();
+ if (project)
+ environment.modify(project->additionalEnvironment());
+ const bool enableJunctions
+ = QVariant(
+ environment.value_or("QTC_CMAKE_USE_JUNCTIONS",
+ Internal::settings().useJunctionsForSourceAndBuildDirectories()
+ ? "1"
+ : "0"))
+ .toBool();
+
+ if (!enableJunctions)
return path;
if (!d->m_junctionsDir.isDir())
@@ -583,14 +596,17 @@ CMakeToolManagerPrivate::CMakeToolManagerPrivate()
m_junctionsDir = FilePath::fromString(*std::min_element(locations.begin(), locations.end()))
.pathAppended("QtCreator/Links");
- if (Utils::qtcEnvironmentVariableIsSet("QTC_CMAKE_JUNCTIONS_DIR")) {
- m_junctionsDir = FilePath::fromUserInput(
- Utils::qtcEnvironmentVariable("QTC_CMAKE_JUNCTIONS_DIR"));
- }
- if (Utils::qtcEnvironmentVariableIsSet("QTC_CMAKE_JUNCTIONS_HASH_LENGTH")) {
+ auto project = ProjectManager::startupProject();
+ auto environment = Environment::systemEnvironment();
+ if (project)
+ environment.modify(project->additionalEnvironment());
+
+ if (environment.hasKey("QTC_CMAKE_JUNCTIONS_DIR"))
+ m_junctionsDir = FilePath::fromUserInput(environment.value("QTC_CMAKE_JUNCTIONS_DIR"));
+
+ if (environment.hasKey("QTC_CMAKE_JUNCTIONS_HASH_LENGTH")) {
bool ok = false;
- const int hashLength
- = Utils::qtcEnvironmentVariableIntValue("QTC_CMAKE_JUNCTIONS_HASH_LENGTH", &ok);
+ const int hashLength = environment.value("QTC_CMAKE_JUNCTIONS_HASH_LENGTH").toInt(&ok);
if (ok && hashLength >= 4 && hashLength < 32)
m_junctionsHashLength = hashLength;
}
diff --git a/src/plugins/cmakeprojectmanager/presetsparser.h b/src/plugins/cmakeprojectmanager/presetsparser.h
index 20d36e389e..6df09014af 100644
--- a/src/plugins/cmakeprojectmanager/presetsparser.h
+++ b/src/plugins/cmakeprojectmanager/presetsparser.h
@@ -140,6 +140,7 @@ class PresetsData
{
public:
int version = 0;
+ bool havePresets = false;
QVersionNumber cmakeMinimimRequired;
QHash<QString, QString> vendor;
std::optional<QStringList> include;
diff --git a/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseproject.cpp b/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseproject.cpp
index 914c6f705f..ebe7ff4475 100644
--- a/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseproject.cpp
+++ b/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseproject.cpp
@@ -332,11 +332,7 @@ CompilationDatabaseBuildSystem::CompilationDatabaseBuildSystem(Target *target)
this, &CompilationDatabaseBuildSystem::updateDeploymentData);
}
-CompilationDatabaseBuildSystem::~CompilationDatabaseBuildSystem()
-{
- m_parserWatcher.cancel();
- m_parserWatcher.waitForFinished();
-}
+CompilationDatabaseBuildSystem::~CompilationDatabaseBuildSystem() = default;
void CompilationDatabaseBuildSystem::triggerParsing()
{
diff --git a/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseproject.h b/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseproject.h
index 25561f5aac..2b8faec020 100644
--- a/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseproject.h
+++ b/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseproject.h
@@ -13,8 +13,6 @@
#include <utils/filesystemwatcher.h>
-#include <QFutureWatcher>
-
namespace ProjectExplorer {
class Kit;
class ProjectUpdater;
@@ -51,7 +49,6 @@ public:
void updateDeploymentData();
void buildTreeAndProjectParts();
- QFutureWatcher<void> m_parserWatcher;
std::unique_ptr<ProjectExplorer::ProjectUpdater> m_cppCodeModelUpdater;
MimeBinaryCache m_mimeBinaryCache;
QByteArray m_projectFileHash;
diff --git a/src/plugins/compilationdatabaseprojectmanager/compilationdbparser.cpp b/src/plugins/compilationdatabaseprojectmanager/compilationdbparser.cpp
index 5f86095602..4ab893a9e6 100644
--- a/src/plugins/compilationdatabaseprojectmanager/compilationdbparser.cpp
+++ b/src/plugins/compilationdatabaseprojectmanager/compilationdbparser.cpp
@@ -8,9 +8,12 @@
#include <coreplugin/progressmanager/progressmanager.h>
+#include <extensionsystem/pluginmanager.h>
+
#include <projectexplorer/treescanner.h>
#include <utils/async.h>
+#include <utils/futuresynchronizer.h>
#include <utils/mimeutils.h>
#include <QCryptographicHash>
@@ -187,6 +190,7 @@ void CompilationDbParser::start()
"CompilationDatabase.Parse");
++m_runningParserJobs;
m_parserWatcher.setFuture(future);
+ ExtensionSystem::PluginManager::futureSynchronizer()->addFuture(future);
}
void CompilationDbParser::stop()
diff --git a/src/plugins/coreplugin/coreplugin.cpp b/src/plugins/coreplugin/coreplugin.cpp
index 3deaab59f2..dd99f47450 100644
--- a/src/plugins/coreplugin/coreplugin.cpp
+++ b/src/plugins/coreplugin/coreplugin.cpp
@@ -33,6 +33,8 @@
#include <utils/infobar.h>
#include <utils/macroexpander.h>
#include <utils/mimeutils.h>
+#include <utils/networkaccessmanager.h>
+#include <utils/passworddialog.h>
#include <utils/pathchooser.h>
#include <utils/savefile.h>
#include <utils/store.h>
@@ -41,6 +43,7 @@
#include <utils/theme/theme.h>
#include <utils/theme/theme_p.h>
+#include <QAuthenticator>
#include <QDateTime>
#include <QDebug>
#include <QDir>
@@ -136,6 +139,30 @@ void CorePlugin::loadMimeFromPlugin(const ExtensionSystem::PluginSpec *plugin)
Utils::addMimeTypes(plugin->name() + ".mimetypes", mimetypeString.trimmed().toUtf8());
}
+static void initProxyAuthDialog()
+{
+ QObject::connect(Utils::NetworkAccessManager::instance(),
+ &QNetworkAccessManager::proxyAuthenticationRequired,
+ Utils::NetworkAccessManager::instance(),
+ [](const QNetworkProxy &, QAuthenticator *authenticator) {
+ static bool doNotAskAgain = false;
+
+ std::optional<QPair<QString, QString>> answer
+ = Utils::PasswordDialog::getUserAndPassword(
+ Tr::tr("Proxy Authentication Required"),
+ authenticator->realm(),
+ Tr::tr("Do not ask again."),
+ {},
+ &doNotAskAgain,
+ Core::ICore::dialogParent());
+
+ if (answer) {
+ authenticator->setUser(answer->first);
+ authenticator->setPassword(answer->second);
+ }
+ });
+}
+
bool CorePlugin::initialize(const QStringList &arguments, QString *errorMessage)
{
// register all mime types from all plugins
@@ -145,6 +172,8 @@ bool CorePlugin::initialize(const QStringList &arguments, QString *errorMessage)
loadMimeFromPlugin(plugin);
}
+ initProxyAuthDialog();
+
if (ThemeEntry::availableThemes().isEmpty()) {
*errorMessage = Tr::tr("No themes found in installation.");
return false;
@@ -238,9 +267,9 @@ bool CorePlugin::initialize(const QStringList &arguments, QString *errorMessage)
[] { return QUuid::createUuid().toString(); });
expander->registerPrefix("#:", Tr::tr("A comment."), [](const QString &) { return QString(); });
- expander->registerPrefix("Asciify:", Tr::tr("Convert string into pure ascii."),
- [expander] (const QString &s) {
- return asciify(expander->expand(s)); });
+ expander->registerPrefix("Asciify:",
+ Tr::tr("Convert string to pure ASCII."),
+ [expander](const QString &s) { return asciify(expander->expand(s)); });
Utils::PathChooser::setAboutToShowContextMenuHandler(&CorePlugin::addToPathChooserContextMenu);
diff --git a/src/plugins/coreplugin/editormanager/editormanager.cpp b/src/plugins/coreplugin/editormanager/editormanager.cpp
index 10cec9f79b..6ec37a6cb8 100644
--- a/src/plugins/coreplugin/editormanager/editormanager.cpp
+++ b/src/plugins/coreplugin/editormanager/editormanager.cpp
@@ -579,7 +579,7 @@ void EditorManagerPrivate::init()
// Go back in navigation history
ActionBuilder goBack(this, Constants::GO_BACK);
goBack.setIcon(Utils::Icons::PREV.icon());
- goBack.setText(Core::Tr::tr("Go Back"));
+ goBack.setText(::Core::Tr::tr("Go Back"));
goBack.bindContextAction(&m_goBackAction);
goBack.setContext(editDesignContext);
goBack.setDefaultKeySequence(::Core::Tr::tr("Ctrl+Alt+Left"), ::Core::Tr::tr("Alt+Left"));
@@ -589,7 +589,7 @@ void EditorManagerPrivate::init()
// Go forward in navigation history
ActionBuilder goForward(this, Constants::GO_FORWARD);
goForward.setIcon(Utils::Icons::NEXT.icon());
- goForward.setText(Core::Tr::tr("Go Forward"));
+ goForward.setText(::Core::Tr::tr("Go Forward"));
goForward.bindContextAction(&m_goForwardAction);
goForward.setContext(editDesignContext);
goForward.setDefaultKeySequence(::Core::Tr::tr("Ctrl+Alt+Right"), ::Core::Tr::tr("Alt+Right"));
@@ -618,7 +618,7 @@ void EditorManagerPrivate::init()
splitSideBySide.setText(::Core::Tr::tr("Split Side by Side"));
splitSideBySide.bindContextAction(&m_splitSideBySideAction);
splitSideBySide.setContext(editManagerContext);
- splitSideBySide.setDefaultKeySequence(::Core::Tr::tr("Meta+E,3"), Core::Tr::tr("Ctrl+E,3"));
+ splitSideBySide.setDefaultKeySequence(::Core::Tr::tr("Meta+E,3"), ::Core::Tr::tr("Ctrl+E,3"));
splitSideBySide.addToContainer(Constants::M_WINDOW, Constants::G_WINDOW_SPLIT);
splitSideBySide.addOnTriggered(this, &EditorManager::splitSideBySide);
diff --git a/src/plugins/coreplugin/editormanager/editorwindow.cpp b/src/plugins/coreplugin/editormanager/editorwindow.cpp
index 3e23a7285e..fbd60ebc15 100644
--- a/src/plugins/coreplugin/editormanager/editorwindow.cpp
+++ b/src/plugins/coreplugin/editormanager/editorwindow.cpp
@@ -47,9 +47,11 @@ EditorWindow::EditorWindow(QWidget *parent) :
static int windowId = 0;
+ const Utils::Id windowContext
+ = Utils::Id("EditorManager.ExternalWindow.").withSuffix(++windowId);
ICore::registerWindow(this,
- Context(Utils::Id("EditorManager.ExternalWindow.").withSuffix(++windowId),
- Constants::C_EDITORMANAGER));
+ Context(windowContext, Constants::C_EDITORMANAGER),
+ Context(windowContext));
connect(m_area, &EditorArea::windowTitleNeedsUpdate,
this, &EditorWindow::updateWindowTitle);
diff --git a/src/plugins/coreplugin/find/ifindfilter.cpp b/src/plugins/coreplugin/find/ifindfilter.cpp
index a849598cfd..704f827bf8 100644
--- a/src/plugins/coreplugin/find/ifindfilter.cpp
+++ b/src/plugins/coreplugin/find/ifindfilter.cpp
@@ -92,7 +92,7 @@ using namespace Utils;
Returns the name of the find filter or scope as presented to the user.
This is the name that appears in the scope selection combo box, for example.
- Always return a translatable string. That is, use \c tr() for the return
+ Always return a translatable string. That is, use \c {Tr::tr()} for the return
value.
*/
diff --git a/src/plugins/coreplugin/icore.cpp b/src/plugins/coreplugin/icore.cpp
index abee4c08ab..54462f3051 100644
--- a/src/plugins/coreplugin/icore.cpp
+++ b/src/plugins/coreplugin/icore.cpp
@@ -1011,14 +1011,15 @@ void ICore::removeAdditionalContext(const Context &context)
Registers a \a window with the specified \a context. Registered windows are
shown in the \uicontrol Window menu and get registered for the various
window related actions, like the minimize, zoom, fullscreen and close
- actions.
+ actions. The context for the actions is \a context by default, but can be
+ overridden with \a actionContext.
Whenever the application focus is in \a window, its \a context is made
active.
*/
-void ICore::registerWindow(QWidget *window, const Context &context)
+void ICore::registerWindow(QWidget *window, const Context &context, const Context &actionContext)
{
- new WindowSupport(window, context); // deletes itself when widget is destroyed
+ new WindowSupport(window, context, actionContext); // deletes itself when widget is destroyed
}
/*!
@@ -1970,14 +1971,32 @@ void ICorePrivate::registerDefaultActions()
toggleMenubarAction.addToContainer(Constants::M_VIEW, Constants::G_VIEW_VIEWS);
toggleMenubarAction.addOnToggled(this, [](bool visible) {
if (!visible) {
- const QString keys = ActionManager::command(Constants::TOGGLE_MENUBAR)
- ->keySequence().toString(QKeySequence::NativeText);
- CheckableMessageBox::information(Core::ICore::dialogParent(),
- Tr::tr("Hide Menu Bar"),
- Tr::tr("This will hide the menu bar completely. "
- "You can show it again by typing %1.")
- .arg(keys),
- Key("ToogleMenuBarHint"));
+ auto keySequenceAndText = [](const Utils::Id &actionName) {
+ const auto command = ActionManager::command(actionName);
+
+ const QString keySequence = command->keySequence().toString(
+ QKeySequence::NativeText);
+ const QString text = command->action()->text();
+
+ return QPair<QString, QString>(keySequence, text);
+ };
+
+ auto [menuBarKeys, menuBarText] = keySequenceAndText(Constants::TOGGLE_MENUBAR);
+ auto [actionsFromMenuKeys, actionsFromMenuText] = keySequenceAndText(
+ "Locator.Actions from the menu");
+
+ CheckableMessageBox::information(
+ Core::ICore::dialogParent(),
+ Tr::tr("Hide Menu Bar"),
+ Tr::tr("This will hide the menu bar completely. "
+ "You can show it again by typing %1."
+ "<br><br>"
+ "Or, trigger the \"%2\" action from the \"%3\" locator filter (%4).")
+ .arg(menuBarKeys)
+ .arg(menuBarText)
+ .arg(actionsFromMenuText)
+ .arg(actionsFromMenuKeys),
+ Key("ToogleMenuBarHint"));
}
globalMenuBar()->setVisible(visible);
});
diff --git a/src/plugins/coreplugin/icore.h b/src/plugins/coreplugin/icore.h
index 215cb94ba8..8c713e156f 100644
--- a/src/plugins/coreplugin/icore.h
+++ b/src/plugins/coreplugin/icore.h
@@ -98,7 +98,9 @@ public:
static void addContextObject(IContext *context);
static void removeContextObject(IContext *context);
- static void registerWindow(QWidget *window, const Context &context);
+ static void registerWindow(QWidget *window,
+ const Context &context,
+ const Context &actionContext = {});
static void restartTrimmer();
enum OpenFilesFlags {
diff --git a/src/plugins/coreplugin/windowsupport.cpp b/src/plugins/coreplugin/windowsupport.cpp
index 4cbfb57d03..5c5cbbfe13 100644
--- a/src/plugins/coreplugin/windowsupport.cpp
+++ b/src/plugins/coreplugin/windowsupport.cpp
@@ -15,8 +15,8 @@
#include <utils/stringutils.h>
#include <QAction>
+#include <QApplication>
#include <QEvent>
-#include <QGuiApplication>
#include <QMenu>
#include <QWidget>
#include <QWindowStateChangeEvent>
@@ -28,9 +28,9 @@ namespace Internal {
Q_GLOBAL_STATIC(WindowList, m_windowList)
-WindowSupport::WindowSupport(QWidget *window, const Context &context)
- : QObject(window),
- m_window(window)
+WindowSupport::WindowSupport(QWidget *window, const Context &context, const Context &actionContext)
+ : QObject(window)
+ , m_window(window)
{
m_window->installEventFilter(this);
@@ -38,14 +38,15 @@ WindowSupport::WindowSupport(QWidget *window, const Context &context)
m_contextObject->setWidget(window);
m_contextObject->setContext(context);
ICore::addContextObject(m_contextObject);
+ const Context ac = actionContext.isEmpty() ? context : actionContext;
if (useMacShortcuts) {
m_minimizeAction = new QAction(this);
- ActionManager::registerAction(m_minimizeAction, Constants::MINIMIZE_WINDOW, context);
+ ActionManager::registerAction(m_minimizeAction, Constants::MINIMIZE_WINDOW, ac);
connect(m_minimizeAction, &QAction::triggered, m_window, &QWidget::showMinimized);
m_zoomAction = new QAction(this);
- ActionManager::registerAction(m_zoomAction, Constants::ZOOM_WINDOW, context);
+ ActionManager::registerAction(m_zoomAction, Constants::ZOOM_WINDOW, ac);
connect(m_zoomAction, &QAction::triggered, m_window, [this] {
if (m_window->isMaximized()) {
// similar to QWidget::showMaximized
@@ -58,13 +59,13 @@ WindowSupport::WindowSupport(QWidget *window, const Context &context)
});
m_closeAction = new QAction(this);
- ActionManager::registerAction(m_closeAction, Constants::CLOSE_WINDOW, context);
+ ActionManager::registerAction(m_closeAction, Constants::CLOSE_WINDOW, ac);
connect(m_closeAction, &QAction::triggered, m_window, &QWidget::close, Qt::QueuedConnection);
}
m_toggleFullScreenAction = new QAction(this);
updateFullScreenAction();
- ActionManager::registerAction(m_toggleFullScreenAction, Constants::TOGGLE_FULLSCREEN, context);
+ ActionManager::registerAction(m_toggleFullScreenAction, Constants::TOGGLE_FULLSCREEN, ac);
connect(m_toggleFullScreenAction, &QAction::triggered, this, &WindowSupport::toggleFullScreen);
m_windowList->addWindow(window);
@@ -105,11 +106,8 @@ bool WindowSupport::eventFilter(QObject *obj, QEvent *event)
updateFullScreenAction();
} else if (event->type() == QEvent::WindowActivate) {
m_windowList->setActiveWindow(m_window);
- } else if (event->type() == QEvent::Hide) {
- // minimized windows are hidden, but we still want to show them
- m_windowList->setWindowVisible(m_window, m_window->isMinimized());
- } else if (event->type() == QEvent::Show) {
- m_windowList->setWindowVisible(m_window, true);
+ } else if (event->type() == QEvent::Hide || event->type() == QEvent::Show) {
+ m_windowList->updateVisibility(m_window);
}
return false;
}
@@ -178,12 +176,15 @@ void WindowList::activateWindow(QAction *action)
int index = m_windowActions.indexOf(action);
QTC_ASSERT(index >= 0, return);
QTC_ASSERT(index < m_windows.size(), return);
- ICore::raiseWindow(m_windows.at(index));
+ QWidget *window = m_windows.at(index);
+ if (window->isMinimized())
+ window->setWindowState(window->windowState() & ~Qt::WindowMinimized);
+ ICore::raiseWindow(window);
}
-void WindowList::updateTitle(QWidget *window)
+void WindowList::updateTitle(QWidget *window, int i)
{
- int index = m_windows.indexOf(window);
+ const int index = i < 0 ? m_windows.indexOf(window) : i;
QTC_ASSERT(index >= 0, return);
QTC_ASSERT(index < m_windowActions.size(), return);
QString title = window->windowTitle();
@@ -192,6 +193,19 @@ void WindowList::updateTitle(QWidget *window)
m_windowActions.at(index)->setText(Utils::quoteAmpersands(title.trimmed()));
}
+void WindowList::updateVisibility(QWidget *window)
+{
+ updateVisibility(window, m_windows.indexOf(window));
+}
+
+void WindowList::updateVisibility(QWidget *window, int index)
+{
+ QTC_ASSERT(index >= 0, return);
+ QTC_ASSERT(index < m_windowActions.size(), return);
+ // minimized windows are hidden, but we still want to show them
+ m_windowActions.at(index)->setVisible(window->isVisible() || window->isMinimized());
+}
+
void WindowList::removeWindow(QWidget *window)
{
// remove window from list,
@@ -206,8 +220,12 @@ void WindowList::removeWindow(QWidget *window)
m_windows.removeOne(window);
- for (int i = index; i < m_windows.size(); ++i)
- updateTitle(m_windows.at(i));
+ for (int i = index; i < m_windows.size(); ++i) {
+ QWidget *window = m_windows.at(i);
+ updateTitle(window, i);
+ updateVisibility(window, i);
+ }
+ setActiveWindow(QApplication::activeWindow());
}
void WindowList::setActiveWindow(QWidget *window)
@@ -216,13 +234,5 @@ void WindowList::setActiveWindow(QWidget *window)
m_windowActions.at(i)->setChecked(m_windows.at(i) == window);
}
-void WindowList::setWindowVisible(QWidget *window, bool visible)
-{
- int index = m_windows.indexOf(window);
- QTC_ASSERT(index >= 0, return);
- QTC_ASSERT(index < m_windowActions.size(), return);
- m_windowActions.at(index)->setVisible(visible);
-}
-
} // Internal
} // Core
diff --git a/src/plugins/coreplugin/windowsupport.h b/src/plugins/coreplugin/windowsupport.h
index c1b48d3917..8b7eb026af 100644
--- a/src/plugins/coreplugin/windowsupport.h
+++ b/src/plugins/coreplugin/windowsupport.h
@@ -24,11 +24,12 @@ public:
void addWindow(QWidget *window);
void removeWindow(QWidget *window);
void setActiveWindow(QWidget *window);
- void setWindowVisible(QWidget *window, bool visible);
+ void updateVisibility(QWidget *window);
private:
void activateWindow(QAction *action);
- void updateTitle(QWidget *window);
+ void updateTitle(QWidget *window, int index = -1);
+ void updateVisibility(QWidget *window, int index);
QMenu *m_dockMenu = nullptr;
QList<QWidget *> m_windows;
@@ -40,7 +41,7 @@ class WindowSupport : public QObject
{
Q_OBJECT
public:
- WindowSupport(QWidget *window, const Context &context);
+ WindowSupport(QWidget *window, const Context &context, const Context &actionContext = {});
~WindowSupport() override;
void setCloseActionEnabled(bool enabled);
diff --git a/src/plugins/cpaster/CMakeLists.txt b/src/plugins/cpaster/CMakeLists.txt
index 2455ea28d6..690862877e 100644
--- a/src/plugins/cpaster/CMakeLists.txt
+++ b/src/plugins/cpaster/CMakeLists.txt
@@ -22,7 +22,6 @@ add_qtc_plugin(CodePaster
pasteview.cpp pasteview.h
protocol.cpp protocol.h
settings.cpp settings.h
- stickynotespasteprotocol.cpp stickynotespasteprotocol.h
urlopenprotocol.cpp urlopenprotocol.h
../../shared/cpaster/cgi.cpp ../../shared/cpaster/cgi.h
diff --git a/src/plugins/cpaster/cpaster.qbs b/src/plugins/cpaster/cpaster.qbs
index 6862eacabd..f2241ba1d0 100644
--- a/src/plugins/cpaster/cpaster.qbs
+++ b/src/plugins/cpaster/cpaster.qbs
@@ -35,8 +35,6 @@ QtcPlugin {
"protocol.h",
"settings.cpp",
"settings.h",
- "stickynotespasteprotocol.cpp",
- "stickynotespasteprotocol.h",
"urlopenprotocol.cpp",
"urlopenprotocol.h",
]
diff --git a/src/plugins/cpaster/stickynotespasteprotocol.cpp b/src/plugins/cpaster/stickynotespasteprotocol.cpp
deleted file mode 100644
index 5e3b2074a5..0000000000
--- a/src/plugins/cpaster/stickynotespasteprotocol.cpp
+++ /dev/null
@@ -1,249 +0,0 @@
-// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-#include "stickynotespasteprotocol.h"
-
-#include "cpastertr.h"
-
-#include <coreplugin/icore.h>
-#include <utils/qtcassert.h>
-
-#include <QDebug>
-#include <QByteArray>
-#include <QStringList>
-#include <QJsonDocument>
-#include <QJsonObject>
-#include <QJsonArray>
-#include <QRegularExpression>
-#include <QNetworkReply>
-
-#include <algorithm>
-
-enum { debug = 0 };
-
-namespace CodePaster {
-
-static QByteArray expiryParameter(int daysRequested)
-{
- // Obtained by 'pastebin.kde.org/api/json/parameter/expire' on 26.03.2014
- static const int expiryTimesSec[] = {1800, 21600, 86400, 604800, 2592000, 31536000};
- const int *end = expiryTimesSec + sizeof(expiryTimesSec) / sizeof(expiryTimesSec[0]);
- // Find the first element >= requested span, search up to n - 1 such that 'end' defaults to last value.
- const int *match = std::lower_bound(expiryTimesSec, end - 1, 24 * 60 * 60 * daysRequested);
- return QByteArray("expire=") + QByteArray::number(*match);
-}
-
-void StickyNotesPasteProtocol::setHostUrl(const QString &hostUrl)
-{
- m_hostUrl = hostUrl;
- if (!m_hostUrl.endsWith(QLatin1Char('/')))
- m_hostUrl.append(QLatin1Char('/'));
-}
-
-unsigned StickyNotesPasteProtocol::capabilities() const
-{
- return ListCapability | PostDescriptionCapability;
-}
-
-bool StickyNotesPasteProtocol::checkConfiguration(QString *errorMessage)
-{
- if (m_hostChecked) // Check the host once.
- return true;
- const bool ok = httpStatus(m_hostUrl, errorMessage, true);
- if (ok)
- m_hostChecked = true;
- return ok;
-}
-
-// Query 'http://pastebin.kde.org/api/json/parameter/language' to obtain the valid values.
-static inline QByteArray pasteLanguage(Protocol::ContentType ct)
-{
- switch (ct) {
- case Protocol::Text:
- break;
- case Protocol::C:
- return "language=c";
- case Protocol::Cpp:
- return "language=cpp-qt";
- case Protocol::JavaScript:
- return "language=javascript";
- case Protocol::Diff:
- return "language=diff";
- case Protocol::Xml:
- return "language=xml";
- }
- return QByteArray("language=text");
-}
-
-void StickyNotesPasteProtocol::paste(
- const QString &text,
- ContentType ct,
- int expiryDays,
- const QString &username,
- const QString &comment,
- const QString &description
- )
-{
- enum { maxDescriptionLength = 30 }; // Length of description is limited.
-
- Q_UNUSED(username)
- Q_UNUSED(comment)
- QTC_ASSERT(!m_pasteReply, return);
-
- // Format body
- QByteArray pasteData = "&data=";
- pasteData += QUrl::toPercentEncoding(fixNewLines(text));
- pasteData += '&';
- pasteData += pasteLanguage(ct);
- pasteData += '&';
- pasteData += expiryParameter(expiryDays);
- if (!description.isEmpty()) {
- pasteData += "&title=";
- pasteData += QUrl::toPercentEncoding(description.left(maxDescriptionLength));
- }
-
- m_pasteReply = httpPost(m_hostUrl + QLatin1String("api/json/create"), pasteData, true);
- connect(m_pasteReply, &QNetworkReply::finished, this, &StickyNotesPasteProtocol::pasteFinished);
- if (debug)
- qDebug() << "paste: sending " << m_pasteReply << pasteData;
-}
-
-// Parse for an element and return its contents
-static QString parseElement(QIODevice *device, const QString &elementName)
-{
- const QJsonDocument doc = QJsonDocument::fromJson(device->readAll());
- if (doc.isEmpty() || !doc.isObject())
- return QString();
-
- QJsonObject obj= doc.object();
- const QString resultKey = QLatin1String("result");
-
- if (obj.contains(resultKey)) {
- QJsonValue value = obj.value(resultKey);
- if (value.isObject()) {
- obj = value.toObject();
- if (obj.contains(elementName)) {
- value = obj.value(elementName);
- return value.toString();
- }
- } else if (value.isArray()) {
- qWarning() << "JsonArray not expected.";
- }
- }
-
- return QString();
-}
-
-void StickyNotesPasteProtocol::pasteFinished()
-{
- if (m_pasteReply->error()) {
- qWarning("%s protocol error: %s", qPrintable(name()),qPrintable(m_pasteReply->errorString()));
- } else {
- // Parse id from '<result><id>143204</id><hash></hash></result>'
- // No useful error reports have been observed.
- const QString id = parseElement(m_pasteReply, QLatin1String("id"));
- if (id.isEmpty())
- qWarning("%s protocol error: Could not send entry.", qPrintable(name()));
- else
- emit pasteDone(m_hostUrl + id);
- }
-
- m_pasteReply->deleteLater();
- m_pasteReply = nullptr;
-}
-
-void StickyNotesPasteProtocol::fetch(const QString &id)
-{
- QTC_ASSERT(!m_fetchReply, return);
-
- // Did we get a complete URL or just an id?
- m_fetchId = id;
- const int lastSlashPos = m_fetchId.lastIndexOf(QLatin1Char('/'));
- if (lastSlashPos != -1)
- m_fetchId.remove(0, lastSlashPos + 1);
- QString url = m_hostUrl + QLatin1String("api/json/show/") + m_fetchId;
- if (debug)
- qDebug() << "fetch: sending " << url;
-
- m_fetchReply = httpGet(url);
- connect(m_fetchReply, &QNetworkReply::finished,
- this, &StickyNotesPasteProtocol::fetchFinished);
-}
-
-// Parse: '<result><id>143228</id><author>foo</author><timestamp>1320661026</timestamp><language>text</language>
-// <data>bar</data></result>'
-
-void StickyNotesPasteProtocol::fetchFinished()
-{
- const QString title = name() + QLatin1String(": ") + m_fetchId;
- QString content;
- const bool error = m_fetchReply->error();
- if (error) {
- content = m_fetchReply->errorString();
- if (debug)
- qDebug() << "fetchFinished: error" << m_fetchId << content;
- } else {
- content = parseElement(m_fetchReply, QLatin1String("data"));
- content.remove(QLatin1Char('\r'));
- }
- m_fetchReply->deleteLater();
- m_fetchReply = nullptr;
- emit fetchDone(title, content, error);
-}
-
-void StickyNotesPasteProtocol::list()
-{
- QTC_ASSERT(!m_listReply, return);
-
- // Trailing slash is important to prevent redirection.
- QString url = m_hostUrl + QLatin1String("api/json/list");
- m_listReply = httpGet(url);
- connect(m_listReply, &QNetworkReply::finished,
- this, &StickyNotesPasteProtocol::listFinished);
- if (debug)
- qDebug() << "list: sending " << url << m_listReply;
-}
-
-// Parse 'result><pastes><paste>id1</paste><paste>id2</paste>...'
-static inline QStringList parseList(QIODevice *device)
-{
- QStringList result;
- const QJsonDocument doc = QJsonDocument::fromJson(device->readAll());
- if (doc.isEmpty() || !doc.isObject())
- return result;
-
- QJsonObject obj= doc.object();
- const QString resultKey = QLatin1String("result");
- const QString pastesKey = QLatin1String("pastes");
-
- if (obj.contains(resultKey)) {
- QJsonValue value = obj.value(resultKey);
- if (value.isObject()) {
- obj = value.toObject();
- if (obj.contains(pastesKey)) {
- value = obj.value(pastesKey);
- if (value.isArray()) {
- const QJsonArray array = value.toArray();
- for (const QJsonValue &val : array)
- result.append(val.toString());
- }
- }
- }
- }
- return result;
-}
-
-void StickyNotesPasteProtocol::listFinished()
-{
- const bool error = m_listReply->error();
- if (error) {
- if (debug)
- qDebug() << "listFinished: error" << m_listReply->errorString();
- } else {
- emit listDone(name(), parseList(m_listReply));
- }
- m_listReply->deleteLater();
- m_listReply = nullptr;
-}
-
-} // CodePaster
diff --git a/src/plugins/cpaster/stickynotespasteprotocol.h b/src/plugins/cpaster/stickynotespasteprotocol.h
deleted file mode 100644
index f212c883ef..0000000000
--- a/src/plugins/cpaster/stickynotespasteprotocol.h
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-#pragma once
-
-#include "protocol.h"
-
-namespace CodePaster {
-
-class StickyNotesPasteProtocol : public NetworkProtocol
-{
-public:
- unsigned capabilities() const override;
-
- void fetch(const QString &id) override;
- void paste(const QString &text,
- ContentType ct = Text,
- int expiryDays = 1,
- const QString &username = QString(),
- const QString &comment = QString(),
- const QString &description = QString()) override;
- void list() override;
-
- QString hostUrl() const { return m_hostUrl; }
- void setHostUrl(const QString &hostUrl);
-
-private:
- bool checkConfiguration(QString *errorMessage = nullptr) override;
-
- void fetchFinished();
- void pasteFinished();
- void listFinished();
-
- QString m_hostUrl;
-
- QNetworkReply *m_fetchReply = nullptr;
- QNetworkReply *m_pasteReply = nullptr;
- QNetworkReply *m_listReply = nullptr;
-
- QString m_fetchId;
- bool m_hostChecked = false;
-};
-
-} // CodePaster
diff --git a/src/plugins/cppeditor/builtincursorinfo.cpp b/src/plugins/cppeditor/builtincursorinfo.cpp
index 15e1e0f492..0bff4406e7 100644
--- a/src/plugins/cppeditor/builtincursorinfo.cpp
+++ b/src/plugins/cppeditor/builtincursorinfo.cpp
@@ -135,17 +135,28 @@ private:
class FindUses
{
public:
- static CursorInfo find(const Document::Ptr document, const Snapshot &snapshot,
- int line, int column, Scope *scope, const QString &expression)
+ static CursorInfo find(const Document::Ptr document,
+ const QString &content,
+ const Snapshot &snapshot,
+ int line,
+ int column,
+ Scope *scope,
+ const QString &expression)
{
- FindUses findUses(document, snapshot, line, column, scope, expression);
+ FindUses findUses(document, content, snapshot, line, column, scope, expression);
return findUses.doFind();
}
private:
- FindUses(const Document::Ptr document, const Snapshot &snapshot, int line, int column,
- Scope *scope, const QString &expression)
+ FindUses(const Document::Ptr document,
+ const QString &content,
+ const Snapshot &snapshot,
+ int line,
+ int column,
+ Scope *scope,
+ const QString &expression)
: m_document(document)
+ , m_content(content)
, m_line(line)
, m_column(column)
, m_scope(scope)
@@ -160,7 +171,7 @@ private:
// findLocalUses operates with 1-based line and 0-based column
const SemanticInfo::LocalUseMap localUses
- = BuiltinCursorInfo::findLocalUses(m_document, m_line, m_column - 1);
+ = BuiltinCursorInfo::findLocalUses(m_document, m_content, m_line, m_column - 1);
result.localUses = localUses;
splitLocalUses(localUses, &result.useRanges, &result.unusedVariablesRanges);
@@ -230,6 +241,8 @@ private:
// Shared
Document::Ptr m_document;
+ const QString m_content;
+
// For local use calculation
int m_line;
int m_column;
@@ -322,11 +335,20 @@ QFuture<CursorInfo> BuiltinCursorInfo::run(const CursorInfoParams &cursorInfoPar
QString expression;
Scope *scope = canonicalSymbol.getScopeAndExpression(textCursor, &expression);
- return Utils::asyncRun(&FindUses::find, document, snapshot, line, column + 1, scope, expression);
+ return Utils::asyncRun(&FindUses::find,
+ document,
+ textCursor.document()->toPlainText(),
+ snapshot,
+ line,
+ column + 1,
+ scope,
+ expression);
}
-SemanticInfo::LocalUseMap
-BuiltinCursorInfo::findLocalUses(const Document::Ptr &document, int line, int column)
+SemanticInfo::LocalUseMap BuiltinCursorInfo::findLocalUses(const Document::Ptr &document,
+ const QString &content,
+ int line,
+ int column)
{
if (!document || !document->translationUnit() || !document->translationUnit()->ast())
return SemanticInfo::LocalUseMap();
@@ -334,7 +356,7 @@ BuiltinCursorInfo::findLocalUses(const Document::Ptr &document, int line, int co
AST *ast = document->translationUnit()->ast();
FunctionDefinitionUnderCursor functionDefinitionUnderCursor(document->translationUnit());
DeclarationAST *declaration = functionDefinitionUnderCursor(ast, line, column);
- return Internal::LocalSymbols(document, declaration).uses;
+ return Internal::LocalSymbols(document, content, declaration).uses;
}
} // namespace CppEditor
diff --git a/src/plugins/cppeditor/builtincursorinfo.h b/src/plugins/cppeditor/builtincursorinfo.h
index 4258f4854c..731c66f4c1 100644
--- a/src/plugins/cppeditor/builtincursorinfo.h
+++ b/src/plugins/cppeditor/builtincursorinfo.h
@@ -18,7 +18,7 @@ public:
static QFuture<CursorInfo> run(const CursorInfoParams &params);
static SemanticInfo::LocalUseMap
- findLocalUses(const CPlusPlus::Document::Ptr &document, int line, int column);
+ findLocalUses(const CPlusPlus::Document::Ptr &document, const QString &content, int line, int column);
};
} // namespace CppEditor
diff --git a/src/plugins/cppeditor/builtineditordocumentprocessor.cpp b/src/plugins/cppeditor/builtineditordocumentprocessor.cpp
index 4d43546334..b934d1e7ae 100644
--- a/src/plugins/cppeditor/builtineditordocumentprocessor.cpp
+++ b/src/plugins/cppeditor/builtineditordocumentprocessor.cpp
@@ -126,7 +126,7 @@ CheckSymbols *createHighlighter(const CPlusPlus::Document::Ptr &doc,
}
LookupContext context(doc, snapshot);
- return CheckSymbols::create(doc, context, macroUses);
+ return CheckSymbols::create(doc, textDocument->toPlainText(), context, macroUses);
}
QList<TextEditor::BlockRange> toTextEditorBlocks(
diff --git a/src/plugins/cppeditor/cppchecksymbols.cpp b/src/plugins/cppeditor/cppchecksymbols.cpp
index e9334b0db2..7fa1ed3f5b 100644
--- a/src/plugins/cppeditor/cppchecksymbols.cpp
+++ b/src/plugins/cppeditor/cppchecksymbols.cpp
@@ -270,28 +270,40 @@ static bool acceptName(NameAST *ast, unsigned *referenceToken)
&& !ast->asOperatorFunctionId();
}
-CheckSymbols::Future CheckSymbols::go(Document::Ptr doc, const LookupContext &context, const QList<CheckSymbols::Result> &macroUses)
+CheckSymbols::Future CheckSymbols::go(Document::Ptr doc,
+ const QString &content,
+ const LookupContext &context,
+ const QList<CheckSymbols::Result> &macroUses)
{
QTC_ASSERT(doc, return Future());
QTC_ASSERT(doc->translationUnit(), return Future());
QTC_ASSERT(doc->translationUnit()->ast(), return Future());
- return (new CheckSymbols(doc, context, macroUses))->start();
+ return (new CheckSymbols(doc, content, context, macroUses))->start();
}
-CheckSymbols * CheckSymbols::create(Document::Ptr doc, const LookupContext &context,
- const QList<CheckSymbols::Result> &macroUses)
+CheckSymbols *CheckSymbols::create(Document::Ptr doc,
+ const QString &content,
+ const LookupContext &context,
+ const QList<CheckSymbols::Result> &macroUses)
{
QTC_ASSERT(doc, return nullptr);
QTC_ASSERT(doc->translationUnit(), return nullptr);
QTC_ASSERT(doc->translationUnit()->ast(), return nullptr);
- return new CheckSymbols(doc, context, macroUses);
+ return new CheckSymbols(doc, content, context, macroUses);
}
-CheckSymbols::CheckSymbols(Document::Ptr doc, const LookupContext &context, const QList<CheckSymbols::Result> &macroUses)
- : ASTVisitor(doc->translationUnit()), _doc(doc), _context(context)
- , _lineOfLastUsage(0), _macroUses(macroUses)
+CheckSymbols::CheckSymbols(Document::Ptr doc,
+ const QString &content,
+ const LookupContext &context,
+ const QList<CheckSymbols::Result> &macroUses)
+ : ASTVisitor(doc->translationUnit())
+ , _doc(doc)
+ , _content(content)
+ , _context(context)
+ , _lineOfLastUsage(0)
+ , _macroUses(macroUses)
{
int line = 0;
getTokenEndPosition(translationUnit()->ast()->lastToken(), &line, nullptr);
@@ -1114,7 +1126,7 @@ bool CheckSymbols::visit(FunctionDefinitionAST *ast)
accept(ast->ctor_initializer);
accept(ast->function_body);
- const Internal::LocalSymbols locals(_doc, ast);
+ const Internal::LocalSymbols locals(_doc, _content, ast);
for (const QList<Result> &uses : std::as_const(locals.uses)) {
for (const Result &u : uses)
addUse(u);
diff --git a/src/plugins/cppeditor/cppchecksymbols.h b/src/plugins/cppeditor/cppchecksymbols.h
index f660da6dc9..38e04f989d 100644
--- a/src/plugins/cppeditor/cppchecksymbols.h
+++ b/src/plugins/cppeditor/cppchecksymbols.h
@@ -42,9 +42,11 @@ public:
}
static Future go(CPlusPlus::Document::Ptr doc,
+ const QString &content,
const CPlusPlus::LookupContext &context,
const QList<Result> &macroUses);
static CheckSymbols * create(CPlusPlus::Document::Ptr doc,
+ const QString &content,
const CPlusPlus::LookupContext &context,
const QList<Result> &macroUses);
@@ -79,6 +81,7 @@ protected:
};
CheckSymbols(CPlusPlus::Document::Ptr doc,
+ const QString &content,
const CPlusPlus::LookupContext &context,
const QList<Result> &otherUses);
@@ -168,6 +171,7 @@ private:
bool isConstructorDeclaration(CPlusPlus::Symbol *declaration);
CPlusPlus::Document::Ptr _doc;
+ const QString _content;
CPlusPlus::LookupContext _context;
CPlusPlus::TypeOfExpression typeOfExpression;
Utils::FilePath _filePath;
diff --git a/src/plugins/cppeditor/cppcodeformatter.cpp b/src/plugins/cppeditor/cppcodeformatter.cpp
index d09fa37d45..ca14d22a7c 100644
--- a/src/plugins/cppeditor/cppcodeformatter.cpp
+++ b/src/plugins/cppeditor/cppcodeformatter.cpp
@@ -151,6 +151,7 @@ void CodeFormatter::recalculateStateAfter(const QTextBlock &block)
case T_OPERATOR: enter(operator_declaration); break;
case T_GREATER_GREATER: break;
case T_LBRACKET: break;
+ case T_NAMESPACE: leave(); enter(namespace_start); break;
default: tryExpression(true); break;
} break;
diff --git a/src/plugins/cppeditor/cppfunctiondecldeflink.cpp b/src/plugins/cppeditor/cppfunctiondecldeflink.cpp
index 4dc31087bc..e489045f35 100644
--- a/src/plugins/cppeditor/cppfunctiondecldeflink.cpp
+++ b/src/plugins/cppeditor/cppfunctiondecldeflink.cpp
@@ -14,8 +14,6 @@
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/command.h>
-#include <texteditor/refactoroverlay.h>
-#include <texteditor/texteditorconstants.h>
#include <cplusplus/ASTPath.h>
#include <cplusplus/CppRewriter.h>
@@ -23,7 +21,13 @@
#include <cplusplus/Overview.h>
#include <cplusplus/TypeOfExpression.h>
+#include <extensionsystem/pluginmanager.h>
+
+#include <texteditor/refactoroverlay.h>
+#include <texteditor/texteditorconstants.h>
+
#include <utils/async.h>
+#include <utils/futuresynchronizer.h>
#include <utils/proxyaction.h>
#include <utils/qtcassert.h>
#include <utils/textutils.h>
@@ -41,21 +45,20 @@ namespace Internal {
FunctionDeclDefLinkFinder::FunctionDeclDefLinkFinder(QObject *parent)
: QObject(parent)
-{
-}
+{}
void FunctionDeclDefLinkFinder::onFutureDone()
{
std::shared_ptr<FunctionDeclDefLink> link = m_watcher->result();
- m_watcher.reset();
+ m_watcher.release()->deleteLater();
if (link) {
link->linkSelection = m_scannedSelection;
link->nameSelection = m_nameSelection;
if (m_nameSelection.selectedText() != link->nameInitial)
link.reset();
}
- m_scannedSelection = QTextCursor();
- m_nameSelection = QTextCursor();
+ m_scannedSelection = {};
+ m_nameSelection = {};
if (link)
emit foundLink(link);
}
@@ -234,8 +237,9 @@ void FunctionDeclDefLinkFinder::startFindLinkAt(
// handle the rest in a thread
m_watcher.reset(new QFutureWatcher<std::shared_ptr<FunctionDeclDefLink> >());
- connect(m_watcher.data(), &QFutureWatcherBase::finished, this, &FunctionDeclDefLinkFinder::onFutureDone);
+ connect(m_watcher.get(), &QFutureWatcherBase::finished, this, &FunctionDeclDefLinkFinder::onFutureDone);
m_watcher->setFuture(Utils::asyncRun(findLinkHelper, result, refactoringChanges));
+ ExtensionSystem::PluginManager::futureSynchronizer()->addFuture(m_watcher->future());
}
bool FunctionDeclDefLink::isValid() const
@@ -890,7 +894,7 @@ ChangeSet FunctionDeclDefLink::changes(const Snapshot &snapshot, int targetOffse
// for function definitions, rename the local usages
FunctionDefinitionAST *targetDefinition = targetDeclaration->asFunctionDefinition();
if (targetDefinition && !renamedTargetParameters.isEmpty()) {
- const LocalSymbols localSymbols(targetFile->cppDocument(), targetDefinition);
+ const LocalSymbols localSymbols(targetFile->cppDocument(), {}, targetDefinition);
const int endOfArguments = targetFile->endOf(targetFunctionDeclarator->rparen_token);
for (auto it = renamedTargetParameters.cbegin(), end = renamedTargetParameters.cend();
diff --git a/src/plugins/cppeditor/cppfunctiondecldeflink.h b/src/plugins/cppeditor/cppfunctiondecldeflink.h
index 4ffce9bf91..8fe6219e33 100644
--- a/src/plugins/cppeditor/cppfunctiondecldeflink.h
+++ b/src/plugins/cppeditor/cppfunctiondecldeflink.h
@@ -36,7 +36,7 @@ private:
QTextCursor m_scannedSelection;
QTextCursor m_nameSelection;
- QScopedPointer<QFutureWatcher<std::shared_ptr<FunctionDeclDefLink>>> m_watcher;
+ std::unique_ptr<QFutureWatcher<std::shared_ptr<FunctionDeclDefLink>>> m_watcher;
};
class FunctionDeclDefLink
diff --git a/src/plugins/cppeditor/cppindexingsupport.cpp b/src/plugins/cppeditor/cppindexingsupport.cpp
index 21a5da4109..3a418a5b78 100644
--- a/src/plugins/cppeditor/cppindexingsupport.cpp
+++ b/src/plugins/cppeditor/cppindexingsupport.cpp
@@ -147,7 +147,7 @@ static void indexFindErrors(QPromise<void> &promise, const ParseParams params)
// Look up symbols
CPlusPlus::LookupContext context(document, parser.snapshot());
- CheckSymbols::go(document, context, QList<CheckSymbols::Result>()).waitForFinished();
+ CheckSymbols::go(document, {}, context, QList<CheckSymbols::Result>()).waitForFinished();
document->releaseSourceAndAST();
diff --git a/src/plugins/cppeditor/cpplocalsymbols.cpp b/src/plugins/cppeditor/cpplocalsymbols.cpp
index 9983f9fba1..ec91dbe349 100644
--- a/src/plugins/cppeditor/cpplocalsymbols.cpp
+++ b/src/plugins/cppeditor/cpplocalsymbols.cpp
@@ -7,12 +7,12 @@
#include "cpptoolsreuse.h"
#include "semantichighlighter.h"
-#include <coreplugin/documentmanager.h>
#include <cplusplus/declarationcomments.h>
#include <cplusplus/Overview.h>
-#include <texteditor/textdocument.h>
#include <utils/textutils.h>
+#include <QTextDocument>
+
using namespace CPlusPlus;
namespace CppEditor::Internal {
@@ -22,8 +22,8 @@ namespace {
class FindLocalSymbols: protected ASTVisitor
{
public:
- explicit FindLocalSymbols(Document::Ptr doc)
- : ASTVisitor(doc->translationUnit()), _doc(doc)
+ explicit FindLocalSymbols(Document::Ptr doc, const QString &content)
+ : ASTVisitor(doc->translationUnit()), _doc(doc), _content(content)
{ }
// local and external uses.
@@ -49,35 +49,26 @@ public:
if (localUses.isEmpty())
return;
- // For tst_checkSymbols
- if (!Core::DocumentManager::instance())
- return;
-
// Look for parameter occurrences in function comments.
- const TextEditor::TextDocument * const editorDoc
- = TextEditor::TextDocument::textDocumentForFilePath(_doc->filePath());
- if (!editorDoc)
- return;
- QTextDocument * const textDoc = editorDoc->document();
- if (!textDoc)
+ if (_content.isEmpty())
return;
- const QString &content = textDoc->toPlainText();
- const QStringView docView(content);
+ QTextDocument textDoc(_content);
+ const QStringView docView(_content);
for (auto it = localUses.begin(); it != localUses.end(); ++it) {
Symbol * const symbol = it.key();
if (!symbol->asArgument())
continue;
- const QList<Token> commentTokens = commentsForDeclaration(symbol, ast, *textDoc, _doc);
+ const QList<Token> commentTokens = commentsForDeclaration(symbol, ast, textDoc, _doc);
if (commentTokens.isEmpty())
continue;
const QString symbolName = Overview().prettyName(symbol->name());
for (const Token &tok : commentTokens) {
- const int commentPos = translationUnit()->getTokenPositionInDocument(tok, textDoc);
+ const int commentPos = translationUnit()->getTokenPositionInDocument(tok, &textDoc);
const int commentEndPos = translationUnit()->getTokenEndPositionInDocument(
- tok, textDoc);
+ tok, &textDoc);
const QStringView commentView = docView.mid(commentPos, commentEndPos - commentPos);
const QList<Utils::Text::Range> ranges = symbolOccurrencesInText(
- *textDoc, commentView, commentPos, symbolName);
+ textDoc, commentView, commentPos, symbolName);
for (const Utils::Text::Range &range : ranges) {
it.value().append(HighlightingResult(range.begin.line, range.begin.column + 1,
symbolName.size(),
@@ -323,14 +314,15 @@ protected:
private:
QList<Scope *> _scopeStack;
Document::Ptr _doc;
+ const QString _content;
};
} // end of anonymous namespace
-LocalSymbols::LocalSymbols(Document::Ptr doc, DeclarationAST *ast)
+LocalSymbols::LocalSymbols(Document::Ptr doc, const QString &content, DeclarationAST *ast)
{
- FindLocalSymbols findLocalSymbols(doc);
+ FindLocalSymbols findLocalSymbols(doc, content);
findLocalSymbols(ast);
uses = findLocalSymbols.localUses;
}
diff --git a/src/plugins/cppeditor/cpplocalsymbols.h b/src/plugins/cppeditor/cpplocalsymbols.h
index 3c178f2f40..26cd185b72 100644
--- a/src/plugins/cppeditor/cpplocalsymbols.h
+++ b/src/plugins/cppeditor/cpplocalsymbols.h
@@ -12,7 +12,7 @@ class LocalSymbols
Q_DISABLE_COPY(LocalSymbols)
public:
- LocalSymbols(CPlusPlus::Document::Ptr doc, CPlusPlus::DeclarationAST *ast);
+ LocalSymbols(CPlusPlus::Document::Ptr doc, const QString &content, CPlusPlus::DeclarationAST *ast);
SemanticInfo::LocalUseMap uses;
};
diff --git a/src/plugins/cppeditor/cpplocalsymbols_test.cpp b/src/plugins/cppeditor/cpplocalsymbols_test.cpp
index 9605f24ffa..740fd8233c 100644
--- a/src/plugins/cppeditor/cpplocalsymbols_test.cpp
+++ b/src/plugins/cppeditor/cpplocalsymbols_test.cpp
@@ -160,7 +160,7 @@ void LocalSymbolsTest::test()
FindFirstFunctionDefinition find(document->translationUnit());
CPlusPlus::DeclarationAST *functionDefinition = find();
- LocalSymbols localSymbols(document, functionDefinition);
+ LocalSymbols localSymbols(document, QString::fromUtf8(source), functionDefinition);
const QList<Result> actualUses = Result::fromLocalUses(localSymbols.uses);
// for (const Result &result : actualUses)
diff --git a/src/plugins/cppeditor/cppuseselectionsupdater.cpp b/src/plugins/cppeditor/cppuseselectionsupdater.cpp
index e03475ea80..67fb6d7a1b 100644
--- a/src/plugins/cppeditor/cppuseselectionsupdater.cpp
+++ b/src/plugins/cppeditor/cppuseselectionsupdater.cpp
@@ -3,18 +3,19 @@
#include "cppuseselectionsupdater.h"
-#include "cppeditorwidget.h"
#include "cppeditordocument.h"
+#include "cppeditorwidget.h"
#include "cppmodelmanager.h"
-#include "cpptoolsreuse.h"
+#include <extensionsystem/pluginmanager.h>
+
+#include <utils/futuresynchronizer.h>
+#include <utils/qtcassert.h>
#include <utils/textutils.h>
#include <QTextBlock>
#include <QTextCursor>
-#include <utils/qtcassert.h>
-
enum { updateUseSelectionsInternalInMs = 500 };
namespace CppEditor {
@@ -67,13 +68,14 @@ CppUseSelectionsUpdater::RunnerInfo CppUseSelectionsUpdater::update(CallType cal
m_runnerWatcher->cancel();
m_runnerWatcher.reset(new QFutureWatcher<CursorInfo>);
- connect(m_runnerWatcher.data(), &QFutureWatcherBase::finished,
+ connect(m_runnerWatcher.get(), &QFutureWatcherBase::finished,
this, &CppUseSelectionsUpdater::onFindUsesFinished);
m_runnerRevision = m_editorWidget->document()->revision();
m_runnerWordStartPosition = params.textCursor.position();
m_runnerWatcher->setFuture(cppEditorDocument->cursorInfo(params));
+ ExtensionSystem::PluginManager::futureSynchronizer()->addFuture(m_runnerWatcher->future());
return RunnerInfo::Started;
} else { // synchronous case
abortSchedule();
@@ -142,7 +144,7 @@ void CppUseSelectionsUpdater::onFindUsesFinished()
processResults(m_runnerWatcher->result());
- m_runnerWatcher.reset();
+ m_runnerWatcher.release()->deleteLater();
}
CppUseSelectionsUpdater::ExtraSelections
diff --git a/src/plugins/cppeditor/cppuseselectionsupdater.h b/src/plugins/cppeditor/cppuseselectionsupdater.h
index b303ce7c25..88205c8974 100644
--- a/src/plugins/cppeditor/cppuseselectionsupdater.h
+++ b/src/plugins/cppeditor/cppuseselectionsupdater.h
@@ -54,7 +54,7 @@ private:
QTimer m_timer;
- QScopedPointer<QFutureWatcher<CursorInfo>> m_runnerWatcher;
+ std::unique_ptr<QFutureWatcher<CursorInfo>> m_runnerWatcher;
int m_runnerRevision = -1;
int m_runnerWordStartPosition = -1;
bool m_updateSelections = true;
diff --git a/src/plugins/cppeditor/semantichighlighter.cpp b/src/plugins/cppeditor/semantichighlighter.cpp
index fe52bbdebd..d841ae19c4 100644
--- a/src/plugins/cppeditor/semantichighlighter.cpp
+++ b/src/plugins/cppeditor/semantichighlighter.cpp
@@ -36,14 +36,7 @@ SemanticHighlighter::SemanticHighlighter(TextDocument *baseTextDocument)
updateFormatMapFromFontSettings();
}
-SemanticHighlighter::~SemanticHighlighter()
-{
- if (m_watcher) {
- disconnectWatcher();
- m_watcher->cancel();
- m_watcher->waitForFinished();
- }
-}
+SemanticHighlighter::~SemanticHighlighter() = default;
void SemanticHighlighter::setHighlightingRunner(HighlightingRunner highlightingRunner)
{
@@ -56,18 +49,20 @@ void SemanticHighlighter::run()
qCDebug(log) << "SemanticHighlighter: run()";
- if (m_watcher) {
- disconnectWatcher();
+ if (m_watcher)
m_watcher->cancel();
- }
m_watcher.reset(new QFutureWatcher<HighlightingResult>);
- connectWatcher();
+ connect(m_watcher.get(), &QFutureWatcherBase::resultsReadyAt,
+ this, &SemanticHighlighter::onHighlighterResultAvailable);
+ connect(m_watcher.get(), &QFutureWatcherBase::finished,
+ this, &SemanticHighlighter::onHighlighterFinished);
m_revision = documentRevision();
m_seenBlocks.clear();
m_nextResultToHandle = m_resultCount = 0;
qCDebug(log) << "starting runner for document revision" << m_revision;
m_watcher->setFuture(m_highlightingRunner());
+ m_futureSynchronizer.addFuture(m_watcher->future());
}
Parentheses SemanticHighlighter::getClearedParentheses(const QTextBlock &block)
@@ -232,28 +227,10 @@ void SemanticHighlighter::onHighlighterFinished()
TextDocumentLayout::setParentheses(currentBlock, getClearedParentheses(currentBlock));
}
- m_watcher.reset();
+ m_watcher.release()->deleteLater();
qCDebug(log) << "onHighlighterFinished() took" << t.elapsed() << "ms";
}
-void SemanticHighlighter::connectWatcher()
-{
- using Watcher = QFutureWatcher<HighlightingResult>;
- connect(m_watcher.data(), &Watcher::resultsReadyAt,
- this, &SemanticHighlighter::onHighlighterResultAvailable);
- connect(m_watcher.data(), &Watcher::finished,
- this, &SemanticHighlighter::onHighlighterFinished);
-}
-
-void SemanticHighlighter::disconnectWatcher()
-{
- using Watcher = QFutureWatcher<HighlightingResult>;
- disconnect(m_watcher.data(), &Watcher::resultsReadyAt,
- this, &SemanticHighlighter::onHighlighterResultAvailable);
- disconnect(m_watcher.data(), &Watcher::finished,
- this, &SemanticHighlighter::onHighlighterFinished);
-}
-
unsigned SemanticHighlighter::documentRevision() const
{
return m_baseTextDocument->document()->revision();
diff --git a/src/plugins/cppeditor/semantichighlighter.h b/src/plugins/cppeditor/semantichighlighter.h
index ea49f289a0..f4fb25ddca 100644
--- a/src/plugins/cppeditor/semantichighlighter.h
+++ b/src/plugins/cppeditor/semantichighlighter.h
@@ -5,12 +5,14 @@
#include "cppeditor_global.h"
+#include <utils/futuresynchronizer.h>
+
#include <QFutureWatcher>
-#include <QScopedPointer>
#include <QTextCharFormat>
#include <QVector>
#include <functional>
+#include <memory>
#include <set>
namespace TextEditor {
@@ -70,9 +72,6 @@ private:
void handleHighlighterResults();
void onHighlighterFinished();
- void connectWatcher();
- void disconnectWatcher();
-
unsigned documentRevision() const;
QVector<TextEditor::Parenthesis> getClearedParentheses(const QTextBlock &block);
@@ -80,13 +79,14 @@ private:
TextEditor::TextDocument *m_baseTextDocument;
unsigned m_revision = 0;
- QScopedPointer<QFutureWatcher<TextEditor::HighlightingResult>> m_watcher;
QHash<int, QTextCharFormat> m_formatMap;
std::set<int> m_seenBlocks;
int m_nextResultToHandle = 0;
int m_resultCount = 0;
HighlightingRunner m_highlightingRunner;
+ Utils::FutureSynchronizer m_futureSynchronizer; // Keep before m_watcher.
+ std::unique_ptr<QFutureWatcher<TextEditor::HighlightingResult>> m_watcher;
};
} // namespace CppEditor
diff --git a/src/plugins/cvs/cvsplugin.cpp b/src/plugins/cvs/cvsplugin.cpp
index 4ca9dd83b3..2688def71e 100644
--- a/src/plugins/cvs/cvsplugin.cpp
+++ b/src/plugins/cvs/cvsplugin.cpp
@@ -292,7 +292,7 @@ public:
VcsEditorFactory commandLogEditorFactory {{
OtherContent,
CVS_COMMANDLOG_EDITOR_ID,
- VcsBase::Tr::tr("CVS Command Log Editor"), // display name
+ ::VcsBase::Tr::tr("CVS Command Log Editor"), // display name
"text/vnd.qtcreator.cvs.commandlog",
[] { return new CvsEditorWidget; },
std::bind(&CvsPluginPrivate::vcsDescribe, this, _1, _2)
@@ -301,7 +301,7 @@ public:
VcsEditorFactory logEditorFactory {{
LogOutput,
CVS_FILELOG_EDITOR_ID,
- VcsBase::Tr::tr("CVS File Log Editor"), // display name
+ ::VcsBase::Tr::tr("CVS File Log Editor"), // display name
"text/vnd.qtcreator.cvs.log",
[] { return new CvsEditorWidget; },
std::bind(&CvsPluginPrivate::vcsDescribe, this, _1, _2)
@@ -310,7 +310,7 @@ public:
VcsEditorFactory annotateEditorFactory {{
AnnotateOutput,
CVS_ANNOTATION_EDITOR_ID,
- VcsBase::Tr::tr("CVS Annotation Editor"), // display name
+ ::VcsBase::Tr::tr("CVS Annotation Editor"), // display name
"text/vnd.qtcreator.cvs.annotation",
[] { return new CvsEditorWidget; },
std::bind(&CvsPluginPrivate::vcsDescribe, this, _1, _2)
@@ -319,7 +319,7 @@ public:
VcsEditorFactory diffEditorFactory {{
DiffOutput,
CVS_DIFF_EDITOR_ID,
- VcsBase::Tr::tr("CVS Diff Editor"), // display name
+ ::VcsBase::Tr::tr("CVS Diff Editor"), // display name
"text/x-patch",
[] { return new CvsEditorWidget; },
std::bind(&CvsPluginPrivate::vcsDescribe, this, _1, _2)
@@ -449,7 +449,7 @@ CvsPluginPrivate::CvsPluginPrivate()
setupVcsSubmitEditor(this, {
CVS_SUBMIT_MIMETYPE,
CVSCOMMITEDITOR_ID,
- VcsBase::Tr::tr("CVS Commit Editor"),
+ ::VcsBase::Tr::tr("CVS Commit Editor"),
VcsBaseSubmitEditorParameters::DiffFiles,
[] { return new CvsSubmitEditor; },
});
diff --git a/src/plugins/debugger/cdb/cdbengine.cpp b/src/plugins/debugger/cdb/cdbengine.cpp
index 3d9777f51e..7a428c6a85 100644
--- a/src/plugins/debugger/cdb/cdbengine.cpp
+++ b/src/plugins/debugger/cdb/cdbengine.cpp
@@ -2096,9 +2096,11 @@ void CdbEngine::handleExtensionMessage(char t, int token, const QString &what, c
}
if (what == "debuggee_output") {
- const QByteArray decoded = QByteArray::fromHex(message.toUtf8());
- showMessage(QString::fromUtf16(reinterpret_cast<const char16_t *>(decoded.data()), decoded.size() / 2),
- AppOutput);
+ const QByteArray encoded = QByteArray::fromHex(message.toUtf8());
+ const QString message = QString::fromUtf16(reinterpret_cast<const char16_t *>(
+ encoded.data()),
+ encoded.size() / 2);
+ showMessage(message.endsWith('\n') ? message : message + '\n', AppOutput);
return;
}
diff --git a/src/plugins/debugger/debuggeritemmanager.cpp b/src/plugins/debugger/debuggeritemmanager.cpp
index 87b6247298..d9926ed59b 100644
--- a/src/plugins/debugger/debuggeritemmanager.cpp
+++ b/src/plugins/debugger/debuggeritemmanager.cpp
@@ -9,6 +9,8 @@
#include <coreplugin/dialogs/ioptionspage.h>
#include <coreplugin/icore.h>
+#include <extensionsystem/pluginmanager.h>
+
#include <projectexplorer/devicesupport/devicemanager.h>
#include <projectexplorer/kitoptionspage.h>
#include <projectexplorer/projectexplorerconstants.h>
@@ -19,6 +21,7 @@
#include <utils/detailswidget.h>
#include <utils/environment.h>
#include <utils/fileutils.h>
+#include <utils/futuresynchronizer.h>
#include <utils/hostosinfo.h>
#include <utils/layoutbuilder.h>
#include <utils/pathchooser.h>
@@ -480,14 +483,14 @@ void DebuggerItemConfigWidget::binaryPathHasChanged()
if (!m_generic) {
m_updateWatcher.cancel();
- DebuggerItem tmp;
if (m_binaryChooser->filePath().isExecutableFile()) {
- tmp = item();
- m_updateWatcher.setFuture(Utils::asyncRun([tmp]() mutable {
+ m_updateWatcher.setFuture(Utils::asyncRun([tmp = item()]() mutable {
tmp.reinitializeFromFile();
return tmp;
}));
+ ExtensionSystem::PluginManager::futureSynchronizer()->addFuture(m_updateWatcher.future());
} else {
+ const DebuggerItem tmp;
setAbis(tmp.abiNames());
m_version->setText(tmp.version());
m_engineType = tmp.engineType();
diff --git a/src/plugins/debugger/lldb/lldbengine.cpp b/src/plugins/debugger/lldb/lldbengine.cpp
index deb42544a8..1bb409bf94 100644
--- a/src/plugins/debugger/lldb/lldbengine.cpp
+++ b/src/plugins/debugger/lldb/lldbengine.cpp
@@ -841,18 +841,23 @@ void LldbEngine::readLldbStandardError()
void LldbEngine::readLldbStandardOutput()
{
- QByteArray outba = m_lldbProc.readAllRawStandardOutput();
- outba.replace("\r\n", "\n");
- QString out = QString::fromUtf8(outba);
- showMessage(out, LogOutput);
+ const QByteArray out = m_lldbProc.readAllRawStandardOutput();
+ showMessage(QString::fromUtf8(out), LogOutput);
m_inbuffer.append(out);
while (true) {
- int pos = m_inbuffer.indexOf("@\n");
- if (pos == -1)
- break;
- QString response = m_inbuffer.left(pos).trimmed();
- m_inbuffer = m_inbuffer.mid(pos + 2);
- emit outputReady(response);
+ if (int pos = m_inbuffer.indexOf("@\n"); pos >= 0) {
+ const QByteArray response = m_inbuffer.left(pos).trimmed();
+ m_inbuffer = m_inbuffer.mid(pos + 2);
+ emit outputReady(QString::fromUtf8(response));
+ continue;
+ }
+ if (int pos = m_inbuffer.indexOf("@\r\n"); pos >= 0) {
+ const QByteArray response = m_inbuffer.left(pos).trimmed();
+ m_inbuffer = m_inbuffer.mid(pos + 3);
+ emit outputReady(QString::fromUtf8(response));
+ continue;
+ }
+ break;
}
}
diff --git a/src/plugins/debugger/lldb/lldbengine.h b/src/plugins/debugger/lldb/lldbengine.h
index db11af9c10..57cbd1e7c7 100644
--- a/src/plugins/debugger/lldb/lldbengine.h
+++ b/src/plugins/debugger/lldb/lldbengine.h
@@ -111,7 +111,7 @@ private:
private:
DebuggerCommand m_lastDebuggableCommand;
- QString m_inbuffer;
+ QByteArray m_inbuffer;
QString m_scriptFileName;
Utils::Process m_lldbProc;
diff --git a/src/plugins/diffeditor/diffeditorwidgetcontroller.cpp b/src/plugins/diffeditor/diffeditorwidgetcontroller.cpp
index 0f3a57ee08..9decc5f1a6 100644
--- a/src/plugins/diffeditor/diffeditorwidgetcontroller.cpp
+++ b/src/plugins/diffeditor/diffeditorwidgetcontroller.cpp
@@ -267,9 +267,12 @@ void DiffEditorWidgetController::addPatchAction(QMenu *menu, int fileIndex, int
const QString actionName = patchAction == PatchAction::Apply ? Tr::tr("Apply Chunk...")
: Tr::tr("Revert Chunk...");
QAction *action = menu->addAction(actionName);
- connect(action, &QAction::triggered, this, [this, fileIndex, chunkIndex, patchAction] {
- patch(patchAction, fileIndex, chunkIndex);
- });
+ connect(
+ action,
+ &QAction::triggered,
+ this,
+ [this, fileIndex, chunkIndex, patchAction] { patch(patchAction, fileIndex, chunkIndex); },
+ Qt::QueuedConnection);
const bool enabled = chunkExists(fileIndex, chunkIndex)
&& (patchAction == PatchAction::Revert || fileNamesAreDifferent(fileIndex));
action->setEnabled(enabled);
diff --git a/src/plugins/effectcomposer/effectcomposerview.h b/src/plugins/effectcomposer/effectcomposerview.h
index a16225dfec..c7a381cb7d 100644
--- a/src/plugins/effectcomposer/effectcomposerview.h
+++ b/src/plugins/effectcomposer/effectcomposerview.h
@@ -24,6 +24,7 @@ public:
class EffectComposerView : public QmlDesigner::AbstractView
{
+ Q_DECLARE_TR_FUNCTIONS(EffectComposer::EffectComposerView)
public:
EffectComposerView(QmlDesigner::ExternalDependenciesInterface &externalDependencies);
~EffectComposerView() override;
diff --git a/src/plugins/git/gitsettings.cpp b/src/plugins/git/gitsettings.cpp
index 95938a41d8..2e7f8bf2de 100644
--- a/src/plugins/git/gitsettings.cpp
+++ b/src/plugins/git/gitsettings.cpp
@@ -33,7 +33,7 @@ GitSettings::GitSettings()
path.setLabelText(Tr::tr("Prepend to PATH:"));
path.setDisplayStyle(StringAspect::LineEditDisplay);
- binaryPath.setLabelText(Tr::tr("Git Command"));
+ binaryPath.setLabelText(Tr::tr("Git command:"));
binaryPath.setDefaultValue("git");
binaryPath.setExpectedKind(PathChooser::ExistingCommand);
binaryPath.setHistoryCompleter("Git.Command.History");
diff --git a/src/plugins/ios/devicectlutils.cpp b/src/plugins/ios/devicectlutils.cpp
index f8d47caf0b..7bbed859b2 100644
--- a/src/plugins/ios/devicectlutils.cpp
+++ b/src/plugins/ios/devicectlutils.cpp
@@ -46,7 +46,7 @@ expected_str<QJsonValue> parseDevicectlResult(const QByteArray &rawOutput)
}
const QJsonValue resultValue = jsonOutput["result"];
if (resultValue.isUndefined()) {
- return make_unexpected(Tr::tr("Failed to parse devicectl output: 'result' is missing"));
+ return make_unexpected(Tr::tr("Failed to parse devicectl output: \"result\" is missing."));
}
return resultValue;
}
diff --git a/src/plugins/ios/iosrunner.cpp b/src/plugins/ios/iosrunner.cpp
index c58c5731ba..cf8c5b70e2 100644
--- a/src/plugins/ios/iosrunner.cpp
+++ b/src/plugins/ios/iosrunner.cpp
@@ -264,7 +264,7 @@ GroupItem DeviceCtlRunner::launchTask(const QString &bundleIdentifier)
void DeviceCtlRunner::reportStoppedImpl()
{
- appendMessage(Tr::tr("\"%1\" exited").arg(m_bundlePath.toUserOutput()),
+ appendMessage(Tr::tr("\"%1\" exited.").arg(m_bundlePath.toUserOutput()),
Utils::NormalMessageFormat);
reportStopped();
}
diff --git a/src/plugins/ios/iossettingspage.cpp b/src/plugins/ios/iossettingspage.cpp
index ad81b81b19..042dfca9af 100644
--- a/src/plugins/ios/iossettingspage.cpp
+++ b/src/plugins/ios/iossettingspage.cpp
@@ -204,9 +204,11 @@ void IosSettingsWidget::onStart()
QList<QFuture<void>> futureList;
for (const SimulatorInfo &info : simulatorInfoList) {
if (!info.isShutdown()) {
- statusDialog->addMessage(Tr::tr("Cannot start simulator (%1, %2) in current state: %3")
- .arg(info.name).arg(info.runtimeName).arg(info.state),
- Utils::StdErrFormat);
+ statusDialog->addMessage(Tr::tr("Cannot start simulator (%1, %2) in current state: %3.")
+ .arg(info.name)
+ .arg(info.runtimeName)
+ .arg(info.state),
+ Utils::StdErrFormat);
} else {
futureList << QFuture<void>(Utils::onResultReady(
SimulatorControl::startSimulator(info.identifier), this,
diff --git a/src/plugins/languageclient/callhierarchy.cpp b/src/plugins/languageclient/callhierarchy.cpp
index a310fde2a4..32023e6a98 100644
--- a/src/plugins/languageclient/callhierarchy.cpp
+++ b/src/plugins/languageclient/callhierarchy.cpp
@@ -280,7 +280,7 @@ public:
Icons::RELOAD_TOOLBAR.icon();
auto button = new QToolButton;
button->setIcon(Icons::RELOAD_TOOLBAR.icon());
- button->setToolTip(Tr::tr("Reloads the call hierarchy for the symbol under cursor position."));
+ button->setToolTip(::LanguageClient::Tr::tr("Reloads the call hierarchy for the symbol under cursor position."));
connect(button, &QToolButton::clicked, this, [h] { h->updateHierarchyAtCursorPosition(); });
return {h, {button}};
}
diff --git a/src/plugins/mercurial/mercurialplugin.cpp b/src/plugins/mercurial/mercurialplugin.cpp
index 76c8f2ba8c..a9ab891c02 100644
--- a/src/plugins/mercurial/mercurialplugin.cpp
+++ b/src/plugins/mercurial/mercurialplugin.cpp
@@ -146,7 +146,7 @@ public:
VcsEditorFactory logEditorFactory {{
LogOutput,
Constants::FILELOG_ID,
- VcsBase::Tr::tr("Mercurial File Log Editor"),
+ ::VcsBase::Tr::tr("Mercurial File Log Editor"),
Constants::LOGAPP,
[] { return new MercurialEditorWidget; },
std::bind(&MercurialPluginPrivate::vcsDescribe, this, _1, _2)
@@ -155,7 +155,7 @@ public:
VcsEditorFactory annotateEditorFactory {{
AnnotateOutput,
Constants::ANNOTATELOG_ID,
- VcsBase::Tr::tr("Mercurial Annotation Editor"),
+ ::VcsBase::Tr::tr("Mercurial Annotation Editor"),
Constants::ANNOTATEAPP,
[] { return new MercurialEditorWidget; },
std::bind(&MercurialPluginPrivate::vcsDescribe, this, _1, _2)
@@ -164,7 +164,7 @@ public:
VcsEditorFactory diffEditorFactory {{
DiffOutput,
Constants::DIFFLOG_ID,
- VcsBase::Tr::tr("Mercurial Diff Editor"),
+ ::VcsBase::Tr::tr("Mercurial Diff Editor"),
Constants::DIFFAPP,
[] { return new MercurialEditorWidget; },
std::bind(&MercurialPluginPrivate::vcsDescribe, this, _1, _2)
@@ -181,7 +181,7 @@ MercurialPluginPrivate::MercurialPluginPrivate()
setupVcsSubmitEditor(this, {
Constants::COMMITMIMETYPE,
Constants::COMMIT_ID,
- VcsBase::Tr::tr("Mercurial Commit Log Editor"),
+ ::VcsBase::Tr::tr("Mercurial Commit Log Editor"),
VcsBaseSubmitEditorParameters::DiffFiles,
[] { return new CommitEditor; }
});
diff --git a/src/plugins/mesonprojectmanager/toolssettingsaccessor.cpp b/src/plugins/mesonprojectmanager/toolssettingsaccessor.cpp
index 1fe381d025..8e941ae21b 100644
--- a/src/plugins/mesonprojectmanager/toolssettingsaccessor.cpp
+++ b/src/plugins/mesonprojectmanager/toolssettingsaccessor.cpp
@@ -77,14 +77,14 @@ std::vector<MesonTools::Tool_t> ToolsSettingsAccessor::loadMesonTools()
std::vector<MesonTools::Tool_t> result;
for (auto toolIndex = 0; toolIndex < entry_count; toolIndex++) {
Key name = entryName(toolIndex);
- if (data.contains(name)) {
- const auto map = data[name].toMap();
- auto type = map.value(ToolsSettings::TOOL_TYPE_KEY, ToolsSettings::TOOL_TYPE_MESON);
- if (type == ToolsSettings::TOOL_TYPE_NINJA)
- result.emplace_back(fromVariantMap<NinjaWrapper *>(storeFromVariant(data[name])));
- else
- result.emplace_back(fromVariantMap<MesonWrapper *>(storeFromVariant(data[name])));
- }
+ Store store = storeFromVariant(data[name]);
+ QString type = store.value(ToolsSettings::TOOL_TYPE_KEY).toString();
+ if (type == ToolsSettings::TOOL_TYPE_NINJA)
+ result.emplace_back(fromVariantMap<NinjaWrapper *>(storeFromVariant(data[name])));
+ else if (type == ToolsSettings::TOOL_TYPE_MESON)
+ result.emplace_back(fromVariantMap<MesonWrapper *>(storeFromVariant(data[name])));
+ else
+ QTC_CHECK(false);
}
return result;
}
diff --git a/src/plugins/perforce/perforceplugin.cpp b/src/plugins/perforce/perforceplugin.cpp
index 42e2bbfcb1..7e8dca8265 100644
--- a/src/plugins/perforce/perforceplugin.cpp
+++ b/src/plugins/perforce/perforceplugin.cpp
@@ -1499,7 +1499,7 @@ QString fileNameFromPerforceName(const QString &perforceName, bool quiet)
//: Failed to run p4 "where" to resolve a Perforce file name to a local
//: file system name.
VcsOutputWindow::appendError(
- Tr::tr("Error running \"where\" on %1: The file is not mapped")
+ Tr::tr("Error running \"where\" on %1: The file is not mapped.")
.arg(QDir::toNativeSeparators(perforceName)));
}
return {};
diff --git a/src/plugins/projectexplorer/abstractprocessstep.cpp b/src/plugins/projectexplorer/abstractprocessstep.cpp
index 84a3113579..547599bc9d 100644
--- a/src/plugins/projectexplorer/abstractprocessstep.cpp
+++ b/src/plugins/projectexplorer/abstractprocessstep.cpp
@@ -79,8 +79,6 @@ public:
std::function<void(Environment &)> m_environmentModifier;
bool m_ignoreReturnValue = false;
bool m_lowPriority = false;
- std::unique_ptr<QTextDecoder> stdOutDecoder;
- std::unique_ptr<QTextDecoder> stdErrDecoder;
OutputFormatter *outputFormatter = nullptr;
};
@@ -146,9 +144,6 @@ bool AbstractProcessStep::init()
if (!setupProcessParameters(processParameters()))
return false;
- d->stdOutDecoder = std::make_unique<QTextDecoder>(buildEnvironment().hasKey("VSLANG")
- ? QTextCodec::codecForName("UTF-8") : QTextCodec::codecForLocale());
- d->stdErrDecoder = std::make_unique<QTextDecoder>(QTextCodec::codecForLocale());
return true;
}
@@ -197,14 +192,18 @@ bool AbstractProcessStep::setupProcess(Process &process)
if (d->m_lowPriority && ProjectExplorerPlugin::projectExplorerSettings().lowBuildPriority)
process.setLowPriority();
- connect(&process, &Process::readyReadStandardOutput, this, [this, &process] {
- emit addOutput(d->stdOutDecoder->toUnicode(process.readAllRawStandardOutput()),
- OutputFormat::Stdout, DontAppendNewline);
+ process.setStdOutCodec(buildEnvironment().hasKey("VSLANG")
+ ? QTextCodec::codecForName("UTF-8") : QTextCodec::codecForLocale());
+ process.setStdErrCodec(QTextCodec::codecForLocale());
+
+ process.setStdOutLineCallback([this](const QString &s){
+ emit addOutput(s, OutputFormat::Stdout, DontAppendNewline);
});
- connect(&process, &Process::readyReadStandardError, this, [this, &process] {
- emit addOutput(d->stdErrDecoder->toUnicode(process.readAllRawStandardError()),
- OutputFormat::Stderr, DontAppendNewline);
+
+ process.setStdErrLineCallback([this](const QString &s){
+ emit addOutput(s, OutputFormat::Stderr, DontAppendNewline);
});
+
connect(&process, &Process::started, this, [this] {
ProcessParameters *params = d->m_displayedParams;
emit addOutput(Tr::tr("Starting: \"%1\" %2")
diff --git a/src/plugins/projectexplorer/buildaspects.cpp b/src/plugins/projectexplorer/buildaspects.cpp
index 18f7fe2b85..0f9c025fce 100644
--- a/src/plugins/projectexplorer/buildaspects.cpp
+++ b/src/plugins/projectexplorer/buildaspects.cpp
@@ -194,7 +194,7 @@ QString BuildDirectoryAspect::updateProblemLabelsHelper(const QString &value)
const auto isInvalid = [](QChar c) { return c.isSpace() || !isascii(c.toLatin1()); };
if (const auto invalidChar = Utils::findOr(value, std::nullopt, isInvalid)) {
genericProblem = Tr::tr(
- "Build directory contains potentially problematic character '%1'.")
+ "Build directory contains potentially problematic character \"%1\".")
.arg(*invalidChar);
genericProblemLabelString
= genericProblem
diff --git a/src/plugins/projectexplorer/jsonwizard/jsonwizardfactory.cpp b/src/plugins/projectexplorer/jsonwizard/jsonwizardfactory.cpp
index 0febbcd414..7f8ff6baf5 100644
--- a/src/plugins/projectexplorer/jsonwizard/jsonwizardfactory.cpp
+++ b/src/plugins/projectexplorer/jsonwizard/jsonwizardfactory.cpp
@@ -504,7 +504,7 @@ QList<Core::IWizardFactory *> JsonWizardFactory::createWizardFactories()
currentFile.parentDir(),
&errorMessage);
if (!factory) {
- verboseLog.append(tr("* Failed to create: %1\n").arg(errorMessage));
+ verboseLog.append(Tr::tr("* Failed to create: %1\n").arg(errorMessage));
continue;
}
diff --git a/src/plugins/projectexplorer/projectwindow.cpp b/src/plugins/projectexplorer/projectwindow.cpp
index c0577c5c52..66dca5ecd5 100644
--- a/src/plugins/projectexplorer/projectwindow.cpp
+++ b/src/plugins/projectexplorer/projectwindow.cpp
@@ -527,11 +527,11 @@ public:
}
case PanelWidgetRole:
- case ActiveItemRole:
- if (m_currentChildIndex == 0)
- return m_targetsItem->data(column, role);
- if (m_currentChildIndex == 1)
- return m_miscItem->data(column, role);
+ case ActiveItemRole: {
+ TreeItem *child = childAt(m_currentChildIndex);
+ if (child)
+ return child->data(column, role);
+ }
}
return {};
}
diff --git a/src/plugins/python/pythonkitaspect.cpp b/src/plugins/python/pythonkitaspect.cpp
index 2c700f58ae..26ad44bad4 100644
--- a/src/plugins/python/pythonkitaspect.cpp
+++ b/src/plugins/python/pythonkitaspect.cpp
@@ -108,15 +108,17 @@ public:
result << BuildSystemTask(Task::Error, Tr::tr("No Python setup."));
} else if (!path.exists()) {
result << BuildSystemTask(Task::Error,
- Tr::tr("Python %1 not found.").arg(path.toUserOutput()));
+ Tr::tr("Python \"%1\" not found.").arg(path.toUserOutput()));
} else if (!path.isExecutableFile()) {
result << BuildSystemTask(Task::Error,
- Tr::tr("Python %1 not executable.").arg(path.toUserOutput()));
+ Tr::tr("Python \"%1\" is not executable.")
+ .arg(path.toUserOutput()));
} else {
if (!pipIsUsable(path)) {
result << BuildSystemTask(
Task::Warning,
- Tr::tr("Python %1 does not contain a usable pip. Pip is used to install python "
+ Tr::tr("Python \"%1\" does not contain a usable pip. Pip is used to install "
+ "python "
"packages from the Python Package Index, like PySide and the python "
"language server. If you want to use any of that functionality "
"ensure pip is installed for that python.")
@@ -125,9 +127,10 @@ public:
if (!venvIsUsable(path)) {
result << BuildSystemTask(
Task::Warning,
- Tr::tr("Python %1 does not contain a usable venv. venv is the recommended way "
- "to isolate a development environment for a project from the globally "
- "installed python.")
+ Tr::tr(
+ "Python \"%1\" does not contain a usable venv. venv is the recommended way "
+ "to isolate a development environment for a project from the globally "
+ "installed python.")
.arg(path.toUserOutput()));
}
}
diff --git a/src/plugins/python/pythonproject.cpp b/src/plugins/python/pythonproject.cpp
index 49216b2d6a..129782773d 100644
--- a/src/plugins/python/pythonproject.cpp
+++ b/src/plugins/python/pythonproject.cpp
@@ -33,8 +33,9 @@ Tasks PythonProject::projectIssues(const Kit *k) const
{
if (PythonKitAspect::python(k))
return {};
- return {BuildSystemTask{Task::Error,
- Tr::tr("No python interpreter set for kit %1").arg(k->displayName())}};
+ return {
+ BuildSystemTask{Task::Error,
+ Tr::tr("No python interpreter set for kit \"%1\"").arg(k->displayName())}};
}
PythonProjectNode::PythonProjectNode(const FilePath &path)
diff --git a/src/plugins/qmljseditor/qmllssettings.cpp b/src/plugins/qmljseditor/qmllssettings.cpp
index 76ce535fa7..15cb8908af 100644
--- a/src/plugins/qmljseditor/qmllssettings.cpp
+++ b/src/plugins/qmljseditor/qmllssettings.cpp
@@ -49,6 +49,7 @@ static FilePath evaluateLatestQmlls()
if (latestQmakeFilePath == qmakeNow && latestUniqueId >= v->uniqueId())
continue;
}
+ latestVersion = vNow;
latestQmlls = qmllsNow;
latestQmakeFilePath = qmakeNow;
latestUniqueId = uniqueIdNow;
diff --git a/src/plugins/qtapplicationmanager/appmanagercmakepackagestep.cpp b/src/plugins/qtapplicationmanager/appmanagercmakepackagestep.cpp
index fee8cd4971..94f91a1585 100644
--- a/src/plugins/qtapplicationmanager/appmanagercmakepackagestep.cpp
+++ b/src/plugins/qtapplicationmanager/appmanagercmakepackagestep.cpp
@@ -42,7 +42,7 @@ public:
QObject::connect(step->project(), &Project::displayNameChanged, step, updaterSlot);
});
- setDisplayName(Tr::tr("Create Appman package with CMake"));
+ setDisplayName(Tr::tr("Create Application Manager package with CMake"));
setSupportedStepList(ProjectExplorer::Constants::BUILDSTEPS_DEPLOY);
}
};
diff --git a/src/plugins/qtapplicationmanager/appmanagerdeployconfigurationfactory.cpp b/src/plugins/qtapplicationmanager/appmanagerdeployconfigurationfactory.cpp
index 8b2792edba..ed524cae28 100644
--- a/src/plugins/qtapplicationmanager/appmanagerdeployconfigurationfactory.cpp
+++ b/src/plugins/qtapplicationmanager/appmanagerdeployconfigurationfactory.cpp
@@ -33,7 +33,7 @@ public:
AppManagerDeployConfigurationFactory()
{
setConfigBaseId(Constants::DEPLOYCONFIGURATION_ID);
- setDefaultDisplayName(Tr::tr("Automatic AppMan Deploy Configuration"));
+ setDefaultDisplayName(Tr::tr("Automatic Application Manager Deploy Configuration"));
addSupportedTargetDeviceType(ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE);
addSupportedTargetDeviceType(RemoteLinux::Constants::GenericLinuxOsType);
addSupportedTargetDeviceType(Qdb::Constants::QdbLinuxOsType);
diff --git a/src/plugins/qtapplicationmanager/appmanagerdeploypackagestep.cpp b/src/plugins/qtapplicationmanager/appmanagerdeploypackagestep.cpp
index da6c605200..6263028a6e 100644
--- a/src/plugins/qtapplicationmanager/appmanagerdeploypackagestep.cpp
+++ b/src/plugins/qtapplicationmanager/appmanagerdeploypackagestep.cpp
@@ -95,9 +95,9 @@ private:
};
const auto onDone = [this](DoneWith result) {
if (result == DoneWith::Success)
- emit addOutput(Tr::tr("Uploading finished"), OutputFormat::NormalMessage);
+ emit addOutput(Tr::tr("Uploading finished."), OutputFormat::NormalMessage);
else
- emit addOutput(Tr::tr("Uploading failed"), OutputFormat::ErrorMessage);
+ emit addOutput(Tr::tr("Uploading failed."), OutputFormat::ErrorMessage);
};
return FileStreamerTask(onSetup, onDone);
}
diff --git a/src/plugins/qtapplicationmanager/appmanagerinstallpackagestep.cpp b/src/plugins/qtapplicationmanager/appmanagerinstallpackagestep.cpp
index 0f995144ec..f89514ba00 100644
--- a/src/plugins/qtapplicationmanager/appmanagerinstallpackagestep.cpp
+++ b/src/plugins/qtapplicationmanager/appmanagerinstallpackagestep.cpp
@@ -52,7 +52,7 @@ private:
AppManagerInstallPackageStep::AppManagerInstallPackageStep(BuildStepList *bsl, Id id)
: AbstractRemoteLinuxDeployStep(bsl, id)
{
- setDisplayName(tr("Install Application Manager package"));
+ setDisplayName(Tr::tr("Install Application Manager package"));
controller.setDefaultPathValue(getToolFilePath(Constants::APPMAN_CONTROLLER,
target()->kit(),
@@ -125,7 +125,7 @@ GroupItem AppManagerInstallPackageStep::deployRecipe()
};
const auto doneHandler = [this](const Process &process, DoneWith result) {
if (result == DoneWith::Success) {
- addProgressMessage(tr("Command finished successfully."));
+ addProgressMessage(Tr::tr("Command finished successfully."));
} else {
if (process.error() != QProcess::UnknownError
|| process.exitStatus() != QProcess::NormalExit) {
diff --git a/src/plugins/qtapplicationmanager/appmanagerrunconfiguration.cpp b/src/plugins/qtapplicationmanager/appmanagerrunconfiguration.cpp
index 77bddffb05..bf901128f7 100644
--- a/src/plugins/qtapplicationmanager/appmanagerrunconfiguration.cpp
+++ b/src/plugins/qtapplicationmanager/appmanagerrunconfiguration.cpp
@@ -33,7 +33,7 @@ public:
AppManagerRunConfiguration(Target *target, Id id)
: RunConfiguration(target, id)
{
- setDefaultDisplayName(Tr::tr("Run an Appman Package"));
+ setDefaultDisplayName(Tr::tr("Run an Application Manager Package"));
setUpdater([this, target] {
QList<TargetInformation> tis = TargetInformation::readFromProject(target, buildKey());
@@ -66,7 +66,7 @@ public:
AppManagerRunAndDebugConfiguration(Target *target, Id id)
: AppManagerRunConfiguration(target, id)
{
- setDefaultDisplayName(Tr::tr("Run and Debug an Appman Package"));
+ setDefaultDisplayName(Tr::tr("Run and Debug an Application Manager Package"));
environment.addPreferredBaseEnvironment(Tr::tr("Clean Environment"), {});
}
diff --git a/src/plugins/qtapplicationmanager/appmanagerruncontrol.cpp b/src/plugins/qtapplicationmanager/appmanagerruncontrol.cpp
index 37ade56316..f1bbebf575 100644
--- a/src/plugins/qtapplicationmanager/appmanagerruncontrol.cpp
+++ b/src/plugins/qtapplicationmanager/appmanagerruncontrol.cpp
@@ -48,7 +48,7 @@ public:
{
setId("ApplicationManagerPlugin.Run.TargetRunner");
connect(this, &RunWorker::stopped, this, [this, runControl] {
- appendMessage(Tr::tr("%1 exited").arg(runControl->runnable().command.toUserOutput()),
+ appendMessage(Tr::tr("%1 exited.").arg(runControl->runnable().command.toUserOutput()),
OutputFormat::NormalMessageFormat);
});
@@ -170,8 +170,8 @@ public:
setProcessMode(ProcessMode::Writer);
setCommandLine(cmd);
- appendMessage(Tr::tr("Starting AppMan Debugging..."), NormalMessageFormat);
- appendMessage(Tr::tr("Using: %1").arg(cmd.toUserOutput()), NormalMessageFormat);
+ appendMessage(Tr::tr("Starting Application Manager debugging..."), NormalMessageFormat);
+ appendMessage(Tr::tr("Using: %1.").arg(cmd.toUserOutput()), NormalMessageFormat);
});
}
@@ -232,7 +232,7 @@ private:
void start() override
{
if (m_symbolFile.isEmpty()) {
- reportFailure(tr("Cannot debug: Local executable is not set."));
+ reportFailure(Tr::tr("Cannot debug: Local executable is not set."));
return;
}
diff --git a/src/plugins/qtapplicationmanager/appmanagerstringaspect.cpp b/src/plugins/qtapplicationmanager/appmanagerstringaspect.cpp
index 23645224c3..6127a7658a 100644
--- a/src/plugins/qtapplicationmanager/appmanagerstringaspect.cpp
+++ b/src/plugins/qtapplicationmanager/appmanagerstringaspect.cpp
@@ -24,7 +24,7 @@ AppManagerIdAspect::AppManagerIdAspect(Utils::AspectContainer *container)
{
setSettingsKey("ApplicationManagerPlugin.ApplicationId");
setDisplayStyle(StringAspect::LineEditDisplay);
- setLabelText(Tr::tr("Application id:"));
+ setLabelText(Tr::tr("Application ID:"));
// setReadOnly(true);
}
@@ -33,9 +33,9 @@ AppManagerInstanceIdAspect::AppManagerInstanceIdAspect(Utils::AspectContainer *c
{
setSettingsKey("ApplicationManagerPlugin.InstanceId");
setDisplayStyle(StringAspect::LineEditDisplay);
- setLabelText(Tr::tr("AppMan instance id:"));
+ setLabelText(Tr::tr("Application Manager instance ID:"));
- makeCheckable(Utils::CheckBoxPlacement::Right, Tr::tr("Default Instance"),
+ makeCheckable(Utils::CheckBoxPlacement::Right, Tr::tr("Default instance"),
"ApplicationManagerPlugin.InstanceIdDefault");
setChecked(true);
@@ -52,16 +52,16 @@ AppManagerDocumentUrlAspect::AppManagerDocumentUrlAspect(Utils::AspectContainer
{
setSettingsKey("ApplicationManagerPlugin.DocumentUrl");
setDisplayStyle(StringAspect::LineEditDisplay);
- setLabelText(Tr::tr("Document url:"));
+ setLabelText(Tr::tr("Document URL:"));
}
AppManagerCustomizeAspect::AppManagerCustomizeAspect(Utils::AspectContainer *container)
: BoolAspect(container)
{
setSettingsKey("ApplicationManagerPlugin.CustomizeStep");
- setLabelText(Tr::tr("Customize Step"));
+ setLabelText(Tr::tr("Customize step"));
setToolTip(Tr::tr("Disables the automatic updates based on the current run configuration and "
- "allows customizing the values"));
+ "allows customizing the values."));
}
AppManagerControllerAspect::AppManagerControllerAspect(Utils::AspectContainer *container)
diff --git a/src/plugins/qtsupport/qscxmlcgenerator.cpp b/src/plugins/qtsupport/qscxmlcgenerator.cpp
index 8aa1c0198f..3bfd201a04 100644
--- a/src/plugins/qtsupport/qscxmlcgenerator.cpp
+++ b/src/plugins/qtsupport/qscxmlcgenerator.cpp
@@ -129,8 +129,9 @@ FileNameToContentsHash QScxmlcGenerator::handleProcessFinished(Process *process)
class QScxmlcGeneratorFactory final : public ExtraCompilerFactory
{
public:
- QScxmlcGeneratorFactory() = default;
+ explicit QScxmlcGeneratorFactory(QObject *guard) : m_guard(guard) {}
+private:
FileType sourceType() const final { return FileType::StateChart; }
QString sourceTag() const final { return QStringLiteral("scxml"); }
@@ -139,13 +140,15 @@ public:
const FilePath &source,
const FilePaths &targets) final
{
- return new QScxmlcGenerator(project, source, targets, this);
+ return new QScxmlcGenerator(project, source, targets, m_guard);
}
+
+ QObject *m_guard;
};
-void setupQScxmlcGenerator()
+void setupQScxmlcGenerator(QObject *guard)
{
- static QScxmlcGeneratorFactory theQScxmlcGeneratorFactory;
+ static QScxmlcGeneratorFactory theQScxmlcGeneratorFactory(guard);
}
} // QtSupport::Internal
diff --git a/src/plugins/qtsupport/qscxmlcgenerator.h b/src/plugins/qtsupport/qscxmlcgenerator.h
index 811f485689..c7c8cf8265 100644
--- a/src/plugins/qtsupport/qscxmlcgenerator.h
+++ b/src/plugins/qtsupport/qscxmlcgenerator.h
@@ -3,8 +3,10 @@
#pragma once
+#include <QObject>
+
namespace QtSupport::Internal {
-void setupQScxmlcGenerator();
+void setupQScxmlcGenerator(QObject *guard);
} // QtSupport::Internal
diff --git a/src/plugins/qtsupport/qtsupportplugin.cpp b/src/plugins/qtsupport/qtsupportplugin.cpp
index 6a34e466d1..db0f8888af 100644
--- a/src/plugins/qtsupport/qtsupportplugin.cpp
+++ b/src/plugins/qtsupport/qtsupportplugin.cpp
@@ -88,8 +88,8 @@ void QtSupportPlugin::initialize()
setupGettingStartedWelcomePage();
setupQtSettingsPage();
setupQtOutputFormatter();
- setupUicGenerator();
- setupQScxmlcGenerator();
+ setupUicGenerator(this);
+ setupQScxmlcGenerator(this);
setupExternalDesigner(this);
setupExternalLinguist();
diff --git a/src/plugins/qtsupport/translationwizardpage.cpp b/src/plugins/qtsupport/translationwizardpage.cpp
index be35a90dec..bde480edd0 100644
--- a/src/plugins/qtsupport/translationwizardpage.cpp
+++ b/src/plugins/qtsupport/translationwizardpage.cpp
@@ -58,10 +58,10 @@ TranslationWizardPage::TranslationWizardPage(const QString &enabledExpr, bool si
{
const auto mainLayout = new QVBoxLayout(this);
const auto descriptionLabel = new QLabel(
- singleFile ? Tr::tr("Please select a language for which a corresponding "
+ singleFile ? Tr::tr("Select a language for which a corresponding "
"translation (.ts) file will be generated for you.")
: Tr::tr("If you plan to provide translations for your project's "
- "user interface via the Qt Linguist tool, please select a "
+ "user interface via the Qt Linguist tool, select a "
"language here. A corresponding translation (.ts) file will be "
"generated for you."));
descriptionLabel->setWordWrap(true);
diff --git a/src/plugins/qtsupport/uicgenerator.cpp b/src/plugins/qtsupport/uicgenerator.cpp
index dee12b9f9c..74b8355af9 100644
--- a/src/plugins/qtsupport/uicgenerator.cpp
+++ b/src/plugins/qtsupport/uicgenerator.cpp
@@ -72,8 +72,9 @@ FileNameToContentsHash UicGenerator::handleProcessFinished(Process *process)
class UicGeneratorFactory final : public ExtraCompilerFactory
{
public:
- UicGeneratorFactory() = default;
+ explicit UicGeneratorFactory(QObject *guard) : m_guard(guard) {}
+private:
FileType sourceType() const final { return FileType::Form; }
QString sourceTag() const final { return QLatin1String("ui"); }
@@ -82,13 +83,15 @@ public:
const FilePath &source,
const FilePaths &targets) final
{
- return new UicGenerator(project, source, targets, this);
+ return new UicGenerator(project, source, targets, m_guard);
}
+
+ QObject *m_guard;
};
-void setupUicGenerator()
+void setupUicGenerator(QObject *guard)
{
- static UicGeneratorFactory theUicGeneratorFactory;
+ static UicGeneratorFactory theUicGeneratorFactory(guard);
}
} // QtSupport::Internal
diff --git a/src/plugins/qtsupport/uicgenerator.h b/src/plugins/qtsupport/uicgenerator.h
index f8fdeb5ca0..3f3d4c20b5 100644
--- a/src/plugins/qtsupport/uicgenerator.h
+++ b/src/plugins/qtsupport/uicgenerator.h
@@ -3,8 +3,10 @@
#pragma once
+#include <QObject>
+
namespace QtSupport::Internal {
-void setupUicGenerator();
+void setupUicGenerator(QObject *guard);
} // QtSupport::Internal
diff --git a/src/plugins/remotelinux/genericdeploystep.cpp b/src/plugins/remotelinux/genericdeploystep.cpp
index 23e8a1b8c7..bddc7bfcd3 100644
--- a/src/plugins/remotelinux/genericdeploystep.cpp
+++ b/src/plugins/remotelinux/genericdeploystep.cpp
@@ -72,6 +72,7 @@ private:
StringAspect flags{this};
BoolAspect ignoreMissingFiles{this};
SelectionAspect method{this};
+ bool m_emittedDowngradeWarning = false;
};
GroupItem GenericDeployStep::mkdirTask(const Storage<FilesToTransfer> &storage)
@@ -153,6 +154,14 @@ GroupItem GenericDeployStep::transferTask(const Storage<FilesToTransfer> &storag
break;
}
}
+ if (!m_emittedDowngradeWarning && transferMethod != preferredTransferMethod) {
+ addWarningMessage(Tr::tr("Transfer method was downgraded from \"%1\" to \"%2\". If "
+ "this is unexpected, please re-test device \"%3\".")
+ .arg(FileTransfer::transferMethodName(preferredTransferMethod),
+ FileTransfer::transferMethodName(transferMethod),
+ deviceConfiguration()->displayName()));
+ m_emittedDowngradeWarning = true;
+ }
transfer.setTransferMethod(transferMethod);
transfer.setRsyncFlags(flags());
diff --git a/src/plugins/remotelinux/linuxdevice.cpp b/src/plugins/remotelinux/linuxdevice.cpp
index 0872ff54d3..30fac20a9d 100644
--- a/src/plugins/remotelinux/linuxdevice.cpp
+++ b/src/plugins/remotelinux/linuxdevice.cpp
@@ -476,8 +476,8 @@ ProcessResult SshProcessInterface::runInShell(const CommandLine &command, const
using namespace std::chrono_literals;
process.runBlocking(2s);
if (process.result() == ProcessResult::Canceled) {
- Core::MessageManager::writeFlashing(tr("Can't send control signal to the %1 device. "
- "The device might have been disconnected.")
+ Core::MessageManager::writeFlashing(Tr::tr("Can't send control signal to the %1 device. "
+ "The device might have been disconnected.")
.arg(d->m_device->displayName()));
}
return process.result();
@@ -1485,23 +1485,24 @@ public:
private:
void startImpl() final
{
- m_currentIndex = 0;
- startNextFile();
+ // Note: This assumes that files do not get renamed when transferring.
+ for (auto it = m_setup.m_files.cbegin(); it != m_setup.m_files.cend(); ++it)
+ m_batches[it->m_target.parentDir()] << *it;
+ startNextBatch();
}
void doneImpl() final
{
- if (m_setup.m_files.size() == 0 || m_currentIndex == m_setup.m_files.size() - 1)
+ if (m_batches.isEmpty())
return handleDone();
if (handleError())
return;
- ++m_currentIndex;
- startNextFile();
+ startNextBatch();
}
- void startNextFile()
+ void startNextBatch()
{
process().close();
@@ -1510,12 +1511,14 @@ private:
<< fullConnectionOptions(), OsTypeLinux);
QStringList options{"-e", sshCmdLine, m_setup.m_rsyncFlags};
- if (!m_setup.m_files.isEmpty()) { // NormalRun
- const FileToTransfer file = m_setup.m_files.at(m_currentIndex);
- const FileToTransfer fixedFile = fixLocalFileOnWindows(file, options);
- const auto fixedPaths = fixPaths(fixedFile, userAtHost());
-
- options << fixedPaths.first << fixedPaths.second;
+ if (!m_batches.isEmpty()) { // NormalRun
+ const auto batchIt = m_batches.begin();
+ for (auto filesIt = batchIt->cbegin(); filesIt != batchIt->cend(); ++filesIt) {
+ const FileToTransfer fixedFile = fixLocalFileOnWindows(*filesIt, options);
+ options << fixedLocalPath(fixedFile.m_source);
+ }
+ options << fixedRemotePath(batchIt.key(), userAtHost());
+ m_batches.erase(batchIt);
} else { // TestRun
options << "-n" << "--exclude=*" << (userAtHost() + ":/tmp");
}
@@ -1542,18 +1545,17 @@ private:
return fixedFile;
}
- QPair<QString, QString> fixPaths(const FileToTransfer &file, const QString &remoteHost) const
+ QString fixedLocalPath(const FilePath &file) const
{
- FilePath localPath = file.m_source;
- FilePath remotePath = file.m_target;
- const QString local = (localPath.isDir() && localPath.path().back() != '/')
- ? localPath.path() + '/' : localPath.path();
- const QString remote = remoteHost + ':' + remotePath.path();
+ return file.isDir() && file.path().back() != '/' ? file.path() + '/' : file.path();
+ }
- return qMakePair(local, remote);
+ QString fixedRemotePath(const FilePath &file, const QString &remoteHost) const
+ {
+ return remoteHost + ':' + file.path();
}
- int m_currentIndex = 0;
+ QHash<FilePath, FilesToTransfer> m_batches;
};
class GenericTransferImpl : public FileTransferInterface
diff --git a/src/plugins/squish/squishnavigationwidget.cpp b/src/plugins/squish/squishnavigationwidget.cpp
index 7921938c37..d3fb523196 100644
--- a/src/plugins/squish/squishnavigationwidget.cpp
+++ b/src/plugins/squish/squishnavigationwidget.cpp
@@ -340,7 +340,12 @@ void SquishNavigationWidget::onRemoveSharedFileTriggered(const QModelIndex &idx)
= CheckableMessageBox::question(Core::ICore::dialogParent(),
Tr::tr("Remove Shared File"),
detail,
- Key("RemoveSharedSquishScript"));
+ Key("RemoveSharedSquishScript"),
+ QMessageBox::Yes | QMessageBox::No,
+ /*defaultButton=*/QMessageBox::No,
+ /*acceptButton=*/QMessageBox::Yes,
+ {{QMessageBox::Yes, Tr::tr("Delete")},
+ {QMessageBox::No, Tr::tr("Cancel")}});
if (pressed != QMessageBox::Yes)
return;
diff --git a/src/plugins/subversion/subversionplugin.cpp b/src/plugins/subversion/subversionplugin.cpp
index fc9d5ed122..64f32a11ff 100644
--- a/src/plugins/subversion/subversionplugin.cpp
+++ b/src/plugins/subversion/subversionplugin.cpp
@@ -248,7 +248,7 @@ public:
VcsEditorFactory logEditorFactory {{
LogOutput,
Constants::SUBVERSION_LOG_EDITOR_ID,
- VcsBase::Tr::tr("Subversion File Log Editor"),
+ ::VcsBase::Tr::tr("Subversion File Log Editor"),
Constants::SUBVERSION_LOG_MIMETYPE,
[] { return new SubversionEditorWidget; },
std::bind(&SubversionPluginPrivate::vcsDescribe, this, _1, _2)
@@ -257,7 +257,7 @@ public:
VcsEditorFactory blameEditorFactory {{
AnnotateOutput,
Constants::SUBVERSION_BLAME_EDITOR_ID,
- VcsBase::Tr::tr("Subversion Annotation Editor"),
+ ::VcsBase::Tr::tr("Subversion Annotation Editor"),
Constants::SUBVERSION_BLAME_MIMETYPE,
[] { return new SubversionEditorWidget; },
std::bind(&SubversionPluginPrivate::vcsDescribe, this, _1, _2)
@@ -468,7 +468,7 @@ SubversionPluginPrivate::SubversionPluginPrivate()
setupVcsSubmitEditor(this, {
Constants::SUBVERSION_SUBMIT_MIMETYPE,
Constants::SUBVERSION_COMMIT_EDITOR_ID,
- VcsBase::Tr::tr("Subversion Commit Editor"),
+ ::VcsBase::Tr::tr("Subversion Commit Editor"),
VcsBaseSubmitEditorParameters::DiffFiles,
[] { return new SubversionSubmitEditor; },
});
diff --git a/src/plugins/texteditor/texteditor.cpp b/src/plugins/texteditor/texteditor.cpp
index c8ef69c63e..70239b286e 100644
--- a/src/plugins/texteditor/texteditor.cpp
+++ b/src/plugins/texteditor/texteditor.cpp
@@ -6891,6 +6891,18 @@ static void showZoomIndicator(QWidget *editor, const int newZoom)
Utils::FadingIndicator::SmallText);
}
+void TextEditorWidget::increaseFontZoom()
+{
+ d->clearVisibleFoldedBlock();
+ showZoomIndicator(this, TextEditorSettings::increaseFontZoom());
+}
+
+void TextEditorWidget::decreaseFontZoom()
+{
+ d->clearVisibleFoldedBlock();
+ showZoomIndicator(this, TextEditorSettings::decreaseFontZoom());
+}
+
void TextEditorWidget::zoomF(float delta)
{
d->clearVisibleFoldedBlock();
diff --git a/src/plugins/texteditor/texteditor.h b/src/plugins/texteditor/texteditor.h
index a2a1aafb2b..33b8cb84f0 100644
--- a/src/plugins/texteditor/texteditor.h
+++ b/src/plugins/texteditor/texteditor.h
@@ -349,6 +349,8 @@ public:
void pasteWithoutFormat();
void switchUtf8bom();
+ void increaseFontZoom();
+ void decreaseFontZoom();
void zoomF(float delta);
void zoomReset();
diff --git a/src/plugins/texteditor/texteditoractionhandler.cpp b/src/plugins/texteditor/texteditoractionhandler.cpp
index 2e48670bf4..240e8498ed 100644
--- a/src/plugins/texteditor/texteditoractionhandler.cpp
+++ b/src/plugins/texteditor/texteditoractionhandler.cpp
@@ -394,11 +394,11 @@ void TextEditorActionHandlerPrivate::createActions()
QKeySequence(),
G_EDIT_COLLAPSING, advancedEditMenu);
registerAction(INCREASE_FONT_SIZE,
- [] (TextEditorWidget *w) { w->zoomF(1.f); }, false, Tr::tr("Increase Font Size"),
+ [] (TextEditorWidget *w) { w->increaseFontZoom(); }, false, Tr::tr("Increase Font Size"),
QKeySequence(Tr::tr("Ctrl++")),
G_EDIT_FONT, advancedEditMenu);
registerAction(DECREASE_FONT_SIZE,
- [] (TextEditorWidget *w) { w->zoomF(-1.f); }, false, Tr::tr("Decrease Font Size"),
+ [] (TextEditorWidget *w) { w->decreaseFontZoom(); }, false, Tr::tr("Decrease Font Size"),
QKeySequence(Tr::tr("Ctrl+-")),
G_EDIT_FONT, advancedEditMenu);
registerAction(RESET_FONT_SIZE,
diff --git a/src/plugins/texteditor/texteditorsettings.cpp b/src/plugins/texteditor/texteditorsettings.cpp
index 1d7dd89386..811852b8a8 100644
--- a/src/plugins/texteditor/texteditorsettings.cpp
+++ b/src/plugins/texteditor/texteditorsettings.cpp
@@ -560,20 +560,33 @@ Utils::Id TextEditorSettings::languageId(const QString &mimeType)
return d->m_mimeTypeToLanguage.value(mimeType);
}
-static void setFontZoom(int zoom)
+static int setFontZoom(int zoom)
+{
+ zoom = qMax(10, zoom);
+ if (d->m_fontSettings.fontZoom() != zoom) {
+ d->m_fontSettings.setFontZoom(zoom);
+ d->m_fontSettings.toSettings(Core::ICore::settings());
+ emit textEditorSettings().fontSettingsChanged(d->m_fontSettings);
+ }
+ return zoom;
+}
+
+int TextEditorSettings::increaseFontZoom()
{
- d->m_fontSettings.setFontZoom(zoom);
- d->m_fontSettings.toSettings(Core::ICore::settings());
- emit textEditorSettings().fontSettingsChanged(d->m_fontSettings);
+ const int previousZoom = d->m_fontSettings.fontZoom();
+ return setFontZoom(previousZoom + 10 - previousZoom % 10);
}
-int TextEditorSettings::increaseFontZoom(int step)
+int TextEditorSettings::decreaseFontZoom()
{
const int previousZoom = d->m_fontSettings.fontZoom();
- const int newZoom = qMax(10, previousZoom + step);
- if (newZoom != previousZoom)
- setFontZoom(newZoom);
- return newZoom;
+ const int delta = previousZoom % 10;
+ return setFontZoom(previousZoom - (delta == 0 ? 10 : delta));
+}
+
+int TextEditorSettings::increaseFontZoom(int step)
+{
+ return setFontZoom(d->m_fontSettings.fontZoom() + step);
}
void TextEditorSettings::resetFontZoom()
diff --git a/src/plugins/texteditor/texteditorsettings.h b/src/plugins/texteditor/texteditorsettings.h
index 88dd057608..1599fcbba5 100644
--- a/src/plugins/texteditor/texteditorsettings.h
+++ b/src/plugins/texteditor/texteditorsettings.h
@@ -76,6 +76,8 @@ public:
static void registerMimeTypeForLanguageId(const char *mimeType, Utils::Id languageId);
static Utils::Id languageId(const QString &mimeType);
+ static int increaseFontZoom();
+ static int decreaseFontZoom();
static int increaseFontZoom(int step);
static void resetFontZoom();
diff --git a/src/plugins/vcsbase/vcsbaseeditor.cpp b/src/plugins/vcsbase/vcsbaseeditor.cpp
index b10758233a..38bb004a2d 100644
--- a/src/plugins/vcsbase/vcsbaseeditor.cpp
+++ b/src/plugins/vcsbase/vcsbaseeditor.cpp
@@ -995,14 +995,20 @@ void VcsBaseEditorWidget::contextMenuEvent(QContextMenuEvent *e)
// the user has "Open With" and choose the right diff editor so that
// fileNameFromDiffSpecification() works.
QAction *applyAction = menu->addAction(Tr::tr("Apply Chunk..."));
- connect(applyAction, &QAction::triggered, this, [this, chunk] {
- slotApplyDiffChunk(chunk, PatchAction::Apply);
- });
+ connect(
+ applyAction,
+ &QAction::triggered,
+ this,
+ [this, chunk] { slotApplyDiffChunk(chunk, PatchAction::Apply); },
+ Qt::QueuedConnection);
// Revert a chunk from a VCS diff, which might be linked to reloading the diff.
QAction *revertAction = menu->addAction(Tr::tr("Revert Chunk..."));
- connect(revertAction, &QAction::triggered, this, [this, chunk] {
- slotApplyDiffChunk(chunk, PatchAction::Revert);
- });
+ connect(
+ revertAction,
+ &QAction::triggered,
+ this,
+ [this, chunk] { slotApplyDiffChunk(chunk, PatchAction::Revert); },
+ Qt::QueuedConnection);
// Custom diff actions
addDiffActions(menu, chunk);
break;
diff --git a/src/shared/qbs b/src/shared/qbs
-Subproject bd0c59e572f95953337177e68fa32cb0c4aa1e2
+Subproject 60a18f09fa547af064fb851e72b816ee25bf71a