diff --git a/client/resources.qrc b/client/resources.qrc
index a8f8718e..5b5fd593 100644
--- a/client/resources.qrc
+++ b/client/resources.qrc
@@ -268,5 +268,6 @@
images/controls/github.svg
images/controls/mail.svg
images/controls/telegram.svg
+ ui/qml/Controls2/TextTypes/SmallTextType.qml
diff --git a/client/ui/controllers/connectionController.cpp b/client/ui/controllers/connectionController.cpp
index dcc15958..aace2857 100644
--- a/client/ui/controllers/connectionController.cpp
+++ b/client/ui/controllers/connectionController.cpp
@@ -6,39 +6,27 @@
ConnectionController::ConnectionController(const QSharedPointer &serversModel,
const QSharedPointer &containersModel,
- const QSharedPointer &vpnConnection,
- QObject *parent)
- : QObject(parent)
- , m_serversModel(serversModel)
- , m_containersModel(containersModel)
- , m_vpnConnection(vpnConnection)
+ const QSharedPointer &vpnConnection, QObject *parent)
+ : QObject(parent), m_serversModel(serversModel), m_containersModel(containersModel), m_vpnConnection(vpnConnection)
{
- connect(m_vpnConnection.get(),
- &VpnConnection::connectionStateChanged,
- this,
- &ConnectionController::connectionStateChanged);
- connect(this,
- &ConnectionController::connectToVpn,
- m_vpnConnection.get(),
- &VpnConnection::connectToVpn,
+ connect(m_vpnConnection.get(), &VpnConnection::connectionStateChanged, this,
+ &ConnectionController::onConnectionStateChanged);
+ connect(this, &ConnectionController::connectToVpn, m_vpnConnection.get(), &VpnConnection::connectToVpn,
Qt::QueuedConnection);
- connect(this,
- &ConnectionController::disconnectFromVpn,
- m_vpnConnection.get(),
- &VpnConnection::disconnectFromVpn,
+ connect(this, &ConnectionController::disconnectFromVpn, m_vpnConnection.get(), &VpnConnection::disconnectFromVpn,
Qt::QueuedConnection);
}
void ConnectionController::openConnection()
{
int serverIndex = m_serversModel->getDefaultServerIndex();
- ServerCredentials credentials = qvariant_cast(
- m_serversModel->data(serverIndex, ServersModel::ServersModelRoles::CredentialsRole));
+ ServerCredentials credentials =
+ qvariant_cast(m_serversModel->data(serverIndex, ServersModel::Roles::CredentialsRole));
DockerContainer container = m_containersModel->getDefaultContainer();
QModelIndex containerModelIndex = m_containersModel->index(container);
- const QJsonObject &containerConfig = qvariant_cast(m_containersModel->data(containerModelIndex,
- ContainersModel::Roles::ConfigRole));
+ const QJsonObject &containerConfig =
+ qvariant_cast(m_containersModel->data(containerModelIndex, ContainersModel::Roles::ConfigRole));
if (container == DockerContainer::None) {
emit connectionErrorOccurred(tr("VPN Protocols is not installed.\n Please install VPN container at first"));
@@ -59,13 +47,65 @@ QString ConnectionController::getLastConnectionError()
return errorString(m_vpnConnection->lastError());
}
-bool ConnectionController::isConnected()
+void ConnectionController::onConnectionStateChanged(Vpn::ConnectionState state)
+{
+ m_isConnected = false;
+ m_connectionStateText = tr("Connection...");
+ switch (state) {
+ case Vpn::ConnectionState::Connected: {
+ m_isConnectionInProgress = false;
+ m_isConnected = true;
+ m_connectionStateText = tr("Disconnect");
+ break;
+ }
+ case Vpn::ConnectionState::Connecting: {
+ m_isConnectionInProgress = true;
+ break;
+ }
+ case Vpn::ConnectionState::Reconnecting: {
+ m_isConnectionInProgress = true;
+ m_connectionStateText = tr("Reconnection...");
+ break;
+ }
+ case Vpn::ConnectionState::Disconnected: {
+ m_isConnectionInProgress = false;
+ m_connectionStateText = tr("Connect");
+ break;
+ }
+ case Vpn::ConnectionState::Disconnecting: {
+ m_isConnectionInProgress = true;
+ m_connectionStateText = tr("Disconnection...");
+ break;
+ }
+ case Vpn::ConnectionState::Preparing: {
+ m_isConnectionInProgress = true;
+ break;
+ }
+ case Vpn::ConnectionState::Error: {
+ m_isConnectionInProgress = false;
+ emit connectionErrorOccurred(getLastConnectionError());
+ break;
+ }
+ case Vpn::ConnectionState::Unknown: {
+ m_isConnectionInProgress = false;
+ emit connectionErrorOccurred(getLastConnectionError());
+ break;
+ }
+ }
+ emit connectionStateChanged();
+}
+
+QString ConnectionController::connectionStateText() const
+{
+ return m_connectionStateText;
+}
+
+bool ConnectionController::isConnectionInProgress() const
+{
+ return m_isConnectionInProgress;
+}
+
+bool ConnectionController::isConnected() const
{
return m_isConnected;
}
-
-void ConnectionController::setIsConnected(bool isConnected)
-{
- m_isConnected = isConnected;
- emit isConnectedChanged();
-}
diff --git a/client/ui/controllers/connectionController.h b/client/ui/controllers/connectionController.h
index c1e81ea3..421ae84f 100644
--- a/client/ui/controllers/connectionController.h
+++ b/client/ui/controllers/connectionController.h
@@ -11,28 +11,30 @@ class ConnectionController : public QObject
Q_OBJECT
public:
- Q_PROPERTY(bool isConnected READ isConnected WRITE setIsConnected NOTIFY isConnectedChanged)
+ Q_PROPERTY(bool isConnected READ isConnected NOTIFY connectionStateChanged)
+ Q_PROPERTY(bool isConnectionInProgress READ isConnectionInProgress NOTIFY connectionStateChanged)
+ Q_PROPERTY(QString connectionStateText READ connectionStateText NOTIFY connectionStateChanged)
explicit ConnectionController(const QSharedPointer &serversModel,
const QSharedPointer &containersModel,
const QSharedPointer &vpnConnection,
QObject *parent = nullptr);
- bool isConnected();
- void setIsConnected(bool isConnected); //todo take state from vpnconnection?
+ bool isConnected() const;
+ bool isConnectionInProgress() const;
+ QString connectionStateText() const;
public slots:
void openConnection();
void closeConnection();
QString getLastConnectionError();
- Vpn::ConnectionState connectionState(){return {};}; //todo update ConnectButton text on page change
+ void onConnectionStateChanged(Vpn::ConnectionState state);
signals:
void connectToVpn(int serverIndex, const ServerCredentials &credentials, DockerContainer container, const QJsonObject &containerConfig);
void disconnectFromVpn();
- void connectionStateChanged(Vpn::ConnectionState state);
- void isConnectedChanged();
+ void connectionStateChanged();
void connectionErrorOccurred(QString errorMessage);
@@ -43,6 +45,8 @@ private:
QSharedPointer m_vpnConnection;
bool m_isConnected = false;
+ bool m_isConnectionInProgress = false;
+ QString m_connectionStateText = tr("Connect");
};
#endif // CONNECTIONCONTROLLER_H
diff --git a/client/ui/controllers/exportController.cpp b/client/ui/controllers/exportController.cpp
index cbb5a1bb..b6cd7abb 100644
--- a/client/ui/controllers/exportController.cpp
+++ b/client/ui/controllers/exportController.cpp
@@ -44,7 +44,7 @@ void ExportController::generateConnectionConfig()
{
int serverIndex = m_serversModel->getCurrentlyProcessedServerIndex();
ServerCredentials credentials = qvariant_cast(
- m_serversModel->data(serverIndex, ServersModel::ServersModelRoles::CredentialsRole));
+ m_serversModel->data(serverIndex, ServersModel::Roles::CredentialsRole));
DockerContainer container = static_cast(
m_containersModel->getCurrentlyProcessedContainerIndex());
diff --git a/client/ui/controllers/importController.cpp b/client/ui/controllers/importController.cpp
index 2724f9cd..99de3131 100644
--- a/client/ui/controllers/importController.cpp
+++ b/client/ui/controllers/importController.cpp
@@ -89,7 +89,7 @@ void ImportController::importConfig()
if (!m_config.value(config_key::containers).toArray().isEmpty()) {
auto newServerIndex = m_serversModel->index(m_serversModel->getServersCount() - 1);
- m_serversModel->setData(newServerIndex, true, ServersModel::ServersModelRoles::IsDefaultRole);
+ m_serversModel->setData(newServerIndex, true, ServersModel::Roles::IsDefaultRole);
}
emit importFinished();
diff --git a/client/ui/controllers/installController.cpp b/client/ui/controllers/installController.cpp
index 08ef69d4..5d3bfc2f 100644
--- a/client/ui/controllers/installController.cpp
+++ b/client/ui/controllers/installController.cpp
@@ -2,40 +2,54 @@
#include
-#include "core/servercontroller.h"
#include "core/errorstrings.h"
+#include "core/servercontroller.h"
+#include "utilities.h"
InstallController::InstallController(const QSharedPointer &serversModel,
- const QSharedPointer &containersModel,
- const std::shared_ptr &settings,
- QObject *parent) : QObject(parent), m_serversModel(serversModel), m_containersModel(containersModel), m_settings(settings)
-{}
+ const QSharedPointer &containersModel,
+ const std::shared_ptr &settings, QObject *parent)
+ : QObject(parent), m_serversModel(serversModel), m_containersModel(containersModel), m_settings(settings)
+{
+}
void InstallController::install(DockerContainer container, int port, TransportProto transportProto)
{
Proto mainProto = ContainerProps::defaultProtocol(container);
- QJsonObject containerConfig {
- { config_key::port, QString::number(port) },
- { config_key::transport_proto, ProtocolProps::transportProtoToString(transportProto, mainProto) }
- };
- QJsonObject config {
- { config_key::container, ContainerProps::containerToString(container) },
- { ProtocolProps::protoToString(mainProto), containerConfig }
- };
+ QJsonObject containerConfig { { config_key::port, QString::number(port) },
+ { config_key::transport_proto,
+ ProtocolProps::transportProtoToString(transportProto, mainProto) } };
+ QJsonObject config { { config_key::container, ContainerProps::containerToString(container) },
+ { ProtocolProps::protoToString(mainProto), containerConfig } };
if (m_shouldCreateServer) {
+ if (isServerAlreadyExists()) {
+ return;
+ }
installServer(container, config);
} else {
installContainer(container, config);
}
}
-void InstallController::installServer(DockerContainer container, QJsonObject& config)
+void InstallController::installServer(DockerContainer container, QJsonObject &config)
{
- //todo check if container already installed
ServerController serverController(m_settings);
- ErrorCode errorCode = serverController.setupContainer(m_currentlyInstalledServerCredentials, container, config);
+
+ QMap installedContainers;
+ ErrorCode errorCode =
+ serverController.getAlreadyInstalledContainers(m_currentlyInstalledServerCredentials, installedContainers);
+ if (!installedContainers.contains(container)) {
+ errorCode = serverController.setupContainer(m_currentlyInstalledServerCredentials, container, config);
+ installedContainers.insert(container, config);
+ }
+
+ bool isInstalledContainerFound = false;
+ if (!installedContainers.isEmpty()) {
+ isInstalledContainerFound = true;
+ }
+
if (errorCode == ErrorCode::NoError) {
QJsonObject server;
server.insert(config_key::hostName, m_currentlyInstalledServerCredentials.hostName);
@@ -44,43 +58,123 @@ void InstallController::installServer(DockerContainer container, QJsonObject& co
server.insert(config_key::port, m_currentlyInstalledServerCredentials.port);
server.insert(config_key::description, m_settings->nextAvailableServerName());
- server.insert(config_key::containers, QJsonArray{ config });
+ QJsonArray containerConfigs;
+ for (const QJsonObject &containerConfig : qAsConst(installedContainers)) {
+ containerConfigs.append(containerConfig);
+ }
+
+ server.insert(config_key::containers, containerConfigs);
server.insert(config_key::defaultContainer, ContainerProps::containerToString(container));
m_serversModel->addServer(server);
auto newServerIndex = m_serversModel->index(m_serversModel->getServersCount() - 1);
- m_serversModel->setData(newServerIndex, true, ServersModel::ServersModelRoles::IsDefaultRole);
+ m_serversModel->setData(newServerIndex, true, ServersModel::Roles::IsDefaultRole);
- emit installServerFinished();
+ emit installServerFinished(isInstalledContainerFound);
return;
}
emit installationErrorOccurred(errorString(errorCode));
}
-void InstallController::installContainer(DockerContainer container, QJsonObject& config)
+void InstallController::installContainer(DockerContainer container, QJsonObject &config)
{
- //todo check if container already installed
int serverIndex = m_serversModel->getCurrentlyProcessedServerIndex();
- ServerCredentials serverCredentials = qvariant_cast(
- m_serversModel->data(serverIndex, ServersModel::ServersModelRoles::CredentialsRole));
+ ServerCredentials serverCredentials =
+ qvariant_cast(m_serversModel->data(serverIndex, ServersModel::Roles::CredentialsRole));
ServerController serverController(m_settings);
- ErrorCode errorCode = serverController.setupContainer(serverCredentials, container, config);
+
+ QMap installedContainers;
+ ErrorCode errorCode = serverController.getAlreadyInstalledContainers(serverCredentials, installedContainers);
+
+ bool isInstalledContainerFound = false;
+ if (!installedContainers.isEmpty()) {
+ isInstalledContainerFound = true;
+ }
+
+ if (!installedContainers.contains(container)) {
+ errorCode = serverController.setupContainer(serverCredentials, container, config);
+ installedContainers.insert(container, config);
+ }
+
if (errorCode == ErrorCode::NoError) {
- m_containersModel->setData(m_containersModel->index(container), config, ContainersModel::Roles::ConfigRole);
- emit installContainerFinished();
+ for (auto iterator = installedContainers.begin(); iterator != installedContainers.end(); iterator++) {
+ auto modelIndex = m_containersModel->index(iterator.key());
+ QJsonObject containerConfig =
+ qvariant_cast(m_containersModel->data(modelIndex, ContainersModel::Roles::ConfigRole));
+ if (containerConfig.isEmpty()) {
+ m_containersModel->setData(m_containersModel->index(iterator.key()), iterator.value(),
+ ContainersModel::Roles::ConfigRole);
+ }
+ }
+
+ emit installContainerFinished(isInstalledContainerFound);
return;
}
emit installationErrorOccurred(errorString(errorCode));
}
-void InstallController::setCurrentlyInstalledServerCredentials(const QString &hostName, const QString &userName, const QString &secretData)
+bool InstallController::isServerAlreadyExists()
+{
+ for (int i = 0; i < m_serversModel->getServersCount(); i++) {
+ auto modelIndex = m_serversModel->index(i);
+ const ServerCredentials credentials =
+ qvariant_cast(m_serversModel->data(modelIndex, ServersModel::Roles::CredentialsRole));
+ if (m_currentlyInstalledServerCredentials.hostName == credentials.hostName
+ && m_currentlyInstalledServerCredentials.port == credentials.port) {
+ emit serverAlreadyExists(i);
+ return true;
+ }
+ }
+ return false;
+}
+
+void InstallController::scanServerForInstalledContainers()
+{
+ int serverIndex = m_serversModel->getCurrentlyProcessedServerIndex();
+ ServerCredentials serverCredentials =
+ qvariant_cast(m_serversModel->data(serverIndex, ServersModel::Roles::CredentialsRole));
+
+ ServerController serverController(m_settings);
+
+ QMap installedContainers;
+ ErrorCode errorCode = serverController.getAlreadyInstalledContainers(serverCredentials, installedContainers);
+
+ if (errorCode == ErrorCode::NoError) {
+ bool isInstalledContainerAddedToGui = false;
+
+ for (auto iterator = installedContainers.begin(); iterator != installedContainers.end(); iterator++) {
+ auto modelIndex = m_containersModel->index(iterator.key());
+ QJsonObject containerConfig =
+ qvariant_cast(m_containersModel->data(modelIndex, ContainersModel::Roles::ConfigRole));
+ if (containerConfig.isEmpty()) {
+ m_containersModel->setData(m_containersModel->index(iterator.key()), iterator.value(),
+ ContainersModel::Roles::ConfigRole);
+ isInstalledContainerAddedToGui = true;
+ }
+ }
+
+ emit scanServerFinished(isInstalledContainerAddedToGui);
+ return;
+ }
+
+ emit installationErrorOccurred(errorString(errorCode));
+}
+
+QRegularExpression InstallController::ipAddressPortRegExp()
+{
+ return Utils::ipAddressPortRegExp();
+}
+
+void InstallController::setCurrentlyInstalledServerCredentials(const QString &hostName, const QString &userName,
+ const QString &secretData)
{
m_currentlyInstalledServerCredentials.hostName = hostName;
if (m_currentlyInstalledServerCredentials.hostName.contains(":")) {
- m_currentlyInstalledServerCredentials.port = m_currentlyInstalledServerCredentials.hostName.split(":").at(1).toInt();
+ m_currentlyInstalledServerCredentials.port =
+ m_currentlyInstalledServerCredentials.hostName.split(":").at(1).toInt();
m_currentlyInstalledServerCredentials.hostName = m_currentlyInstalledServerCredentials.hostName.split(":").at(0);
}
m_currentlyInstalledServerCredentials.userName = userName;
diff --git a/client/ui/controllers/installController.h b/client/ui/controllers/installController.h
index d9e1ad95..6b01e102 100644
--- a/client/ui/controllers/installController.h
+++ b/client/ui/controllers/installController.h
@@ -3,10 +3,10 @@
#include
-#include "core/defs.h"
#include "containers/containers_defs.h"
-#include "ui/models/servers_model.h"
+#include "core/defs.h"
#include "ui/models/containers_model.h"
+#include "ui/models/servers_model.h"
class InstallController : public QObject
{
@@ -14,22 +14,32 @@ class InstallController : public QObject
public:
explicit InstallController(const QSharedPointer &serversModel,
const QSharedPointer &containersModel,
- const std::shared_ptr &settings,
- QObject *parent = nullptr);
+ const std::shared_ptr &settings, QObject *parent = nullptr);
public slots:
void install(DockerContainer container, int port, TransportProto transportProto);
- void setCurrentlyInstalledServerCredentials(const QString &hostName, const QString &userName, const QString &secretData);
+ void setCurrentlyInstalledServerCredentials(const QString &hostName, const QString &userName,
+ const QString &secretData);
void setShouldCreateServer(bool shouldCreateServer);
+ void scanServerForInstalledContainers();
+
+ QRegularExpression ipAddressPortRegExp();
+
signals:
- void installContainerFinished();
- void installServerFinished();
+ void installContainerFinished(bool isInstalledContainerFound);
+ void installServerFinished(bool isInstalledContainerFound);
+
+ void scanServerFinished(bool isInstalledContainerFound);
void installationErrorOccurred(QString errorMessage);
+
+ void serverAlreadyExists(int serverIndex);
+
private:
- void installServer(DockerContainer container, QJsonObject& config);
- void installContainer(DockerContainer container, QJsonObject& config);
+ void installServer(DockerContainer container, QJsonObject &config);
+ void installContainer(DockerContainer container, QJsonObject &config);
+ bool isServerAlreadyExists();
QSharedPointer m_serversModel;
QSharedPointer m_containersModel;
diff --git a/client/ui/controllers/pageController.cpp b/client/ui/controllers/pageController.cpp
index e49177a5..4ee9b3bf 100644
--- a/client/ui/controllers/pageController.cpp
+++ b/client/ui/controllers/pageController.cpp
@@ -10,7 +10,7 @@ QString PageController::getInitialPage()
if (m_serversModel->getServersCount()) {
if (m_serversModel->getDefaultServerIndex() < 0) {
auto defaultServerIndex = m_serversModel->index(0);
- m_serversModel->setData(defaultServerIndex, true, ServersModel::ServersModelRoles::IsDefaultRole);
+ m_serversModel->setData(defaultServerIndex, true, ServersModel::Roles::IsDefaultRole);
}
return getPagePath(PageLoader::PageEnum::PageStart);
} else {
diff --git a/client/ui/controllers/pageController.h b/client/ui/controllers/pageController.h
index 587e0e38..384d3c8d 100644
--- a/client/ui/controllers/pageController.h
+++ b/client/ui/controllers/pageController.h
@@ -40,14 +40,9 @@ namespace PageLoader
};
Q_ENUM_NS(PageEnum)
- static void declareQmlPageEnum() {
- qmlRegisterUncreatableMetaObject(
- PageLoader::staticMetaObject,
- "PageEnum",
- 1, 0,
- "PageEnum",
- "Error: only enums"
- );
+ static void declareQmlPageEnum()
+ {
+ qmlRegisterUncreatableMetaObject(PageLoader::staticMetaObject, "PageEnum", 1, 0, "PageEnum", "Error: only enums");
}
}
@@ -55,8 +50,7 @@ class PageController : public QObject
{
Q_OBJECT
public:
- explicit PageController(const QSharedPointer &serversModel,
- QObject *parent = nullptr);
+ explicit PageController(const QSharedPointer &serversModel, QObject *parent = nullptr);
public slots:
QString getInitialPage();
@@ -64,9 +58,11 @@ public slots:
signals:
void goToPageHome();
+ void goToPageSettings();
void restorePageHomeState(bool isContainerInstalled = false);
void replaceStartPage();
void showErrorMessage(QString errorMessage);
+ void showInfoMessage(QString message);
private:
QSharedPointer m_serversModel;
diff --git a/client/ui/models/containers_model.cpp b/client/ui/models/containers_model.cpp
index 1caf6944..f095dd02 100644
--- a/client/ui/models/containers_model.cpp
+++ b/client/ui/models/containers_model.cpp
@@ -2,7 +2,8 @@
#include "core/servercontroller.h"
-ContainersModel::ContainersModel(std::shared_ptr settings, QObject *parent) : m_settings(settings), QAbstractListModel(parent)
+ContainersModel::ContainersModel(std::shared_ptr settings, QObject *parent)
+ : m_settings(settings), QAbstractListModel(parent)
{
}
@@ -21,25 +22,25 @@ bool ContainersModel::setData(const QModelIndex &index, const QVariant &value, i
DockerContainer container = ContainerProps::allContainers().at(index.row());
switch (role) {
- case NameRole:
- // return ContainerProps::containerHumanNames().value(container);
- case DescRole:
- // return ContainerProps::containerDescriptions().value(container);
- case ConfigRole: //todo save to model also
- m_settings->setContainerConfig(m_currentlyProcessedServerIndex,
- container,
- value.toJsonObject());
- case ServiceTypeRole:
- // return ContainerProps::containerService(container);
- case DockerContainerRole:
- // return container;
- case IsInstalledRole:
- // return m_settings->containers(m_currentlyProcessedServerIndex).contains(container);
- case IsDefaultRole: {
- m_settings->setDefaultContainer(m_currentlyProcessedServerIndex, container);
- m_defaultContainerIndex = container;
- emit defaultContainerChanged();
- }
+ case NameRole:
+ // return ContainerProps::containerHumanNames().value(container);
+ case DescRole:
+ // return ContainerProps::containerDescriptions().value(container);
+ case ConfigRole: {
+ m_settings->setContainerConfig(m_currentlyProcessedServerIndex, container, value.toJsonObject());
+ m_containers = m_settings->containers(m_currentlyProcessedServerIndex);
+ }
+ case ServiceTypeRole:
+ // return ContainerProps::containerService(container);
+ case DockerContainerRole:
+ // return container;
+ case IsInstalledRole:
+ // return m_settings->containers(m_currentlyProcessedServerIndex).contains(container);
+ case IsDefaultRole: {
+ m_settings->setDefaultContainer(m_currentlyProcessedServerIndex, container);
+ m_defaultContainerIndex = container;
+ emit defaultContainerChanged();
+ }
}
emit dataChanged(index, index);
@@ -48,40 +49,30 @@ bool ContainersModel::setData(const QModelIndex &index, const QVariant &value, i
QVariant ContainersModel::data(const QModelIndex &index, int role) const
{
- if (!index.isValid() || index.row() < 0
- || index.row() >= ContainerProps::allContainers().size()) {
+ if (!index.isValid() || index.row() < 0 || index.row() >= ContainerProps::allContainers().size()) {
return QVariant();
}
DockerContainer container = ContainerProps::allContainers().at(index.row());
switch (role) {
- case NameRole:
- return ContainerProps::containerHumanNames().value(container);
- case DescRole:
- return ContainerProps::containerDescriptions().value(container);
- case ConfigRole: {
- if (container == DockerContainer::None) return QJsonObject();
- return m_containers.value(container);
+ case NameRole: return ContainerProps::containerHumanNames().value(container);
+ case DescRole: return ContainerProps::containerDescriptions().value(container);
+ case ConfigRole: {
+ if (container == DockerContainer::None) {
+ return QJsonObject();
}
- case ServiceTypeRole:
- return ContainerProps::containerService(container);
- case DockerContainerRole:
- return container;
- case IsEasySetupContainerRole:
- return ContainerProps::isEasySetupContainer(container);
- case EasySetupHeaderRole:
- return ContainerProps::easySetupHeader(container);
- case EasySetupDescriptionRole:
- return ContainerProps::easySetupDescription(container);
- case IsInstalledRole:
- return m_containers.contains(container);
- case IsCurrentlyProcessedRole:
- return container == static_cast(m_currentlyProcessedContainerIndex);
- case IsDefaultRole:
- return container == m_defaultContainerIndex;
- case IsSupportedRole:
- return ContainerProps::isSupportedByCurrentPlatform(container);
+ return m_containers.value(container);
+ }
+ case ServiceTypeRole: return ContainerProps::containerService(container);
+ case DockerContainerRole: return container;
+ case IsEasySetupContainerRole: return ContainerProps::isEasySetupContainer(container);
+ case EasySetupHeaderRole: return ContainerProps::easySetupHeader(container);
+ case EasySetupDescriptionRole: return ContainerProps::easySetupDescription(container);
+ case IsInstalledRole: return m_containers.contains(container);
+ case IsCurrentlyProcessedRole: return container == static_cast(m_currentlyProcessedContainerIndex);
+ case IsDefaultRole: return container == m_defaultContainerIndex;
+ case IsSupportedRole: return ContainerProps::isSupportedByCurrentPlatform(container);
}
return QVariant();
@@ -130,7 +121,7 @@ void ContainersModel::removeAllContainers()
endResetModel();
}
- //todo process errors
+ // todo process errors
}
void ContainersModel::clearCachedProfiles()
@@ -141,7 +132,8 @@ void ContainersModel::clearCachedProfiles()
}
}
-QHash ContainersModel::roleNames() const {
+QHash ContainersModel::roleNames() const
+{
QHash roles;
roles[NameRole] = "name";
roles[DescRole] = "description";
diff --git a/client/ui/models/servers_model.cpp b/client/ui/models/servers_model.cpp
index f027a90d..94267ed1 100644
--- a/client/ui/models/servers_model.cpp
+++ b/client/ui/models/servers_model.cpp
@@ -1,6 +1,7 @@
#include "servers_model.h"
-ServersModel::ServersModel(std::shared_ptr settings, QObject *parent) : m_settings(settings), QAbstractListModel(parent)
+ServersModel::ServersModel(std::shared_ptr settings, QObject *parent)
+ : m_settings(settings), QAbstractListModel(parent)
{
m_servers = m_settings->serversArray();
m_defaultServerIndex = m_settings->defaultServerIndex();
@@ -14,8 +15,7 @@ int ServersModel::rowCount(const QModelIndex &parent) const
bool ServersModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
- if (!index.isValid() || index.row() < 0
- || index.row() >= static_cast(m_servers.size())) {
+ if (!index.isValid() || index.row() < 0 || index.row() >= static_cast(m_servers.size())) {
return false;
}
@@ -29,8 +29,7 @@ bool ServersModel::setData(const QModelIndex &index, const QVariant &value, int
break;
}
case IsDefaultRole: {
- m_settings->setDefaultServer(index.row());
- m_defaultServerIndex = m_settings->defaultServerIndex();
+ setDefaultServerIndex(index.row());
break;
}
default: {
@@ -58,16 +57,11 @@ QVariant ServersModel::data(const QModelIndex &index, int role) const
}
return description;
}
- case HostNameRole:
- return server.value(config_key::hostName).toString();
- case CredentialsRole:
- return QVariant::fromValue(m_settings->serverCredentials(index.row()));
- case CredentialsLoginRole:
- return m_settings->serverCredentials(index.row()).userName;
- case IsDefaultRole:
- return index.row() == m_defaultServerIndex;
- case IsCurrentlyProcessedRole:
- return index.row() == m_currenlyProcessedServerIndex;
+ case HostNameRole: return server.value(config_key::hostName).toString();
+ case CredentialsRole: return QVariant::fromValue(m_settings->serverCredentials(index.row()));
+ case CredentialsLoginRole: return m_settings->serverCredentials(index.row()).userName;
+ case IsDefaultRole: return index.row() == m_defaultServerIndex;
+ case IsCurrentlyProcessedRole: return index.row() == m_currenlyProcessedServerIndex;
}
return QVariant();
@@ -92,6 +86,7 @@ const int ServersModel::getServersCount()
void ServersModel::setCurrentlyProcessedServerIndex(int index)
{
m_currenlyProcessedServerIndex = index;
+ emit currentlyProcessedServerIndexChanged();
}
int ServersModel::getCurrentlyProcessedServerIndex()
@@ -104,6 +99,12 @@ bool ServersModel::isDefaultServerCurrentlyProcessed()
return m_defaultServerIndex == m_currenlyProcessedServerIndex;
}
+bool ServersModel::isCurrentlyProcessedServerHasWriteAccess()
+{
+ auto credentials = m_settings->serverCredentials(m_currenlyProcessedServerIndex);
+ return (!credentials.userName.isEmpty() && !credentials.secretData.isEmpty());
+}
+
void ServersModel::addServer(const QJsonObject &server)
{
beginResetModel();
@@ -119,18 +120,19 @@ void ServersModel::removeServer()
m_servers = m_settings->serversArray();
if (m_settings->defaultServerIndex() == m_currenlyProcessedServerIndex) {
- m_settings->setDefaultServer(0);
+ setDefaultServerIndex(0);
} else if (m_settings->defaultServerIndex() > m_currenlyProcessedServerIndex) {
- m_settings->setDefaultServer(m_settings->defaultServerIndex() - 1);
+ setDefaultServerIndex(m_settings->defaultServerIndex() - 1);
}
if (m_settings->serversCount() == 0) {
- m_settings->setDefaultServer(-1);
+ setDefaultServerIndex(-1);
}
endResetModel();
}
-QHash ServersModel::roleNames() const {
+QHash ServersModel::roleNames() const
+{
QHash roles;
roles[NameRole] = "name";
roles[HostNameRole] = "hostName";
@@ -140,3 +142,9 @@ QHash ServersModel::roleNames() const {
roles[IsCurrentlyProcessedRole] = "isCurrentlyProcessed";
return roles;
}
+
+void ServersModel::setDefaultServerIndex(const int index)
+{
+ m_settings->setDefaultServer(index);
+ m_defaultServerIndex = m_settings->defaultServerIndex();
+}
diff --git a/client/ui/models/servers_model.h b/client/ui/models/servers_model.h
index be13d61b..891d6ad1 100644
--- a/client/ui/models/servers_model.h
+++ b/client/ui/models/servers_model.h
@@ -5,7 +5,8 @@
#include "settings.h"
-struct ServerModelContent {
+struct ServerModelContent
+{
QString desc;
QString address;
bool isDefault;
@@ -15,7 +16,7 @@ class ServersModel : public QAbstractListModel
{
Q_OBJECT
public:
- enum ServersModelRoles {
+ enum Roles {
NameRole = Qt::UserRole + 1,
HostNameRole,
CredentialsRole,
@@ -35,6 +36,7 @@ public:
public slots:
const int getDefaultServerIndex();
bool isDefaultServerCurrentlyProcessed();
+ bool isCurrentlyProcessedServerHasWriteAccess();
const int getServersCount();
@@ -47,7 +49,12 @@ public slots:
protected:
QHash roleNames() const override;
+signals:
+ void currentlyProcessedServerIndexChanged();
+
private:
+ void setDefaultServerIndex(const int index);
+
QJsonArray m_servers;
std::shared_ptr m_settings;
diff --git a/client/ui/qml/Components/ConnectButton.qml b/client/ui/qml/Components/ConnectButton.qml
index 3c34a6b0..626c4ffb 100644
--- a/client/ui/qml/Components/ConnectButton.qml
+++ b/client/ui/qml/Components/ConnectButton.qml
@@ -15,7 +15,7 @@ Button {
}
}
- text: qsTr("Connect")
+ text: ConnectionController.connectionStateText
background: Item {
clip: true
@@ -26,13 +26,21 @@ Button {
Image {
id: border
- source: connectionProccess.running ? "/images/connectionProgress.svg" :
- ConnectionController.isConnected ? "/images/connectionOff.svg" : "/images/connectionOn.svg"
+ source: {
+ if (ConnectionController.isConnectionInProgress) {
+ return "/images/connectionProgress.svg"
+ } else if (ConnectionController.isConnected) {
+ return "/images/connectionOff.svg"
+ } else {
+ return "/images/connectionOn.svg"
+ }
+ }
+
RotationAnimator {
id: connectionProccess
target: border
- running: false
+ running: ConnectionController.isConnectionInProgress
from: 0
to: 360
loops: Animation.Infinite
@@ -67,63 +75,12 @@ Button {
}
onClicked: {
- connectionProccess.running ? ConnectionController.closeConnection() : ConnectionController.openConnection()
- }
-
- Connections {
- target: ConnectionController
- function onConnectionStateChanged(state) {
- switch(state) {
- case ConnectionState.Unknown: {
- console.log("Unknown")
- break
- }
- case ConnectionState.Disconnected: {
- console.log("Disconnected")
- connectionProccess.running = false
- root.text = qsTr("Connect")
- ConnectionController.isConnected = false
- break
- }
- case ConnectionState.Preparing: {
- console.log("Preparing")
- connectionProccess.running = true
- root.text = qsTr("Connection...")
- break
- }
- case ConnectionState.Connecting: {
- console.log("Connecting")
- connectionProccess.running = true
- root.text = qsTr("Connection...")
- break
- }
- case ConnectionState.Connected: {
- console.log("Connected")
- connectionProccess.running = false
- root.text = qsTr("Disconnect")
- ConnectionController.isConnected = true
- break
- }
- case ConnectionState.Disconnecting: {
- console.log("Disconnecting")
- connectionProccess.running = true
- root.text = qsTr("Disconnection...")
- break
- }
- case ConnectionState.Reconnecting: {
- console.log("Reconnecting")
- connectionProccess.running = true
- root.text = qsTr("Reconnection...")
- break
- }
- case ConnectionState.Error: {
- console.log("Error")
- connectionProccess.running = false
- root.text = qsTr("Connect")
- PageController.showErrorMessage(ConnectionController.getLastConnectionError())
- break
- }
- }
+ if (ConnectionController.isConnectionInProgress) {
+ ConnectionController.closeConnection()
+ } else if (ConnectionController.isConnected) {
+ ConnectionController.closeConnection()
+ } else {
+ ConnectionController.openConnection()
}
}
}
diff --git a/client/ui/qml/Components/ShareConnectionDrawer.qml b/client/ui/qml/Components/ShareConnectionDrawer.qml
index 627eba81..e03738c8 100644
--- a/client/ui/qml/Components/ShareConnectionDrawer.qml
+++ b/client/ui/qml/Components/ShareConnectionDrawer.qml
@@ -141,6 +141,7 @@ DrawerType {
Layout.bottomMargin: 16
padding: 0
+ leftPadding: 0
height: 24
color: "#D7D8DB"
diff --git a/client/ui/qml/Controls2/TextFieldWithHeaderType.qml b/client/ui/qml/Controls2/TextFieldWithHeaderType.qml
index b41f0b40..8ad92d54 100644
--- a/client/ui/qml/Controls2/TextFieldWithHeaderType.qml
+++ b/client/ui/qml/Controls2/TextFieldWithHeaderType.qml
@@ -2,6 +2,8 @@ import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
+import "TextTypes"
+
Item {
id: root
@@ -34,15 +36,10 @@ Item {
anchors.fill: backgroud
ColumnLayout {
- Text {
+ LabelTextType {
text: root.headerText
color: "#878b91"
- font.pixelSize: 13
- font.weight: 400
- font.family: "PT Root UI VF"
- font.letterSpacing: 0.02
- height: 16
Layout.fillWidth: true
Layout.rightMargin: 16
Layout.leftMargin: 16
diff --git a/client/ui/qml/Controls2/TextTypes/SmallTextType.qml b/client/ui/qml/Controls2/TextTypes/SmallTextType.qml
new file mode 100644
index 00000000..96f3342d
--- /dev/null
+++ b/client/ui/qml/Controls2/TextTypes/SmallTextType.qml
@@ -0,0 +1,12 @@
+import QtQuick
+
+Text {
+ height: 20
+
+ color: "#D7D8DB"
+ font.pixelSize: 14
+ font.weight: Font.Normal
+ font.family: "PT Root UI VF"
+
+ wrapMode: Text.WordWrap
+}
diff --git a/client/ui/qml/Pages2/PageHome.qml b/client/ui/qml/Pages2/PageHome.qml
index 282c1408..a4e90117 100644
--- a/client/ui/qml/Pages2/PageHome.qml
+++ b/client/ui/qml/Pages2/PageHome.qml
@@ -21,8 +21,8 @@ PageType {
property string borderColor: "#2C2D30"
- property string currentServerName: serversMenuContent.currentItem.delegateData.name
- property string currentServerHostName: serversMenuContent.currentItem.delegateData.hostName
+ property string currentServerName
+ property string currentServerHostName
property string currentContainerName
ConnectButton {
@@ -93,7 +93,15 @@ PageType {
Layout.bottomMargin: 44
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
- text: root.currentContainerName + " | " + root.currentServerHostName
+ text: {
+ var string = ""
+ if (SettingsController.isAmneziaDnsEnabled()) {
+ string += "Amnezia DNS | "
+ }
+
+ string += root.currentContainerName + " | " + root.currentServerHostName
+ return string
+ }
}
}
@@ -153,6 +161,8 @@ PageType {
headerBackButtonImage: "qrc:/images/controls/arrow-left.svg"
rootButtonClickedFunction: function() {
+ // todo check if server index changed before set Currently processed
+ // todo make signal slot for change server index in containersModel
ServersModel.setCurrentlyProcessedServerIndex(serversMenuContent.currentIndex)
ContainersModel.setCurrentlyProcessedServerIndex(serversMenuContent.currentIndex)
containersDropDown.menuVisible = true
@@ -161,20 +171,45 @@ PageType {
listView: HomeContainersListView {
rootWidth: root.width
+ Connections {
+ target: ServersModel
+
+ function onCurrentlyProcessedServerIndexChanged() {
+ updateContainersModelFilters()
+ }
+
+ function updateContainersModelFilters() {
+ if (ServersModel.isCurrentlyProcessedServerHasWriteAccess()) {
+ proxyContainersModel.filters = [serviceTypeFilter, supportedFilter]
+ } else {
+ proxyContainersModel.filters = installedFilter
+ }
+ }
+ }
+
+ ValueFilter {
+ id: serviceTypeFilter
+ roleName: "serviceType"
+ value: ProtocolEnum.Vpn
+ }
+ ValueFilter {
+ id: supportedFilter
+ roleName: "isSupported"
+ value: true
+ }
+ ValueFilter {
+ id: installedFilter
+ roleName: "isInstalled"
+ value: true
+ }
+
model: SortFilterProxyModel {
id: proxyContainersModel
sourceModel: ContainersModel
- filters: [
- ValueFilter {
- roleName: "serviceType"
- value: ProtocolEnum.Vpn
- },
- ValueFilter {
- roleName: "isSupported"
- value: true
- }
- ]
+
+ Component.onCompleted: updateContainersModelFilters()
}
+
currentIndex: ContainersModel.getDefaultContainer()
}
}
@@ -272,6 +307,9 @@ PageType {
isDefault = true
ContainersModel.setCurrentlyProcessedServerIndex(index)
+
+ root.currentServerName = name
+ root.currentServerHostName = hostName
}
MouseArea {
@@ -302,6 +340,13 @@ PageType {
Layout.fillWidth: true
}
}
+
+ Component.onCompleted: {
+ if (serversMenuContent.currentIndex === index) {
+ root.currentServerName = name
+ root.currentServerHostName = hostName
+ }
+ }
}
}
}
diff --git a/client/ui/qml/Pages2/PageSettingsServerData.qml b/client/ui/qml/Pages2/PageSettingsServerData.qml
index 6179983b..b98d2b8c 100644
--- a/client/ui/qml/Pages2/PageSettingsServerData.qml
+++ b/client/ui/qml/Pages2/PageSettingsServerData.qml
@@ -14,6 +14,21 @@ import "../Components"
PageType {
id: root
+ Connections {
+ target: InstallController
+
+ function onScanServerFinished(isInstalledContainerFound) {
+ var message = ""
+ if (isInstalledContainerFound) {
+ message = qsTr("All installed containers have been added to the application")
+ } else {
+ message = qsTr("Не найдено установленных контейнеров")
+ }
+
+ PageController.showErrorMessage(message)
+ }
+ }
+
FlickableType {
id: fl
anchors.top: parent.top
@@ -30,8 +45,8 @@ PageType {
LabelWithButtonType {
Layout.fillWidth: true
- text: "Clear Amnezia cache"
- descriptionText: "May be needed when changing other settings"
+ text: qsTr("Clear Amnezia cache")
+ descriptionText: qsTr("May be needed when changing other settings")
clickedFunction: function() {
questionDrawer.headerText = qsTr("Clear cached profiles?")
@@ -52,6 +67,19 @@ PageType {
DividerType {}
+ LabelWithButtonType {
+ Layout.fillWidth: true
+
+ text: qsTr("Проверить сервер на наличие ранее установленных сервисов Amnezia")
+ descriptionText: qsTr("Добавим их в приложение, если они не отображались")
+
+ clickedFunction: function() {
+ InstallController.scanServerForInstalledContainers()
+ }
+ }
+
+ DividerType {}
+
LabelWithButtonType {
Layout.fillWidth: true
diff --git a/client/ui/qml/Pages2/PageSetupWizardCredentials.qml b/client/ui/qml/Pages2/PageSetupWizardCredentials.qml
index 3f037035..fa6b1f92 100644
--- a/client/ui/qml/Pages2/PageSetupWizardCredentials.qml
+++ b/client/ui/qml/Pages2/PageSetupWizardCredentials.qml
@@ -7,6 +7,7 @@ import PageEnum 1.0
import "./"
import "../Controls2"
import "../Config"
+import "../Controls2/TextTypes"
PageType {
id: root
@@ -42,28 +43,32 @@ PageType {
HeaderType {
Layout.fillWidth: true
- headerText: "Подключение к серверу"
+ headerText: qsTr("Server connection")
}
TextFieldWithHeaderType {
id: hostname
Layout.fillWidth: true
- headerText: "Server IP address [:port]"
+ headerText: qsTr("Server IP address [:port]")
+ textFieldPlaceholderText: qsTr("Enter the address in the format 255.255.255.255:88")
+ textField.validator: RegularExpressionValidator {
+ regularExpression: InstallController.ipAddressPortRegExp()
+ }
}
TextFieldWithHeaderType {
id: username
Layout.fillWidth: true
- headerText: "Login to connect via SSH"
+ headerText: qsTr("Login to connect via SSH")
}
TextFieldWithHeaderType {
id: secretData
Layout.fillWidth: true
- headerText: "Password / Private key"
+ headerText: qsTr("Password / Private key")
textField.echoMode: TextInput.Password
}
@@ -71,7 +76,7 @@ PageType {
Layout.fillWidth: true
Layout.topMargin: 24
- text: qsTr("Настроить сервер простым образом")
+ text: qsTr("Set up a server the easy way")
onClicked: function() {
InstallController.setShouldCreateServer(true)
@@ -92,7 +97,7 @@ PageType {
textColor: "#D7D8DB"
borderWidth: 1
- text: qsTr("Выбрать протокол для установки")
+ text: qsTr("Select protocol to install")
onClicked: function() {
InstallController.setShouldCreateServer(true)
diff --git a/client/ui/qml/Pages2/PageSetupWizardInstalling.qml b/client/ui/qml/Pages2/PageSetupWizardInstalling.qml
index 9631e258..d0fdeabd 100644
--- a/client/ui/qml/Pages2/PageSetupWizardInstalling.qml
+++ b/client/ui/qml/Pages2/PageSetupWizardInstalling.qml
@@ -24,7 +24,7 @@ PageType {
PageController.showErrorMessage(errorMessage)
}
- function onInstallContainerFinished() {
+ function onInstallContainerFinished(isInstalledContainerFound) {
goToStartPage()
if (stackView.currentItem.objectName === PageController.getPagePath(PageEnum.PageHome)) {
PageController.restorePageHomeState(true)
@@ -34,9 +34,15 @@ PageType {
} else {
goToPage(PageEnum.PageHome)
}
+
+ if (isInstalledContainerFound) {
+ //todo change to info message
+ PageController.showErrorMessage(qsTr("The container you are trying to install is already installed on the server. " +
+ "All installed containers have been added to the application"))
+ }
}
- function onInstallServerFinished() {
+ function onInstallServerFinished(isInstalledContainerFound) {
goToStartPage()
if (stackView.currentItem.objectName === PageController.getPagePath(PageEnum.PageHome)) {
PageController.restorePageHomeState()
@@ -46,6 +52,19 @@ PageType {
var pagePath = PageController.getPagePath(PageEnum.PageStart)
stackView.replace(pagePath, { "objectName" : pagePath })
}
+
+ if (isInstalledContainerFound) {
+ PageController.showErrorMessage(qsTr("The container you are trying to install is already installed on the server. " +
+ "All installed containers have been added to the application"))
+ }
+ }
+
+ function onServerAlreadyExists(serverIndex) {
+ goToStartPage()
+ ServersModel.setCurrentlyProcessedServerIndex(serverIndex)
+ goToPage(PageEnum.PageSettingsServerInfo, false)
+
+ PageController.showErrorMessage(qsTr("The server has already been added to the application"))
}
}
diff --git a/client/ui/qml/Pages2/PageStart.qml b/client/ui/qml/Pages2/PageStart.qml
index a91cab6a..1307ee05 100644
--- a/client/ui/qml/Pages2/PageStart.qml
+++ b/client/ui/qml/Pages2/PageStart.qml
@@ -20,6 +20,11 @@ PageType {
tabBarStackView.goToTabBarPage(PageController.getPagePath(PageEnum.PageHome))
}
+ function onGoToPageSettings() {
+ tabBar.currentIndex = 2
+ tabBarStackView.goToTabBarPage(PageController.getPagePath(PageEnum.PageSettings))
+ }
+
function onShowErrorMessage(errorMessage) {
popupErrorMessage.popupErrorMessageText = errorMessage
popupErrorMessage.open()