From 1e180489a40b89265c7789edbfb3813985d201e0 Mon Sep 17 00:00:00 2001 From: "vladimir.kuznetsov" Date: Sat, 27 May 2023 22:46:41 +0800 Subject: [PATCH] added display of vpn containers and services on the settings page - added PageSettingsData and implementation of 'remove all containers' button --- client/images/controls/edit-3.svg | 4 + client/resources.qrc | 5 + client/ui/models/containers_model.cpp | 18 +++ client/ui/models/containers_model.h | 2 + .../ConnectionTypeSelectionDrawer.qml | 22 ++-- .../Components/ContainersPageHomeListView.qml | 1 - .../PageSettingsContainersListView.qml | 107 ++++++++++++++++++ client/ui/qml/Controls2/DividerType.qml | 8 ++ .../ui/qml/Controls2/LabelWithButtonType.qml | 58 +++++++--- .../Controls2/TextTypes/ListItemTitleType.qml | 12 ++ client/ui/qml/Pages2/PageHome.qml | 19 +--- client/ui/qml/Pages2/PageSettings.qml | 95 ++++++++++++++-- client/ui/qml/Pages2/PageSettingsData.qml | 67 +++++++++++ .../ui/qml/Pages2/PageSettingsServersList.qml | 13 +-- .../Pages2/PageSetupWizardConfigSource.qml | 27 ++--- .../qml/Pages2/PageSetupWizardInstalling.qml | 8 ++ .../qml/Pages2/PageSetupWizardProtocols.qml | 10 +- client/ui/qml/Pages2/PageSetupWizardStart.qml | 3 +- client/ui/qml/Pages2/PageStart.qml | 16 ++- 19 files changed, 393 insertions(+), 102 deletions(-) create mode 100644 client/images/controls/edit-3.svg create mode 100644 client/ui/qml/Components/PageSettingsContainersListView.qml create mode 100644 client/ui/qml/Controls2/DividerType.qml create mode 100644 client/ui/qml/Controls2/TextTypes/ListItemTitleType.qml create mode 100644 client/ui/qml/Pages2/PageSettingsData.qml diff --git a/client/images/controls/edit-3.svg b/client/images/controls/edit-3.svg new file mode 100644 index 00000000..4e1dc071 --- /dev/null +++ b/client/images/controls/edit-3.svg @@ -0,0 +1,4 @@ + + + + diff --git a/client/resources.qrc b/client/resources.qrc index ca1674af..ca02df7d 100644 --- a/client/resources.qrc +++ b/client/resources.qrc @@ -234,5 +234,10 @@ ui/qml/Pages2/PageSettings.qml ui/qml/Controls2/PageType.qml ui/qml/Controls2/PopupType.qml + images/controls/edit-3.svg + ui/qml/Pages2/PageSettingsData.qml + ui/qml/Components/PageSettingsContainersListView.qml + ui/qml/Controls2/TextTypes/ListItemTitleType.qml + ui/qml/Controls2/DividerType.qml diff --git a/client/ui/models/containers_model.cpp b/client/ui/models/containers_model.cpp index 6a999011..4dc7010e 100644 --- a/client/ui/models/containers_model.cpp +++ b/client/ui/models/containers_model.cpp @@ -1,5 +1,7 @@ #include "containers_model.h" +#include "core/servercontroller.h" + ContainersModel::ContainersModel(std::shared_ptr settings, QObject *parent) : m_settings(settings), QAbstractListModel(parent) { } @@ -106,6 +108,22 @@ int ContainersModel::getCurrentlyInstalledContainerIndex() return m_currentlyInstalledContainerIndex; } +void ContainersModel::removeAllContainers() +{ + + ServerController serverController(m_settings); + auto errorCode = serverController.removeAllContainers(m_settings->serverCredentials(m_currentlyProcessedServerIndex)); + + if (errorCode == ErrorCode::NoError) { + beginResetModel(); + m_settings->setContainers(m_currentlyProcessedServerIndex, {}); + m_settings->setDefaultContainer(m_currentlyProcessedServerIndex, DockerContainer::None); + endResetModel(); + } + + //todo process errors +} + QHash ContainersModel::roleNames() const { QHash roles; roles[NameRole] = "name"; diff --git a/client/ui/models/containers_model.h b/client/ui/models/containers_model.h index 36b5567a..642b6680 100644 --- a/client/ui/models/containers_model.h +++ b/client/ui/models/containers_model.h @@ -48,6 +48,8 @@ public slots: void setCurrentlyInstalledContainerIndex(int index); int getCurrentlyInstalledContainerIndex(); + void removeAllContainers(); + protected: QHash roleNames() const override; diff --git a/client/ui/qml/Components/ConnectionTypeSelectionDrawer.qml b/client/ui/qml/Components/ConnectionTypeSelectionDrawer.qml index 20029eb0..2e6b3f2e 100644 --- a/client/ui/qml/Components/ConnectionTypeSelectionDrawer.qml +++ b/client/ui/qml/Components/ConnectionTypeSelectionDrawer.qml @@ -37,12 +37,11 @@ Drawer { anchors.left: parent.left anchors.right: parent.right - anchors.rightMargin: 16 - anchors.leftMargin: 16 - Header2TextType { Layout.fillWidth: true Layout.topMargin: 24 + Layout.rightMargin: 16 + Layout.leftMargin: 16 Layout.alignment: Qt.AlignHCenter text: "Данные для подключения" @@ -52,7 +51,7 @@ Drawer { LabelWithButtonType { id: ip Layout.fillWidth: true - Layout.topMargin: 32 + Layout.topMargin: 16 text: "IP, логин и пароль от сервера" buttonImage: "qrc:/images/controls/chevron-right.svg" @@ -62,11 +61,9 @@ Drawer { root.visible = false } } - Rectangle { - Layout.fillWidth: true - height: 1 - color: "#2C2D30" - } + + DividerType {} + LabelWithButtonType { Layout.fillWidth: true @@ -78,10 +75,7 @@ Drawer { root.visible = false } } - Rectangle { - Layout.fillWidth: true - height: 1 - color: "#2C2D30" - } + + DividerType {} } } diff --git a/client/ui/qml/Components/ContainersPageHomeListView.qml b/client/ui/qml/Components/ContainersPageHomeListView.qml index 309b4217..f8b5101e 100644 --- a/client/ui/qml/Components/ContainersPageHomeListView.qml +++ b/client/ui/qml/Components/ContainersPageHomeListView.qml @@ -116,4 +116,3 @@ ListView { } } } - diff --git a/client/ui/qml/Components/PageSettingsContainersListView.qml b/client/ui/qml/Components/PageSettingsContainersListView.qml new file mode 100644 index 00000000..2a59b8b2 --- /dev/null +++ b/client/ui/qml/Components/PageSettingsContainersListView.qml @@ -0,0 +1,107 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts + +import SortFilterProxyModel 0.2 + +import PageEnum 1.0 +import ProtocolEnum 1.0 + +import "../Controls2" +import "../Controls2/TextTypes" + + +ListView { + id: root + + height: root.contentItem.height + + clip: true + + ButtonGroup { + id: containersRadioButtonGroup + } + + delegate: Item { + implicitWidth: parent.width + implicitHeight: containerRadioButton.implicitHeight + + RadioButton { + id: containerRadioButton + + implicitWidth: parent.width + implicitHeight: containerRadioButtonContent.implicitHeight + + hoverEnabled: true + + ButtonGroup.group: containersRadioButtonGroup + + checked: isDefault + + indicator: Rectangle { + anchors.fill: parent + color: containerRadioButton.hovered ? Qt.rgba(1, 1, 1, 0.08) : "transparent" + + Behavior on color { + PropertyAnimation { duration: 200 } + } + } + + checkable: isInstalled + + RowLayout { + id: containerRadioButtonContent + anchors.fill: parent + + anchors.rightMargin: 16 + anchors.leftMargin: 16 + + z: 1 + + ColumnLayout { + Layout.topMargin: 20 + Layout.bottomMargin: 20 + + ListItemTitleType { + Layout.fillWidth: true + + text: name + } + + CaptionTextType { + Layout.fillWidth: true + + text: description + color: "#878B91" + } + } + + Image { + source: isInstalled ? "qrc:/images/controls/chevron-right.svg" : "qrc:/images/controls/download.svg" + + width: 24 + height: 24 + + Layout.rightMargin: 8 + } + } + + onClicked: { + if (isInstalled) { +// isDefault = true +// root.currentIndex = index + } else { + ContainersModel.setCurrentlyInstalledContainerIndex(root.model.mapToSource(index)) + InstallController.setShouldCreateServer(false) + goToPage(PageEnum.PageSetupWizardProtocolSettings) + } + } + + MouseArea { + anchors.fill: containerRadioButton + cursorShape: Qt.PointingHandCursor + enabled: false + } + } + } +} diff --git a/client/ui/qml/Controls2/DividerType.qml b/client/ui/qml/Controls2/DividerType.qml new file mode 100644 index 00000000..6341807a --- /dev/null +++ b/client/ui/qml/Controls2/DividerType.qml @@ -0,0 +1,8 @@ +import QtQuick +import QtQuick.Layouts + +Rectangle { + Layout.fillWidth: true + height: 1 + color: "#2C2D30" +} diff --git a/client/ui/qml/Controls2/LabelWithButtonType.qml b/client/ui/qml/Controls2/LabelWithButtonType.qml index 2530f583..e4e711a6 100644 --- a/client/ui/qml/Controls2/LabelWithButtonType.qml +++ b/client/ui/qml/Controls2/LabelWithButtonType.qml @@ -2,6 +2,8 @@ import QtQuick import QtQuick.Controls import QtQuick.Layouts +import "TextTypes" + Item { id: root @@ -13,12 +15,16 @@ Item { property alias buttonImage: button.image property string iconImage + property string textColor: "#d7d8db" + implicitWidth: content.implicitWidth implicitHeight: content.implicitHeight RowLayout { id: content anchors.fill: parent + anchors.leftMargin: 16 + anchors.rightMargin: 16 Image { id: icon @@ -28,34 +34,28 @@ Item { } ColumnLayout { - Text { - font.family: "PT Root UI VF" - font.styleName: "normal" - font.pixelSize: 18 - color: "#d7d8db" + ListItemTitleType { text: root.text - wrapMode: Text.WordWrap + color: textColor Layout.fillWidth: true - height: 22 + Layout.topMargin: 16 + Layout.bottomMargin: description.visible ? 0 : 16 horizontalAlignment: Text.AlignLeft verticalAlignment: Text.AlignVCenter } - Text { - font.family: "PT Root UI VF" - font.styleName: "normal" - font.pixelSize: 13 - font.letterSpacing: 0.02 + CaptionTextType { + id: description + color: "#878B91" text: root.descriptionText - wrapMode: Text.WordWrap visible: root.descriptionText !== "" Layout.fillWidth: true - height: 16 + Layout.bottomMargin: 16 horizontalAlignment: Text.AlignLeft verticalAlignment: Text.AlignVCenter @@ -88,21 +88,45 @@ Item { } } } + + Rectangle { + id: background + anchors.fill: root + color: "transparent" + + + Behavior on color { + PropertyAnimation { duration: 200 } + } + } + MouseArea { anchors.fill: parent cursorShape: Qt.PointingHandCursor hoverEnabled: true onEntered: { - imageBackground.color = button.hoveredColor + if (buttonImage) { + imageBackground.color = button.hoveredColor + } else { + background.color = button.hoveredColor + } } onExited: { - imageBackground.color = button.defaultColor + if (buttonImage) { + imageBackground.color = button.defaultColor + } else { + background.color = button.defaultColor + } } onPressedChanged: { - imageBackground.color = pressed ? button.pressedColor : entered ? button.hoveredColor : button.defaultColor + if (buttonImage) { + imageBackground.color = pressed ? button.pressedColor : entered ? button.hoveredColor : button.defaultColor + } else { + background.color = pressed ? button.pressedColor : entered ? button.hoveredColor : button.defaultColor + } } onClicked: { diff --git a/client/ui/qml/Controls2/TextTypes/ListItemTitleType.qml b/client/ui/qml/Controls2/TextTypes/ListItemTitleType.qml new file mode 100644 index 00000000..23069db2 --- /dev/null +++ b/client/ui/qml/Controls2/TextTypes/ListItemTitleType.qml @@ -0,0 +1,12 @@ +import QtQuick + +Text { + height: 21.6 + + color: "#D7D8DB" + font.pixelSize: 18 + 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 d5455849..1fba3bff 100644 --- a/client/ui/qml/Pages2/PageHome.qml +++ b/client/ui/qml/Pages2/PageHome.qml @@ -37,21 +37,6 @@ PageType { } } - Connections { - target: InstallController - - function onInstallContainerFinished() { - goToStartPage() - menu.visible = true - containersDropDown.menuVisible = true - } - - function onInstallServerFinished() { - goToStartPage() - menu.visible = true - } - } - Rectangle { id: buttonBackground anchors.fill: buttonContent @@ -166,6 +151,10 @@ PageType { ValueFilter { roleName: "serviceType" value: ProtocolEnum.Vpn + }, + ValueFilter { + roleName: "isSupported" + value: true } ] } diff --git a/client/ui/qml/Pages2/PageSettings.qml b/client/ui/qml/Pages2/PageSettings.qml index 9d5b7442..57c252b4 100644 --- a/client/ui/qml/Pages2/PageSettings.qml +++ b/client/ui/qml/Pages2/PageSettings.qml @@ -5,6 +5,7 @@ import QtQuick.Layouts import SortFilterProxyModel 0.2 import PageEnum 1.0 +import ProtocolEnum 1.0 import ContainerProps 1.0 import ProtocolProps 1.0 @@ -12,6 +13,7 @@ import "./" import "../Controls2" import "../Controls2/TextTypes" import "../Config" +import "../Components" PageType { id: root @@ -27,35 +29,28 @@ PageType { ] } - FlickableType { - id: fl - anchors.fill: parent - contentHeight: content.height - ColumnLayout { id: content - anchors.top: parent.top - anchors.left: parent.left - anchors.right: parent.right + anchors.fill: parent spacing: 16 Repeater { + id: header model: proxyServersModel delegate: HeaderType { - id: header - Layout.fillWidth: true Layout.topMargin: 20 Layout.leftMargin: 16 Layout.rightMargin: 16 - actionButtonImage: "qrc:/images/controls/plus.svg" + actionButtonImage: "qrc:/images/controls/edit-3.svg" backButtonImage: "qrc:/images/controls/arrow-left.svg" headerText: name + descriptionText: hostName actionButtonFunction: function() { connectionTypeSelection.visible = true @@ -66,6 +61,82 @@ PageType { } } } + + TabBar { + id: tabBar + + Layout.fillWidth: true + + background: Rectangle { + color: "transparent" + } + + TabButtonType { + isSelected: tabBar.currentIndex === 0 + text: qsTr("Protocols") + } + TabButtonType { + isSelected: tabBar.currentIndex === 1 + text: qsTr("Services") + } + TabButtonType { + isSelected: tabBar.currentIndex === 2 + text: qsTr("Data") + } + } + + StackLayout { + id: stackLayout + currentIndex: tabBar.currentIndex + + Layout.fillWidth: true + height: root.height + + StackView { + id: protocolsStackView + initialItem: PageSettingsContainersListView { + model: SortFilterProxyModel { + sourceModel: ContainersModel + filters: [ + ValueFilter { + roleName: "serviceType" + value: ProtocolEnum.Vpn + }, + ValueFilter { + roleName: "isSupported" + value: true + } + ] + } + } + } + + StackView { + id: servicesStackView + initialItem: PageSettingsContainersListView { + model: SortFilterProxyModel { + sourceModel: ContainersModel + filters: [ + ValueFilter { + roleName: "serviceType" + value: ProtocolEnum.Other + }, + ValueFilter { + roleName: "isSupported" + value: true + } + ] + } + } + } + + StackView { + id: dataStackView + initialItem: PageSettingsData { + + } + } + } } - } +// } } diff --git a/client/ui/qml/Pages2/PageSettingsData.qml b/client/ui/qml/Pages2/PageSettingsData.qml new file mode 100644 index 00000000..74293aa5 --- /dev/null +++ b/client/ui/qml/Pages2/PageSettingsData.qml @@ -0,0 +1,67 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts + +import SortFilterProxyModel 0.2 + +import PageEnum 1.0 +import ProtocolEnum 1.0 + +import "../Controls2" +import "../Controls2/TextTypes" + +PageType { + id: root + + FlickableType { + id: fl + anchors.top: root.top + anchors.bottom: root.bottom + contentHeight: content.height + + ColumnLayout { + id: content + + anchors.top: parent.top + anchors.left: parent.left + anchors.right: parent.right + + LabelWithButtonType { + Layout.fillWidth: true + + text: "Clear Amnezia cache" + descriptionText: "May be needed when changing other settings" + + clickedFunction: function() { + } + } + + DividerType {} + + LabelWithButtonType { + Layout.fillWidth: true + + text: "Remove server from application" + textColor: "#EB5757" + + clickedFunction: function() { + } + } + + DividerType {} + + LabelWithButtonType { + Layout.fillWidth: true + + text: "Clear server from Amnezia software" + textColor: "#EB5757" + + clickedFunction: function() { + ContainersModel.removeAllContainers() + } + } + + DividerType {} + } + } +} diff --git a/client/ui/qml/Pages2/PageSettingsServersList.qml b/client/ui/qml/Pages2/PageSettingsServersList.qml index 79e24f75..2344b7e8 100644 --- a/client/ui/qml/Pages2/PageSettingsServersList.qml +++ b/client/ui/qml/Pages2/PageSettingsServersList.qml @@ -57,11 +57,6 @@ PageType { anchors.left: parent.left anchors.right: parent.right - anchors.leftMargin: 16 - anchors.rightMargin: 16 - - spacing: 16 - ListView { id: servers width: parent.width @@ -85,8 +80,6 @@ PageType { LabelWithButtonType { id: server Layout.fillWidth: true - Layout.topMargin: 16 - Layout.bottomMargin: 16 text: name descriptionText: hostName @@ -98,11 +91,7 @@ PageType { } } - Rectangle { - Layout.fillWidth: true - height: 1 - color: "#2C2D30" - } + DividerType {} } } } diff --git a/client/ui/qml/Pages2/PageSetupWizardConfigSource.qml b/client/ui/qml/Pages2/PageSetupWizardConfigSource.qml index 53a40889..25b88f76 100644 --- a/client/ui/qml/Pages2/PageSetupWizardConfigSource.qml +++ b/client/ui/qml/Pages2/PageSetupWizardConfigSource.qml @@ -33,14 +33,12 @@ PageType { 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 + Layout.rightMargin: 16 + Layout.leftMargin: 16 backButtonImage: "qrc:/images/controls/arrow-left.svg" @@ -52,6 +50,8 @@ PageType { Header2TextType { Layout.fillWidth: true Layout.topMargin: 32 + Layout.rightMargin: 16 + Layout.leftMargin: 16 text: "Что у вас есть?" } @@ -75,11 +75,8 @@ PageType { } } } - Rectangle { - Layout.fillWidth: true - height: 1 - color: "#2C2D30" - } + + DividerType {} //todo ifdef mobile platforms LabelWithButtonType { @@ -93,11 +90,7 @@ PageType { } } - Rectangle { - Layout.fillWidth: true - height: 1 - color: "#2C2D30" - } + DividerType {} LabelWithButtonType { Layout.fillWidth: true @@ -111,11 +104,7 @@ PageType { } } - Rectangle { - Layout.fillWidth: true - height: 1 - color: "#2C2D30" - } + DividerType {} } } } diff --git a/client/ui/qml/Pages2/PageSetupWizardInstalling.qml b/client/ui/qml/Pages2/PageSetupWizardInstalling.qml index fd8aac6b..006743d9 100644 --- a/client/ui/qml/Pages2/PageSetupWizardInstalling.qml +++ b/client/ui/qml/Pages2/PageSetupWizardInstalling.qml @@ -23,6 +23,14 @@ PageType { closePage() PageController.showErrorMessage(errorMessage) } + + function onInstallContainerFinished() { + goToStartPage() + } + + function onInstallServerFinished() { + goToStartPage() + } } SortFilterProxyModel { diff --git a/client/ui/qml/Pages2/PageSetupWizardProtocols.qml b/client/ui/qml/Pages2/PageSetupWizardProtocols.qml index bffe09cb..cdacaf04 100644 --- a/client/ui/qml/Pages2/PageSetupWizardProtocols.qml +++ b/client/ui/qml/Pages2/PageSetupWizardProtocols.qml @@ -75,12 +75,12 @@ PageType { anchors.top: parent.top anchors.left: parent.left anchors.right: parent.right + anchors.rightMargin: -16 + anchors.leftMargin: -16 LabelWithButtonType { id: container Layout.fillWidth: true - Layout.topMargin: 16 - Layout.bottomMargin: 16 text: name descriptionText: description @@ -92,11 +92,7 @@ PageType { } } - Rectangle { - Layout.fillWidth: true - height: 1 - color: "#2C2D30" - } + DividerType {} } } } diff --git a/client/ui/qml/Pages2/PageSetupWizardStart.qml b/client/ui/qml/Pages2/PageSetupWizardStart.qml index 4d0f4c5c..804e145c 100644 --- a/client/ui/qml/Pages2/PageSetupWizardStart.qml +++ b/client/ui/qml/Pages2/PageSetupWizardStart.qml @@ -26,8 +26,9 @@ PageType { target: InstallController function onInstallServerFinished() { + //todo add smt like changeStartPage goToStartPage() -// goToPage(PageEnum.PageStart) + goToPage(PageEnum.PageStart) } } diff --git a/client/ui/qml/Pages2/PageStart.qml b/client/ui/qml/Pages2/PageStart.qml index 19ea3bc4..c50d4591 100644 --- a/client/ui/qml/Pages2/PageStart.qml +++ b/client/ui/qml/Pages2/PageStart.qml @@ -38,8 +38,9 @@ PageType { height: root.height - tabBar.implicitHeight StackView { - id: homeStackView - initialItem: "PageHome.qml" //PageController.getPagePath(PageEnum.PageSettingsServersList) + initialItem: PageHome { + id: pageHome + } } Item { @@ -47,8 +48,9 @@ PageType { } StackView { - id: settingsStackView - initialItem: "PageSettingsServersList.qml" //PageController.getPagePath(PageEnum.PageSettingsServersList) + initialItem: PageSettingsServersList { + id: pageSettingsServersList + } } } @@ -72,6 +74,9 @@ PageType { TabImageButtonType { isSelected: tabBar.currentIndex === 0 image: "qrc:/images/controls/home.svg" + onClicked: { + pageSettingsServersList.goToStartPage() + } } TabImageButtonType { isSelected: tabBar.currentIndex === 1 @@ -80,6 +85,9 @@ PageType { TabImageButtonType { isSelected: tabBar.currentIndex === 2 image: "qrc:/images/controls/settings-2.svg" + onClicked: { + pageHome.goToStartPage() + } } }