From 35d4222c7a87f6374fe324514ef0018cc96fe92a Mon Sep 17 00:00:00 2001 From: "vladimir.kuznetsov" Date: Fri, 12 May 2023 23:54:31 +0800 Subject: [PATCH] added connectionController and ConnectionButton.qml --- client/CMakeLists.txt | 5 ++ client/amnezia_application.cpp | 12 +++- client/amnezia_application.h | 10 ++- client/resources.qrc | 1 + .../ui/controllers/connectionController.cpp | 71 +++++++++++++++++++ client/ui/controllers/connectionController.h | 33 +++++++++ client/ui/models/containers_model.cpp | 48 +++++++------ client/ui/models/containers_model.h | 10 ++- client/ui/models/servers_model.cpp | 27 ++----- client/ui/models/servers_model.h | 1 + client/ui/qml/Components/ConnectButton.qml | 40 +++++++++++ .../Controls2/TextTypes/ButtonTextType.qml | 2 +- .../Controls2/TextTypes/Header1TextType.qml | 2 +- .../Controls2/TextTypes/Header2TextType.qml | 2 +- .../qml/Controls2/TextTypes/LabelTextType.qml | 2 +- .../Controls2/TextTypes/ParagraphTextType.qml | 2 +- client/ui/qml/Pages2/PageHome.qml | 25 ++++--- 17 files changed, 233 insertions(+), 60 deletions(-) create mode 100644 client/ui/controllers/connectionController.cpp create mode 100644 client/ui/controllers/connectionController.h create mode 100644 client/ui/qml/Components/ConnectButton.qml diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index 9b110666..d86431d5 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -128,17 +128,22 @@ file(GLOB CONFIGURATORS_CPP CONFIGURE_DEPENDS ${CMAKE_CURRENT_LIST_DIR}/configur file(GLOB UI_MODELS_H CONFIGURE_DEPENDS ${CMAKE_CURRENT_LIST_DIR}/ui/models/*.h) file(GLOB UI_MODELS_CPP CONFIGURE_DEPENDS ${CMAKE_CURRENT_LIST_DIR}/ui/models/*.cpp) +file(GLOB UI_CONTROLLERS_H CONFIGURE_DEPENDS ${CMAKE_CURRENT_LIST_DIR}/ui/controllers/*.h) +file(GLOB UI_CONTROLLERS_CPP CONFIGURE_DEPENDS ${CMAKE_CURRENT_LIST_DIR}/ui/controllers/*.cpp) + set(HEADERS ${HEADERS} ${COMMON_FILES_H} ${PAGE_LOGIC_H} ${CONFIGURATORS_H} ${UI_MODELS_H} + ${UI_CONTROLLERS_H} ) set(SOURCES ${SOURCES} ${COMMON_FILES_CPP} ${PAGE_LOGIC_CPP} ${CONFIGURATORS_CPP} ${UI_MODELS_CPP} + ${UI_CONTROLLERS_CPP} ) qt6_add_resources(QRC ${QRC} ${CMAKE_CURRENT_LIST_DIR}/resources.qrc) diff --git a/client/amnezia_application.cpp b/client/amnezia_application.cpp index dea868e4..6fadcabb 100644 --- a/client/amnezia_application.cpp +++ b/client/amnezia_application.cpp @@ -5,7 +5,6 @@ #include #include - #include "core/servercontroller.h" #include "logger.h" #include "defines.h" @@ -100,12 +99,23 @@ void AmneziaApplication::init() m_engine->rootContext()->setContextProperty("Debug", &Logger::Instance()); + // m_containersModel.reset(new ContainersModel(m_settings, this)); m_engine->rootContext()->setContextProperty("ContainersModel", m_containersModel.get()); m_serversModel.reset(new ServersModel(m_settings, this)); m_engine->rootContext()->setContextProperty("ServersModel", m_serversModel.get()); + m_vpnConnection.reset(new VpnConnection(m_settings, m_configurator)); + + m_connectionController.reset(new ConnectionController(m_serversModel, m_containersModel)); + connect(m_connectionController.get(), &ConnectionController::connectToVpn, + m_vpnConnection.get(), &VpnConnection::connectToVpn, Qt::QueuedConnection); + connect(m_connectionController.get(), &ConnectionController::disconnectFromVpn, + m_vpnConnection.get(), &VpnConnection::disconnectFromVpn, Qt::QueuedConnection); + m_engine->rootContext()->setContextProperty("ConnectionController", m_connectionController.get()); + + // m_uiLogic->registerPagesLogic(); #if defined(Q_OS_IOS) diff --git a/client/amnezia_application.h b/client/amnezia_application.h index d15864e1..322a440c 100644 --- a/client/amnezia_application.h +++ b/client/amnezia_application.h @@ -9,11 +9,13 @@ #include #include "settings.h" +#include "vpnconnection.h" #include "ui/uilogic.h" #include "configurators/vpn_configurator.h" #include "ui/models/servers_model.h" #include "ui/models/containers_model.h" +#include "ui/controllers/connectionController.h" #define amnApp (static_cast(QCoreApplication::instance())) @@ -58,8 +60,12 @@ private: QTranslator* m_translator; QCommandLineParser m_parser; - QScopedPointer m_containersModel; - QScopedPointer m_serversModel; + QSharedPointer m_containersModel; + QSharedPointer m_serversModel; + + QScopedPointer m_vpnConnection; + + QScopedPointer m_connectionController; }; diff --git a/client/resources.qrc b/client/resources.qrc index 307c992d..1ea7bf38 100644 --- a/client/resources.qrc +++ b/client/resources.qrc @@ -222,5 +222,6 @@ ui/qml/Controls2/TextTypes/ButtonTextType.qml ui/qml/Controls2/Header2Type.qml images/controls/plus.svg + ui/qml/Components/ConnectButton.qml diff --git a/client/ui/controllers/connectionController.cpp b/client/ui/controllers/connectionController.cpp new file mode 100644 index 00000000..41dbed64 --- /dev/null +++ b/client/ui/controllers/connectionController.cpp @@ -0,0 +1,71 @@ +#include "connectionController.h" + +#include + +ConnectionController::ConnectionController(const QSharedPointer &serversModel, + const QSharedPointer &containersModel, + QObject *parent) : QObject(parent), m_serversModel(serversModel), m_containersModel(containersModel) +{ + +} + +bool ConnectionController::onConnectionButtonClicked() +{ + if (!isConnected) { + openVpnConnection(); + } else { + closeVpnConnection(); + } +} + +bool ConnectionController::openVpnConnection() +{ + int serverIndex = m_serversModel->getDefaultServerIndex(); + QModelIndex serverModelIndex = m_serversModel->index(serverIndex); + ServerCredentials credentials = qvariant_cast(m_serversModel->data(serverModelIndex, + ServersModel::ServersModelRoles::CredentialsRole)); + + DockerContainer container = m_containersModel->getDefaultContainer(); + QModelIndex containerModelIndex = m_containersModel->index(container); + const QJsonObject &containerConfig = qvariant_cast(m_containersModel->data(containerModelIndex, + ContainersModel::ContainersModelRoles::ConfigRole)); + + //todo error handling + qApp->processEvents(); + emit connectToVpn(serverIndex, credentials, container, containerConfig); + isConnected = true; + + +// int serverIndex = m_settings->defaultServerIndex(); +// ServerCredentials credentials = m_settings->serverCredentials(serverIndex); +// DockerContainer container = m_settings->defaultContainer(serverIndex); + +// if (m_settings->containers(serverIndex).isEmpty()) { +// set_labelErrorText(tr("VPN Protocols is not installed.\n Please install VPN container at first")); +// set_pushButtonConnectChecked(false); +// return; +// } + +// if (container == DockerContainer::None) { +// set_labelErrorText(tr("VPN Protocol not chosen")); +// set_pushButtonConnectChecked(false); +// return; +// } + + +// const QJsonObject &containerConfig = m_settings->containerConfig(serverIndex, container); + +// set_labelErrorText(""); +// set_pushButtonConnectChecked(true); +// set_pushButtonConnectEnabled(false); + +// qApp->processEvents(); + +// emit connectToVpn(serverIndex, credentials, container, containerConfig); +} + +bool ConnectionController::closeVpnConnection() +{ + emit disconnectFromVpn(); +} + diff --git a/client/ui/controllers/connectionController.h b/client/ui/controllers/connectionController.h new file mode 100644 index 00000000..125e9204 --- /dev/null +++ b/client/ui/controllers/connectionController.h @@ -0,0 +1,33 @@ +#ifndef CONNECTIONCONTROLLER_H +#define CONNECTIONCONTROLLER_H + +#include "ui/models/servers_model.h" +#include "ui/models/containers_model.h" + +class ConnectionController : public QObject +{ + Q_OBJECT + +public: + explicit ConnectionController(const QSharedPointer &serversModel, + const QSharedPointer &containersModel, + QObject *parent = nullptr); + +public slots: + bool onConnectionButtonClicked(); + +signals: + void connectToVpn(int serverIndex, const ServerCredentials &credentials, DockerContainer container, const QJsonObject &containerConfig); + void disconnectFromVpn(); + +private: + bool openVpnConnection(); + bool closeVpnConnection(); + + QSharedPointer m_serversModel; + QSharedPointer m_containersModel; + + bool isConnected = false; +}; + +#endif // CONNECTIONCONTROLLER_H diff --git a/client/ui/models/containers_model.cpp b/client/ui/models/containers_model.cpp index c7aa0ec1..db7572e6 100644 --- a/client/ui/models/containers_model.cpp +++ b/client/ui/models/containers_model.cpp @@ -17,7 +17,7 @@ bool ContainersModel::setData(const QModelIndex &index, const QVariant &value, i return false; } - if (role == DefaultRole) { + if (role == IsDefaultRole) { DockerContainer container = ContainerProps::allContainers().at(index.row()); m_settings->setDefaultContainer(m_selectedServerIndex, container); } @@ -33,22 +33,23 @@ QVariant ContainersModel::data(const QModelIndex &index, int role) const return QVariant(); } - DockerContainer c = ContainerProps::allContainers().at(index.row()); - if (role == NameRole) { - return ContainerProps::containerHumanNames().value(c); - } - if (role == DescRole) { - return ContainerProps::containerDescriptions().value(c); - } - if (role == DefaultRole) { - return c == m_settings->defaultContainer(m_selectedServerIndex); - } - if (role == ServiceTypeRole) { - return ContainerProps::containerService(c); - } - if (role == IsInstalledRole) { - return m_settings->containers(m_selectedServerIndex).contains(c); + 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: + return m_settings->containerConfig(m_selectedServerIndex, container); + case ServiceTypeRole: + return ContainerProps::containerService(container); + case IsInstalledRole: + return m_settings->containers(m_selectedServerIndex).contains(container); + case IsDefaultRole: + return container == m_settings->defaultContainer(m_selectedServerIndex); } + return QVariant(); } @@ -71,12 +72,17 @@ QString ContainersModel::getCurrentlyInstalledContainerName() return data(m_currentlyInstalledContainerIndex, NameRole).toString(); } +DockerContainer ContainersModel::getDefaultContainer() +{ + return m_settings->defaultContainer(m_selectedServerIndex); +} + QHash ContainersModel::roleNames() const { QHash roles; - roles[NameRole] = "name_role"; - roles[DescRole] = "desc_role"; - roles[DefaultRole] = "default_role"; - roles[ServiceTypeRole] = "service_type_role"; - roles[IsInstalledRole] = "is_installed_role"; + roles[NameRole] = "name"; + roles[DescRole] = "description"; + roles[ServiceTypeRole] = "serviceType"; + roles[IsInstalledRole] = "isInstalled"; + roles[IsDefaultRole] = "isDefault"; return roles; } diff --git a/client/ui/models/containers_model.h b/client/ui/models/containers_model.h index ba0fea57..c56511db 100644 --- a/client/ui/models/containers_model.h +++ b/client/ui/models/containers_model.h @@ -15,12 +15,13 @@ class ContainersModel : public QAbstractListModel public: ContainersModel(std::shared_ptr settings, QObject *parent = nullptr); public: - enum SiteRoles { + enum ContainersModelRoles { NameRole = Qt::UserRole + 1, DescRole, - DefaultRole, ServiceTypeRole, - IsInstalledRole + ConfigRole, + IsInstalledRole, + IsDefaultRole }; int rowCount(const QModelIndex &parent = QModelIndex()) const override; @@ -32,6 +33,9 @@ public: Q_INVOKABLE QString getCurrentlyInstalledContainerName(); +public slots: + DockerContainer getDefaultContainer(); + protected: QHash roleNames() const override; diff --git a/client/ui/models/servers_model.cpp b/client/ui/models/servers_model.cpp index 44ed2619..dccf59b9 100644 --- a/client/ui/models/servers_model.cpp +++ b/client/ui/models/servers_model.cpp @@ -37,36 +37,23 @@ QVariant ServersModel::data(const QModelIndex &index, int role) const const QJsonArray &servers = m_settings->serversArray(); const QJsonObject server = servers.at(index.row()).toObject(); - if (role == DescRole) { + switch (role) { + case DescRole: { auto description = server.value(config_key::description).toString(); if (description.isEmpty()) { return server.value(config_key::hostName).toString(); } return description; } - if (role == AddressRole) { + case AddressRole: return server.value(config_key::hostName).toString(); - } - if (role == IsDefaultRole) { + case CredentialsRole: + return QVariant::fromValue(m_settings->serverCredentials(index.row())); + case IsDefaultRole: return index.row() == m_settings->defaultServerIndex(); } + return QVariant(); - - -// if (!index.isValid() || index.row() < 0 -// || index.row() >= static_cast(m_data.size())) { -// return QVariant(); -// } -// if (role == DescRole) { -// return m_data[index.row()].desc; -// } -// if (role == AddressRole) { -// return m_data[index.row()].address; -// } -// if (role == IsDefaultRole) { -// return m_data[index.row()].isDefault; -// } -// return QVariant(); } void ServersModel::setDefaultServerIndex(int index) diff --git a/client/ui/models/servers_model.h b/client/ui/models/servers_model.h index cd46846b..30c8b5a2 100644 --- a/client/ui/models/servers_model.h +++ b/client/ui/models/servers_model.h @@ -18,6 +18,7 @@ public: enum ServersModelRoles { DescRole = Qt::UserRole + 1, AddressRole, + CredentialsRole, IsDefaultRole }; diff --git a/client/ui/qml/Components/ConnectButton.qml b/client/ui/qml/Components/ConnectButton.qml new file mode 100644 index 00000000..5457cf55 --- /dev/null +++ b/client/ui/qml/Components/ConnectButton.qml @@ -0,0 +1,40 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts + +Button { + id: root + + implicitHeight: 190 + implicitWidth: 190 + + background: Rectangle { + id: background + + radius: parent.width * 0.5 + + color: "transparent" + + border.width: 2 + border.color: "white" + } + + contentItem: Text { + height: 24 + + font.family: "PT Root UI VF" + font.weight: 700 + font.pixelSize: 20 + + color: "#D7D8DB" + text: root.text + + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + } + + onClicked: { + background.color = "red" + ConnectionController.onConnectionButtonClicked() + } +} diff --git a/client/ui/qml/Controls2/TextTypes/ButtonTextType.qml b/client/ui/qml/Controls2/TextTypes/ButtonTextType.qml index 93a36578..d26594d6 100644 --- a/client/ui/qml/Controls2/TextTypes/ButtonTextType.qml +++ b/client/ui/qml/Controls2/TextTypes/ButtonTextType.qml @@ -5,7 +5,7 @@ Text { color: "#D7D8DB" font.pixelSize: 16 - font.weight: 500 + font.weight: Font.Medium font.family: "PT Root UI VF" wrapMode: Text.WordWrap diff --git a/client/ui/qml/Controls2/TextTypes/Header1TextType.qml b/client/ui/qml/Controls2/TextTypes/Header1TextType.qml index dbc04b6a..99addc7b 100644 --- a/client/ui/qml/Controls2/TextTypes/Header1TextType.qml +++ b/client/ui/qml/Controls2/TextTypes/Header1TextType.qml @@ -5,7 +5,7 @@ Text { color: "#D7D8DB" font.pixelSize: 36 - font.weight: 700 + font.weight: Font.Bold font.family: "PT Root UI VF" font.letterSpacing: -0.03 diff --git a/client/ui/qml/Controls2/TextTypes/Header2TextType.qml b/client/ui/qml/Controls2/TextTypes/Header2TextType.qml index 1400ceb2..ed96f6f1 100644 --- a/client/ui/qml/Controls2/TextTypes/Header2TextType.qml +++ b/client/ui/qml/Controls2/TextTypes/Header2TextType.qml @@ -5,7 +5,7 @@ Text { color: "#D7D8DB" font.pixelSize: 25 - font.weight: 700 + font.weight: Font.Bold font.family: "PT Root UI VF" wrapMode: Text.WordWrap diff --git a/client/ui/qml/Controls2/TextTypes/LabelTextType.qml b/client/ui/qml/Controls2/TextTypes/LabelTextType.qml index 38649022..a2ffa18b 100644 --- a/client/ui/qml/Controls2/TextTypes/LabelTextType.qml +++ b/client/ui/qml/Controls2/TextTypes/LabelTextType.qml @@ -5,7 +5,7 @@ Text { color: "#878B91" font.pixelSize: 13 - font.weight: 400 + font.weight: Font.Normal font.family: "PT Root UI VF" font.letterSpacing: 0.02 diff --git a/client/ui/qml/Controls2/TextTypes/ParagraphTextType.qml b/client/ui/qml/Controls2/TextTypes/ParagraphTextType.qml index 269830bc..74b155ab 100644 --- a/client/ui/qml/Controls2/TextTypes/ParagraphTextType.qml +++ b/client/ui/qml/Controls2/TextTypes/ParagraphTextType.qml @@ -5,7 +5,7 @@ Text { color: "#D7D8DB" font.pixelSize: 16 - font.weight: 400 + 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 f4f4d13c..40eba148 100644 --- a/client/ui/qml/Pages2/PageHome.qml +++ b/client/ui/qml/Pages2/PageHome.qml @@ -12,6 +12,7 @@ import "../Pages" import "../Controls2" import "../Controls2/TextTypes" import "../Config" +import "../Components" PageBase { id: root @@ -24,6 +25,12 @@ PageBase { property string currentServerName: serversMenuContent.currentItem.delegateData.desc property string currentServerDescription: serversMenuContent.currentItem.delegateData.address + ConnectButton { + anchors.centerIn: parent + + text: "Подключиться" + } + Rectangle { id: buttonBackground anchors.fill: buttonContent @@ -136,11 +143,11 @@ PageBase { sourceModel: ContainersModel filters: [ ValueFilter { - roleName: "service_type_role" + roleName: "serviceType" value: ProtocolEnum.Vpn }, ValueFilter { - roleName: "is_installed_role" + roleName: "isInstalled" value: true } ] @@ -153,7 +160,7 @@ PageBase { borderWidth: 0 buttonImageColor: "#0E0E11" - buttonMaximumWidth: 150 + buttonMaximumWidth: 150 //todo make it dynamic defaultColor: "#D7D8DB" @@ -183,7 +190,7 @@ PageBase { checked: { if (modelData !== null) { - return modelData.default_role + return modelData.isDefault } return false } @@ -208,7 +215,7 @@ PageBase { // todo remove dirty hack? text: { if (modelData !== null) { - return modelData.name_role + return modelData.name } else return "" } @@ -235,7 +242,7 @@ PageBase { } onClicked: { - modelData.default_role = true + modelData.isDefault = true containersDropDown.text = containerRadioButtonText.text containersDropDown.menuVisible = false @@ -243,14 +250,16 @@ PageBase { } Component.onCompleted: { - if (modelData !== null && modelData.default_role) { - containersDropDown.text = modelData.name_role + if (modelData !== null && modelData.isDefault) { + containersDropDown.text = modelData.name } } } } BasicButtonType { + id: dnsButton + implicitHeight: 40 text: "Amnezia DNS"