From 91b6a6141dd08a3842597b9740c37db52ced1f4e Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Tue, 9 Oct 2018 16:24:30 +0200 Subject: [PATCH] server interface settings upcoming --- libnymea-app-core/basicconfiguration.cpp | 111 --------- libnymea-app-core/basicconfiguration.h | 54 ----- .../configuration/basicconfiguration.cpp | 228 ++++++++++++++++++ .../configuration/basicconfiguration.h | 98 ++++++++ .../configuration/serverconfiguration.cpp | 37 +++ .../configuration/serverconfiguration.h | 33 +++ .../configuration/serverconfigurations.cpp | 59 +++++ .../configuration/serverconfigurations.h | 41 ++++ .../connection/nymeaconnection.cpp | 5 + .../connection/nymeaconnection.h | 6 +- libnymea-app-core/devicemanager.cpp | 2 +- libnymea-app-core/engine.cpp | 2 +- libnymea-app-core/jsonrpc/jsonrpcclient.cpp | 4 +- libnymea-app-core/libnymea-app-core.h | 2 +- libnymea-app-core/libnymea-app-core.pro | 12 +- nymea-app/resources.qrc | 2 + nymea-app/ui/SettingsPage.qml | 208 ++++++++++------ .../ui/components/MeaListItemDelegate.qml | 3 + .../ui/system/ConnectionInterfaceDelegate.qml | 25 ++ .../ui/system/ConnectionInterfacesPage.qml | 63 +++++ 20 files changed, 741 insertions(+), 254 deletions(-) delete mode 100644 libnymea-app-core/basicconfiguration.cpp delete mode 100644 libnymea-app-core/basicconfiguration.h create mode 100644 libnymea-app-core/configuration/basicconfiguration.cpp create mode 100644 libnymea-app-core/configuration/basicconfiguration.h create mode 100644 libnymea-app-core/configuration/serverconfiguration.cpp create mode 100644 libnymea-app-core/configuration/serverconfiguration.h create mode 100644 libnymea-app-core/configuration/serverconfigurations.cpp create mode 100644 libnymea-app-core/configuration/serverconfigurations.h create mode 100644 nymea-app/ui/system/ConnectionInterfaceDelegate.qml create mode 100644 nymea-app/ui/system/ConnectionInterfacesPage.qml diff --git a/libnymea-app-core/basicconfiguration.cpp b/libnymea-app-core/basicconfiguration.cpp deleted file mode 100644 index b158a82e..00000000 --- a/libnymea-app-core/basicconfiguration.cpp +++ /dev/null @@ -1,111 +0,0 @@ -#include "basicconfiguration.h" - -#include "jsonrpc/jsonrpcclient.h" - -BasicConfiguration::BasicConfiguration(JsonRpcClient* client, QObject *parent) : - JsonHandler(parent), - m_client(client) -{ - client->registerNotificationHandler(this, "notificationReceived"); -} - -QString BasicConfiguration::nameSpace() const -{ - return "Configuration"; -} - -bool BasicConfiguration::debugServerEnabled() const -{ - return m_debugServerEnabled; -} - -void BasicConfiguration::setDebugServerEnabled(bool debugServerEnabled) -{ - QVariantMap params; - params.insert("enabled", debugServerEnabled); - m_client->sendCommand("Configuration.SetDebugServerEnabled", params, this, "setDebugServerEnabledResponse"); -} - -QString BasicConfiguration::serverName() const -{ - return m_serverName; -} - -void BasicConfiguration::setServerName(const QString &serverName) -{ - QVariantMap params; - params.insert("serverName", serverName); - m_client->sendCommand("Configuration.SetServerName", params, this, "setServerNameResponse"); -} - -bool BasicConfiguration::cloudEnabled() const -{ - return m_cloudEnabled; -} - -void BasicConfiguration::setCloudEnabled(bool cloudEnabled) -{ - QVariantMap params; - params.insert("enabled", cloudEnabled); - m_client->sendCommand("Configuration.SetCloudEnabled", params, this, "setCloudEnabledResponse"); -} - -void BasicConfiguration::init() -{ - m_client->sendCommand("Configuration.GetConfigurations", this, "getConfigurationsResponse"); -} - -void BasicConfiguration::getConfigurationsResponse(const QVariantMap ¶ms) -{ -// qDebug() << "have config reply" << params; - QVariantMap basicConfig = params.value("params").toMap().value("basicConfiguration").toMap(); - m_debugServerEnabled = basicConfig.value("debugServerEnabled").toBool(); - emit debugServerEnabledChanged(); - m_serverName = basicConfig.value("serverName").toString(); - emit serverNameChanged(); - QVariantMap cloudConfig = params.value("params").toMap().value("cloud").toMap(); - m_cloudEnabled = cloudConfig.value("enabled").toBool(); - emit cloudEnabledChanged(); -} - -void BasicConfiguration::getCloudConfigurationResponse(const QVariantMap ¶ms) -{ - qDebug() << "Cloud config reply" << params; -} - -void BasicConfiguration::setDebugServerEnabledResponse(const QVariantMap ¶ms) -{ - qDebug() << "Debug server set:" << params; -} - -void BasicConfiguration::setServerNameResponse(const QVariantMap ¶ms) -{ - qDebug() << "Server name set:" << params; -} - -void BasicConfiguration::setCloudEnabledResponse(const QVariantMap ¶ms) -{ - qDebug() << "Set cloud enabled:" << params; -} - -void BasicConfiguration::notificationReceived(const QVariantMap ¬ification) -{ - QString notif = notification.value("notification").toString(); - if (notif == "Configuration.BasicConfigurationChanged") { - QVariantMap params = notification.value("params").toMap().value("basicConfiguration").toMap(); - qDebug() << "notif" << params; - m_debugServerEnabled = params.value("debugServerEnabled").toBool(); - emit debugServerEnabled(); - m_serverName = params.value("serverName").toString(); - emit serverNameChanged(); - return; - } - if (notif == "Configuration.CloudConfigurationChanged") { - QVariantMap params = notification.value("params").toMap().value("cloudConfiguration").toMap(); - qDebug() << "notif" << params; - m_cloudEnabled = params.value("enabled").toBool(); - emit cloudEnabledChanged(); - return; - } - qDebug() << "Unhandled Configuration notification" << notif; -} diff --git a/libnymea-app-core/basicconfiguration.h b/libnymea-app-core/basicconfiguration.h deleted file mode 100644 index 64ddcc7e..00000000 --- a/libnymea-app-core/basicconfiguration.h +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef BASICCONFIGURATION_H -#define BASICCONFIGURATION_H - -#include -#include "jsonrpc/jsonhandler.h" - -class JsonRpcClient; - -class BasicConfiguration : public JsonHandler -{ - Q_OBJECT - Q_PROPERTY(bool debugServerEnabled READ debugServerEnabled WRITE setDebugServerEnabled NOTIFY debugServerEnabledChanged) - Q_PROPERTY(QString serverName READ serverName WRITE setServerName NOTIFY serverNameChanged) - - Q_PROPERTY(bool cloudEnabled READ cloudEnabled WRITE setCloudEnabled NOTIFY cloudEnabledChanged) - -public: - explicit BasicConfiguration(JsonRpcClient* client, QObject *parent = nullptr); - - QString nameSpace() const override; - - bool debugServerEnabled() const; - void setDebugServerEnabled(bool debugServerEnabled); - - QString serverName() const; - void setServerName(const QString &serverName); - - bool cloudEnabled() const; - void setCloudEnabled(bool cloudEnabled); - - void init(); - -private: - Q_INVOKABLE void getConfigurationsResponse(const QVariantMap ¶ms); - Q_INVOKABLE void getCloudConfigurationResponse(const QVariantMap ¶ms); - Q_INVOKABLE void setDebugServerEnabledResponse(const QVariantMap ¶ms); - Q_INVOKABLE void setServerNameResponse(const QVariantMap ¶ms); - Q_INVOKABLE void setCloudEnabledResponse(const QVariantMap ¶ms); - - Q_INVOKABLE void notificationReceived(const QVariantMap ¬ification); - -signals: - void debugServerEnabledChanged(); - void serverNameChanged(); - void cloudEnabledChanged(); - -private: - JsonRpcClient* m_client = nullptr; - bool m_debugServerEnabled = false; - QString m_serverName; - bool m_cloudEnabled = false; -}; - -#endif // BASICCONFIGURATION_H diff --git a/libnymea-app-core/configuration/basicconfiguration.cpp b/libnymea-app-core/configuration/basicconfiguration.cpp new file mode 100644 index 00000000..eeec7685 --- /dev/null +++ b/libnymea-app-core/configuration/basicconfiguration.cpp @@ -0,0 +1,228 @@ +#include "basicconfiguration.h" +#include "serverconfiguration.h" + +#include "jsonrpc/jsonrpcclient.h" + +BasicConfiguration::BasicConfiguration(JsonRpcClient* client, QObject *parent) : + JsonHandler(parent), + m_client(client), + m_tcpServerConfigurations(new ServerConfigurations(this)), + m_websocketServerConfigurations(new ServerConfigurations(this)) +{ + client->registerNotificationHandler(this, "notificationReceived"); +} + +QString BasicConfiguration::nameSpace() const +{ + return "Configuration"; +} + +bool BasicConfiguration::debugServerEnabled() const +{ + return m_debugServerEnabled; +} + +void BasicConfiguration::setDebugServerEnabled(bool debugServerEnabled) +{ + QVariantMap params; + params.insert("enabled", debugServerEnabled); + m_client->sendCommand("Configuration.SetDebugServerEnabled", params, this, "setDebugServerEnabledResponse"); +} + +QString BasicConfiguration::serverName() const +{ + return m_serverName; +} + +void BasicConfiguration::setServerName(const QString &serverName) +{ + QVariantMap params; + params.insert("serverName", serverName); + m_client->sendCommand("Configuration.SetServerName", params, this, "setServerNameResponse"); +} + +bool BasicConfiguration::cloudEnabled() const +{ + return m_cloudEnabled; +} + +void BasicConfiguration::setCloudEnabled(bool cloudEnabled) +{ + QVariantMap params; + params.insert("enabled", cloudEnabled); + m_client->sendCommand("Configuration.SetCloudEnabled", params, this, "setCloudEnabledResponse"); +} + +QString BasicConfiguration::language() const +{ + return m_language; +} + +void BasicConfiguration::setLanguage(const QString &language) +{ + QVariantMap params; + params.insert("language", language); + m_client->sendCommand("Configuration.SetLanguage", params); +} + +QString BasicConfiguration::timezone() const +{ + return m_timezone; +} + +void BasicConfiguration::setTimezone(const QString &timezone) +{ + QVariantMap params; + params.insert("timeZone", timezone); + m_client->sendCommand("Configuration.SetTimeZone", params, this, "setTimezoneResponse"); +} + +QStringList BasicConfiguration::timezones() const +{ + return m_timezones; +} + +ServerConfigurations *BasicConfiguration::tcpServerConfigurations() const +{ + return m_tcpServerConfigurations; +} + +ServerConfigurations *BasicConfiguration::websocketServerConfigurations() const +{ + return m_websocketServerConfigurations; +} + +void BasicConfiguration::setTcpServerConfiguration(ServerConfiguration *configuration) const +{ + QVariantMap params; + params.insert("id", configuration->id()); + params.insert("address", configuration->address()); + params.insert("port", configuration->address()); + params.insert("authentiactionEnabled", configuration->authenticationEnabled()); + params.insert("sslEnabled", configuration->sslEnabled()); + m_client->sendCommand("Configuration.SetTcpServerConfiguration", params); +} + +void BasicConfiguration::deleteTcpServerConfiguration(const QString &id) const +{ + QVariantMap params; + params.insert("id", id); + m_client->sendCommand("Configuration.DeleteTcpServerConfiguration", params, this, "deleteTcpConfigReply"); +} + +void BasicConfiguration::deleteWebsocketServerConfiguration(const QString &id) const +{ + QVariantMap params; + params.insert("id", id); + m_client->sendCommand("Configuration.DeleteWebSocketServerConfiguration", params, this, "deleteWebSocketConfigReply"); +} + +QStringList BasicConfiguration::availableLanguages() const +{ + return m_availableLanguages; +} + +void BasicConfiguration::init() +{ + m_client->sendCommand("Configuration.GetConfigurations", this, "getConfigurationsResponse"); + m_client->sendCommand("Configuration.GetAvailableLanguages", this, "getAvailableLanguagesResponse"); + m_client->sendCommand("Configuration.GetTimeZones", this, "getTimezonesResponse"); +} + +void BasicConfiguration::getConfigurationsResponse(const QVariantMap ¶ms) +{ + qDebug() << "have config reply" << params; + QVariantMap basicConfig = params.value("params").toMap().value("basicConfiguration").toMap(); + m_debugServerEnabled = basicConfig.value("debugServerEnabled").toBool(); + emit debugServerEnabledChanged(); + m_serverName = basicConfig.value("serverName").toString(); + emit serverNameChanged(); + m_language = basicConfig.value("language").toString(); + emit languageChanged(); + m_timezone = basicConfig.value("timeZone").toString(); + emit timezoneChanged(); + QVariantMap cloudConfig = params.value("params").toMap().value("cloud").toMap(); + m_cloudEnabled = cloudConfig.value("enabled").toBool(); + emit cloudEnabledChanged(); + + tcpServerConfigurations()->clear(); + foreach (const QVariant &tcpServerVariant, params.value("params").toMap().value("tcpServerConfigurations").toList()) { + qDebug() << "tcp server config:" << tcpServerVariant; + QVariantMap tcpConfigMap = tcpServerVariant.toMap(); + ServerConfiguration *config = new ServerConfiguration(tcpConfigMap.value("id").toString(), QHostAddress(tcpConfigMap.value("address").toString()), tcpConfigMap.value("port").toInt(), tcpConfigMap.value("authenticationEnabled").toBool(), tcpConfigMap.value("sslEnabled").toBool()); + m_tcpServerConfigurations->addConfiguration(config); + } + websocketServerConfigurations()->clear(); + foreach (const QVariant &websocketServerVariant, params.value("params").toMap().value("webSocketServerConfigurations").toList()) { + QVariantMap websocketConfigMap = websocketServerVariant.toMap(); + ServerConfiguration *config = new ServerConfiguration(websocketConfigMap.value("id").toString(), QHostAddress(websocketConfigMap.value("address").toString()), websocketConfigMap.value("port").toInt(), websocketConfigMap.value("authenticationEnabled").toBool(), websocketConfigMap.value("sslEnabled").toBool()); + m_websocketServerConfigurations->addConfiguration(config); + } +} + +void BasicConfiguration::getCloudConfigurationResponse(const QVariantMap ¶ms) +{ + qDebug() << "Cloud config reply" << params; +} + +void BasicConfiguration::setDebugServerEnabledResponse(const QVariantMap ¶ms) +{ + qDebug() << "Debug server set:" << params; +} + +void BasicConfiguration::setServerNameResponse(const QVariantMap ¶ms) +{ + qDebug() << "Server name set:" << params; +} + +void BasicConfiguration::setCloudEnabledResponse(const QVariantMap ¶ms) +{ + qDebug() << "Set cloud enabled:" << params; +} + +void BasicConfiguration::getAvailableLanguagesResponse(const QVariantMap ¶ms) +{ +// qDebug() << "Get available languages response" << params; + m_availableLanguages = params.value("params").toMap().value("languages").toStringList(); + emit availableLanguagesChanged(); +} + +void BasicConfiguration::getTimezonesResponse(const QVariantMap ¶ms) +{ +// qDebug() << "Get timezones response" << params; + m_timezones = params.value("params").toMap().value("timeZones").toStringList(); + emit timezonesChanged(); +} + +void BasicConfiguration::setTimezoneResponse(const QVariantMap ¶ms) +{ + qDebug() << "Set timezones response" << params; +} + +void BasicConfiguration::deleteTcpConfigReply(const QVariantMap ¶ms) +{ + if (params.value("params").toMap().value("configurationError").toString() == "ConfigurationErrorNoError") { + } +} + +void BasicConfiguration::notificationReceived(const QVariantMap ¬ification) +{ + QString notif = notification.value("notification").toString(); + if (notif == "Configuration.BasicConfigurationChanged") { + QVariantMap params = notification.value("params").toMap().value("basicConfiguration").toMap(); + qDebug() << "notif" << params; + m_debugServerEnabled = params.value("debugServerEnabled").toBool(); + emit debugServerEnabled(); + m_serverName = params.value("serverName").toString(); + emit serverNameChanged(); + return; + } + if (notif == "Configuration.CloudConfigurationChanged") { + QVariantMap params = notification.value("params").toMap().value("cloudConfiguration").toMap(); + qDebug() << "notif" << params; + m_cloudEnabled = params.value("enabled").toBool(); + emit cloudEnabledChanged(); + return; + } + qDebug() << "Unhandled Configuration notification" << notif; +} diff --git a/libnymea-app-core/configuration/basicconfiguration.h b/libnymea-app-core/configuration/basicconfiguration.h new file mode 100644 index 00000000..304a1c25 --- /dev/null +++ b/libnymea-app-core/configuration/basicconfiguration.h @@ -0,0 +1,98 @@ +#ifndef BASICCONFIGURATION_H +#define BASICCONFIGURATION_H + +#include +#include "jsonrpc/jsonhandler.h" +#include "serverconfigurations.h" + +class JsonRpcClient; + +class BasicConfiguration : public JsonHandler +{ + Q_OBJECT + Q_PROPERTY(bool debugServerEnabled READ debugServerEnabled WRITE setDebugServerEnabled NOTIFY debugServerEnabledChanged) + Q_PROPERTY(QString serverName READ serverName WRITE setServerName NOTIFY serverNameChanged) + Q_PROPERTY(QString language READ language WRITE setLanguage NOTIFY languageChanged) + Q_PROPERTY(QString timezone READ timezone WRITE setTimezone NOTIFY timezoneChanged) + + Q_PROPERTY(bool cloudEnabled READ cloudEnabled NOTIFY cloudEnabledChanged) + + Q_PROPERTY(QStringList availableLanguages READ availableLanguages NOTIFY availableLanguagesChanged) + Q_PROPERTY(QStringList timezones READ timezones NOTIFY timezonesChanged) + + Q_PROPERTY(ServerConfigurations* tcpServerConfigurations READ tcpServerConfigurations CONSTANT) + Q_PROPERTY(ServerConfigurations* websocketServerConfigurations READ websocketServerConfigurations CONSTANT) + +public: + explicit BasicConfiguration(JsonRpcClient* client, QObject *parent = nullptr); + + QString nameSpace() const override; + + bool debugServerEnabled() const; + void setDebugServerEnabled(bool debugServerEnabled); + + QString serverName() const; + void setServerName(const QString &serverName); + + bool cloudEnabled() const; + void setCloudEnabled(bool cloudEnabled); + + QString language() const; + void setLanguage(const QString &language); + + QStringList availableLanguages() const; + + QString timezone() const; + void setTimezone(const QString &timezone); + + QStringList timezones() const; + + ServerConfigurations *tcpServerConfigurations() const; + ServerConfigurations *websocketServerConfigurations() const; + + void setTcpServerConfiguration(ServerConfiguration *configuration) const; + void setWebsocketServerConfiguration(ServerConfiguration *configuration) const; + + Q_INVOKABLE void deleteTcpServerConfiguration(const QString &id) const; + Q_INVOKABLE void deleteWebsocketServerConfiguration(const QString &id) const; + + void init(); + +private: + Q_INVOKABLE void getConfigurationsResponse(const QVariantMap ¶ms); + Q_INVOKABLE void getCloudConfigurationResponse(const QVariantMap ¶ms); + Q_INVOKABLE void setDebugServerEnabledResponse(const QVariantMap ¶ms); + Q_INVOKABLE void setServerNameResponse(const QVariantMap ¶ms); + Q_INVOKABLE void setCloudEnabledResponse(const QVariantMap ¶ms); + Q_INVOKABLE void getAvailableLanguagesResponse(const QVariantMap ¶ms); + Q_INVOKABLE void getTimezonesResponse(const QVariantMap ¶ms); + Q_INVOKABLE void setTimezoneResponse(const QVariantMap ¶ms); + Q_INVOKABLE void deleteTcpConfigReply(const QVariantMap ¶ms); + Q_INVOKABLE void deleteWebSocketConfigReply(const QVariantMap ¶ms); + + Q_INVOKABLE void notificationReceived(const QVariantMap ¬ification); + +signals: + void debugServerEnabledChanged(); + void serverNameChanged(); + void languageChanged(); + void availableLanguagesChanged(); + void timezoneChanged(); + void timezonesChanged(); + void cloudEnabledChanged(); + +private: + JsonRpcClient* m_client = nullptr; + bool m_debugServerEnabled = false; + QString m_serverName; + QString m_language; + QStringList m_availableLanguages; + QString m_timezone; + QStringList m_timezones; + bool m_cloudEnabled = false; + + ServerConfigurations *m_tcpServerConfigurations = nullptr; + ServerConfigurations *m_websocketServerConfigurations = nullptr; +}; + +#endif // BASICCONFIGURATION_H diff --git a/libnymea-app-core/configuration/serverconfiguration.cpp b/libnymea-app-core/configuration/serverconfiguration.cpp new file mode 100644 index 00000000..1c30454c --- /dev/null +++ b/libnymea-app-core/configuration/serverconfiguration.cpp @@ -0,0 +1,37 @@ +#include "serverconfiguration.h" + +ServerConfiguration::ServerConfiguration(const QString &id, const QHostAddress &address, int port, bool authEnabled, bool sslEnabled, QObject *parent): + QObject(parent), + m_id(id), + m_hostAddress(address), + m_port(port), + m_authEnabled(authEnabled), + m_sslEnabled(sslEnabled) +{ + +} + +QString ServerConfiguration::id() const +{ + return m_id; +} + +QString ServerConfiguration::address() const +{ + return m_hostAddress.toString(); +} + +int ServerConfiguration::port() const +{ + return m_port; +} + +bool ServerConfiguration::authenticationEnabled() const +{ + return m_authEnabled; +} + +bool ServerConfiguration::sslEnabled() const +{ + return m_sslEnabled; +} diff --git a/libnymea-app-core/configuration/serverconfiguration.h b/libnymea-app-core/configuration/serverconfiguration.h new file mode 100644 index 00000000..2f0c1d0f --- /dev/null +++ b/libnymea-app-core/configuration/serverconfiguration.h @@ -0,0 +1,33 @@ +#ifndef SERVERCONFIGURATION_H +#define SERVERCONFIGURATION_H + +#include +#include +#include + +class ServerConfiguration : public QObject +{ + Q_OBJECT + Q_PROPERTY(QString id READ id CONSTANT) + Q_PROPERTY(QString address READ address CONSTANT) + Q_PROPERTY(int port READ port CONSTANT) + Q_PROPERTY(bool authenticationEnabled READ authenticationEnabled CONSTANT) + Q_PROPERTY(bool sslEnabled READ sslEnabled CONSTANT) +public: + explicit ServerConfiguration(const QString &id, const QHostAddress &address, int port, bool authEnabled, bool sslEnabled, QObject *parent = nullptr); + + QString id() const; + QString address() const; + int port() const; + bool authenticationEnabled() const; + bool sslEnabled() const; + +private: + QString m_id; + QHostAddress m_hostAddress; + int m_port; + bool m_authEnabled; + bool m_sslEnabled; +}; + +#endif // SERVERCONFIGURATION_H diff --git a/libnymea-app-core/configuration/serverconfigurations.cpp b/libnymea-app-core/configuration/serverconfigurations.cpp new file mode 100644 index 00000000..40bf13d7 --- /dev/null +++ b/libnymea-app-core/configuration/serverconfigurations.cpp @@ -0,0 +1,59 @@ +#include "serverconfigurations.h" +#include "serverconfiguration.h" + +ServerConfigurations::ServerConfigurations(QObject *parent) : QAbstractListModel(parent) +{ + +} + +int ServerConfigurations::rowCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent) + return m_list.count(); +} + +QVariant ServerConfigurations::data(const QModelIndex &index, int role) const +{ + switch (role) { + case RoleId: + return m_list.at(index.row())->id(); + case RoleAddress: + return m_list.at(index.row())->address(); + case RolePort: + return m_list.at(index.row())->port(); + case RoleAuthenticationEnabled: + return m_list.at(index.row())->authenticationEnabled(); + case RoleSslEnabled: + return m_list.at(index.row())->sslEnabled(); + } + return QVariant(); +} + +QHash ServerConfigurations::roleNames() const +{ + QHash roles; + roles.insert(RoleId, "id"); + roles.insert(RoleAddress, "address"); + roles.insert(RolePort, "port"); + roles.insert(RoleAuthenticationEnabled, "authenticationEnabled"); + roles.insert(RoleSslEnabled, "sslEnabled"); + return roles; +} + +void ServerConfigurations::addConfiguration(ServerConfiguration *configuration) +{ + configuration->setParent(this); + beginInsertRows(QModelIndex(), m_list.count(), m_list.count()); + m_list.append(configuration); + endInsertRows(); + emit countChanged(); +} + +void ServerConfigurations::clear() +{ + beginResetModel(); + qDeleteAll(m_list); + m_list.clear(); + endResetModel(); + emit countChanged(); +} diff --git a/libnymea-app-core/configuration/serverconfigurations.h b/libnymea-app-core/configuration/serverconfigurations.h new file mode 100644 index 00000000..8695d52b --- /dev/null +++ b/libnymea-app-core/configuration/serverconfigurations.h @@ -0,0 +1,41 @@ +#ifndef SERVERCONFIGURATIONS_H +#define SERVERCONFIGURATIONS_H + +#include +#include + +class ServerConfiguration; + +class ServerConfigurations : public QAbstractListModel +{ + Q_OBJECT + Q_PROPERTY(int count READ rowCount NOTIFY countChanged) + +public: + enum Roles { + RoleId, + RoleAddress, + RolePort, + RoleAuthenticationEnabled, + RoleSslEnabled + }; + Q_ENUM(Roles) + + explicit ServerConfigurations(QObject *parent = nullptr); + + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + QVariant data(const QModelIndex &index, int role) const override; + QHash roleNames() const override; + + void addConfiguration(ServerConfiguration *configuration); + + void clear(); + +signals: + void countChanged(); + +private: + QList m_list; +}; + +#endif // SERVERCONFIGURATIONS_H diff --git a/libnymea-app-core/connection/nymeaconnection.cpp b/libnymea-app-core/connection/nymeaconnection.cpp index 0f7033f3..36f57efc 100644 --- a/libnymea-app-core/connection/nymeaconnection.cpp +++ b/libnymea-app-core/connection/nymeaconnection.cpp @@ -99,6 +99,11 @@ QString NymeaConnection::hostAddress() const return m_currentUrl.host(); } +int NymeaConnection::port() const +{ + return m_currentUrl.port(); +} + QString NymeaConnection::bluetoothAddress() const { QUrlQuery query(m_currentUrl); diff --git a/libnymea-app-core/connection/nymeaconnection.h b/libnymea-app-core/connection/nymeaconnection.h index c43fb76a..6bb0cda3 100644 --- a/libnymea-app-core/connection/nymeaconnection.h +++ b/libnymea-app-core/connection/nymeaconnection.h @@ -15,8 +15,9 @@ class NymeaConnection : public QObject Q_OBJECT Q_PROPERTY(bool connected READ connected NOTIFY connectedChanged) Q_PROPERTY(QString url READ url NOTIFY currentUrlChanged) - Q_PROPERTY(QString hostAddress READ hostAddress NOTIFY connectedChanged) - Q_PROPERTY(QString bluetoothAddress READ bluetoothAddress NOTIFY connectedChanged) + Q_PROPERTY(QString hostAddress READ hostAddress NOTIFY currentUrlChanged) + Q_PROPERTY(int port READ port NOTIFY currentUrlChanged) + Q_PROPERTY(QString bluetoothAddress READ bluetoothAddress NOTIFY currentUrlChanged) public: explicit NymeaConnection(QObject *parent = nullptr); @@ -32,6 +33,7 @@ public: QString url() const; QString hostAddress() const; + int port() const; QString bluetoothAddress() const; void sendData(const QByteArray &data); diff --git a/libnymea-app-core/devicemanager.cpp b/libnymea-app-core/devicemanager.cpp index 18b66f13..bd358724 100644 --- a/libnymea-app-core/devicemanager.cpp +++ b/libnymea-app-core/devicemanager.cpp @@ -238,7 +238,7 @@ void DeviceManager::getConfiguredDevicesResponse(const QVariantMap ¶ms) value.convert(QVariant::Int); } device->setStateValue(stateTypeId, value); - qDebug() << "Set device state value:" << device->stateValue(stateTypeId) << value; +// qDebug() << "Set device state value:" << device->stateValue(stateTypeId) << value; } devices()->addDevice(device); } diff --git a/libnymea-app-core/engine.cpp b/libnymea-app-core/engine.cpp index 8e6a83f3..c7f1129b 100644 --- a/libnymea-app-core/engine.cpp +++ b/libnymea-app-core/engine.cpp @@ -23,7 +23,7 @@ #include "rulemanager.h" #include "logmanager.h" #include "tagsmanager.h" -#include "basicconfiguration.h" +#include "configuration/basicconfiguration.h" #include "connection/awsclient.h" #include "connection/tcpsockettransport.h" diff --git a/libnymea-app-core/jsonrpc/jsonrpcclient.cpp b/libnymea-app-core/jsonrpc/jsonrpcclient.cpp index 69656d5d..eddce39f 100644 --- a/libnymea-app-core/jsonrpc/jsonrpcclient.cpp +++ b/libnymea-app-core/jsonrpc/jsonrpcclient.cpp @@ -303,7 +303,7 @@ void JsonRpcClient::sendRequest(const QVariantMap &request) { QVariantMap newRequest = request; newRequest.insert("token", m_token); -// qDebug() << "Sending request" << qUtf8Printable(QJsonDocument::fromVariant(newRequest).toJson()); + qDebug() << "Sending request" << qUtf8Printable(QJsonDocument::fromVariant(newRequest).toJson()); m_connection->sendData(QJsonDocument::fromVariant(newRequest).toJson(QJsonDocument::Compact) + "\n"); } @@ -340,7 +340,7 @@ void JsonRpcClient::dataReceived(const QByteArray &data) // qWarning() << "Could not parse json data from nymea" << m_receiveBuffer.left(splitIndex) << error.errorString(); return; } -// qDebug() << "received response" << qUtf8Printable(jsonDoc.toJson(QJsonDocument::Indented)); + qDebug() << "received response" << qUtf8Printable(jsonDoc.toJson(QJsonDocument::Indented)); m_receiveBuffer = m_receiveBuffer.right(m_receiveBuffer.length() - splitIndex - 1); if (!m_receiveBuffer.isEmpty()) { staticMetaObject.invokeMethod(this, "dataReceived", Qt::QueuedConnection, Q_ARG(QByteArray, QByteArray())); diff --git a/libnymea-app-core/libnymea-app-core.h b/libnymea-app-core/libnymea-app-core.h index 6e27fd5c..876578c8 100644 --- a/libnymea-app-core/libnymea-app-core.h +++ b/libnymea-app-core/libnymea-app-core.h @@ -35,7 +35,7 @@ #include "models/logsmodelng.h" #include "models/valuelogsproxymodel.h" #include "models/interfacesproxy.h" -#include "basicconfiguration.h" +#include "configuration/basicconfiguration.h" #include "wifisetup/networkmanagercontroler.h" #include "wifisetup/wirelessaccesspoint.h" #include "wifisetup/wirelessaccesspoints.h" diff --git a/libnymea-app-core/libnymea-app-core.pro b/libnymea-app-core/libnymea-app-core.pro index 451e2091..0a2f6509 100644 --- a/libnymea-app-core/libnymea-app-core.pro +++ b/libnymea-app-core/libnymea-app-core.pro @@ -55,7 +55,7 @@ SOURCES += \ models/valuelogsproxymodel.cpp \ discovery/nymeadiscovery.cpp \ logmanager.cpp \ - basicconfiguration.cpp \ + configuration/basicconfiguration.cpp \ wifisetup/bluetoothdevice.cpp \ wifisetup/bluetoothdeviceinfo.cpp \ wifisetup/bluetoothdeviceinfos.cpp \ @@ -78,7 +78,9 @@ SOURCES += \ discovery/bluetoothservicediscovery.cpp \ connection/cloudtransport.cpp \ connection/sigv4utils.cpp \ - ruletemplates/ruleactionparamtemplate.cpp + ruletemplates/ruleactionparamtemplate.cpp \ + configuration/serverconfiguration.cpp \ + configuration/serverconfigurations.cpp HEADERS += \ engine.h \ @@ -113,7 +115,7 @@ HEADERS += \ models/valuelogsproxymodel.h \ discovery/nymeadiscovery.h \ logmanager.h \ - basicconfiguration.h \ + configuration/basicconfiguration.h \ wifisetup/bluetoothdevice.h \ wifisetup/bluetoothdeviceinfo.h \ wifisetup/bluetoothdeviceinfos.h \ @@ -136,7 +138,9 @@ HEADERS += \ ruletemplates/statedescriptortemplate.h \ discovery/bluetoothservicediscovery.h \ connection/cloudtransport.h \ - ruletemplates/ruleactionparamtemplate.h + ruletemplates/ruleactionparamtemplate.h \ + configuration/serverconfiguration.h \ + configuration/serverconfigurations.h unix { target.path = /usr/lib diff --git a/nymea-app/resources.qrc b/nymea-app/resources.qrc index 4447fe24..63c24e04 100644 --- a/nymea-app/resources.qrc +++ b/nymea-app/resources.qrc @@ -268,5 +268,7 @@ ui/images/find.svg ui/images/erase.svg ui/components/ListFilterInput.qml + ui/system/ConnectionInterfacesPage.qml + ui/system/ConnectionInterfaceDelegate.qml diff --git a/nymea-app/ui/SettingsPage.qml b/nymea-app/ui/SettingsPage.qml index cb5c8d14..55c4e9d2 100644 --- a/nymea-app/ui/SettingsPage.qml +++ b/nymea-app/ui/SettingsPage.qml @@ -13,60 +13,43 @@ Page { onBackPressed: pageStack.pop() } - ColumnLayout { - anchors { left: parent.left; right: parent.right; top: parent.top } + Flickable { + anchors.fill: parent + contentHeight: settingsColumn.implicitHeight + interactive: contentHeight > height ColumnLayout { - Layout.fillWidth: true - Layout.margins: app.margins + id: settingsColumn + anchors { left: parent.left; right: parent.right; top: parent.top } - Label { - Layout.fillWidth: true - text: qsTr("Connected to:") - color: Material.accent - } - RowLayout { + ColumnLayout { Layout.fillWidth: true + Layout.margins: app.margins Label { Layout.fillWidth: true - elide: Text.ElideMiddle - text: engine.connection.url + text: qsTr("Connected to:") + color: Material.accent } - Button { - text: qsTr("Disconnect") - onClicked: { - tabSettings.lastConnectedHost = ""; - engine.connection.disconnect(); + RowLayout { + Layout.fillWidth: true + + Label { + Layout.fillWidth: true + elide: Text.ElideMiddle + text: engine.connection.url + } + Button { + text: qsTr("Disconnect") + onClicked: { + tabSettings.lastConnectedHost = ""; + engine.connection.disconnect(); + } } } } - } - ThinDivider {} - - RowLayout { - Layout.fillWidth: true - Layout.leftMargin: app.margins - Layout.rightMargin: app.margins - spacing: app.margins - Label { - text: qsTr("Server name") - } - TextField { - id: nameTextField - Layout.fillWidth: true - text: engine.basicConfiguration.serverName - } - Button { - text: qsTr("OK") - visible: nameTextField.displayText !== engine.basicConfiguration.serverName - onClicked: engine.basicConfiguration.serverName = nameTextField.displayText - } - } - - ColumnLayout { - Layout.fillWidth: true + ThinDivider {} RowLayout { Layout.fillWidth: true @@ -74,53 +57,122 @@ Page { Layout.rightMargin: app.margins spacing: app.margins Label { - text: qsTr("Debug server enabled") + text: qsTr("Name") + } + TextField { + id: nameTextField Layout.fillWidth: true + text: engine.basicConfiguration.serverName } - Switch { - id: debugServerEnabledSwitch - checked: engine.basicConfiguration.debugServerEnabled - onClicked: engine.basicConfiguration.debugServerEnabled = checked + Button { + text: qsTr("OK") + visible: nameTextField.displayText !== engine.basicConfiguration.serverName + onClicked: engine.basicConfiguration.serverName = nameTextField.displayText } } - Button { - id: debugServerButton + RowLayout { Layout.fillWidth: true - Layout.margins: app.margins - visible: debugServerEnabledSwitch.checked - text: qsTr("Open debug interface") - onClicked: Qt.openUrlExternally("http://" + engine.connection.hostAddress + "/debug") + Layout.leftMargin: app.margins + Layout.rightMargin: app.margins + spacing: app.margins + Label { + Layout.fillWidth: true + text: qsTr("Language") + } + ComboBox { + model: engine.basicConfiguration.availableLanguages + currentIndex: model.indexOf(engine.basicConfiguration.language) + onActivated: { + engine.basicConfiguration.language = currentText; + } + } } - } + RowLayout { + Layout.fillWidth: true + Layout.leftMargin: app.margins + Layout.rightMargin: app.margins + spacing: app.margins + Label { + Layout.fillWidth: true + text: qsTr("Time zone") + } + ComboBox { + Layout.minimumWidth: 200 + model: engine.basicConfiguration.timezones + currentIndex: model.indexOf(engine.basicConfiguration.timezone) + onActivated: { + engine.basicConfiguration.timezone = currentText; + } + } + } - MeaListItemDelegate { - Layout.fillWidth: true - iconName: "../images/cloud.svg" - text: qsTr("Cloud") - visible: engine.jsonRpcClient.ensureServerVersion("1.9") - onClicked: pageStack.push(Qt.resolvedUrl("system/CloudSettingsPage.qml")) - } + ColumnLayout { + Layout.fillWidth: true - MeaListItemDelegate { - Layout.fillWidth: true - iconName: "../images/plugin.svg" - text: qsTr("Plugins") - onClicked:pageStack.push(Qt.resolvedUrl("system/PluginsPage.qml")) - } + RowLayout { + Layout.fillWidth: true + Layout.leftMargin: app.margins + Layout.rightMargin: app.margins + spacing: app.margins + Label { + text: qsTr("Debug server enabled") + Layout.fillWidth: true + } + Switch { + id: debugServerEnabledSwitch + checked: engine.basicConfiguration.debugServerEnabled + onClicked: engine.basicConfiguration.debugServerEnabled = checked + } + } - MeaListItemDelegate { - Layout.fillWidth: true - iconName: "../images/logs.svg" - text: qsTr("Log viewer") - onClicked: pageStack.push(Qt.resolvedUrl("system/LogViewerPage.qml")) - } - MeaListItemDelegate { - Layout.fillWidth: true - iconName: "../images/info.svg" - text: qsTr("About nymea") - onClicked: pageStack.push(Qt.resolvedUrl("system/AboutNymeaPage.qml")) + Button { + id: debugServerButton + Layout.fillWidth: true + Layout.margins: app.margins + visible: debugServerEnabledSwitch.checked + text: qsTr("Open debug interface") + onClicked: Qt.openUrlExternally("http://" + engine.connection.hostAddress + "/debug") + } + + } + + MeaListItemDelegate { + Layout.fillWidth: true + iconName: "../images/network-vpn.svg" + text: qsTr("Server interfaces") + onClicked: pageStack.push(Qt.resolvedUrl("system/ConnectionInterfacesPage.qml")) + } + + MeaListItemDelegate { + Layout.fillWidth: true + iconName: "../images/cloud.svg" + text: qsTr("Cloud") + visible: engine.jsonRpcClient.ensureServerVersion("1.9") + onClicked: pageStack.push(Qt.resolvedUrl("system/CloudSettingsPage.qml")) + } + + MeaListItemDelegate { + Layout.fillWidth: true + iconName: "../images/plugin.svg" + text: qsTr("Plugins") + onClicked:pageStack.push(Qt.resolvedUrl("system/PluginsPage.qml")) + } + + MeaListItemDelegate { + Layout.fillWidth: true + iconName: "../images/logs.svg" + text: qsTr("Log viewer") + onClicked: pageStack.push(Qt.resolvedUrl("system/LogViewerPage.qml")) + } + MeaListItemDelegate { + Layout.fillWidth: true + iconName: "../images/info.svg" + text: qsTr("About nymea") + onClicked: pageStack.push(Qt.resolvedUrl("system/AboutNymeaPage.qml")) + } } } + } diff --git a/nymea-app/ui/components/MeaListItemDelegate.qml b/nymea-app/ui/components/MeaListItemDelegate.qml index 41be3c54..a243ab2d 100644 --- a/nymea-app/ui/components/MeaListItemDelegate.qml +++ b/nymea-app/ui/components/MeaListItemDelegate.qml @@ -16,10 +16,13 @@ SwipeDelegate { property string iconName property int iconSize: app.iconSize property color iconColor: app.accentColor + property alias iconKeyColor: icon.keyColor property alias secondaryIconName: secondaryIcon.name property alias secondaryIconColor: secondaryIcon.color + property alias secondaryIconKeyColor: secondaryIcon.keyColor property alias tertiaryIconName: tertiaryIcon.name property alias tertiaryIconColor: tertiaryIcon.color + property alias tertiaryIconKeyColor: tertiaryIcon.keyColor signal deleteClicked() diff --git a/nymea-app/ui/system/ConnectionInterfaceDelegate.qml b/nymea-app/ui/system/ConnectionInterfaceDelegate.qml new file mode 100644 index 00000000..8463f1e5 --- /dev/null +++ b/nymea-app/ui/system/ConnectionInterfaceDelegate.qml @@ -0,0 +1,25 @@ +import QtQuick 2.9 +import QtQuick.Controls 2.2 +import QtQuick.Layouts 1.3 +import Nymea 1.0 +import "../components" + +MeaListItemDelegate { + text: model.address + subText: model.port + iconName: "../images/network-wifi-symbolic.svg" + iconColor: { + if ((engine.connection.hostAddress === model.address || model.address === "0.0.0.0") + && engine.connection.port === model.port) { + return app.accentColor + } + return iconKeyColor + } + + secondaryIconName: "../images/account.svg" + secondaryIconColor: model.authenticationEnabled ? app.accentColor : secondaryIconKeyColor + tertiaryIconName: "../images/network-secure.svg" + tertiaryIconColor: model.sslEnabled ? app.accentColor : tertiaryIconKeyColor + + canDelete: true +} diff --git a/nymea-app/ui/system/ConnectionInterfacesPage.qml b/nymea-app/ui/system/ConnectionInterfacesPage.qml new file mode 100644 index 00000000..2fed94b1 --- /dev/null +++ b/nymea-app/ui/system/ConnectionInterfacesPage.qml @@ -0,0 +1,63 @@ +import QtQuick 2.9 +import QtQuick.Controls 2.2 +import QtQuick.Layouts 1.3 +import Nymea 1.0 +import "../components" + +Page { + id: root + header: GuhHeader { + text: qsTr("Connection interfaces") + onBackPressed: pageStack.pop(); + } + + Flickable { + anchors.fill: parent + contentHeight: connectionsColumn.implicitHeight + interactive: contentHeight > height + + ColumnLayout { + id: connectionsColumn + anchors { left: parent.left; top: parent.top; right: parent.right } + + Label { + Layout.fillWidth: true + Layout.leftMargin: app.margins + Layout.rightMargin: app.margins + Layout.topMargin: app.margins + text: qsTr("TCP Server Interfaces") + wrapMode: Text.WordWrap + } + + Repeater { + model: engine.basicConfiguration.tcpServerConfigurations + delegate: ConnectionInterfaceDelegate { + Layout.fillWidth: true + onDeleteClicked: { + print("should delete") + engine.basicConfiguration.deleteTcpServerConfiguration(model.id) + } + } + } + Label { + Layout.fillWidth: true + Layout.leftMargin: app.margins + Layout.rightMargin: app.margins + Layout.topMargin: app.margins + text: qsTr("WebSocket Server Interfaces") + wrapMode: Text.WordWrap + } + + Repeater { + model: engine.basicConfiguration.websocketServerConfigurations + delegate: ConnectionInterfaceDelegate { + Layout.fillWidth: true + onDeleteClicked: { + print("should delete", model.id) + engine.basicConfiguration.deleteWebsocketServerConfiguration(model.id) + } + } + } + } + } +}