Implement backend access with SSO

This commit is contained in:
2025-11-03 13:18:14 +01:00
parent 0909bfb0e7
commit 587d61ce55
24 changed files with 429 additions and 569 deletions
+1 -1
View File
@@ -1203,7 +1203,7 @@
</message>
</context>
<context>
<name>DevicesConnection</name>
<name>DeviceConnection</name>
<message>
<location filename="../../flotten-updater/deviceconnection.cpp" line="79"/>
<location filename="../../flotten-updater/deviceconnection.cpp" line="311"/>
+5
View File
@@ -160,6 +160,11 @@ NavigationPage {
text: qsTr("Skip server cert verification")
}
GeneralOnOffSwitch {
apiKey: "ocppt"
text: qsTr("Accept time from backend")
}
// TODO clientKey
// TODO clientCert
+3 -3
View File
@@ -12,9 +12,9 @@ qt_add_executable(flotten-updater WIN32 MACOSX_BUNDLE
devicesmodel.h
flottenupdatersettings.cpp
flottenupdatersettings.h
importcertificatedialog.cpp
importcertificatedialog.h
importcertificatedialog.ui
importcredentialsdialog.cpp
importcredentialsdialog.h
importcredentialsdialog.ui
main.cpp
mainwindow.cpp
mainwindow.h
+111 -100
View File
@@ -24,42 +24,44 @@ const constexpr QColor blue{150, 150, 255};
const constexpr QColor magenta{255, 150, 255};
}
DevicesConnection::DevicesConnection(const QSslKey &key, const QSslCertificate &cert, QString &&serial, QObject *parent) :
DeviceConnection::DeviceConnection(const QByteArray &username, const QByteArray &password, QString &&serial, QObject *parent) :
QObject{parent},
m_serial(std::move(serial)),
m_key{key},
m_cert{cert}
m_username{username},
m_password{password}
{
init();
}
DevicesConnection::DevicesConnection(const QSslKey &key, const QSslCertificate &cert, const QString &serial, QObject *parent) :
DeviceConnection::DeviceConnection(const QByteArray &username, const QByteArray &password, const QString &serial, QObject *parent) :
QObject{parent},
m_serial(serial),
m_key{key},
m_cert{cert}
m_username{username},
m_password{password}
{
init();
}
void DevicesConnection::start()
void DeviceConnection::start()
{
const QUrl url{QString("wss://solalaweb.com/%0").arg(m_serial)};
qDebug() << url;
m_websocket.open(url);
QNetworkRequest request{QString("wss://solalaweb.com/%0").arg(m_serial)};
QString credentials = m_username + ':' + m_password;
QString base64 = credentials.toUtf8().toBase64();
request.setRawHeader("Authorization", "Basic " + base64.toUtf8());
m_websocket.open(request);
}
void DevicesConnection::stop()
void DeviceConnection::stop()
{
m_websocket.close();
}
QString DevicesConnection::wsStatusText() const
QString DeviceConnection::wsStatusText() const
{
return QMetaEnum::fromType<QAbstractSocket::SocketState>().valueToKey(m_websocket.state());
}
QBrush DevicesConnection::wsStatusBackground() const
QBrush DeviceConnection::wsStatusBackground() const
{
switch (m_websocket.state())
{
@@ -72,7 +74,7 @@ QBrush DevicesConnection::wsStatusBackground() const
return {};
}
QString DevicesConnection::statusText() const
QString DeviceConnection::statusText() const
{
switch (m_status)
{
@@ -84,7 +86,7 @@ QString DevicesConnection::statusText() const
return QString::number(std::to_underlying(m_status));
}
QBrush DevicesConnection::statusBackground() const
QBrush DeviceConnection::statusBackground() const
{
switch (m_status)
{
@@ -95,7 +97,7 @@ QBrush DevicesConnection::statusBackground() const
return {};
}
QString DevicesConnection::variantText() const
QString DeviceConnection::variantText() const
{
if (!m_fullStatus.contains("var"))
return {};
@@ -103,7 +105,7 @@ QString DevicesConnection::variantText() const
return m_fullStatus.value("var").toString();
}
QBrush DevicesConnection::variantBackground() const
QBrush DeviceConnection::variantBackground() const
{
if (!m_fullStatus.contains("var"))
return {};
@@ -116,7 +118,7 @@ QBrush DevicesConnection::variantBackground() const
return red;
}
QString DevicesConnection::isGoText() const
QString DeviceConnection::isGoText() const
{
if (!m_fullStatus.contains("isgo"))
return {};
@@ -124,7 +126,7 @@ QString DevicesConnection::isGoText() const
return m_fullStatus.value("isgo").toBool() ? "yes" : "no";
}
QBrush DevicesConnection::isGoBackground() const
QBrush DeviceConnection::isGoBackground() const
{
if (!m_fullStatus.contains("isgo"))
return {};
@@ -132,7 +134,7 @@ QBrush DevicesConnection::isGoBackground() const
return m_fullStatus.value("isgo").toBool() ? blue : yellow;
}
QString DevicesConnection::isAustralienText() const
QString DeviceConnection::isAustralienText() const
{
if (!m_fullStatus.contains("aus"))
return {};
@@ -140,7 +142,7 @@ QString DevicesConnection::isAustralienText() const
return m_fullStatus.value("aus").toBool() ? "yes" : "no";
}
QBrush DevicesConnection::isAustralienBackground() const
QBrush DeviceConnection::isAustralienBackground() const
{
if (!m_fullStatus.contains("aus"))
return {};
@@ -148,7 +150,7 @@ QBrush DevicesConnection::isAustralienBackground() const
return m_fullStatus.value("aus").toBool() ? yellow : blue;
}
QString DevicesConnection::resetCardText() const
QString DeviceConnection::resetCardText() const
{
if (!m_fullStatus.contains("frci"))
return {};
@@ -156,7 +158,7 @@ QString DevicesConnection::resetCardText() const
return m_fullStatus.value("frci").toBool() ? "yes" : "no";
}
QBrush DevicesConnection::resetCardBackground() const
QBrush DeviceConnection::resetCardBackground() const
{
if (!m_fullStatus.contains("frci"))
return {};
@@ -164,7 +166,7 @@ QBrush DevicesConnection::resetCardBackground() const
return m_fullStatus.value("frci").toBool() ? green : red;
}
QString DevicesConnection::connectedWifiText() const
QString DeviceConnection::connectedWifiText() const
{
if (!m_fullStatus.contains("ccw"))
return {};
@@ -176,7 +178,7 @@ QString DevicesConnection::connectedWifiText() const
return apd.value("ssid").toString();
}
QString DevicesConnection::projectText() const
QString DeviceConnection::projectText() const
{
if (!m_fullStatus.contains("apd"))
return {};
@@ -188,7 +190,7 @@ QString DevicesConnection::projectText() const
return apd.value("project_name").toString();
}
QString DevicesConnection::versionText() const
QString DeviceConnection::versionText() const
{
if (!m_fullStatus.contains("apd"))
return {};
@@ -200,7 +202,7 @@ QString DevicesConnection::versionText() const
return apd.value("version").toString();
}
QString DevicesConnection::idfVersionText() const
QString DeviceConnection::idfVersionText() const
{
if (!m_fullStatus.contains("apd"))
return {};
@@ -212,7 +214,7 @@ QString DevicesConnection::idfVersionText() const
return apd.value("idf_ver").toString();
}
QString DevicesConnection::updateText() const
QString DeviceConnection::updateText() const
{
if (!m_fullStatus.contains("ocs"))
return {};
@@ -241,7 +243,7 @@ QString DevicesConnection::updateText() const
return QString::number(ocs);
}
QBrush DevicesConnection::updateBackground() const
QBrush DeviceConnection::updateBackground() const
{
if (!m_fullStatus.contains("ocs"))
return {};
@@ -259,7 +261,7 @@ QBrush DevicesConnection::updateBackground() const
return {};
}
std::optional<qulonglong> DevicesConnection::uptime() const
std::optional<qulonglong> DeviceConnection::uptime() const
{
if (!m_fullStatus.contains("rbt"))
return {};
@@ -267,7 +269,7 @@ std::optional<qulonglong> DevicesConnection::uptime() const
return m_fullStatus.value("rbt").toULongLong();
}
QString DevicesConnection::uptimeText() const
QString DeviceConnection::uptimeText() const
{
if (!m_fullStatus.contains("rbt"))
return {};
@@ -275,7 +277,7 @@ QString DevicesConnection::uptimeText() const
return QString::number(m_fullStatus.value("rbt").toULongLong());
}
QString DevicesConnection::currentPartition() const
QString DeviceConnection::currentPartition() const
{
if (!m_fullStatus.contains("otap"))
return {};
@@ -287,7 +289,7 @@ QString DevicesConnection::currentPartition() const
return otap.value("label").toString();
}
std::optional<int> DevicesConnection::reboots() const
std::optional<int> DeviceConnection::reboots() const
{
if (!m_fullStatus.contains("rbc"))
return {};
@@ -295,7 +297,7 @@ std::optional<int> DevicesConnection::reboots() const
return m_fullStatus.value("rbc").toInt();
}
QString DevicesConnection::rebootsText() const
QString DeviceConnection::rebootsText() const
{
if (!m_fullStatus.contains("rbc"))
return {};
@@ -303,7 +305,7 @@ QString DevicesConnection::rebootsText() const
return QString::number(m_fullStatus.value("rbc").toInt());
}
QString DevicesConnection::carStateText() const
QString DeviceConnection::carStateText() const
{
if (!m_fullStatus.contains("car"))
return {};
@@ -315,7 +317,7 @@ QString DevicesConnection::carStateText() const
return QString::number(car);
}
std::optional<double> DevicesConnection::energy() const
std::optional<double> DeviceConnection::energy() const
{
if (!m_fullStatus.contains("eto"))
return {};
@@ -323,7 +325,7 @@ std::optional<double> DevicesConnection::energy() const
return m_fullStatus.value("eto").toDouble();
}
QString DevicesConnection::energyText() const
QString DeviceConnection::energyText() const
{
if (!m_fullStatus.contains("eto"))
return {};
@@ -331,7 +333,7 @@ QString DevicesConnection::energyText() const
return QString("%0kWh").arg(m_fullStatus.value("eto").toDouble() / 1000.);
}
QString DevicesConnection::livedataText() const
QString DeviceConnection::livedataText() const
{
if (!m_fullStatus.contains("nrg"))
return {};
@@ -346,85 +348,94 @@ QString DevicesConnection::livedataText() const
return {};
}
QVariant DevicesConnection::getApiKey(const QString &apiKey) const
QVariant DeviceConnection::getApiKey(const QString &apiKey) const
{
return m_fullStatus.value(apiKey);
}
void DevicesConnection::sendMessage(const QJsonDocument &doc)
void DeviceConnection::sendMessage(const QJsonDocument &doc)
{
sendMessage(QString::fromUtf8(doc.toJson()));
}
void DevicesConnection::sendMessage(const QJsonObject &obj)
void DeviceConnection::sendMessage(const QJsonObject &obj)
{
sendMessage(QJsonDocument{obj});
}
void DevicesConnection::sendMessage(const QString &msg)
void DeviceConnection::sendMessage(const QString &msg)
{
qDebug() << msg << m_websocket.errorString();
if (const auto written = m_websocket.sendTextMessage(msg); written != msg.size())
qCritical() << "sending message failed" << written << "(expected:" << msg.size() << ')';
}
void DevicesConnection::init()
QString DeviceConnection::errorString() const
{
return m_websocket.errorString();
}
void DeviceConnection::init()
{
if (auto model = qobject_cast<DevicesModel*>(parent()))
{
connect(this, &DevicesConnection::wsStatusChanged, model, &DevicesModel::wsStatusChanged);
connect(this, &DevicesConnection::statusChanged, model, &DevicesModel::statusChanged);
connect(this, &DevicesConnection::variantChanged, model, &DevicesModel::variantChanged);
connect(this, &DevicesConnection::isGoChanged, model, &DevicesModel::isGoChanged);
connect(this, &DevicesConnection::isAustralienChanged, model, &DevicesModel::isAustralienChanged);
connect(this, &DevicesConnection::resetCardChanged, model, &DevicesModel::resetCardChanged);
connect(this, &DevicesConnection::connectedWifiChanged, model, &DevicesModel::connectedWifiChanged);
connect(this, &DevicesConnection::projectChanged, model, &DevicesModel::projectChanged);
connect(this, &DevicesConnection::versionChanged, model, &DevicesModel::versionChanged);
connect(this, &DevicesConnection::idfVersionChanged, model, &DevicesModel::idfVersionChanged);
connect(this, &DevicesConnection::updateChanged, model, &DevicesModel::updateChanged);
connect(this, &DevicesConnection::uptimeChanged, model, &DevicesModel::uptimeChanged);
connect(this, &DevicesConnection::currentPartitionChanged, model, &DevicesModel::currentPartitionChanged);
connect(this, &DevicesConnection::rebootsChanged, model, &DevicesModel::rebootsChanged);
connect(this, &DevicesConnection::carStateChanged, model, &DevicesModel::carStateChanged);
connect(this, &DevicesConnection::energyChanged, model, &DevicesModel::energyChanged);
connect(this, &DevicesConnection::livedataChanged, model, &DevicesModel::livedataChanged);
connect(this, &DevicesConnection::apiKeyChanged, model, &DevicesModel::apiKeyChanged);
connect(this, &DeviceConnection::wsStatusChanged, model, &DevicesModel::wsStatusChanged);
connect(this, &DeviceConnection::statusChanged, model, &DevicesModel::statusChanged);
connect(this, &DeviceConnection::variantChanged, model, &DevicesModel::variantChanged);
connect(this, &DeviceConnection::isGoChanged, model, &DevicesModel::isGoChanged);
connect(this, &DeviceConnection::isAustralienChanged, model, &DevicesModel::isAustralienChanged);
connect(this, &DeviceConnection::resetCardChanged, model, &DevicesModel::resetCardChanged);
connect(this, &DeviceConnection::connectedWifiChanged, model, &DevicesModel::connectedWifiChanged);
connect(this, &DeviceConnection::projectChanged, model, &DevicesModel::projectChanged);
connect(this, &DeviceConnection::versionChanged, model, &DevicesModel::versionChanged);
connect(this, &DeviceConnection::idfVersionChanged, model, &DevicesModel::idfVersionChanged);
connect(this, &DeviceConnection::updateChanged, model, &DevicesModel::updateChanged);
connect(this, &DeviceConnection::uptimeChanged, model, &DevicesModel::uptimeChanged);
connect(this, &DeviceConnection::currentPartitionChanged, model, &DevicesModel::currentPartitionChanged);
connect(this, &DeviceConnection::rebootsChanged, model, &DevicesModel::rebootsChanged);
connect(this, &DeviceConnection::carStateChanged, model, &DevicesModel::carStateChanged);
connect(this, &DeviceConnection::energyChanged, model, &DevicesModel::energyChanged);
connect(this, &DeviceConnection::livedataChanged, model, &DevicesModel::livedataChanged);
connect(this, &DeviceConnection::apiKeyChanged, model, &DevicesModel::apiKeyChanged);
}
else
qWarning() << "unexpected parent";
{
auto sslConfig = m_websocket.sslConfiguration();
sslConfig.setPeerVerifyMode(QSslSocket::VerifyNone);
//sslConfig.setPeerVerifyMode(QSslSocket::VerifyPeer);
{
auto caCerts = QSslCertificate::fromPath(":/goe-root-ca.pem");
if (caCerts.empty())
qFatal("could not parse root ca");
for (const auto &caCert : std::as_const(caCerts))
qDebug() << caCert.issuerDisplayName();
sslConfig.setCaCertificates(std::move(caCerts));
}
sslConfig.setPrivateKey(m_key);
sslConfig.setLocalCertificate(m_cert);
m_websocket.setSslConfiguration(sslConfig);
m_websocket.ignoreSslErrors();
//{
// auto sslConfig = m_websocket.sslConfiguration();
// sslConfig.setPeerVerifyMode(QSslSocket::VerifyNone);
// //sslConfig.setPeerVerifyMode(QSslSocket::VerifyPeer);
// {
// auto caCerts = QSslCertificate::fromPath(":/goe-root-ca.pem");
// if (caCerts.empty())
// qFatal("could not parse root ca");
// for (const auto &caCert : std::as_const(caCerts))
// qDebug() << caCert.issuerDisplayName();
// sslConfig.setCaCertificates(std::move(caCerts));
// }
// sslConfig.setPrivateKey(m_key);
// sslConfig.setLocalCertificate(m_cert);
// m_websocket.setSslConfiguration(sslConfig);
// m_websocket.ignoreSslErrors();
//}
connect(&m_websocket, &QWebSocket::connected, this, &DeviceConnection::connectedSignal);
connect(&m_websocket, &QWebSocket::disconnected, this, &DeviceConnection::disconnectedSignal);
connect(&m_websocket, &QWebSocket::errorOccurred, this, &DeviceConnection::errorOccurredSignal);
connect(&m_websocket, &QWebSocket::connected, this, &DeviceConnection::connected);
connect(&m_websocket, &QWebSocket::disconnected, this, &DeviceConnection::disconnected);
connect(&m_websocket, &QWebSocket::stateChanged, this, &DeviceConnection::stateChanged);
connect(&m_websocket, &QWebSocket::textMessageReceived, this, &DeviceConnection::textMessageReceived);
connect(&m_websocket, &QWebSocket::binaryMessageReceived, this, &DeviceConnection::binaryMessageReceived);
connect(&m_websocket, &QWebSocket::errorOccurred, this, &DeviceConnection::errorOccurred);
connect(&m_websocket, &QWebSocket::peerVerifyError, this, &DeviceConnection::peerVerifyError);
connect(&m_websocket, &QWebSocket::sslErrors, this, &DeviceConnection::sslErrors);
connect(&m_websocket, &QWebSocket::alertReceived, this, &DeviceConnection::alertReceived);
connect(&m_websocket, &QWebSocket::handshakeInterruptedOnError, this, &DeviceConnection::handshakeInterruptedOnError);
}
connect(&m_websocket, &QWebSocket::connected, this, &DevicesConnection::connected);
connect(&m_websocket, &QWebSocket::disconnected, this, &DevicesConnection::disconnected);
connect(&m_websocket, &QWebSocket::stateChanged, this, &DevicesConnection::stateChanged);
connect(&m_websocket, &QWebSocket::textMessageReceived, this, &DevicesConnection::textMessageReceived);
connect(&m_websocket, &QWebSocket::binaryMessageReceived, this, &DevicesConnection::binaryMessageReceived);
connect(&m_websocket, &QWebSocket::errorOccurred, this, &DevicesConnection::errorOccurred);
connect(&m_websocket, &QWebSocket::peerVerifyError, this, &DevicesConnection::peerVerifyError);
connect(&m_websocket, &QWebSocket::sslErrors, this, &DevicesConnection::sslErrors);
connect(&m_websocket, &QWebSocket::alertReceived, this, &DevicesConnection::alertReceived);
connect(&m_websocket, &QWebSocket::handshakeInterruptedOnError, this, &DevicesConnection::handshakeInterruptedOnError);
}
void DevicesConnection::maintainStatus(const QJsonObject &msg, bool forceChange)
void DeviceConnection::maintainStatus(const QJsonObject &msg, bool forceChange)
{
bool variantChanged{forceChange};
bool isGoChanged{forceChange};
@@ -507,17 +518,17 @@ void DevicesConnection::maintainStatus(const QJsonObject &msg, bool forceChange)
emit this->livedataChanged();
}
void DevicesConnection::connected()
void DeviceConnection::connected()
{
qDebug() << "called";
}
void DevicesConnection::disconnected()
void DeviceConnection::disconnected()
{
qDebug() << "called";
}
void DevicesConnection::stateChanged(QAbstractSocket::SocketState state)
void DeviceConnection::stateChanged(QAbstractSocket::SocketState state)
{
// qDebug() << "called" << state;
@@ -533,7 +544,7 @@ void DevicesConnection::stateChanged(QAbstractSocket::SocketState state)
emit wsStatusChanged();
}
void DevicesConnection::textMessageReceived(const QString &message)
void DeviceConnection::textMessageReceived(const QString &message)
{
// qDebug() << "called" << message;
@@ -614,32 +625,32 @@ void DevicesConnection::textMessageReceived(const QString &message)
qWarning() << "unknown message type" << msgObj;
}
void DevicesConnection::binaryMessageReceived(const QByteArray &message)
void DeviceConnection::binaryMessageReceived(const QByteArray &message)
{
qDebug() << "called" << message;
}
void DevicesConnection::errorOccurred(QAbstractSocket::SocketError error)
void DeviceConnection::errorOccurred(QAbstractSocket::SocketError error)
{
qDebug() << "called" << QMetaEnum::fromType<QAbstractSocket::SocketError>().valueToKey(error) << m_websocket.errorString();
}
void DevicesConnection::peerVerifyError(const QSslError &error)
void DeviceConnection::peerVerifyError(const QSslError &error)
{
qDebug() << "called" << error;
}
void DevicesConnection::sslErrors(const QList<QSslError> &errors)
void DeviceConnection::sslErrors(const QList<QSslError> &errors)
{
qDebug() << "called" << errors;
}
void DevicesConnection::alertReceived(QSsl::AlertLevel level, QSsl::AlertType type, const QString &description)
void DeviceConnection::alertReceived(QSsl::AlertLevel level, QSsl::AlertType type, const QString &description)
{
qDebug() << "called" << std::to_underlying(level) << std::to_underlying(type) << description;
}
void DevicesConnection::handshakeInterruptedOnError(const QSslError &error)
void DeviceConnection::handshakeInterruptedOnError(const QSslError &error)
{
qDebug() << "called" << error;
}
+11 -5
View File
@@ -9,13 +9,13 @@ class QSslKey;
class QSslCertificate;
class QJsonObject;
class DevicesConnection : public QObject
class DeviceConnection : public QObject
{
Q_OBJECT
public:
explicit DevicesConnection(const QSslKey &key, const QSslCertificate &cert, QString &&serial, QObject *parent = nullptr);
explicit DevicesConnection(const QSslKey &key, const QSslCertificate &cert, const QString &serial, QObject *parent = nullptr);
explicit DeviceConnection(const QByteArray &username, const QByteArray &password, QString &&serial, QObject *parent = nullptr);
explicit DeviceConnection(const QByteArray &username, const QByteArray &password, const QString &serial, QObject *parent = nullptr);
void start();
void stop();
@@ -72,7 +72,13 @@ public:
void sendMessage(const QJsonObject &obj);
void sendMessage(const QString &msg);
QString errorString() const;
signals:
void connectedSignal();
void disconnectedSignal();
void errorOccurredSignal(QAbstractSocket::SocketError error);
void responseReceived(const QString &requestId, const QJsonObject &msg);
void wsStatusChanged();
@@ -112,8 +118,8 @@ private slots:
private:
const QString m_serial;
const QSslKey &m_key;
const QSslCertificate &m_cert;
const QByteArray m_username;
const QByteArray m_password;
enum Status {
Unknown,
+11 -11
View File
@@ -34,12 +34,12 @@ enum {
};
}
DevicesModel::DevicesModel(FlottenUpdaterSettings &settings, const QSslKey &key,
const QSslCertificate &cert, QObject *parent) :
DevicesModel::DevicesModel(FlottenUpdaterSettings &settings, const QByteArray &username,
const QByteArray &password, QObject *parent) :
QAbstractTableModel{parent},
m_settings{settings},
m_key{key},
m_cert{cert},
m_username{username},
m_password{password},
m_customColumns{settings.customColumns()}
{
for (const auto &serial : m_settings.serials())
@@ -47,7 +47,7 @@ DevicesModel::DevicesModel(FlottenUpdaterSettings &settings, const QSslKey &key,
if (std::none_of(std::cbegin(m_devices), std::cend(m_devices), [&serial](auto &ptr){
return ptr->serial() == serial;
}))
m_devices.emplace_back(std::make_shared<DevicesConnection>(m_key, m_cert, serial, this));
m_devices.emplace_back(std::make_shared<DeviceConnection>(m_username, m_password, serial, this));
}
}
@@ -71,7 +71,7 @@ QVariant DevicesModel::data(const QModelIndex &index, int role) const
return {};
}
const DevicesConnection &device = **std::next(std::begin(m_devices), index.row());
const DeviceConnection &device = **std::next(std::begin(m_devices), index.row());
switch (index.column())
{
@@ -332,7 +332,7 @@ bool DevicesModel::addClient(const QString &serial)
beginInsertRows({}, m_devices.size(), m_devices.size());
auto clientPtr = std::make_shared<DevicesConnection>(m_key, m_cert, serial, this);
auto clientPtr = std::make_shared<DeviceConnection>(m_username, m_password, serial, this);
auto client = clientPtr.get();
m_devices.emplace_back(std::move(clientPtr));
@@ -343,7 +343,7 @@ bool DevicesModel::addClient(const QString &serial)
return true;
}
std::shared_ptr<DevicesConnection> DevicesModel::getDevice(QModelIndex index)
std::shared_ptr<DeviceConnection> DevicesModel::getDevice(QModelIndex index)
{
Q_ASSERT(!index.parent().isValid());
Q_ASSERT(index.row() >= 0 && index.row() < m_devices.size());
@@ -352,7 +352,7 @@ std::shared_ptr<DevicesConnection> DevicesModel::getDevice(QModelIndex index)
return device;
}
std::shared_ptr<const DevicesConnection> DevicesModel::getDevice(QModelIndex index) const
std::shared_ptr<const DeviceConnection> DevicesModel::getDevice(QModelIndex index) const
{
Q_ASSERT(!index.parent().isValid());
return m_devices.at(index.row());
@@ -500,14 +500,14 @@ void DevicesModel::apiKeyChanged(const QString &apiKey)
void DevicesModel::columnChanged(int column, const QList<int> &roles)
{
auto device = qobject_cast<DevicesConnection*>(sender());
auto device = qobject_cast<DeviceConnection*>(sender());
if (!device)
{
qWarning() << "unknown sender" << sender();
return;
}
auto iter = std::find_if(std::cbegin(m_devices), std::cend(m_devices), [&device](const std::shared_ptr<DevicesConnection> &ptr){ return device == ptr.get(); });
auto iter = std::find_if(std::cbegin(m_devices), std::cend(m_devices), [&device](const std::shared_ptr<DeviceConnection> &ptr){ return device == ptr.get(); });
if (iter == std::cend(m_devices))
{
qWarning() << "unknown sender" << device;
+8 -8
View File
@@ -9,7 +9,7 @@ class QSslKey;
class QSslCertificate;
class FlottenUpdaterSettings;
class DevicesConnection;
class DeviceConnection;
class DevicesModel : public QAbstractTableModel
{
@@ -18,8 +18,8 @@ class DevicesModel : public QAbstractTableModel
using base = QAbstractTableModel;
public:
explicit DevicesModel(FlottenUpdaterSettings &settings, const QSslKey &key,
const QSslCertificate &cert, QObject *parent = nullptr);
explicit DevicesModel(FlottenUpdaterSettings &settings, const QByteArray &username,
const QByteArray &password, QObject *parent = nullptr);
~DevicesModel() override;
int rowCount(const QModelIndex &parent) const override;
@@ -30,8 +30,8 @@ public:
bool addClient(const QString &serial);
std::shared_ptr<DevicesConnection> getDevice(QModelIndex index);
std::shared_ptr<const DevicesConnection> getDevice(QModelIndex index) const;
std::shared_ptr<DeviceConnection> getDevice(QModelIndex index);
std::shared_ptr<const DeviceConnection> getDevice(QModelIndex index) const;
void addCustomColumn(const QString &apiKey);
bool customColumnRemovable(int section);
@@ -64,11 +64,11 @@ public slots:
private:
FlottenUpdaterSettings &m_settings;
const QSslKey &m_key;
const QSslCertificate &m_cert;
const QByteArray m_username;
const QByteArray m_password;
void columnChanged(int column, const QList<int> &roles = QList<int>());
std::vector<std::shared_ptr<DevicesConnection>> m_devices;
std::vector<std::shared_ptr<DeviceConnection>> m_devices;
QStringList m_customColumns;
};
+8 -8
View File
@@ -1,23 +1,23 @@
#include "flottenupdatersettings.h"
QByteArray FlottenUpdaterSettings::privateKey() const
QByteArray FlottenUpdaterSettings::username() const
{
return value("privateKey").toByteArray();
return value("username").toByteArray();
}
void FlottenUpdaterSettings::setPrivateKey(const QByteArray &key)
void FlottenUpdaterSettings::setUsername(const QByteArray &username)
{
setValue("privateKey", key);
setValue("username", username);
}
QByteArray FlottenUpdaterSettings::privateCert() const
QByteArray FlottenUpdaterSettings::password() const
{
return value("privateCert").toByteArray();
return value("password").toByteArray();
}
void FlottenUpdaterSettings::setPrivateCert(const QByteArray &cert)
void FlottenUpdaterSettings::setPassword(const QByteArray &password)
{
setValue("privateCert", cert);
setValue("password", password);
}
QStringList FlottenUpdaterSettings::customColumns() const
+4 -4
View File
@@ -9,11 +9,11 @@ class FlottenUpdaterSettings : public QSettings
public:
using QSettings::QSettings;
QByteArray privateKey() const;
void setPrivateKey(const QByteArray &key);
QByteArray username() const;
void setUsername(const QByteArray &key);
QByteArray privateCert() const;
void setPrivateCert(const QByteArray &cert);
QByteArray password() const;
void setPassword(const QByteArray &cert);
QStringList customColumns() const;
void setCustomColumns(const QStringList &customColumns);
-157
View File
@@ -1,157 +0,0 @@
#include "importcertificatedialog.h"
#include "ui_importcertificatedialog.h"
#include <QFileDialog>
#include <QFile>
#include <QMessageBox>
#include <QInputDialog>
#include <QSslSocket>
#ifdef HAS_OPENSSL
#include <openssl/provider.h>
#endif
#ifdef HAS_OPENSSL
namespace {
OSSL_PROVIDER *legacy{};
}
#endif
ImportCertificateDialog::ImportCertificateDialog(QWidget *parent) :
QDialog{parent},
m_ui{std::make_unique<Ui::ImportCertificateDialog>()}
{
m_ui->setupUi(this);
connect(m_ui->pushButtonImport, &QPushButton::clicked, this, &ImportCertificateDialog::loadP12File);
connect(m_ui->plainTextEditKey, &QPlainTextEdit::textChanged, this, &ImportCertificateDialog::keyChanged);
connect(m_ui->plainTextEditCert, &QPlainTextEdit::textChanged, this, &ImportCertificateDialog::certChanged);
m_ui->labelSupportsSslValue->setText(QSslSocket::supportsSsl() ? tr("Yes") : tr("No"));
m_ui->labelSslLibraryVersionValue->setText(QSslSocket::sslLibraryVersionString());
m_ui->labelSslLibraryBuildVersionValue->setText(QSslSocket::sslLibraryBuildVersionString());
const auto &availableBackends = QSslSocket::availableBackends();
for (const auto &backend : availableBackends)
m_ui->comboBoxSslBackend->addItem(backend);
m_ui->comboBoxSslBackend->setCurrentText(QSslSocket::activeBackend());
connect(m_ui->comboBoxSslBackend, &QComboBox::currentIndexChanged,
this, &ImportCertificateDialog::updateActiveBackend);
}
ImportCertificateDialog::~ImportCertificateDialog() = default;
void ImportCertificateDialog::accept()
{
if (m_key.isNull())
return;
if (m_cert.isNull())
return;
QDialog::accept();
}
void ImportCertificateDialog::loadP12File()
{
auto selected = QFileDialog::getOpenFileName(this, tr("Select certificate..."), {}, "Certificates (*.p12)");
if (selected.isEmpty())
return;
QFile file{selected};
if (!file.open(QIODevice::ReadOnly))
{
QMessageBox::warning(this, tr("Could not open file!"), tr("Could not open file!") + "\n\n" + file.errorString());
return;
}
bool ok{};
QString passwordStr = QInputDialog::getText(this, tr("Please enter password"), tr("Certificate password:"), QLineEdit::PasswordEchoOnEdit, {}, &ok);
if (!ok)
return;
auto password = passwordStr.toUtf8();
QSslKey key;
QSslCertificate cert;
QList<QSslCertificate> certChain;
#ifdef HAS_OPENSSL
if (QSslSocket::activeBackend() == "openssl" && !legacy)
{
legacy = OSSL_PROVIDER_load(NULL, "legacy");
if (!legacy)
QMessageBox::warning(this, tr("Failed to load openssl legacy provider!"), tr("Failed to load openssl legacy provider!"));
}
#endif
if (!QSslCertificate::importPkcs12(&file, &key, &cert, &certChain, password))
{
QMessageBox::warning(this, tr("Failed processing certificate!"), tr("Failed processing certificate!") + "\n\n" + tr("Possible reasons: openssl has a problem, the file is corrupt/invalid or the password is incorrect."));
return;
}
if (key.isNull())
{
QMessageBox::warning(this, tr("Failed processing certificate!"), tr("Failed processing certificate!") + "\n\n" + tr("The key seems to be invalid."));
return;
}
if (cert.isNull())
{
QMessageBox::warning(this, tr("Failed processing certificate!"), tr("Failed processing certificate!") + "\n\n" + tr("The cert seems to be invalid."));
return;
}
m_key = std::move(key);
m_cert = std::move(cert);
{
QSignalBlocker blocker{m_ui->plainTextEditKey};
m_ui->plainTextEditKey->setPlainText(m_key.toPem());
}
{
auto palette = m_ui->plainTextEditKey->palette();
palette.setBrush(QPalette::Base, QColor{200, 255, 200});
palette.setBrush(QPalette::Window, QColor{200, 255, 200});
m_ui->plainTextEditKey->setPalette(palette);
}
{
QSignalBlocker blocker{m_ui->plainTextEditCert};
m_ui->plainTextEditCert->setPlainText(m_cert.toPem());
}
{
auto palette = m_ui->plainTextEditCert->palette();
palette.setBrush(QPalette::Base, QColor{200, 255, 200});
palette.setBrush(QPalette::Window, QColor{200, 255, 200});
m_ui->plainTextEditCert->setPalette(palette);
}
}
void ImportCertificateDialog::keyChanged()
{
m_key = QSslKey{m_ui->plainTextEditKey->toPlainText().toUtf8(), QSsl::KeyAlgorithm::Rsa, QSsl::Pem};
auto palette = m_ui->plainTextEditKey->palette();
palette.setBrush(QPalette::Base, m_key.isNull() ? QColor{255, 200, 200} : QColor{200, 255, 200});
palette.setBrush(QPalette::Window, m_key.isNull() ? QColor{255, 200, 200} : QColor{200, 255, 200});
m_ui->plainTextEditKey->setPalette(palette);
}
void ImportCertificateDialog::certChanged()
{
m_cert = QSslCertificate{m_ui->plainTextEditCert->toPlainText().toUtf8()};
auto palette = m_ui->plainTextEditCert->palette();
palette.setBrush(QPalette::Base, m_cert.isNull() ? QColor{255, 200, 200} : QColor{200, 255, 200});
palette.setBrush(QPalette::Window, m_cert.isNull() ? QColor{255, 200, 200} : QColor{200, 255, 200});
m_ui->plainTextEditCert->setPalette(palette);
}
void ImportCertificateDialog::updateActiveBackend()
{
if (!QSslSocket::setActiveBackend(m_ui->comboBoxSslBackend->currentText()))
QMessageBox::warning(this, tr("Could not change active backend"), tr("Could not change active backend"));
m_ui->comboBoxSslBackend->setCurrentText(QSslSocket::activeBackend());
}
-36
View File
@@ -1,36 +0,0 @@
#pragma once
#include <QDialog>
#include <QSslKey>
#include <QSslCertificate>
#include <memory>
namespace Ui { class ImportCertificateDialog; }
class ImportCertificateDialog : public QDialog
{
Q_OBJECT
public:
explicit ImportCertificateDialog(QWidget *parent = nullptr);
~ImportCertificateDialog();
const QSslKey &privateKey() const { return m_key; }
const QSslCertificate &privateCert() const { return m_cert; }
public slots:
void accept() override;
private slots:
void loadP12File();
void keyChanged();
void certChanged();
void updateActiveBackend();
private:
const std::unique_ptr<Ui::ImportCertificateDialog> m_ui;
QSslKey m_key;
QSslCertificate m_cert;
};
-184
View File
@@ -1,184 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ImportCertificateDialog</class>
<widget class="QDialog" name="ImportCertificateDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>459</width>
<height>429</height>
</rect>
</property>
<property name="windowTitle">
<string>Import Certificate</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="labelSupportsSsl">
<property name="text">
<string>Supports Ssl:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="labelSupportsSslValue">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="labelSslLibraryVersion">
<property name="text">
<string>Ssl Library Version:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="labelSslLibraryVersionValue">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="labelSslLibraryBuildVersion">
<property name="text">
<string>Ssl Library Build Version:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="labelSslLibraryBuildVersionValue">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="labelSslBackend">
<property name="text">
<string>Ssl Backend:</string>
</property>
<property name="buddy">
<cstring>comboBoxSslBackend</cstring>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QComboBox" name="comboBoxSslBackend"/>
</item>
<item row="4" column="0">
<widget class="QLabel" name="labelAutomaticImport">
<property name="text">
<string>Automatic Import:</string>
</property>
<property name="buddy">
<cstring>pushButtonImport</cstring>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QPushButton" name="pushButtonImport">
<property name="text">
<string>Load p12 file...</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="labelPrivateKey">
<property name="text">
<string>Private Key:</string>
</property>
<property name="buddy">
<cstring>plainTextEditKey</cstring>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QPlainTextEdit" name="plainTextEditKey">
<property name="autoFillBackground">
<bool>true</bool>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="labelPrivateCert">
<property name="text">
<string>Private Cert:</string>
</property>
<property name="buddy">
<cstring>plainTextEditCert</cstring>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QPlainTextEdit" name="plainTextEditCert">
<property name="autoFillBackground">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="labelWarning">
<property name="text">
<string>Warning: Your private key and cert will be stored on this machine, but can later be erased from the main window.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Save</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>ImportCertificateDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>ImportCertificateDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>
@@ -0,0 +1,89 @@
#include "importcredentialsdialog.h"
#include "ui_importcredentialsdialog.h"
#include <QMessageBox>
#include <QPushButton>
#include "deviceconnection.h"
ImportCredentialsDialog::ImportCredentialsDialog(QWidget *parent) :
QDialog{parent},
m_ui{std::make_unique<Ui::ImportCredentialsDialog>()}
{
m_ui->setupUi(this);
}
ImportCredentialsDialog::~ImportCredentialsDialog() = default;
QByteArray ImportCredentialsDialog::username() const
{
return m_ui->lineEditUsername->text().toUtf8();
}
QByteArray ImportCredentialsDialog::password() const
{
return m_ui->lineEditPassword->text().toUtf8();
}
void ImportCredentialsDialog::accept()
{
if (username().isEmpty() ||
password().isEmpty())
{
QMessageBox::warning(this, tr("Please fill out all fields!"), tr("Please fill out all fields!"));
return;
}
m_ui->lineEditUsername->setEnabled(false);
m_ui->lineEditPassword->setEnabled(false);
if (auto button = m_ui->buttonBox->button(QDialogButtonBox::Save))
button->setEnabled(false);
m_testConnection = std::make_unique<DeviceConnection>(username(), password(), "123456");
connect(m_testConnection.get(), &DeviceConnection::connectedSignal,
this, &ImportCredentialsDialog::connected);
connect(m_testConnection.get(), &DeviceConnection::disconnectedSignal,
this, &ImportCredentialsDialog::disconnected);
connect(m_testConnection.get(), &DeviceConnection::errorOccurredSignal,
this, &ImportCredentialsDialog::errorOccurred);
m_testConnection->start();
}
void ImportCredentialsDialog::connected()
{
qDebug() << "called";
QDialog::accept();
finishTestConnection();
}
void ImportCredentialsDialog::disconnected()
{
qDebug() << "called";
finishTestConnection();
}
void ImportCredentialsDialog::errorOccurred(QAbstractSocket::SocketError error)
{
Q_ASSERT(m_testConnection);
QMessageBox::warning(this,
tr("Problem verifying credentials!"),
QString("%0\n\n%1")
.arg(QMetaEnum::fromType<QAbstractSocket::SocketError>().valueToKey(error))
.arg(m_testConnection->errorString())
);
}
void ImportCredentialsDialog::finishTestConnection()
{
Q_ASSERT(m_testConnection);
m_ui->lineEditUsername->setEnabled(true);
m_ui->lineEditPassword->setEnabled(true);
if (auto button = m_ui->buttonBox->button(QDialogButtonBox::Save))
button->setEnabled(true);
m_testConnection.release()->deleteLater();
}
+35
View File
@@ -0,0 +1,35 @@
#pragma once
#include <QDialog>
#include <QAbstractSocket>
#include <memory>
namespace Ui { class ImportCredentialsDialog; }
class DeviceConnection;
class ImportCredentialsDialog : public QDialog
{
Q_OBJECT
public:
explicit ImportCredentialsDialog(QWidget *parent = nullptr);
~ImportCredentialsDialog();
QByteArray username() const;
QByteArray password() const;
public slots:
void accept() override;
private slots:
void connected();
void disconnected();
void errorOccurred(QAbstractSocket::SocketError error);
private:
void finishTestConnection();
const std::unique_ptr<Ui::ImportCredentialsDialog> m_ui;
std::unique_ptr<DeviceConnection> m_testConnection;
};
+114
View File
@@ -0,0 +1,114 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ImportCredentialsDialog</class>
<widget class="QDialog" name="ImportCredentialsDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>442</width>
<height>164</height>
</rect>
</property>
<property name="windowTitle">
<string>Import Credentials</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="labelTitle">
<property name="text">
<string>Please enter your credentials to access solalaweb.com:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Please create an app password in &lt;a href=&quot;https://auth.go-e.com/if/user/#/settings;{%22page%22:%22page-tokens%22}&quot;&gt;our SSO&lt;/a&gt;.</string>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::TextInteractionFlag::TextBrowserInteraction</set>
</property>
</widget>
</item>
<item>
<layout class="QFormLayout" name="formLayout">
<item row="1" column="0">
<widget class="QLabel" name="labelUsername">
<property name="text">
<string>Username:</string>
</property>
<property name="buddy">
<cstring>lineEditUsername</cstring>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="labelPassword">
<property name="text">
<string>App-Password:</string>
</property>
<property name="buddy">
<cstring>lineEditPassword</cstring>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="lineEditUsername"/>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="lineEditPassword"/>
</item>
</layout>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Save</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>ImportCredentialsDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>ImportCredentialsDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>
+14 -37
View File
@@ -1,14 +1,9 @@
#include <QApplication>
#include <QMessageBox>
#include <QDebug>
#include <QSslKey>
#include <QSslCertificate>
#ifdef Q_OS_WIN
#include <QSslSocket>
#endif
#include "flottenupdatersettings.h"
#include "importcertificatedialog.h"
#include "importcredentialsdialog.h"
#include "mainwindow.h"
int main(int argc, char *argv[])
@@ -36,50 +31,32 @@ int main(int argc, char *argv[])
#endif
FlottenUpdaterSettings settings;
QByteArray keyBuf = settings.privateKey();
QByteArray certBuf = settings.privateCert();
QSslKey key{keyBuf, QSsl::KeyAlgorithm::Rsa, QSsl::Pem};
QSslCertificate cert{certBuf};
QByteArray username = settings.username();
QByteArray password = settings.password();
if (keyBuf.isEmpty())
goto loadCert;
if (username.isEmpty())
goto loadCredentials;
if (certBuf.isEmpty())
goto loadCert;
if (key.isNull())
{
QMessageBox::warning(nullptr,
QCoreApplication::translate("main", "Could not parse private key!"),
QCoreApplication::translate("main", "Could not parse private key!"));
goto loadCert;
}
if (cert.isNull())
{
QMessageBox::warning(nullptr,
QCoreApplication::translate("main", "Could not parse private cert!"),
QCoreApplication::translate("main", "Could not parse private cert!"));
goto loadCert;
}
if (password.isEmpty())
goto loadCredentials;
goto showMainWindow;
{
loadCert:
ImportCertificateDialog dialog;
loadCredentials:
ImportCredentialsDialog dialog;
if (dialog.exec() != QDialog::Accepted)
return 0;
key = dialog.privateKey();
cert = dialog.privateCert();
settings.setPrivateKey(key.toPem());
settings.setPrivateCert(cert.toPem());
username = dialog.username();
password = dialog.password();
settings.setUsername(username);
settings.setPassword(password);
}
showMainWindow:
MainWindow mainWindow{settings, key, cert};
MainWindow mainWindow{settings, username, password};
mainWindow.show();
return app.exec();
+4 -4
View File
@@ -18,12 +18,12 @@
#include "setarbitraryapikeydialog.h"
#include "addserialsrangedialog.h"
MainWindow::MainWindow(FlottenUpdaterSettings &settings, const QSslKey &key,
const QSslCertificate &cert, QWidget *parent) :
MainWindow::MainWindow(FlottenUpdaterSettings &settings, const QByteArray &username,
const QByteArray &password, QWidget *parent) :
QMainWindow{parent},
m_ui{std::make_unique<Ui::MainWindow>()},
m_settings{settings},
m_model{std::make_unique<DevicesModel>(settings, key, cert, this)},
m_model{std::make_unique<DevicesModel>(settings, username, password, this)},
m_proxyModel{std::make_unique<QSortFilterProxyModel>(this)}
{
m_ui->setupUi(this);
@@ -146,7 +146,7 @@ void MainWindow::contextMenuRequested(const QPoint &pos)
[&](const QModelIndex &index){ return m_proxyModel->mapToSource(index); });
// get all the devices for selected indices
std::vector<std::shared_ptr<DevicesConnection>> devices;
std::vector<std::shared_ptr<DeviceConnection>> devices;
devices.reserve(selectedRows.size());
std::transform(std::begin(selectedRows), std::end(selectedRows), std::back_inserter(devices),
[&](const QModelIndex &index){ auto device = m_model->getDevice(index); Q_ASSERT(device); return device; });
+2 -2
View File
@@ -18,8 +18,8 @@ class MainWindow : public QMainWindow
Q_OBJECT
public:
explicit MainWindow(FlottenUpdaterSettings &settings, const QSslKey &key,
const QSslCertificate &cert, QWidget *parent = nullptr);
explicit MainWindow(FlottenUpdaterSettings &settings, const QByteArray &username,
const QByteArray &password, QWidget *parent = nullptr);
~MainWindow() override;
private slots:
+1 -1
View File
@@ -7,7 +7,7 @@
#include "deviceconnection.h"
#include "requestmodel.h"
RequestDialog::RequestDialog(QJsonObject &&msg, std::vector<std::shared_ptr<DevicesConnection>> &&devices, QWidget *parent) :
RequestDialog::RequestDialog(QJsonObject &&msg, std::vector<std::shared_ptr<DeviceConnection>> &&devices, QWidget *parent) :
QDialog{parent},
m_ui{std::make_unique<Ui::RequestDialog>()},
m_model{std::make_unique<RequestModel>(std::move(msg), std::move(devices), this)}
+2 -2
View File
@@ -5,7 +5,7 @@
#include <memory>
class QJsonObject;
class DevicesConnection;
class DeviceConnection;
class RequestModel;
namespace Ui { class RequestDialog; }
@@ -15,7 +15,7 @@ class RequestDialog : public QDialog
Q_OBJECT
public:
explicit RequestDialog(QJsonObject &&msg, std::vector<std::shared_ptr<DevicesConnection>> &&devices, QWidget *parent = nullptr);
explicit RequestDialog(QJsonObject &&msg, std::vector<std::shared_ptr<DeviceConnection>> &&devices, QWidget *parent = nullptr);
~RequestDialog();
private:
+2 -2
View File
@@ -21,7 +21,7 @@ enum {
QString getRandomString();
}
RequestModel::RequestModel(QJsonObject &&msg, std::vector<std::shared_ptr<DevicesConnection>> &&devices, QObject *parent) :
RequestModel::RequestModel(QJsonObject &&msg, std::vector<std::shared_ptr<DeviceConnection>> &&devices, QObject *parent) :
QAbstractTableModel{parent}
{
m_requests.reserve(devices.size());
@@ -33,7 +33,7 @@ RequestModel::RequestModel(QJsonObject &&msg, std::vector<std::shared_ptr<Device
.requestId = getRandomString()
};
connect(request.device.get(), &DevicesConnection::responseReceived, this, &RequestModel::responseReceived);
connect(request.device.get(), &DeviceConnection::responseReceived, this, &RequestModel::responseReceived);
{
QJsonObject msg2 = msg;
+3 -3
View File
@@ -6,14 +6,14 @@
#include <memory>
class QJsonObject;
class DevicesConnection;
class DeviceConnection;
class RequestModel : public QAbstractTableModel
{
Q_OBJECT
public:
explicit RequestModel(QJsonObject &&msg, std::vector<std::shared_ptr<DevicesConnection>> &&devices, QObject *parent = nullptr);
explicit RequestModel(QJsonObject &&msg, std::vector<std::shared_ptr<DeviceConnection>> &&devices, QObject *parent = nullptr);
~RequestModel() override;
// QAbstractItemModel interface
@@ -27,7 +27,7 @@ private slots:
private:
struct Request {
std::shared_ptr<DevicesConnection> device;
std::shared_ptr<DeviceConnection> device;
QString requestId;
enum class Status { Pending, Failed, Succeeded };
Status status{Status::Pending};