Provide functionality for fetching project information

Change-Id: Id0968c08eb3017eb6f902c3cea3a363bc3f0c35c
Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
Christian Stenger
2022-12-14 12:11:03 +01:00
parent cc0b392e87
commit b741b2eeeb
9 changed files with 285 additions and 3 deletions

View File

@@ -89,4 +89,9 @@ void AxivionOutputPane::goToPrev()
{ {
} }
void AxivionOutputPane::updateDashboard()
{
}
} // Axivion::Internal } // Axivion::Internal

View File

@@ -33,6 +33,7 @@ public:
void goToNext() override; void goToNext() override;
void goToPrev() override; void goToPrev() override;
void updateDashboard();
private: private:
QStackedWidget *m_outputWidget = nullptr; QStackedWidget *m_outputWidget = nullptr;
}; };

View File

@@ -5,14 +5,18 @@
#include "axivionoutputpane.h" #include "axivionoutputpane.h"
#include "axivionprojectsettings.h" #include "axivionprojectsettings.h"
#include "axivionquery.h"
#include "axivionresultparser.h"
#include "axivionsettings.h" #include "axivionsettings.h"
#include "axivionsettingspage.h" #include "axivionsettingspage.h"
#include "axiviontr.h" #include "axiviontr.h"
#include <coreplugin/icore.h> #include <coreplugin/icore.h>
#include <coreplugin/messagemanager.h>
#include <extensionsystem/pluginmanager.h> #include <extensionsystem/pluginmanager.h>
#include <projectexplorer/project.h> #include <projectexplorer/project.h>
#include <projectexplorer/projectpanelfactory.h> #include <projectexplorer/projectpanelfactory.h>
#include <projectexplorer/session.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#ifdef LICENSECHECKER #ifdef LICENSECHECKER
@@ -20,16 +24,22 @@
#endif #endif
#include <QMessageBox> #include <QMessageBox>
#include <QTimer>
namespace Axivion::Internal { namespace Axivion::Internal {
class AxivionPluginPrivate class AxivionPluginPrivate : public QObject
{ {
public: public:
void fetchProjectInfo(const QString &projectName);
void handleProjectInfo(const ProjectInfo &info);
AxivionSettings axivionSettings; AxivionSettings axivionSettings;
AxivionSettingsPage axivionSettingsPage{&axivionSettings}; AxivionSettingsPage axivionSettingsPage{&axivionSettings};
AxivionOutputPane axivionOutputPane; AxivionOutputPane axivionOutputPane;
QHash<ProjectExplorer::Project *, AxivionProjectSettings *> projectSettings; QHash<ProjectExplorer::Project *, AxivionProjectSettings *> projectSettings;
ProjectInfo currentProjectInfo;
bool runningQuery = false;
}; };
static AxivionPlugin *s_instance = nullptr; static AxivionPlugin *s_instance = nullptr;
@@ -78,9 +88,26 @@ bool AxivionPlugin::initialize(const QStringList &arguments, QString *errorMessa
return new AxivionProjectSettingsWidget(project); return new AxivionProjectSettingsWidget(project);
}); });
ProjectExplorer::ProjectPanelFactory::registerFactory(panelFactory); ProjectExplorer::ProjectPanelFactory::registerFactory(panelFactory);
connect(ProjectExplorer::SessionManager::instance(),
&ProjectExplorer::SessionManager::startupProjectChanged,
this, &AxivionPlugin::onStartupProjectChanged);
return true; return true;
} }
void AxivionPlugin::onStartupProjectChanged()
{
QTC_ASSERT(dd, return);
ProjectExplorer::Project *project = ProjectExplorer::SessionManager::startupProject();
if (!project) {
dd->currentProjectInfo = ProjectInfo();
dd->axivionOutputPane.updateDashboard();
return;
}
const AxivionProjectSettings *projSettings = projectSettings(project);
dd->fetchProjectInfo(projSettings->dashboardProjectName());
}
AxivionSettings *AxivionPlugin::settings() AxivionSettings *AxivionPlugin::settings()
{ {
QTC_ASSERT(dd, return nullptr); QTC_ASSERT(dd, return nullptr);
@@ -116,4 +143,44 @@ bool AxivionPlugin::handleCertificateIssue()
return true; return true;
} }
void AxivionPlugin::fetchProjectInfo(const QString &projectName)
{
QTC_ASSERT(dd, return);
dd->fetchProjectInfo(projectName);
}
void AxivionPluginPrivate::fetchProjectInfo(const QString &projectName)
{
if (runningQuery) { // re-schedule
QTimer::singleShot(3000, [this, projectName]{ fetchProjectInfo(projectName); });
return;
}
if (projectName.isEmpty()) {
currentProjectInfo = ProjectInfo();
axivionOutputPane.updateDashboard();
return;
}
runningQuery = true;
AxivionQuery query(AxivionQuery::ProjectInfo, {projectName});
AxivionQueryRunner *runner = new AxivionQueryRunner(query, this);
connect(runner, &AxivionQueryRunner::resultRetrieved, this, [this](const QByteArray &result){
handleProjectInfo(ResultParser::parseProjectInfo(result));
});
connect(runner, &AxivionQueryRunner::finished, [runner]{ runner->deleteLater(); });
runner->start();
}
void AxivionPluginPrivate::handleProjectInfo(const ProjectInfo &info)
{
runningQuery = false;
if (!info.error.isEmpty()) {
Core::MessageManager::writeFlashing("Axivion: " + info.error);
return;
}
currentProjectInfo = info;
axivionOutputPane.updateDashboard();
}
} // Axivion::Internal } // Axivion::Internal

View File

@@ -26,6 +26,7 @@ public:
static AxivionProjectSettings *projectSettings(ProjectExplorer::Project *project); static AxivionProjectSettings *projectSettings(ProjectExplorer::Project *project);
static bool handleCertificateIssue(); static bool handleCertificateIssue();
static void fetchProjectInfo(const QString &projectName);
signals: signals:
void settingsChanged(); void settingsChanged();
@@ -33,6 +34,7 @@ signals:
private: private:
bool initialize(const QStringList &arguments, QString *errorMessage) final; bool initialize(const QStringList &arguments, QString *errorMessage) final;
void extensionsInitialized() final {} void extensionsInitialized() final {}
void onStartupProjectChanged();
}; };
} // Axivion::Internal } // Axivion::Internal

View File

@@ -136,8 +136,10 @@ void AxivionProjectSettingsWidget::linkProject()
const QList<QTreeWidgetItem *> selected = m_dashboardProjects->selectedItems(); const QList<QTreeWidgetItem *> selected = m_dashboardProjects->selectedItems();
QTC_ASSERT(selected.size() == 1, return); QTC_ASSERT(selected.size() == 1, return);
m_projectSettings->setDashboardProjectName(selected.first()->text(0)); const QString projectName = selected.first()->text(0);
m_projectSettings->setDashboardProjectName(projectName);
updateUi(); updateUi();
AxivionPlugin::fetchProjectInfo(projectName);
} }
void AxivionProjectSettingsWidget::unlinkProject() void AxivionProjectSettingsWidget::unlinkProject()

View File

@@ -9,6 +9,8 @@
#include <utils/processenums.h> #include <utils/processenums.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <QUrl>
using namespace Utils; using namespace Utils;
namespace Axivion::Internal { namespace Axivion::Internal {
@@ -27,6 +29,10 @@ QString AxivionQuery::toString() const
return {}; return {};
case DashboardInfo: case DashboardInfo:
return query; return query;
case ProjectInfo:
QTC_ASSERT(m_parameters.size() == 1, return {});
query += "/projects/" + QUrl::toPercentEncoding(m_parameters.first());
return query;
} }
return {}; return {};

View File

@@ -12,7 +12,7 @@ namespace Axivion::Internal {
class AxivionQuery class AxivionQuery
{ {
public: public:
enum QueryType {NoQuery, DashboardInfo}; enum QueryType {NoQuery, DashboardInfo, ProjectInfo};
explicit AxivionQuery(QueryType type, const QStringList &parameters = {}); explicit AxivionQuery(QueryType type, const QStringList &parameters = {});
QString toString() const; QString toString() const;

View File

@@ -70,6 +70,124 @@ static std::pair<BaseResult, QJsonDocument> prehandleHeaderAndBody(const QByteAr
return {result, doc}; return {result, doc};
} }
static User::UserType userTypeForString(const QString &type)
{
if (type == "DASHBOARD_USER")
return User::Dashboard;
if (type == "VIRTUAL_USER")
return User::Virtual;
return User::Unknown;
}
static User userFromJson(const QJsonObject &object)
{
User result;
if (object.isEmpty()) {
result.error = "Not a user object.";
return result;
}
result.name = object.value("name").toString();
result.displayName = object.value("displayName").toString();
result.type = userTypeForString(object.value("type").toString());
return result;
}
static QList<User> usersFromJson(const QJsonArray &array)
{
QList<User> result;
for (const QJsonValue &value : array) {
User user = userFromJson(value.toObject());
if (!user.error.isEmpty()) // add this error to result.error?
continue;
result.append(user);
}
return result;
}
static IssueCount issueCountFromJson(const QJsonObject &object)
{
IssueCount result;
if (object.isEmpty()) {
result.error = "Not an issue count object.";
return result;
}
result.added = object.value("Added").toInt();
result.removed = object.value("Removed").toInt();
result.total = object.value("Total").toInt();
return result;
}
static QList<IssueCount> issueCountsFromJson(const QJsonObject &object)
{
QList<IssueCount> result;
const QStringList keys = object.keys();
for (const QString &k : keys) {
IssueCount issue = issueCountFromJson(object.value(k).toObject());
if (!issue.error.isEmpty()) // add this error to result.error?
continue;
issue.issueKind = k;
result.append(issue);
}
return result;
}
static ResultVersion versionFromJson(const QJsonObject &object)
{
ResultVersion result;
if (object.isEmpty()) {
result.error = "Not a version object.";
return result;
}
const QJsonValue issuesValue = object.value("issueCounts");
if (!issuesValue.isObject()) {
result.error = "Not an object (issueCounts).";
return result;
}
result.issueCounts = issueCountsFromJson(issuesValue.toObject());
result.timeStamp = object.value("date").toString();
result.name = object.value("name").toString();
result.linesOfCode = object.value("linesOfCode").toInt();
return result;
}
static QList<ResultVersion> versionsFromJson(const QJsonArray &array)
{
QList<ResultVersion> result;
for (const QJsonValue &value : array) {
ResultVersion version = versionFromJson(value.toObject());
if (!version.error.isEmpty()) // add this error to result.error?
continue;
result.append(version);
}
return result;
}
static IssueKind issueKindFromJson(const QJsonObject &object)
{
IssueKind result;
if (object.isEmpty()) {
result.error = "Not an issue kind object.";
return result;
}
result.prefix = object.value("prefix").toString();
result.niceSingular = object.value("niceSingularName").toString();
result.nicePlural = object.value("nicePluralName").toString();
return result;
}
static QList<IssueKind> issueKindsFromJson(const QJsonArray &array)
{
QList<IssueKind> result;
for (const QJsonValue &value : array) {
IssueKind kind = issueKindFromJson(value.toObject());
if (!kind.error.isEmpty()) // add this error to result.error?
continue;
result.append(kind);
}
return result;
}
namespace ResultParser { namespace ResultParser {
DashboardInfo parseDashboardInfo(const QByteArray &input) DashboardInfo parseDashboardInfo(const QByteArray &input)
@@ -109,6 +227,43 @@ DashboardInfo parseDashboardInfo(const QByteArray &input)
return result; return result;
} }
ProjectInfo parseProjectInfo(const QByteArray &input)
{
ProjectInfo result;
auto [header, body] = splitHeaderAndBody(input);
auto [error, doc] = prehandleHeaderAndBody(header, body);
if (!error.error.isEmpty()) {
result.error = error.error;
return result;
}
const QJsonObject object = doc.object();
result.name = object.value("name").toString();
const QJsonValue usersValue = object.value("users");
if (!usersValue.isArray()) {
result.error = "Malformed json response (users).";
return result;
}
result.users = usersFromJson(usersValue.toArray());
const QJsonValue versionsValue = object.value("versions");
if (!versionsValue.isArray()) {
result.error = "Malformed json response (versions).";
return result;
}
result.versions = versionsFromJson(versionsValue.toArray());
const QJsonValue issueKindsValue = object.value("issueKinds");
if (!issueKindsValue.isArray()) {
result.error = "Malformed json response (issueKinds).";
return result;
}
result.issueKinds = issueKindsFromJson(issueKindsValue.toArray());
return result;
}
} // ResultParser } // ResultParser
} // Axivion::Internal } // Axivion::Internal

View File

@@ -27,9 +27,53 @@ public:
QList<Project> projects; QList<Project> projects;
}; };
class User : public BaseResult
{
public:
QString name;
QString displayName;
enum UserType { Dashboard, Virtual, Unknown } type;
};
class IssueKind : public BaseResult
{
public:
QString prefix;
QString niceSingular;
QString nicePlural;
};
class IssueCount : public BaseResult
{
public:
QString issueKind;
int total = 0;
int added = 0;
int removed = 0;
};
class ResultVersion : public BaseResult
{
public:
QString name;
QString timeStamp;
QList<IssueCount> issueCounts;
int linesOfCode = 0;
};
class ProjectInfo : public BaseResult
{
public:
QString name;
QList<User> users;
QList<ResultVersion> versions;
QList<IssueKind> issueKinds;
};
namespace ResultParser { namespace ResultParser {
DashboardInfo parseDashboardInfo(const QByteArray &input); DashboardInfo parseDashboardInfo(const QByteArray &input);
ProjectInfo parseProjectInfo(const QByteArray &input);
} // ResultParser } // ResultParser