forked from qt-creator/qt-creator
Axivion: Begin to use QNetworkAccessManager instead of curl for HTTP
Change-Id: I2fd7ba2a72e749bdc5407d222057cb66ff341b04 Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
@@ -13,4 +13,5 @@ add_qtc_plugin(Axivion
|
|||||||
axiviontr.h
|
axiviontr.h
|
||||||
dashboard/dto.cpp dashboard/dto.h
|
dashboard/dto.cpp dashboard/dto.h
|
||||||
dashboard/concat.cpp dashboard/concat.h
|
dashboard/concat.cpp dashboard/concat.h
|
||||||
|
dashboard/dashboardclient.cpp dashboard/dashboardclient.h
|
||||||
)
|
)
|
||||||
|
@@ -26,6 +26,8 @@ QtcPlugin {
|
|||||||
"axivionsettings.cpp",
|
"axivionsettings.cpp",
|
||||||
"axivionsettings.h",
|
"axivionsettings.h",
|
||||||
"axiviontr.h",
|
"axiviontr.h",
|
||||||
|
"dashboard/dashboardclient.cpp",
|
||||||
|
"dashboard/dashboardclient.h",
|
||||||
]
|
]
|
||||||
|
|
||||||
cpp.includePaths: base.concat(["."]) // needed for the generated stuff below
|
cpp.includePaths: base.concat(["."]) // needed for the generated stuff below
|
||||||
|
@@ -8,6 +8,7 @@
|
|||||||
#include "axivionquery.h"
|
#include "axivionquery.h"
|
||||||
#include "axivionresultparser.h"
|
#include "axivionresultparser.h"
|
||||||
#include "axiviontr.h"
|
#include "axiviontr.h"
|
||||||
|
#include "dashboard/dashboardclient.h"
|
||||||
#include "dashboard/dto.h"
|
#include "dashboard/dto.h"
|
||||||
|
|
||||||
#include <coreplugin/editormanager/documentmodel.h>
|
#include <coreplugin/editormanager/documentmodel.h>
|
||||||
@@ -26,10 +27,12 @@
|
|||||||
#include <texteditor/textmark.h>
|
#include <texteditor/textmark.h>
|
||||||
|
|
||||||
#include <utils/expected.h>
|
#include <utils/expected.h>
|
||||||
|
#include <utils/networkaccessmanager.h>
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
#include <utils/utilsicons.h>
|
#include <utils/utilsicons.h>
|
||||||
|
|
||||||
#include <QAction>
|
#include <QAction>
|
||||||
|
#include <QFutureWatcher>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
|
||||||
#include <exception>
|
#include <exception>
|
||||||
@@ -44,7 +47,7 @@ class AxivionPluginPrivate : public QObject
|
|||||||
public:
|
public:
|
||||||
void onStartupProjectChanged();
|
void onStartupProjectChanged();
|
||||||
void fetchProjectInfo(const QString &projectName);
|
void fetchProjectInfo(const QString &projectName);
|
||||||
void handleProjectInfo(const QByteArray &result);
|
void handleProjectInfo(Utils::expected_str<Dto::ProjectInfoDto> rawInfo);
|
||||||
void handleOpenedDocs(ProjectExplorer::Project *project);
|
void handleOpenedDocs(ProjectExplorer::Project *project);
|
||||||
void onDocumentOpened(Core::IDocument *doc);
|
void onDocumentOpened(Core::IDocument *doc);
|
||||||
void onDocumentClosed(Core::IDocument * doc);
|
void onDocumentClosed(Core::IDocument * doc);
|
||||||
@@ -52,6 +55,7 @@ public:
|
|||||||
void handleIssuesForFile(const IssuesList &issues);
|
void handleIssuesForFile(const IssuesList &issues);
|
||||||
void fetchRuleInfo(const QString &id);
|
void fetchRuleInfo(const QString &id);
|
||||||
|
|
||||||
|
Utils::NetworkAccessManager *m_networkAccessManager = Utils::NetworkAccessManager::instance();
|
||||||
AxivionOutputPane m_axivionOutputPane;
|
AxivionOutputPane m_axivionOutputPane;
|
||||||
std::shared_ptr<const Dto::ProjectInfoDto> m_currentProjectInfo;
|
std::shared_ptr<const Dto::ProjectInfoDto> m_currentProjectInfo;
|
||||||
bool m_runningQuery = false;
|
bool m_runningQuery = false;
|
||||||
@@ -151,14 +155,16 @@ void AxivionPluginPrivate::fetchProjectInfo(const QString &projectName)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_runningQuery = true;
|
m_runningQuery = true;
|
||||||
|
DashboardClient client { *this->m_networkAccessManager };
|
||||||
AxivionQuery query(AxivionQuery::ProjectInfo, {projectName});
|
QFuture<DashboardClient::RawProjectInfo> response = client.fetchProjectInfo(projectName);
|
||||||
AxivionQueryRunner *runner = new AxivionQueryRunner(query, this);
|
auto responseWatcher = std::make_shared<QFutureWatcher<DashboardClient::RawProjectInfo>>();
|
||||||
connect(runner, &AxivionQueryRunner::resultRetrieved, this, [this](const QByteArray &result){
|
connect(responseWatcher.get(),
|
||||||
handleProjectInfo(result);
|
&QFutureWatcher<DashboardClient::RawProjectInfo>::finished,
|
||||||
});
|
this,
|
||||||
connect(runner, &AxivionQueryRunner::finished, [runner]{ runner->deleteLater(); });
|
[this, responseWatcher]() {
|
||||||
runner->start();
|
handleProjectInfo(responseWatcher->result());
|
||||||
|
});
|
||||||
|
responseWatcher->setFuture(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AxivionPluginPrivate::fetchRuleInfo(const QString &id)
|
void AxivionPluginPrivate::fetchRuleInfo(const QString &id)
|
||||||
@@ -201,15 +207,14 @@ void AxivionPluginPrivate::clearAllMarks()
|
|||||||
onDocumentClosed(doc);
|
onDocumentClosed(doc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AxivionPluginPrivate::handleProjectInfo(const QByteArray &result)
|
void AxivionPluginPrivate::handleProjectInfo(Utils::expected_str<Dto::ProjectInfoDto> rawInfo)
|
||||||
{
|
{
|
||||||
Utils::expected_str<Dto::ProjectInfoDto> raw_info = ResultParser::parseProjectInfo(result);
|
|
||||||
m_runningQuery = false;
|
m_runningQuery = false;
|
||||||
if (!raw_info) {
|
if (!rawInfo) {
|
||||||
Core::MessageManager::writeFlashing(QStringLiteral(u"Axivion: ") + raw_info.error());
|
Core::MessageManager::writeFlashing(QStringLiteral(u"Axivion: ") + rawInfo.error());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_currentProjectInfo = std::make_shared<const Dto::ProjectInfoDto>(std::move(raw_info.value()));
|
m_currentProjectInfo = std::make_shared<const Dto::ProjectInfoDto>(std::move(rawInfo.value()));
|
||||||
m_axivionOutputPane.updateDashboard();
|
m_axivionOutputPane.updateDashboard();
|
||||||
// handle already opened documents
|
// handle already opened documents
|
||||||
if (auto buildSystem = ProjectExplorer::ProjectManager::startupBuildSystem();
|
if (auto buildSystem = ProjectExplorer::ProjectManager::startupBuildSystem();
|
||||||
|
@@ -2,7 +2,6 @@
|
|||||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||||
|
|
||||||
#include "axivionresultparser.h"
|
#include "axivionresultparser.h"
|
||||||
#include "dashboard/dto.h"
|
|
||||||
|
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
|
|
||||||
@@ -120,20 +119,6 @@ DashboardInfo parseDashboardInfo(const QByteArray &input)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Utils::expected_str<Dto::ProjectInfoDto> 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)
|
static QRegularExpression issueCsvLineRegex(const QByteArray &firstCsvLine)
|
||||||
{
|
{
|
||||||
QString pattern = "^";
|
QString pattern = "^";
|
||||||
|
88
src/plugins/axivion/dashboard/dashboardclient.cpp
Normal file
88
src/plugins/axivion/dashboard/dashboardclient.cpp
Normal file
@@ -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 <QByteArray>
|
||||||
|
#include <QCoreApplication>
|
||||||
|
#include <QLatin1String>
|
||||||
|
#include <QNetworkReply>
|
||||||
|
#include <QNetworkRequest>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace Axivion::Internal
|
||||||
|
{
|
||||||
|
|
||||||
|
DashboardClient::DashboardClient(Utils::NetworkAccessManager &networkAccessManager)
|
||||||
|
: m_networkAccessManager(networkAccessManager)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void deleteLater(QObject *obj)
|
||||||
|
{
|
||||||
|
obj->deleteLater();
|
||||||
|
}
|
||||||
|
|
||||||
|
using RawBody = Utils::expected_str<QByteArray>;
|
||||||
|
|
||||||
|
class RawBodyReader final
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
RawBodyReader(std::shared_ptr<QNetworkReply> 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<QNetworkReply> m_reply;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
static Utils::expected_str<T> 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::RawProjectInfo> 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<QNetworkReply> reply{ this->m_networkAccessManager.get(request), deleteLater };
|
||||||
|
return QtFuture::connect(reply.get(), &QNetworkReply::finished)
|
||||||
|
.then(RawBodyReader(reply))
|
||||||
|
.then(QtFuture::Launch::Async, &RawBodyParser<Dto::ProjectInfoDto>);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
33
src/plugins/axivion/dashboard/dashboardclient.h
Normal file
33
src/plugins/axivion/dashboard/dashboardclient.h
Normal file
@@ -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 <utils/expected.h>
|
||||||
|
#include <utils/networkaccessmanager.h>
|
||||||
|
|
||||||
|
#include <QFuture>
|
||||||
|
|
||||||
|
namespace Axivion::Internal
|
||||||
|
{
|
||||||
|
|
||||||
|
class DashboardClient
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using RawProjectInfo = Utils::expected_str<Dto::ProjectInfoDto>;
|
||||||
|
|
||||||
|
DashboardClient(Utils::NetworkAccessManager &networkAccessManager);
|
||||||
|
|
||||||
|
QFuture<RawProjectInfo> fetchProjectInfo(const QString &projectName);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Utils::NetworkAccessManager &m_networkAccessManager;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Axivion::Internal
|
Reference in New Issue
Block a user