Provide minimal settings to work with

Change-Id: I73d09612ac2bb66c4f359ecfffc01650d56359ee
Reviewed-by: David Schulz <david.schulz@qt.io>
Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
Christian Stenger
2022-12-12 16:45:31 +01:00
parent 5a468556d7
commit ffc9eff670
9 changed files with 346 additions and 168 deletions

View File

@@ -1,20 +1,5 @@
/**************************************************************************** // Copyright (C) 2022 The Qt Company Ltd.
** // SPDX-License-Identifier: LicenseRef-Qt-Commercial
** Copyright (C) 2022 The Qt Company Ltd
** All rights reserved.
** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us
**
** This file is part of the Qt Enterprise Axivion Add-on.
**
** Licensees holding valid Qt Enterprise licenses may use this file in
** accordance with the Qt Enterprise License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company.
**
** If you have questions regarding the use of this file, please use
** contact form at http://www.qt.io/contact-us
**
****************************************************************************/
#include "axivionoutputpane.h" #include "axivionoutputpane.h"
@@ -104,4 +89,4 @@ void AxivionOutputPane::goToPrev()
{ {
} }
} // namespace Axivion::Internal } // Axivion::Internal

View File

@@ -1,20 +1,5 @@
/**************************************************************************** // Copyright (C) 2022 The Qt Company Ltd.
** // SPDX-License-Identifier: LicenseRef-Qt-Commercial
** Copyright (C) 2022 The Qt Company Ltd
** All rights reserved.
** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us
**
** This file is part of the Qt Enterprise Axivion Add-on.
**
** Licensees holding valid Qt Enterprise licenses may use this file in
** accordance with the Qt Enterprise License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company.
**
** If you have questions regarding the use of this file, please use
** contact form at http://www.qt.io/contact-us
**
****************************************************************************/
#pragma once #pragma once
@@ -52,4 +37,4 @@ private:
QStackedWidget *m_outputWidget = nullptr; QStackedWidget *m_outputWidget = nullptr;
}; };
} // namespace Axivion::Internal } // Axivion::Internal

View File

@@ -1,20 +1,5 @@
/**************************************************************************** // Copyright (C) 2022 The Qt Company Ltd.
** // SPDX-License-Identifier: LicenseRef-Qt-Commercial
** Copyright (C) 2015 The Qt Company Ltd
** All rights reserved.
** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us
**
** This file is part of the Qt Enterprise Axivion Add-on.
**
** Licensees holding valid Qt Enterprise licenses may use this file in
** accordance with the Qt Enterprise License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company.
**
** If you have questions regarding the use of this file, please use
** contact form at http://www.qt.io/contact-us
**
****************************************************************************/
#include "axivionplugin.h" #include "axivionplugin.h"
@@ -22,13 +7,13 @@
#include "axivionsettings.h" #include "axivionsettings.h"
#include "axivionsettingspage.h" #include "axivionsettingspage.h"
#include <coreplugin/icore.h>
#include <extensionsystem/pluginmanager.h>
#ifdef LICENSECHECKER #ifdef LICENSECHECKER
# include <licensechecker/licensecheckerplugin.h> # include <licensechecker/licensecheckerplugin.h>
#endif #endif
#include <extensionsystem/pluginmanager.h>
namespace Axivion::Internal { namespace Axivion::Internal {
class AxivionPluginPrivate class AxivionPluginPrivate
@@ -58,6 +43,7 @@ bool AxivionPlugin::initialize(const QStringList &arguments, QString *errorMessa
#endif // LICENSECHECKER #endif // LICENSECHECKER
d = new AxivionPluginPrivate; d = new AxivionPluginPrivate;
d->axivionSettings.fromSettings(Core::ICore::settings());
return true; return true;
} }

View File

@@ -1,20 +1,5 @@
/**************************************************************************** // Copyright (C) 2022 The Qt Company Ltd.
** // SPDX-License-Identifier: LicenseRef-Qt-Commercial
** Copyright (C) 2022 The Qt Company Ltd
** All rights reserved.
** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us
**
** This file is part of the Qt Enterprise Axivion Add-on.
**
** Licensees holding valid Qt Enterprise licenses may use this file in
** accordance with the Qt Enterprise License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company.
**
** If you have questions regarding the use of this file, please use
** contact form at http://www.qt.io/contact-us
**
****************************************************************************/
#pragma once #pragma once
@@ -38,5 +23,5 @@ private:
class AxivionPluginPrivate *d = nullptr; class AxivionPluginPrivate *d = nullptr;
}; };
} // namespace Axivion::Internal } // Axivion::Internal

View File

@@ -1,41 +1,131 @@
/**************************************************************************** // Copyright (C) 2022 The Qt Company Ltd.
** // SPDX-License-Identifier: LicenseRef-Qt-Commercial
** Copyright (C) 2022 The Qt Company Ltd
** All rights reserved.
** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us
**
** This file is part of the Qt Enterprise Axivion Add-on.
**
** Licensees holding valid Qt Enterprise licenses may use this file in
** accordance with the Qt Enterprise License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company.
**
** If you have questions regarding the use of this file, please use
** contact form at http://www.qt.io/contact-us
**
****************************************************************************/
#include "axivionsettings.h" #include "axivionsettings.h"
#include <utils/hostosinfo.h>
#include <QJsonDocument>
#include <QJsonObject>
#include <QSettings> #include <QSettings>
#include <QStandardPaths>
namespace Axivion::Internal { namespace Axivion::Internal {
const char curlKeyC[] = "Curl";
AxivionServer::AxivionServer(const Utils::Id &id, const QString &dashboard,
const QString &description, const QString &token)
: id(id)
, dashboard(dashboard)
, description(description)
, token(token)
{
}
bool AxivionServer::operator==(const AxivionServer &other) const
{
return id == other.id && dashboard == other.dashboard
&& description == other.description && token == other.token;
}
bool AxivionServer::operator!=(const AxivionServer &other) const
{
return !(*this == other);
}
QJsonObject AxivionServer::toJson() const
{
QJsonObject result;
result.insert("id", id.toString());
result.insert("dashboard", dashboard);
result.insert("description", description);
result.insert("token", token);
return result;
}
AxivionServer AxivionServer::fromJson(const QJsonObject &json)
{
const AxivionServer invalidServer;
const QJsonValue id = json.value("id");
if (id == QJsonValue::Undefined)
return invalidServer;
const QJsonValue dashboard = json.value("dashboard");
if (dashboard == 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 { Utils::Id::fromString(id.toString()), dashboard.toString(),
description.toString(), token.toString() };
}
QStringList AxivionServer::curlArguments() const
{
QStringList args { "-sS" }; // silent, but show error
if (dashboard.startsWith("https://") && !validateCert)
args << "-k";
return args;
}
AxivionSettings::AxivionSettings() AxivionSettings::AxivionSettings()
{ {
} }
static Utils::FilePath tokensFilePath(const QSettings *s)
{
return Utils::FilePath::fromString(s->fileName()).parentDir()
.pathAppended("qtcreator/axivion.json");
}
static void writeTokenFile(const Utils::FilePath &filePath, const AxivionServer &server)
{
QJsonDocument doc;
doc.setObject(server.toJson());
// FIXME error handling?
filePath.writeFileContents(doc.toJson());
filePath.setPermissions(QFile::ReadUser | QFile::WriteUser);
}
static AxivionServer readTokenFile(const Utils::FilePath &filePath)
{
if (!filePath.exists())
return {};
Utils::expected_str<QByteArray> contents = filePath.fileContents();
if (!contents)
return {};
const QJsonDocument doc = QJsonDocument::fromJson(*contents);
if (!doc.isObject())
return {};
return AxivionServer::fromJson(doc.object());
}
void AxivionSettings::toSettings(QSettings *s) const void AxivionSettings::toSettings(QSettings *s) const
{ {
writeTokenFile(tokensFilePath(s), server);
s->beginGroup("Axivion"); s->beginGroup("Axivion");
s->setValue(curlKeyC, curl.toVariant());
s->endGroup(); s->endGroup();
} }
void AxivionSettings::fromSettings(QSettings *s) void AxivionSettings::fromSettings(QSettings *s)
{ {
s->beginGroup("Axivion"); s->beginGroup("Axivion");
curl = Utils::FilePath::fromVariant(curlKeyC);
s->endGroup(); s->endGroup();
server = readTokenFile(tokensFilePath(s));
if (curl.isEmpty() || !curl.exists()) {
const QString curlPath = QStandardPaths::findExecutable(
Utils::HostOsInfo::withExecutableSuffix("curl"));
if (!curlPath.isEmpty())
curl = Utils::FilePath::fromString(curlPath);
}
} }
} // namespace Axivion::Internal } // Axivion::Internal

View File

@@ -1,37 +1,51 @@
/**************************************************************************** // Copyright (C) 2022 The Qt Company Ltd.
** // SPDX-License-Identifier: LicenseRef-Qt-Commercial
** Copyright (C) 2022 The Qt Company Ltd
** All rights reserved.
** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us
**
** This file is part of the Qt Enterprise Axivion Add-on.
**
** Licensees holding valid Qt Enterprise licenses may use this file in
** accordance with the Qt Enterprise License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company.
**
** If you have questions regarding the use of this file, please use
** contact form at http://www.qt.io/contact-us
**
****************************************************************************/
#pragma once #pragma once
#include <utils/filepath.h>
#include <utils/id.h>
#include <QtGlobal> #include <QtGlobal>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QJsonObject;
class QSettings; class QSettings;
QT_END_NAMESPACE QT_END_NAMESPACE
namespace Axivion::Internal { namespace Axivion::Internal {
class AxivionServer
{
public:
AxivionServer() = default;
AxivionServer(const Utils::Id &id, const QString &dashboardUrl,
const QString &description, const QString &token);
bool operator==(const AxivionServer &other) const;
bool operator!=(const AxivionServer &other) const;
QJsonObject toJson() const;
static AxivionServer fromJson(const QJsonObject &json);
QStringList curlArguments() const;
Utils::Id id;
QString dashboard;
QString description;
QString token;
bool validateCert = true;
};
class AxivionSettings class AxivionSettings
{ {
public: public:
AxivionSettings(); AxivionSettings();
void toSettings(QSettings *s) const; void toSettings(QSettings *s) const;
void fromSettings(QSettings *s); void fromSettings(QSettings *s);
AxivionServer server; // shall we have more than one?
Utils::FilePath curl;
}; };
} // namespace Axivion::Internal } // Axivion::Internal

View File

@@ -1,20 +1,5 @@
/**************************************************************************** // Copyright (C) 2022 The Qt Company Ltd.
** // SPDX-License-Identifier: LicenseRef-Qt-Commercial
** Copyright (C) 2022 The Qt Company Ltd
** All rights reserved.
** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us
**
** This file is part of the Qt Enterprise Axivion Add-on.
**
** Licensees holding valid Qt Enterprise licenses may use this file in
** accordance with the Qt Enterprise License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company.
**
** If you have questions regarding the use of this file, please use
** contact form at http://www.qt.io/contact-us
**
****************************************************************************/
#include "axivionsettingspage.h" #include "axivionsettingspage.h"
@@ -23,12 +8,115 @@
#include <coreplugin/icore.h> #include <coreplugin/icore.h>
#include <utils/layoutbuilder.h> #include <utils/layoutbuilder.h>
#include <utils/pathchooser.h>
#include <QDialog>
#include <QDialogButtonBox>
#include <QLabel> #include <QLabel>
#include <QWidget> #include <QPushButton>
#include <QRegularExpression>
#include <QUuid>
#include <QVBoxLayout>
using namespace Utils;
namespace Axivion::Internal { namespace Axivion::Internal {
// may allow some invalid, but does some minimal check for legality
static bool hostValid(const QString &host)
{
static const QRegularExpression ip(R"(^(\d+).(\d+).(\d+).(\d+)$)");
static const QRegularExpression dn(R"(^([a-zA-Z0-9][a-zA-Z0-9-]+\.)+[a-zA-Z0-9][a-zA-Z0-9-]+$)");
const QRegularExpressionMatch match = ip.match(host);
if (match.hasMatch()) {
for (int i = 1; i < 5; ++i) {
int val = match.captured(i).toInt();
if (val < 0 || val > 255)
return false;
}
return true;
}
return (host == "localhost") || dn.match(host).hasMatch();
}
static bool isUrlValid(const QString &in)
{
const QUrl url(in);
return hostValid(url.host()) && url.scheme() == "https" || url.scheme() == "http";
}
DashboardWidget::DashboardWidget(Mode mode, QWidget *parent)
: QWidget(parent)
, m_mode(mode)
{
auto labelStyle = mode == Display ? StringAspect::LabelDisplay : StringAspect::LineEditDisplay;
m_dashboardUrl.setLabelText(Tr::tr("Dashboard URL:"));
m_dashboardUrl.setDisplayStyle(labelStyle);
m_dashboardUrl.setValidationFunction([](FancyLineEdit *edit, QString *){
return isUrlValid(edit->text());
});
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;
Row {
Form {
m_dashboardUrl,
m_description,
m_token
}
}.attachTo(this, mode == Edit ? WithMargins : WithoutMargins);
auto checkValidity = [this](){
bool old = m_valid;
m_valid = isValid();
if (old != m_valid)
emit validChanged(m_valid);
};
if (mode == Edit) {
connect(&m_dashboardUrl, &StringAspect::valueChanged,
this, checkValidity);
connect(&m_description, &StringAspect::valueChanged,
this, checkValidity);
connect(&m_token, &StringAspect::valueChanged,
this, checkValidity);
}
}
AxivionServer DashboardWidget::dashboardServer() const
{
AxivionServer result;
if (m_id.isValid())
result.id = m_id;
else
result.id = m_mode == Edit ? Utils::Id::fromName(QUuid::createUuid().toByteArray()) : m_id;
result.dashboard = m_dashboardUrl.value();
result.description = m_description.value();
result.token = m_token.value();
return result;
}
void DashboardWidget::setDashboardServer(const AxivionServer &server)
{
m_id = server.id;
m_dashboardUrl.setValue(server.dashboard);
m_description.setValue(server.description);
m_token.setValue(server.token);
}
bool DashboardWidget::isValid() const
{
return !m_token.value().isEmpty() && !m_description.value().isEmpty()
&& isUrlValid(m_dashboardUrl.value());
}
class AxivionSettingsWidget : public Core::IOptionsPageWidget class AxivionSettingsWidget : public Core::IOptionsPageWidget
{ {
public: public:
@@ -36,26 +124,73 @@ public:
void apply() override; void apply() override;
private: private:
void showEditServerDialog();
AxivionSettings *m_settings; AxivionSettings *m_settings;
Utils::StringAspect m_curlPC;
DashboardWidget *m_dashboardDisplay = nullptr;
QPushButton *m_edit = nullptr;
}; };
AxivionSettingsWidget::AxivionSettingsWidget(AxivionSettings *settings) AxivionSettingsWidget::AxivionSettingsWidget(AxivionSettings *settings)
: m_settings(settings) : m_settings(settings)
{ {
using namespace Utils::Layouting; using namespace Layouting;
auto label = new QLabel(Tr::tr("...Placeholder...")); m_dashboardDisplay = new DashboardWidget(DashboardWidget::Display, this);
Row { m_dashboardDisplay->setDashboardServer(m_settings->server);
Column { label, st } m_edit = new QPushButton(Tr::tr("Edit..."), this);
m_curlPC.setLabelText(Tr::tr("curl:"));
m_curlPC.setDisplayStyle(StringAspect::PathChooserDisplay);
m_curlPC.setExpectedKind(PathChooser::ExistingCommand);
m_curlPC.setFilePath(m_settings->curl);
Grid {
Form {
m_dashboardDisplay, br,
m_curlPC, br,
}, Column { m_edit, st }
}.attachTo(this); }.attachTo(this);
connect(m_edit, &QPushButton::clicked, this, &AxivionSettingsWidget::showEditServerDialog);
} }
void AxivionSettingsWidget::apply() void AxivionSettingsWidget::apply()
{ {
// set m_settings from widget m_settings->server = m_dashboardDisplay->dashboardServer();
m_settings->curl = m_curlPC.filePath();
m_settings->toSettings(Core::ICore::settings()); m_settings->toSettings(Core::ICore::settings());
} }
void AxivionSettingsWidget::showEditServerDialog()
{
const AxivionServer old = m_dashboardDisplay->dashboardServer();
QDialog d;
d.setWindowTitle(Tr::tr("Edit Dashboard Configuration"));
QVBoxLayout *layout = new QVBoxLayout;
DashboardWidget *dashboardWidget = new DashboardWidget(DashboardWidget::Edit, this);
dashboardWidget->setDashboardServer(old);
layout->addWidget(dashboardWidget);
auto buttons = new QDialogButtonBox(QDialogButtonBox::Cancel, this);
auto modify = buttons->addButton(Tr::tr("Modify"), QDialogButtonBox::AcceptRole);
modify->setEnabled(m_dashboardDisplay->isValid());
connect(buttons->button(QDialogButtonBox::Cancel), &QPushButton::clicked, &d, &QDialog::reject);
connect(modify, &QPushButton::clicked, &d, &QDialog::accept);
connect(dashboardWidget, &DashboardWidget::validChanged,
modify, &QPushButton::setEnabled);
layout->addWidget(buttons);
d.setLayout(layout);
d.resize(500, 200);
if (d.exec() != QDialog::Accepted)
return;
if (dashboardWidget->isValid()) {
const AxivionServer server = dashboardWidget->dashboardServer();
if (server != old)
m_dashboardDisplay->setDashboardServer(server);
}
}
AxivionSettingsPage::AxivionSettingsPage(AxivionSettings *settings) AxivionSettingsPage::AxivionSettingsPage(AxivionSettings *settings)
: m_settings(settings) : m_settings(settings)
{ {

View File

@@ -1,32 +1,45 @@
/**************************************************************************** // Copyright (C) 2022 The Qt Company Ltd.
** // SPDX-License-Identifier: LicenseRef-Qt-Commercial
** Copyright (C) 2022 The Qt Company Ltd
** All rights reserved.
** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us
**
** This file is part of the Qt Enterprise Axivion Add-on.
**
** Licensees holding valid Qt Enterprise licenses may use this file in
** accordance with the Qt Enterprise License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company.
**
** If you have questions regarding the use of this file, please use
** contact form at http://www.qt.io/contact-us
**
****************************************************************************/
#pragma once #pragma once
#include <coreplugin/dialogs/ioptionspage.h> #include <coreplugin/dialogs/ioptionspage.h>
#include <utils/aspects.h>
#include <utils/id.h>
#include <QPointer> #include <QPointer>
#include <QWidget>
namespace Axivion::Internal { namespace Axivion::Internal {
class AxivionServer;
class AxivionSettings; class AxivionSettings;
class AxivionSettingsWidget; class AxivionSettingsWidget;
class DashboardWidget : public QWidget
{
Q_OBJECT
public:
enum Mode { Display, Edit };
explicit DashboardWidget(Mode m = Display, QWidget *parent = nullptr);
AxivionServer dashboardServer() const;
void setDashboardServer(const AxivionServer &server);
bool isValid() const;
signals:
void validChanged(bool valid);
private:
Mode m_mode = Display;
Utils::Id m_id;
Utils::StringAspect m_dashboardUrl;
Utils::StringAspect m_description;
Utils::StringAspect m_token;
bool m_valid = false;
};
class AxivionSettingsPage : public Core::IOptionsPage class AxivionSettingsPage : public Core::IOptionsPage
{ {
Q_OBJECT Q_OBJECT
@@ -37,4 +50,4 @@ private:
AxivionSettings *m_settings; AxivionSettings *m_settings;
}; };
} // namespace Axivion::Internal } // Axivion::Internal

View File

@@ -1,20 +1,5 @@
/**************************************************************************** // Copyright (C) 2022 The Qt Company Ltd.
** // SPDX-License-Identifier: LicenseRef-Qt-Commercial
** Copyright (C) 2022 The Qt Company Ltd
** All rights reserved.
** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us
**
** This file is part of the Qt Enterprise Axivion Add-on.
**
** Licensees holding valid Qt Enterprise licenses may use this file in
** accordance with the Qt Enterprise License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company.
**
** If you have questions regarding the use of this file, please use
** contact form at http://www.qt.io/contact-us
**
****************************************************************************/
#pragma once #pragma once
@@ -27,4 +12,4 @@ struct Tr
Q_DECLARE_TR_FUNCTIONS(Axivion) Q_DECLARE_TR_FUNCTIONS(Axivion)
}; };
} // namespace Axivion } // Axivion