added display of vpn containers and services on the settings page

- added PageSettingsData and implementation of 'remove all containers'  button
This commit is contained in:
vladimir.kuznetsov 2023-05-27 22:46:41 +08:00
parent e00656d757
commit 1e180489a4
19 changed files with 393 additions and 102 deletions

View file

@ -0,0 +1,4 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M12 20H21" stroke="#CBCBCB" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M16.5 3.49998C16.8978 3.10216 17.4374 2.87866 18 2.87866C18.2786 2.87866 18.5544 2.93353 18.8118 3.04014C19.0692 3.14674 19.303 3.303 19.5 3.49998C19.697 3.69697 19.8532 3.93082 19.9598 4.18819C20.0665 4.44556 20.1213 4.72141 20.1213 4.99998C20.1213 5.27856 20.0665 5.55441 19.9598 5.81178C19.8532 6.06915 19.697 6.303 19.5 6.49998L7 19L3 20L4 16L16.5 3.49998Z" stroke="#CBCBCB" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 660 B

View file

@ -234,5 +234,10 @@
<file>ui/qml/Pages2/PageSettings.qml</file> <file>ui/qml/Pages2/PageSettings.qml</file>
<file>ui/qml/Controls2/PageType.qml</file> <file>ui/qml/Controls2/PageType.qml</file>
<file>ui/qml/Controls2/PopupType.qml</file> <file>ui/qml/Controls2/PopupType.qml</file>
<file>images/controls/edit-3.svg</file>
<file>ui/qml/Pages2/PageSettingsData.qml</file>
<file>ui/qml/Components/PageSettingsContainersListView.qml</file>
<file>ui/qml/Controls2/TextTypes/ListItemTitleType.qml</file>
<file>ui/qml/Controls2/DividerType.qml</file>
</qresource> </qresource>
</RCC> </RCC>

View file

@ -1,5 +1,7 @@
#include "containers_model.h" #include "containers_model.h"
#include "core/servercontroller.h"
ContainersModel::ContainersModel(std::shared_ptr<Settings> settings, QObject *parent) : m_settings(settings), QAbstractListModel(parent) ContainersModel::ContainersModel(std::shared_ptr<Settings> settings, QObject *parent) : m_settings(settings), QAbstractListModel(parent)
{ {
} }
@ -106,6 +108,22 @@ int ContainersModel::getCurrentlyInstalledContainerIndex()
return m_currentlyInstalledContainerIndex; 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<int, QByteArray> ContainersModel::roleNames() const { QHash<int, QByteArray> ContainersModel::roleNames() const {
QHash<int, QByteArray> roles; QHash<int, QByteArray> roles;
roles[NameRole] = "name"; roles[NameRole] = "name";

View file

@ -48,6 +48,8 @@ public slots:
void setCurrentlyInstalledContainerIndex(int index); void setCurrentlyInstalledContainerIndex(int index);
int getCurrentlyInstalledContainerIndex(); int getCurrentlyInstalledContainerIndex();
void removeAllContainers();
protected: protected:
QHash<int, QByteArray> roleNames() const override; QHash<int, QByteArray> roleNames() const override;

View file

@ -37,12 +37,11 @@ Drawer {
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
anchors.rightMargin: 16
anchors.leftMargin: 16
Header2TextType { Header2TextType {
Layout.fillWidth: true Layout.fillWidth: true
Layout.topMargin: 24 Layout.topMargin: 24
Layout.rightMargin: 16
Layout.leftMargin: 16
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
text: "Данные для подключения" text: "Данные для подключения"
@ -52,7 +51,7 @@ Drawer {
LabelWithButtonType { LabelWithButtonType {
id: ip id: ip
Layout.fillWidth: true Layout.fillWidth: true
Layout.topMargin: 32 Layout.topMargin: 16
text: "IP, логин и пароль от сервера" text: "IP, логин и пароль от сервера"
buttonImage: "qrc:/images/controls/chevron-right.svg" buttonImage: "qrc:/images/controls/chevron-right.svg"
@ -62,11 +61,9 @@ Drawer {
root.visible = false root.visible = false
} }
} }
Rectangle {
Layout.fillWidth: true DividerType {}
height: 1
color: "#2C2D30"
}
LabelWithButtonType { LabelWithButtonType {
Layout.fillWidth: true Layout.fillWidth: true
@ -78,10 +75,7 @@ Drawer {
root.visible = false root.visible = false
} }
} }
Rectangle {
Layout.fillWidth: true DividerType {}
height: 1
color: "#2C2D30"
}
} }
} }

View file

@ -116,4 +116,3 @@ ListView {
} }
} }
} }

View file

@ -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
}
}
}
}

View file

@ -0,0 +1,8 @@
import QtQuick
import QtQuick.Layouts
Rectangle {
Layout.fillWidth: true
height: 1
color: "#2C2D30"
}

View file

@ -2,6 +2,8 @@ import QtQuick
import QtQuick.Controls import QtQuick.Controls
import QtQuick.Layouts import QtQuick.Layouts
import "TextTypes"
Item { Item {
id: root id: root
@ -13,12 +15,16 @@ Item {
property alias buttonImage: button.image property alias buttonImage: button.image
property string iconImage property string iconImage
property string textColor: "#d7d8db"
implicitWidth: content.implicitWidth implicitWidth: content.implicitWidth
implicitHeight: content.implicitHeight implicitHeight: content.implicitHeight
RowLayout { RowLayout {
id: content id: content
anchors.fill: parent anchors.fill: parent
anchors.leftMargin: 16
anchors.rightMargin: 16
Image { Image {
id: icon id: icon
@ -28,34 +34,28 @@ Item {
} }
ColumnLayout { ColumnLayout {
Text { ListItemTitleType {
font.family: "PT Root UI VF"
font.styleName: "normal"
font.pixelSize: 18
color: "#d7d8db"
text: root.text text: root.text
wrapMode: Text.WordWrap color: textColor
Layout.fillWidth: true Layout.fillWidth: true
height: 22 Layout.topMargin: 16
Layout.bottomMargin: description.visible ? 0 : 16
horizontalAlignment: Text.AlignLeft horizontalAlignment: Text.AlignLeft
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter
} }
Text { CaptionTextType {
font.family: "PT Root UI VF" id: description
font.styleName: "normal"
font.pixelSize: 13
font.letterSpacing: 0.02
color: "#878B91" color: "#878B91"
text: root.descriptionText text: root.descriptionText
wrapMode: Text.WordWrap
visible: root.descriptionText !== "" visible: root.descriptionText !== ""
Layout.fillWidth: true Layout.fillWidth: true
height: 16 Layout.bottomMargin: 16
horizontalAlignment: Text.AlignLeft horizontalAlignment: Text.AlignLeft
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter
@ -88,21 +88,45 @@ Item {
} }
} }
} }
Rectangle {
id: background
anchors.fill: root
color: "transparent"
Behavior on color {
PropertyAnimation { duration: 200 }
}
}
MouseArea { MouseArea {
anchors.fill: parent anchors.fill: parent
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
hoverEnabled: true hoverEnabled: true
onEntered: { onEntered: {
imageBackground.color = button.hoveredColor if (buttonImage) {
imageBackground.color = button.hoveredColor
} else {
background.color = button.hoveredColor
}
} }
onExited: { onExited: {
imageBackground.color = button.defaultColor if (buttonImage) {
imageBackground.color = button.defaultColor
} else {
background.color = button.defaultColor
}
} }
onPressedChanged: { 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: { onClicked: {

View file

@ -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
}

View file

@ -37,21 +37,6 @@ PageType {
} }
} }
Connections {
target: InstallController
function onInstallContainerFinished() {
goToStartPage()
menu.visible = true
containersDropDown.menuVisible = true
}
function onInstallServerFinished() {
goToStartPage()
menu.visible = true
}
}
Rectangle { Rectangle {
id: buttonBackground id: buttonBackground
anchors.fill: buttonContent anchors.fill: buttonContent
@ -166,6 +151,10 @@ PageType {
ValueFilter { ValueFilter {
roleName: "serviceType" roleName: "serviceType"
value: ProtocolEnum.Vpn value: ProtocolEnum.Vpn
},
ValueFilter {
roleName: "isSupported"
value: true
} }
] ]
} }

View file

@ -5,6 +5,7 @@ import QtQuick.Layouts
import SortFilterProxyModel 0.2 import SortFilterProxyModel 0.2
import PageEnum 1.0 import PageEnum 1.0
import ProtocolEnum 1.0
import ContainerProps 1.0 import ContainerProps 1.0
import ProtocolProps 1.0 import ProtocolProps 1.0
@ -12,6 +13,7 @@ import "./"
import "../Controls2" import "../Controls2"
import "../Controls2/TextTypes" import "../Controls2/TextTypes"
import "../Config" import "../Config"
import "../Components"
PageType { PageType {
id: root id: root
@ -27,35 +29,28 @@ PageType {
] ]
} }
FlickableType {
id: fl
anchors.fill: parent
contentHeight: content.height
ColumnLayout { ColumnLayout {
id: content id: content
anchors.top: parent.top anchors.fill: parent
anchors.left: parent.left
anchors.right: parent.right
spacing: 16 spacing: 16
Repeater { Repeater {
id: header
model: proxyServersModel model: proxyServersModel
delegate: HeaderType { delegate: HeaderType {
id: header
Layout.fillWidth: true Layout.fillWidth: true
Layout.topMargin: 20 Layout.topMargin: 20
Layout.leftMargin: 16 Layout.leftMargin: 16
Layout.rightMargin: 16 Layout.rightMargin: 16
actionButtonImage: "qrc:/images/controls/plus.svg" actionButtonImage: "qrc:/images/controls/edit-3.svg"
backButtonImage: "qrc:/images/controls/arrow-left.svg" backButtonImage: "qrc:/images/controls/arrow-left.svg"
headerText: name headerText: name
descriptionText: hostName
actionButtonFunction: function() { actionButtonFunction: function() {
connectionTypeSelection.visible = true 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 {
}
}
}
} }
} // }
} }

View file

@ -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 {}
}
}
}

View file

@ -57,11 +57,6 @@ PageType {
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
anchors.leftMargin: 16
anchors.rightMargin: 16
spacing: 16
ListView { ListView {
id: servers id: servers
width: parent.width width: parent.width
@ -85,8 +80,6 @@ PageType {
LabelWithButtonType { LabelWithButtonType {
id: server id: server
Layout.fillWidth: true Layout.fillWidth: true
Layout.topMargin: 16
Layout.bottomMargin: 16
text: name text: name
descriptionText: hostName descriptionText: hostName
@ -98,11 +91,7 @@ PageType {
} }
} }
Rectangle { DividerType {}
Layout.fillWidth: true
height: 1
color: "#2C2D30"
}
} }
} }
} }

View file

@ -33,14 +33,12 @@ PageType {
anchors.top: parent.top anchors.top: parent.top
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
anchors.rightMargin: 16
anchors.leftMargin: 16
spacing: 16
HeaderType { HeaderType {
Layout.fillWidth: true Layout.fillWidth: true
Layout.topMargin: 20 Layout.topMargin: 20
Layout.rightMargin: 16
Layout.leftMargin: 16
backButtonImage: "qrc:/images/controls/arrow-left.svg" backButtonImage: "qrc:/images/controls/arrow-left.svg"
@ -52,6 +50,8 @@ PageType {
Header2TextType { Header2TextType {
Layout.fillWidth: true Layout.fillWidth: true
Layout.topMargin: 32 Layout.topMargin: 32
Layout.rightMargin: 16
Layout.leftMargin: 16
text: "Что у вас есть?" text: "Что у вас есть?"
} }
@ -75,11 +75,8 @@ PageType {
} }
} }
} }
Rectangle {
Layout.fillWidth: true DividerType {}
height: 1
color: "#2C2D30"
}
//todo ifdef mobile platforms //todo ifdef mobile platforms
LabelWithButtonType { LabelWithButtonType {
@ -93,11 +90,7 @@ PageType {
} }
} }
Rectangle { DividerType {}
Layout.fillWidth: true
height: 1
color: "#2C2D30"
}
LabelWithButtonType { LabelWithButtonType {
Layout.fillWidth: true Layout.fillWidth: true
@ -111,11 +104,7 @@ PageType {
} }
} }
Rectangle { DividerType {}
Layout.fillWidth: true
height: 1
color: "#2C2D30"
}
} }
} }
} }

View file

@ -23,6 +23,14 @@ PageType {
closePage() closePage()
PageController.showErrorMessage(errorMessage) PageController.showErrorMessage(errorMessage)
} }
function onInstallContainerFinished() {
goToStartPage()
}
function onInstallServerFinished() {
goToStartPage()
}
} }
SortFilterProxyModel { SortFilterProxyModel {

View file

@ -75,12 +75,12 @@ PageType {
anchors.top: parent.top anchors.top: parent.top
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
anchors.rightMargin: -16
anchors.leftMargin: -16
LabelWithButtonType { LabelWithButtonType {
id: container id: container
Layout.fillWidth: true Layout.fillWidth: true
Layout.topMargin: 16
Layout.bottomMargin: 16
text: name text: name
descriptionText: description descriptionText: description
@ -92,11 +92,7 @@ PageType {
} }
} }
Rectangle { DividerType {}
Layout.fillWidth: true
height: 1
color: "#2C2D30"
}
} }
} }
} }

View file

@ -26,8 +26,9 @@ PageType {
target: InstallController target: InstallController
function onInstallServerFinished() { function onInstallServerFinished() {
//todo add smt like changeStartPage
goToStartPage() goToStartPage()
// goToPage(PageEnum.PageStart) goToPage(PageEnum.PageStart)
} }
} }

View file

@ -38,8 +38,9 @@ PageType {
height: root.height - tabBar.implicitHeight height: root.height - tabBar.implicitHeight
StackView { StackView {
id: homeStackView initialItem: PageHome {
initialItem: "PageHome.qml" //PageController.getPagePath(PageEnum.PageSettingsServersList) id: pageHome
}
} }
Item { Item {
@ -47,8 +48,9 @@ PageType {
} }
StackView { StackView {
id: settingsStackView initialItem: PageSettingsServersList {
initialItem: "PageSettingsServersList.qml" //PageController.getPagePath(PageEnum.PageSettingsServersList) id: pageSettingsServersList
}
} }
} }
@ -72,6 +74,9 @@ PageType {
TabImageButtonType { TabImageButtonType {
isSelected: tabBar.currentIndex === 0 isSelected: tabBar.currentIndex === 0
image: "qrc:/images/controls/home.svg" image: "qrc:/images/controls/home.svg"
onClicked: {
pageSettingsServersList.goToStartPage()
}
} }
TabImageButtonType { TabImageButtonType {
isSelected: tabBar.currentIndex === 1 isSelected: tabBar.currentIndex === 1
@ -80,6 +85,9 @@ PageType {
TabImageButtonType { TabImageButtonType {
isSelected: tabBar.currentIndex === 2 isSelected: tabBar.currentIndex === 2
image: "qrc:/images/controls/settings-2.svg" image: "qrc:/images/controls/settings-2.svg"
onClicked: {
pageHome.goToStartPage()
}
} }
} }