diff --git a/src/plugins/axivion/CMakeLists.txt b/src/plugins/axivion/CMakeLists.txt index 8768544764c..c71df674750 100644 --- a/src/plugins/axivion/CMakeLists.txt +++ b/src/plugins/axivion/CMakeLists.txt @@ -13,4 +13,5 @@ add_qtc_plugin(Axivion axiviontr.h dashboard/dto.cpp dashboard/dto.h dashboard/concat.cpp dashboard/concat.h + dashboard/dashboardclient.cpp dashboard/dashboardclient.h ) diff --git a/src/plugins/axivion/axivion.qbs b/src/plugins/axivion/axivion.qbs index 73db674adc4..bdd20a89349 100644 --- a/src/plugins/axivion/axivion.qbs +++ b/src/plugins/axivion/axivion.qbs @@ -26,6 +26,8 @@ QtcPlugin { "axivionsettings.cpp", "axivionsettings.h", "axiviontr.h", + "dashboard/dashboardclient.cpp", + "dashboard/dashboardclient.h", ] cpp.includePaths: base.concat(["."]) // needed for the generated stuff below diff --git a/src/plugins/axivion/axivionplugin.cpp b/src/plugins/axivion/axivionplugin.cpp index 3d89c8ba957..bd595a57b0b 100644 --- a/src/plugins/axivion/axivionplugin.cpp +++ b/src/plugins/axivion/axivionplugin.cpp @@ -8,6 +8,7 @@ #include "axivionquery.h" #include "axivionresultparser.h" #include "axiviontr.h" +#include "dashboard/dashboardclient.h" #include "dashboard/dto.h" #include @@ -26,10 +27,12 @@ #include #include +#include #include #include #include +#include #include #include @@ -44,7 +47,7 @@ class AxivionPluginPrivate : public QObject public: void onStartupProjectChanged(); void fetchProjectInfo(const QString &projectName); - void handleProjectInfo(const QByteArray &result); + void handleProjectInfo(Utils::expected_str rawInfo); void handleOpenedDocs(ProjectExplorer::Project *project); void onDocumentOpened(Core::IDocument *doc); void onDocumentClosed(Core::IDocument * doc); @@ -52,6 +55,7 @@ public: void handleIssuesForFile(const IssuesList &issues); void fetchRuleInfo(const QString &id); + Utils::NetworkAccessManager *m_networkAccessManager = Utils::NetworkAccessManager::instance(); AxivionOutputPane m_axivionOutputPane; std::shared_ptr m_currentProjectInfo; bool m_runningQuery = false; @@ -151,14 +155,16 @@ void AxivionPluginPrivate::fetchProjectInfo(const QString &projectName) return; } m_runningQuery = true; - - AxivionQuery query(AxivionQuery::ProjectInfo, {projectName}); - AxivionQueryRunner *runner = new AxivionQueryRunner(query, this); - connect(runner, &AxivionQueryRunner::resultRetrieved, this, [this](const QByteArray &result){ - handleProjectInfo(result); - }); - connect(runner, &AxivionQueryRunner::finished, [runner]{ runner->deleteLater(); }); - runner->start(); + DashboardClient client { *this->m_networkAccessManager }; + QFuture response = client.fetchProjectInfo(projectName); + auto responseWatcher = std::make_shared>(); + connect(responseWatcher.get(), + &QFutureWatcher::finished, + this, + [this, responseWatcher]() { + handleProjectInfo(responseWatcher->result()); + }); + responseWatcher->setFuture(response); } void AxivionPluginPrivate::fetchRuleInfo(const QString &id) @@ -201,15 +207,14 @@ void AxivionPluginPrivate::clearAllMarks() onDocumentClosed(doc); } -void AxivionPluginPrivate::handleProjectInfo(const QByteArray &result) +void AxivionPluginPrivate::handleProjectInfo(Utils::expected_str rawInfo) { - Utils::expected_str raw_info = ResultParser::parseProjectInfo(result); m_runningQuery = false; - if (!raw_info) { - Core::MessageManager::writeFlashing(QStringLiteral(u"Axivion: ") + raw_info.error()); + if (!rawInfo) { + Core::MessageManager::writeFlashing(QStringLiteral(u"Axivion: ") + rawInfo.error()); return; } - m_currentProjectInfo = std::make_shared(std::move(raw_info.value())); + m_currentProjectInfo = std::make_shared(std::move(rawInfo.value())); m_axivionOutputPane.updateDashboard(); // handle already opened documents if (auto buildSystem = ProjectExplorer::ProjectManager::startupBuildSystem(); diff --git a/src/plugins/axivion/axivionresultparser.cpp b/src/plugins/axivion/axivionresultparser.cpp index 81ae9787170..cd4ec0b11c6 100644 --- a/src/plugins/axivion/axivionresultparser.cpp +++ b/src/plugins/axivion/axivionresultparser.cpp @@ -2,7 +2,6 @@ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "axivionresultparser.h" -#include "dashboard/dto.h" #include @@ -120,20 +119,6 @@ DashboardInfo parseDashboardInfo(const QByteArray &input) return result; } -Utils::expected_str parseProjectInfo(const QByteArray &input) -{ - auto [header, body] = splitHeaderAndBody(input); - auto [error, doc] = prehandleHeaderAndBody(header, body); - if (!error.error.isEmpty()) - return tl::make_unexpected(std::move(error.error)); - try - { - return { Dto::ProjectInfoDto::deserialize(body) }; - } catch (const Dto::invalid_dto_exception &e) { - return tl::make_unexpected(QString::fromUtf8(e.what())); - } -} - static QRegularExpression issueCsvLineRegex(const QByteArray &firstCsvLine) { QString pattern = "^"; diff --git a/src/plugins/axivion/dashboard/dashboardclient.cpp b/src/plugins/axivion/dashboard/dashboardclient.cpp new file mode 100644 index 00000000000..4956f106360 --- /dev/null +++ b/src/plugins/axivion/dashboard/dashboardclient.cpp @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2022-current by Axivion GmbH + * https://www.axivion.com/ + * + * SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + */ + +#include "dashboardclient.h" + +#include "axivionsettings.h" + +#include +#include +#include +#include +#include + +#include + +namespace Axivion::Internal +{ + +DashboardClient::DashboardClient(Utils::NetworkAccessManager &networkAccessManager) + : m_networkAccessManager(networkAccessManager) +{ +} + +static void deleteLater(QObject *obj) +{ + obj->deleteLater(); +} + +using RawBody = Utils::expected_str; + +class RawBodyReader final +{ +public: + RawBodyReader(std::shared_ptr reply) + : m_reply(std::move(reply)) + { } + + ~RawBodyReader() { } + + RawBody operator()() + { + QNetworkReply::NetworkError error = m_reply->error(); + if (error != QNetworkReply::NetworkError::NoError) + return tl::make_unexpected(QString::number(error) + + QLatin1String(": ") + + m_reply->errorString()); + return m_reply->readAll(); + } + +private: + std::shared_ptr m_reply; +}; + +template +static Utils::expected_str RawBodyParser(RawBody rawBody) +{ + if (!rawBody) + return tl::make_unexpected(std::move(rawBody.error())); + try { + return { T::deserialize(rawBody.value()) }; + } catch (const Dto::invalid_dto_exception &e) { + return tl::make_unexpected(QString::fromUtf8(e.what())); + } +} + +QFuture DashboardClient::fetchProjectInfo(const QString &projectName) +{ + const AxivionServer &server = settings().server; + QUrl url { server.dashboard + QStringLiteral(u"/api/projects/") + QUrl::toPercentEncoding(projectName) }; + QNetworkRequest request{ url }; + request.setRawHeader(QByteArrayLiteral(u8"Authorization"), + QByteArrayLiteral(u8"AxToken ") + server.token.toUtf8()); + QByteArray ua = QByteArrayLiteral(u8"Axivion") + + QCoreApplication::applicationName().toUtf8() + + QByteArrayLiteral(u8"Plugin/") + + QCoreApplication::applicationVersion().toUtf8(); + request.setRawHeader(QByteArrayLiteral(u8"X-Axivion-User-Agent"), ua); + std::shared_ptr reply{ this->m_networkAccessManager.get(request), deleteLater }; + return QtFuture::connect(reply.get(), &QNetworkReply::finished) + .then(RawBodyReader(reply)) + .then(QtFuture::Launch::Async, &RawBodyParser); +} + +} diff --git a/src/plugins/axivion/dashboard/dashboardclient.h b/src/plugins/axivion/dashboard/dashboardclient.h new file mode 100644 index 00000000000..544f1430b17 --- /dev/null +++ b/src/plugins/axivion/dashboard/dashboardclient.h @@ -0,0 +1,33 @@ +#pragma once + +/* + * Copyright (C) 2022-current by Axivion GmbH + * https://www.axivion.com/ + * + * SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + */ + +#include "dashboard/dto.h" + +#include +#include + +#include + +namespace Axivion::Internal +{ + +class DashboardClient +{ +public: + using RawProjectInfo = Utils::expected_str; + + DashboardClient(Utils::NetworkAccessManager &networkAccessManager); + + QFuture fetchProjectInfo(const QString &projectName); + +private: + Utils::NetworkAccessManager &m_networkAccessManager; +}; + +} // namespace Axivion::Internal