diff --git a/client/amnezia_application.cpp b/client/amnezia_application.cpp index 4b7f31b7..df4a4ec1 100644 --- a/client/amnezia_application.cpp +++ b/client/amnezia_application.cpp @@ -121,6 +121,9 @@ void AmneziaApplication::init() m_pageController.reset(new PageController(m_serversModel)); m_engine->rootContext()->setContextProperty("PageController", m_pageController.get()); + m_installController.reset(new InstallController(m_serversModel, m_containersModel, m_settings)); + m_engine->rootContext()->setContextProperty("InstallController", m_installController.get()); + // m_uiLogic->registerPagesLogic(); diff --git a/client/resources.qrc b/client/resources.qrc index 77e7d86f..a50a23c5 100644 --- a/client/resources.qrc +++ b/client/resources.qrc @@ -227,5 +227,6 @@ images/connectionOff.svg images/connectionOn.svg images/controls/download.svg + ui/qml/Controls2/ProgressBarType.qml diff --git a/client/ui/controllers/connectionController.cpp b/client/ui/controllers/connectionController.cpp index ce52a2c8..58fef373 100644 --- a/client/ui/controllers/connectionController.cpp +++ b/client/ui/controllers/connectionController.cpp @@ -33,7 +33,7 @@ bool ConnectionController::openVpnConnection() DockerContainer container = m_containersModel->getDefaultContainer(); QModelIndex containerModelIndex = m_containersModel->index(container); const QJsonObject &containerConfig = qvariant_cast(m_containersModel->data(containerModelIndex, - ContainersModel::ContainersModelRoles::ConfigRole)); + ContainersModel::Roles::ConfigRole)); //todo error handling qApp->processEvents(); diff --git a/client/ui/controllers/installController.cpp b/client/ui/controllers/installController.cpp new file mode 100644 index 00000000..ae753382 --- /dev/null +++ b/client/ui/controllers/installController.cpp @@ -0,0 +1,82 @@ +#include "installController.h" + +#include + +#include "core/servercontroller.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) +{ + +} + +ErrorCode 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 } + }; + + if (m_shouldCreateServer) { + return installServer(container, config); + } else { + return installContainer(container, config); + } +} + +ErrorCode InstallController::installServer(DockerContainer container, QJsonObject& config) +{ + //todo check if container already installed + ServerController serverController(m_settings); + ErrorCode errorCode = serverController.setupContainer(m_currentlyInstalledServerCredentials, container, config); + if (errorCode == ErrorCode::NoError) { + QJsonObject server; + server.insert(config_key::hostName, m_currentlyInstalledServerCredentials.hostName); + server.insert(config_key::userName, m_currentlyInstalledServerCredentials.userName); + server.insert(config_key::password, m_currentlyInstalledServerCredentials.password); + server.insert(config_key::port, m_currentlyInstalledServerCredentials.port); + server.insert(config_key::description, m_settings->nextAvailableServerName()); + + server.insert(config_key::containers, QJsonArray{ config }); + server.insert(config_key::defaultContainer, ContainerProps::containerToString(container)); + + m_settings->addServer(server); + m_settings->setDefaultServer(m_settings->serversCount() - 1); + } + + return errorCode; +} + +ErrorCode InstallController::installContainer(DockerContainer container, QJsonObject& config) +{ + //todo check if container already installed + ServerCredentials serverCredentials = m_serversModel->getCurrentlyProcessedServerCredentials(); + + ServerController serverController(m_settings); + ErrorCode errorCode = serverController.setupContainer(serverCredentials, container, config); + if (errorCode == ErrorCode::NoError) { + m_containersModel->setData(m_containersModel->index(container), config, ContainersModel::Roles::ConfigRole); + emit installContainerFinished(); + } + + //todo error processing + return errorCode; +} + +void InstallController::setCurrentlyInstalledServerCredentials(const QString &hostName, const QString &userName, const QString &password, const int &port) +{ + m_currentlyInstalledServerCredentials = { hostName, userName, password, port }; +} + +void InstallController::setShouldCreateServer(bool shouldCreateServer) +{ + m_shouldCreateServer = shouldCreateServer; +} diff --git a/client/ui/controllers/installController.h b/client/ui/controllers/installController.h new file mode 100644 index 00000000..f9cd9fb0 --- /dev/null +++ b/client/ui/controllers/installController.h @@ -0,0 +1,40 @@ +#ifndef INSTALLCONTROLLER_H +#define INSTALLCONTROLLER_H + +#include + +#include "core/defs.h" +#include "containers/containers_defs.h" +#include "ui/models/servers_model.h" +#include "ui/models/containers_model.h" + +class InstallController : public QObject +{ + Q_OBJECT +public: + explicit InstallController(const QSharedPointer &serversModel, + const QSharedPointer &containersModel, + const std::shared_ptr &settings, + QObject *parent = nullptr); + +public slots: + ErrorCode install(DockerContainer container, int port, TransportProto transportProto); + void setCurrentlyInstalledServerCredentials(const QString &hostName, const QString &userName, const QString &password, const int &port); + void setShouldCreateServer(bool shouldCreateServer); + +signals: + void installContainerFinished(); +private: + ErrorCode installServer(DockerContainer container, QJsonObject& config); + ErrorCode installContainer(DockerContainer container, QJsonObject& config); + + QSharedPointer m_serversModel; + QSharedPointer m_containersModel; + std::shared_ptr m_settings; + + ServerCredentials m_currentlyInstalledServerCredentials; + + bool m_shouldCreateServer; +}; + +#endif // INSTALLCONTROLLER_H diff --git a/client/ui/models/containers_model.cpp b/client/ui/models/containers_model.cpp index db7572e6..a814a838 100644 --- a/client/ui/models/containers_model.cpp +++ b/client/ui/models/containers_model.cpp @@ -2,7 +2,6 @@ ContainersModel::ContainersModel(std::shared_ptr settings, QObject *parent) : m_settings(settings), QAbstractListModel(parent) { - setSelectedServerIndex(m_settings->defaultServerIndex()); } int ContainersModel::rowCount(const QModelIndex &parent) const @@ -17,9 +16,23 @@ bool ContainersModel::setData(const QModelIndex &index, const QVariant &value, i return false; } - if (role == IsDefaultRole) { - DockerContainer container = ContainerProps::allContainers().at(index.row()); - m_settings->setDefaultContainer(m_selectedServerIndex, container); + 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: + 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); } emit dataChanged(index, index); @@ -41,40 +54,42 @@ QVariant ContainersModel::data(const QModelIndex &index, int role) const case DescRole: return ContainerProps::containerDescriptions().value(container); case ConfigRole: - return m_settings->containerConfig(m_selectedServerIndex, container); + return m_settings->containerConfig(m_currentlyProcessedServerIndex, container); case ServiceTypeRole: return ContainerProps::containerService(container); + case DockerContainerRole: + return container; case IsInstalledRole: - return m_settings->containers(m_selectedServerIndex).contains(container); + return m_settings->containers(m_currentlyProcessedServerIndex).contains(container); + case IsCurrentlyInstalled: + return container == static_cast(m_currentlyInstalledContainerIndex); case IsDefaultRole: - return container == m_settings->defaultContainer(m_selectedServerIndex); + return container == m_settings->defaultContainer(m_currentlyProcessedServerIndex); } return QVariant(); } -void ContainersModel::setSelectedServerIndex(int index) +void ContainersModel::setCurrentlyProcessedServerIndex(int index) { beginResetModel(); - m_selectedServerIndex = index; + m_currentlyProcessedServerIndex = index; endResetModel(); } void ContainersModel::setCurrentlyInstalledContainerIndex(int index) { -// beginResetModel(); - m_currentlyInstalledContainerIndex = createIndex(index, 0); -// endResetModel(); -} - -QString ContainersModel::getCurrentlyInstalledContainerName() -{ - return data(m_currentlyInstalledContainerIndex, NameRole).toString(); + m_currentlyInstalledContainerIndex = index; } DockerContainer ContainersModel::getDefaultContainer() { - return m_settings->defaultContainer(m_selectedServerIndex); + return m_settings->defaultContainer(m_currentlyProcessedServerIndex); +} + +int ContainersModel::getCurrentlyInstalledContainerIndex() +{ + return m_currentlyInstalledContainerIndex; } QHash ContainersModel::roleNames() const { @@ -82,7 +97,9 @@ QHash ContainersModel::roleNames() const { roles[NameRole] = "name"; roles[DescRole] = "description"; roles[ServiceTypeRole] = "serviceType"; + roles[DockerContainerRole] = "dockerContainer"; roles[IsInstalledRole] = "isInstalled"; + roles[IsCurrentlyInstalled] = "isCurrentlyInstalled"; roles[IsDefaultRole] = "isDefault"; return roles; } diff --git a/client/ui/models/containers_model.h b/client/ui/models/containers_model.h index c56511db..15012925 100644 --- a/client/ui/models/containers_model.h +++ b/client/ui/models/containers_model.h @@ -15,12 +15,14 @@ class ContainersModel : public QAbstractListModel public: ContainersModel(std::shared_ptr settings, QObject *parent = nullptr); public: - enum ContainersModelRoles { + enum Roles { NameRole = Qt::UserRole + 1, DescRole, ServiceTypeRole, ConfigRole, + DockerContainerRole, IsInstalledRole, + IsCurrentlyInstalled, IsDefaultRole }; @@ -28,20 +30,20 @@ public: bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; - Q_INVOKABLE void setSelectedServerIndex(int index); - Q_INVOKABLE void setCurrentlyInstalledContainerIndex(int index); - - Q_INVOKABLE QString getCurrentlyInstalledContainerName(); public slots: DockerContainer getDefaultContainer(); + void setCurrentlyProcessedServerIndex(int index); + void setCurrentlyInstalledContainerIndex(int index); + int getCurrentlyInstalledContainerIndex(); + protected: QHash roleNames() const override; private: - int m_selectedServerIndex; - QModelIndex m_currentlyInstalledContainerIndex; + int m_currentlyProcessedServerIndex; + int m_currentlyInstalledContainerIndex; std::shared_ptr m_settings; }; diff --git a/client/ui/models/servers_model.cpp b/client/ui/models/servers_model.cpp index 8f39e140..fe973811 100644 --- a/client/ui/models/servers_model.cpp +++ b/client/ui/models/servers_model.cpp @@ -38,14 +38,14 @@ QVariant ServersModel::data(const QModelIndex &index, int role) const const QJsonObject server = servers.at(index.row()).toObject(); switch (role) { - case DescRole: { + case NameRole: { auto description = server.value(config_key::description).toString(); if (description.isEmpty()) { return server.value(config_key::hostName).toString(); } return description; } - case AddressRole: + case HostNameRole: return server.value(config_key::hostName).toString(); case CredentialsRole: return QVariant::fromValue(m_settings->serverCredentials(index.row())); @@ -74,10 +74,21 @@ const int ServersModel::getServersCount() return m_settings->serversCount(); } +void ServersModel::setCurrentlyProcessedServerIndex(int index) +{ + m_currenlyProcessedServerIndex = index; +} + +ServerCredentials ServersModel::getCurrentlyProcessedServerCredentials() +{ + return qvariant_cast(data(index(m_currenlyProcessedServerIndex), CredentialsRole)); +} + QHash ServersModel::roleNames() const { QHash roles; - roles[DescRole] = "desc"; - roles[AddressRole] = "address"; - roles[IsDefaultRole] = "is_default"; + roles[NameRole] = "name"; + roles[HostNameRole] = "hostName"; + roles[CredentialsRole] = "credentials"; + roles[IsDefaultRole] = "isDefault"; return roles; } diff --git a/client/ui/models/servers_model.h b/client/ui/models/servers_model.h index 9fb5ac1a..08b44976 100644 --- a/client/ui/models/servers_model.h +++ b/client/ui/models/servers_model.h @@ -16,8 +16,8 @@ class ServersModel : public QAbstractListModel Q_OBJECT public: enum ServersModelRoles { - DescRole = Qt::UserRole + 1, - AddressRole, + NameRole = Qt::UserRole + 1, + HostNameRole, CredentialsRole, IsDefaultRole }; @@ -34,11 +34,16 @@ public slots: const int getDefaultServerIndex(); const int getServersCount(); + void setCurrentlyProcessedServerIndex(int index); + ServerCredentials getCurrentlyProcessedServerCredentials(); + protected: QHash roleNames() const override; private: std::shared_ptr m_settings; + + int m_currenlyProcessedServerIndex; }; #endif // SERVERSMODEL_H diff --git a/client/ui/qml/Components/ConnectButton.qml b/client/ui/qml/Components/ConnectButton.qml index 8bf39f03..5002d5bd 100644 --- a/client/ui/qml/Components/ConnectButton.qml +++ b/client/ui/qml/Components/ConnectButton.qml @@ -65,6 +65,8 @@ Button { } case ConnectionState.Preparing: { console.log("Preparing") + connectionProccess.running = true + root.text = "Подключение..." break } case ConnectionState.Connecting: { diff --git a/client/ui/qml/Controls2/DropDownType.qml b/client/ui/qml/Controls2/DropDownType.qml index eab189f3..e2a3531f 100644 --- a/client/ui/qml/Controls2/DropDownType.qml +++ b/client/ui/qml/Controls2/DropDownType.qml @@ -8,40 +8,38 @@ Item { id: root property string text + property string textColor: "#d7d8db" + property string descriptionText property string headerText property string headerBackButtonImage - property var onClickedFunc - property string buttonImage: "qrc:/images/controls/chevron-down.svg" - property string buttonImageColor: "#494B50" + property var onRootButtonClicked + property string rootButtonImage: "qrc:/images/controls/chevron-down.svg" + property string rootButtonImageColor: "#494B50" + property string rootButtonDefaultColor: "#1C1D21" + property int rootButtonMaximumWidth - property int buttonMaximumWidth - - property string defaultColor: "#1C1D21" - - property string textColor: "#d7d8db" - - property string borderColor: "#494B50" - property int borderWidth: 1 + property string rootButtonBorderColor: "#494B50" + property int rootButtonBorderWidth: 1 property Component menuDelegate property variant menuModel property alias menuVisible: menu.visible - implicitWidth: buttonContent.implicitWidth - implicitHeight: buttonContent.implicitHeight + implicitWidth: rootButtonContent.implicitWidth + implicitHeight: rootButtonContent.implicitHeight Rectangle { - id: buttonBackground - anchors.fill: buttonContent + id: rootButtonBackground + anchors.fill: rootButtonContent radius: 16 - color: defaultColor - border.color: borderColor - border.width: borderWidth + color: rootButtonDefaultColor + border.color: rootButtonBorderColor + border.width: rootButtonBorderWidth Behavior on border.width { PropertyAnimation { duration: 200 } @@ -49,7 +47,7 @@ Item { } RowLayout { - id: buttonContent + id: rootButtonContent anchors.fill: parent spacing: 0 @@ -71,7 +69,7 @@ Item { horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter - Layout.maximumWidth: buttonMaximumWidth ? buttonMaximumWidth : implicitWidth + Layout.maximumWidth: rootButtonMaximumWidth ? rootButtonMaximumWidth : implicitWidth color: root.textColor text: root.text @@ -81,38 +79,36 @@ Item { } } + //todo change to image type ImageButtonType { - id: button - Layout.leftMargin: 4 Layout.rightMargin: 16 hoverEnabled: false - image: buttonImage - imageColor: buttonImageColor - onClicked: { - if (onClickedFunc && typeof onClickedFunc === "function") { - onClickedFunc() - } - } + image: rootButtonImage + imageColor: rootButtonImageColor } } MouseArea { - anchors.fill: buttonContent + anchors.fill: rootButtonContent cursorShape: Qt.PointingHandCursor hoverEnabled: true onEntered: { - buttonBackground.border.width = borderWidth + rootButtonBackground.border.width = rootButtonBorderWidth } onExited: { - buttonBackground.border.width = 0 + rootButtonBackground.border.width = 0 } onClicked: { - menu.visible = true + if (onRootButtonClicked && typeof onRootButtonClicked === "function") { + onRootButtonClicked() + } else { + menu.visible = true + } } } @@ -132,7 +128,7 @@ Item { radius: 16 color: "#1C1D21" - border.color: borderColor + border.color: "#494B50" border.width: 1 } diff --git a/client/ui/qml/Controls2/Header2Type.qml b/client/ui/qml/Controls2/Header2Type.qml index ef463acd..f985d523 100644 --- a/client/ui/qml/Controls2/Header2Type.qml +++ b/client/ui/qml/Controls2/Header2Type.qml @@ -59,8 +59,8 @@ Item { visible: image ? true : false onClicked: { - if (actionButtonImage && typeof actionButtonImage === "function") { - actionButtonImage() + if (actionButtonFunction && typeof actionButtonFunction === "function") { + actionButtonFunction() } } } diff --git a/client/ui/qml/Controls2/ProgressBarType.qml b/client/ui/qml/Controls2/ProgressBarType.qml new file mode 100644 index 00000000..f2f2370a --- /dev/null +++ b/client/ui/qml/Controls2/ProgressBarType.qml @@ -0,0 +1,19 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts + +ProgressBar { + id: root + + implicitHeight: 4 + + background: Rectangle { + color: "#412102" + } + + contentItem: Rectangle { + width: root.visualPosition * root.width + height: root.height + color: "#FBB26A" + } +} diff --git a/client/ui/qml/Pages2/PageHome.qml b/client/ui/qml/Pages2/PageHome.qml index 8edd6b12..a29a4089 100644 --- a/client/ui/qml/Pages2/PageHome.qml +++ b/client/ui/qml/Pages2/PageHome.qml @@ -20,8 +20,10 @@ Item { property string borderColor: "#2C2D30" - property string currentServerName: serversMenuContent.currentItem.delegateData.desc - property string currentServerDescription: serversMenuContent.currentItem.delegateData.address + property string currentServerName: serversMenuContent.currentItem.delegateData.name + property string currentServerHostName: serversMenuContent.currentItem.delegateData.hostName + + property string currentContainerName ConnectButton { anchors.centerIn: parent @@ -72,7 +74,7 @@ Item { Layout.bottomMargin: 44 Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter - text: currentServerDescription + text: currentContainerName + " | " + currentServerHostName } } @@ -127,7 +129,7 @@ Item { Layout.bottomMargin: 24 Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter - text: currentServerDescription + text: currentServerHostName } RowLayout { @@ -150,16 +152,21 @@ Item { implicitHeight: 40 - borderWidth: 0 - buttonImageColor: "#0E0E11" - buttonMaximumWidth: 150 //todo make it dynamic - - defaultColor: "#D7D8DB" + rootButtonBorderWidth: 0 + rootButtonImageColor: "#0E0E11" + rootButtonMaximumWidth: 150 //todo make it dynamic + rootButtonDefaultColor: "#D7D8DB" textColor: "#0E0E11" headerText: "Протокол подключения" headerBackButtonImage: "qrc:/images/controls/arrow-left.svg" + onRootButtonClicked: function() { + ServersModel.setCurrentlyProcessedServerIndex(serversMenuContent.currentIndex) + ContainersModel.setCurrentlyProcessedServerIndex(serversMenuContent.currentIndex) + containersDropDown.menuVisible = true + } + menuModel: proxyContainersModel ButtonGroup { @@ -265,9 +272,11 @@ Item { modelData.isDefault = true containersDropDown.text = containerRadioButtonText.text + root.currentContainerName = containerRadioButtonText.text containersDropDown.menuVisible = false } else { ContainersModel.setCurrentlyInstalledContainerIndex(proxyContainersModel.mapToSource(delegateIndex)) + InstallController.setShouldCreateServer(false) PageController.goToPage(PageEnum.PageSetupWizardProtocolSettings) containersDropDown.menuVisible = false menu.visible = false @@ -307,6 +316,10 @@ Item { actionButtonImage: "qrc:/images/controls/plus.svg" headerText: "Серверы" + + actionButtonFunction: function() { + PageController.goToPage(PageEnum.PageSetupWizardStart) + } } } @@ -378,7 +391,7 @@ Item { Text { id: serverRadioButtonText - text: desc + text: name color: "#D7D8DB" font.pixelSize: 16 font.weight: 400 @@ -402,11 +415,11 @@ Item { } onClicked: { - root.currentServerName = desc - root.currentServerDescription = address + serversMenuContent.currentIndex = index + root.currentServerName = name + root.currentServerHostName = hostName ServersModel.setDefaultServerIndex(index) - ContainersModel.setSelectedServerIndex(index) } MouseArea { diff --git a/client/ui/qml/Pages2/PageSetupWizardCredentials.qml b/client/ui/qml/Pages2/PageSetupWizardCredentials.qml index 479e4bfa..def76b89 100644 --- a/client/ui/qml/Pages2/PageSetupWizardCredentials.qml +++ b/client/ui/qml/Pages2/PageSetupWizardCredentials.qml @@ -38,18 +38,25 @@ Item { } TextFieldWithHeaderType { + id: hostname + Layout.fillWidth: true headerText: "Server IP adress [:port]" } TextFieldWithHeaderType { + id: username + Layout.fillWidth: true headerText: "Login to connect via SSH" } TextFieldWithHeaderType { + id: secretData + Layout.fillWidth: true headerText: "Password / Private key" + textField.echoMode: TextInput.Password } BasicButtonType { @@ -77,6 +84,9 @@ Item { text: qsTr("Выбрать протокол для установки") onClicked: function() { + InstallController.setShouldCreateServer(true) + InstallController.setCurrentlyInstalledServerCredentials(hostname.textField.text, username.textField.text, secretData.textField.text) + PageController.goToPage(PageEnum.PageSetupWizardProtocols) } } diff --git a/client/ui/qml/Pages2/PageSetupWizardInstalling.qml b/client/ui/qml/Pages2/PageSetupWizardInstalling.qml index fa0d5a14..c2c761cc 100644 --- a/client/ui/qml/Pages2/PageSetupWizardInstalling.qml +++ b/client/ui/qml/Pages2/PageSetupWizardInstalling.qml @@ -2,6 +2,8 @@ import QtQuick import QtQuick.Controls import QtQuick.Layouts +import SortFilterProxyModel 0.2 + import PageEnum 1.0 import "./" @@ -12,32 +14,111 @@ import "../Config" Item { id: root + property real progressBarValue: 0 + + SortFilterProxyModel { + id: proxyContainersModel + sourceModel: ContainersModel + filters: [ + ValueFilter { + roleName: "isCurrentlyInstalled" + value: true + } + ] + } + FlickableType { id: fl - anchors.top: root.top - anchors.bottom: root.bottom + anchors.fill: parent contentHeight: content.height - ColumnLayout { + Column { id: content anchors.top: parent.top anchors.left: parent.left anchors.right: parent.right - anchors.rightMargin: 16 - anchors.leftMargin: 16 spacing: 16 - HeaderType { - Layout.fillWidth: true - Layout.topMargin: 20 + ListView { + // todo change id naming + id: container + width: parent.width + height: container.contentItem.height + currentIndex: -1 + clip: true + interactive: false + model: proxyContainersModel - //TODO remove later - backButtonImage: "qrc:/images/controls/arrow-left.svg" + delegate: Item { + implicitWidth: container.width + implicitHeight: delegateContent.implicitHeight - headerText: "Установка" - descriptionText: ContainersModel.getCurrentlyInstalledContainerName() + ColumnLayout { + id: delegateContent + + anchors.fill: parent + anchors.rightMargin: 16 + anchors.leftMargin: 16 + + HeaderType { + Layout.fillWidth: true + Layout.topMargin: 20 + + headerText: "Установка" + descriptionText: name + } + + ProgressBarType { + id: progressBar + + Layout.fillWidth: true + Layout.topMargin: 32 + + value: progressBarValue + + Timer { + id: timer + + interval: 300 + repeat: true + running: true + onTriggered: { + progressBarValue += 0.001 + } + } + } + + ParagraphTextType { + Layout.fillWidth: true + Layout.topMargin: 8 + + text: "Обычно это занимает не больше 5 минут" + } + } + } + } + } + + Timer { + id: closePageTimer + + interval: 1000 + repeat: false + running: false + onTriggered: { + // todo go to root installing page + PageController.goToPage(PageEnum.PageHome) + } + } + + Connections { + target: InstallController + + function onInstallContainerFinished() { + progressBarValue = 1 + closePageTimer.start() } } } diff --git a/client/ui/qml/Pages2/PageSetupWizardProtocolSettings.qml b/client/ui/qml/Pages2/PageSetupWizardProtocolSettings.qml index 6c3b64b9..9499f5a5 100644 --- a/client/ui/qml/Pages2/PageSetupWizardProtocolSettings.qml +++ b/client/ui/qml/Pages2/PageSetupWizardProtocolSettings.qml @@ -2,7 +2,11 @@ import QtQuick import QtQuick.Controls import QtQuick.Layouts +import SortFilterProxyModel 0.2 + import PageEnum 1.0 +import ContainerProps 1.0 +import ProtocolProps 1.0 import "./" import "../Controls2" @@ -12,83 +16,169 @@ import "../Config" Item { id: root + SortFilterProxyModel { + id: proxyContainersModel + sourceModel: ContainersModel + filters: [ + ValueFilter { + roleName: "isCurrentlyInstalled" + value: true + } + ] + } + FlickableType { id: fl - anchors.top: root.top - anchors.bottom: root.bottom + anchors.fill: parent contentHeight: content.height - ColumnLayout { + Column { id: content anchors.top: parent.top anchors.left: parent.left anchors.right: parent.right - anchors.rightMargin: 16 - anchors.leftMargin: 16 spacing: 16 - HeaderType { - Layout.fillWidth: true - Layout.topMargin: 20 + ListView { + // todo change id naming + id: containers + width: parent.width + height: containers.contentItem.height + currentIndex: -1 + clip: true + interactive: false + model: proxyContainersModel - backButtonImage: "qrc:/images/controls/arrow-left.svg" + delegate: Item { + implicitWidth: containers.width + implicitHeight: delegateContent.implicitHeight - headerText: "Установка " + ContainersModel.getCurrentlyInstalledContainerName() - descriptionText: "Эти настройки можно будет изменить позже" - } + ColumnLayout { + id: delegateContent - ParagraphTextType { - Layout.topMargin: 16 + anchors.fill: parent + anchors.rightMargin: 16 + anchors.leftMargin: 16 - text: "Network protocol" - } + HeaderType { + id: header - //TODO move to separete control - Rectangle { - implicitWidth: buttonGroup.implicitWidth - implicitHeight: buttonGroup.implicitHeight + Layout.fillWidth: true + Layout.topMargin: 20 - color: "#1C1D21" - radius: 16 + backButtonImage: "qrc:/images/controls/arrow-left.svg" - RowLayout { - id: buttonGroup + headerText: "Установка " + name + descriptionText: "Эти настройки можно будет изменить позже" + } - spacing: 0 + ParagraphTextType { + id: transportProtoHeader - HorizontalRadioButton { - implicitWidth: (root.width - 32) / 2 - text: "UDP" - } + Layout.topMargin: 16 - HorizontalRadioButton { - implicitWidth: (root.width - 32) / 2 - text: "TCP" + text: "Network protocol" + } + + Rectangle { + id: transportProtoBackground + + implicitWidth: transportProtoButtonGroup.implicitWidth + implicitHeight: transportProtoButtonGroup.implicitHeight + + color: "#1C1D21" + radius: 16 + + RowLayout { + id: transportProtoButtonGroup + + property int currentIndex + spacing: 0 + + HorizontalRadioButton { + checked: transportProtoButtonGroup.currentIndex === 0 + + implicitWidth: (root.width - 32) / 2 + text: "UDP" + + hoverEnabled: !transportProtoButtonMouseArea.enabled + + onClicked: { + transportProtoButtonGroup.currentIndex = 0 + } + } + + HorizontalRadioButton { + checked: transportProtoButtonGroup.currentIndex === 1 + + implicitWidth: (root.width - 32) / 2 + text: "TCP" + + hoverEnabled: !transportProtoButtonMouseArea.enabled + + onClicked: { + transportProtoButtonGroup.currentIndex = 1 + } + } + } + + MouseArea { + id: transportProtoButtonMouseArea + + anchors.fill: parent + } + } + + TextFieldWithHeaderType { + id: port + + Layout.fillWidth: true + headerText: "Port" + } + + Rectangle { + // todo make it dynamic + implicitHeight: root.height - port.implicitHeight - + transportProtoBackground.implicitHeight - transportProtoHeader.implicitHeight - + header.implicitHeight - installButton.implicitHeight - 100 + + color: "transparent" + } + + BasicButtonType { + id: installButton + + Layout.fillWidth: true + Layout.bottomMargin: 32 + + text: qsTr("Установить") + + onClicked: function() { + PageController.goToPage(PageEnum.PageSetupWizardInstalling); + + InstallController.install(dockerContainer, port.textFieldText, transportProtoButtonGroup.currentIndex) + } + } + + Component.onCompleted: { + //todo move to protocols model? + var defaultContainerProto = ContainerProps.defaultProtocol(dockerContainer) + + if (ProtocolProps.defaultPort(defaultContainerProto) < 0) { + port.visible = false + } else { + port.textFieldText = ProtocolProps.defaultPort(defaultContainerProto) + } + transportProtoButtonGroup.currentIndex = ProtocolProps.defaultTransportProto(defaultContainerProto) + + port.enabled = ProtocolProps.defaultPortChangeable(defaultContainerProto) + transportProtoButtonMouseArea.enabled = !ProtocolProps.defaultTransportProtoChangeable(defaultContainerProto) + } } } } - - TextFieldWithHeaderType { - Layout.fillWidth: true - headerText: "Port" - } - } - } - - BasicButtonType { - anchors.bottom: parent.bottom - anchors.left: parent.left - anchors.right: parent.right - anchors.rightMargin: 16 - anchors.leftMargin: 16 - anchors.bottomMargin: 32 - - text: qsTr("Установить") - - onClicked: function() { - PageController.goToPage(PageEnum.PageSetupWizardInstalling) } } } diff --git a/client/ui/qml/Pages2/PageSetupWizardProtocols.qml b/client/ui/qml/Pages2/PageSetupWizardProtocols.qml index 24a86a07..11b09edd 100644 --- a/client/ui/qml/Pages2/PageSetupWizardProtocols.qml +++ b/client/ui/qml/Pages2/PageSetupWizardProtocols.qml @@ -18,10 +18,6 @@ Item { id: proxyContainersModel sourceModel: ContainersModel filters: [ - ValueFilter { - roleName: "is_installed_role" - value: false - }, ValueFilter { roleName: "service_type_role" value: ProtocolEnum.Vpn diff --git a/client/ui/qml/Pages2/PageSetupWizardStart.qml b/client/ui/qml/Pages2/PageSetupWizardStart.qml index 5f1a0479..8293b210 100644 --- a/client/ui/qml/Pages2/PageSetupWizardStart.qml +++ b/client/ui/qml/Pages2/PageSetupWizardStart.qml @@ -96,7 +96,7 @@ Item { radius: 16 color: "#1C1D21" - border.color: borderColor + border.color: "#2C2D30" border.width: 1 }