added PageSettingsSplitTunneling

- added a call to the context menu when clicking the right mouse button for textInput
This commit is contained in:
vladimir.kuznetsov 2023-08-08 19:10:14 +05:00
parent 2c429fd406
commit 90ae0b3e44
31 changed files with 1018 additions and 240 deletions

View file

@ -20,6 +20,8 @@ Button {
property string imageSource
property bool squareLeftSide: false
implicitHeight: 56
hoverEnabled: true
@ -44,6 +46,32 @@ Button {
Behavior on color {
PropertyAnimation { duration: 200 }
}
Rectangle {
visible: root.squareLeftSide
z: 1
width: parent.radius
height: parent.radius
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.left: parent.left
color: {
if (root.enabled) {
if (root.pressed) {
return pressedColor
}
return root.hovered ? hoveredColor : defaultColor
} else {
return disabledColor
}
}
Behavior on color {
PropertyAnimation { duration: 200 }
}
}
}
MouseArea {

View file

@ -0,0 +1,33 @@
import QtQuick
import QtQuick.Controls
import Qt.labs.platform
Menu {
property var textObj
MenuItem {
text: qsTr("C&ut")
shortcut: StandardKey.Cut
enabled: textObj.selectedText
onTriggered: textObj.cut()
}
MenuItem {
text: qsTr("&Copy")
shortcut: StandardKey.Copy
enabled: textObj.selectedText
onTriggered: textObj.copy()
}
MenuItem {
text: qsTr("&Paste")
shortcut: StandardKey.Paste
enabled: textObj.canPaste
onTriggered: textObj.paste()
}
MenuItem {
text: qsTr("&SelectAll")
shortcut: StandardKey.SelectAll
enabled: textObj.length > 0
onTriggered: textObj.selectAll()
}
}

View file

@ -24,9 +24,11 @@ Item {
property string rootButtonBackgroundColor: "#1C1D21"
property string rootButtonHoveredBorderColor: "#494B50"
property string rootButtonDefaultBorderColor: "transparent"
property string rootButtonDefaultBorderColor: "#2C2D30"
property string rootButtonPressedBorderColor: "#D7D8DB"
property int rootButtonTextMargins: 16
property real drawerHeight: 0.9
property Component listView
@ -74,7 +76,9 @@ Item {
spacing: 0
ColumnLayout {
Layout.leftMargin: 16
Layout.leftMargin: rootButtonTextMargins
Layout.topMargin: rootButtonTextMargins
Layout.bottomMargin: rootButtonTextMargins
LabelTextType {
Layout.fillWidth: true
@ -96,16 +100,10 @@ Item {
color: root.enabled ? root.textColor : root.textDisabledColor
text: root.text
wrapMode: Text.NoWrap
elide: Text.ElideRight
}
}
ImageButtonType {
Layout.leftMargin: 4
Layout.rightMargin: 16
hoverEnabled: false
image: rootButtonImage
imageColor: rootButtonImageColor

View file

@ -0,0 +1,70 @@
import QtQuick
import QtQuick.Controls
Rectangle {
id: root
property string placeholderText
property string text
property var onEditingFinished
height: 148
color: "#1C1D21"
border.width: 1
border.color: "#2C2D30"
radius: 16
FlickableType {
anchors.top: parent.top
anchors.bottom: parent.bottom
contentHeight: textArea.implicitHeight
TextArea {
id: textArea
width: parent.width
topPadding: 16
leftPadding: 16
anchors.topMargin: 16
anchors.bottomMargin: 16
color: "#D7D8DB"
selectionColor: "#412102"
selectedTextColor: "#D7D8DB"
placeholderTextColor: "#878B91"
font.pixelSize: 16
font.weight: Font.Medium
font.family: "PT Root UI VF"
placeholderText: root.placeholderText
text: root.text
onEditingFinished: {
if (root.onEditingFinished && typeof root.onEditingFinished === "function") {
root.onEditingFinished()
}
}
wrapMode: Text.Wrap
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.RightButton
onClicked: contextMenu.open()
}
ContextMenuType {
id: contextMenu
textObj: textArea
}
}
}
//todo make whole background clickable, with code below we lose ability to select text by mouse
// MouseArea {
// anchors.fill: parent
// cursorShape: Qt.IBeamCursor
// onClicked: textArea.forceActiveFocus()
// }
}

View file

@ -41,7 +41,7 @@ Item {
Rectangle {
id: backgroud
Layout.fillWidth: true
Layout.preferredHeight: 74
Layout.preferredHeight: input.implicitHeight
color: root.enabled ? root.backgroundColor : root.backgroundDisabledColor
radius: 16
border.color: textField.focus ? root.borderFocusedColor : root.borderColor
@ -52,16 +52,17 @@ Item {
}
RowLayout {
id: input
anchors.fill: backgroud
ColumnLayout {
Layout.margins: 16
LabelTextType {
text: root.headerText
color: root.enabled ? root.headerTextColor : root.headerTextDisabledColor
visible: text !== ""
Layout.fillWidth: true
Layout.rightMargin: 16
Layout.leftMargin: 16
Layout.topMargin: 16
}
TextField {
@ -82,9 +83,7 @@ Item {
height: 24
Layout.fillWidth: true
Layout.rightMargin: 16
Layout.leftMargin: 16
Layout.bottomMargin: 16
topPadding: 0
rightPadding: 0
leftPadding: 0
@ -98,24 +97,37 @@ Item {
onTextChanged: {
root.errorText = ""
}
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.RightButton
onClicked: contextMenu.open()
}
ContextMenuType {
id: contextMenu
textObj: textField
}
}
}
BasicButtonType {
visible: (root.buttonText !== "") || (root.buttonImageSource !== "")
defaultColor: "transparent"
hoveredColor: Qt.rgba(1, 1, 1, 0.08)
pressedColor: Qt.rgba(1, 1, 1, 0.12)
disabledColor: "#878B91"
textColor: "#D7D8DB"
borderWidth: 0
// defaultColor: "transparent"
// hoveredColor: Qt.rgba(1, 1, 1, 0.08)
// pressedColor: Qt.rgba(1, 1, 1, 0.12)
// disabledColor: "#878B91"
// textColor: "#D7D8DB"
// borderWidth: 0
text: root.buttonText
imageSource: root.buttonImageSource
Layout.rightMargin: 24
Layout.preferredHeight: 32
// Layout.rightMargin: 24
Layout.preferredHeight: content.implicitHeight
Layout.preferredWidth: content.implicitHeight
squareLeftSide: true
onClicked: {
if (root.clickedFunc && typeof root.clickedFunc === "function") {

View file

@ -148,10 +148,11 @@ PageType {
DropDownType {
id: containersDropDown
implicitHeight: 40
rootButtonImageColor: "#0E0E11"
rootButtonBackgroundColor: "#D7D8DB"
rootButtonHoveredBorderColor: "transparent"
rootButtonPressedBorderColor: "transparent"
rootButtonTextMargins: 8
text: root.defaultContainerName
textColor: "#0E0E11"

View file

@ -301,50 +301,18 @@ PageType {
text: qsTr("Additional client configuration commands")
}
Rectangle {
TextAreaType {
Layout.fillWidth: true
Layout.topMargin: 16
height: 148
color: "#1C1D21"
border.width: 1
border.color: "#2C2D30"
radius: 16
visible: additionalClientCommandsSwitcher.checked
FlickableType {
anchors.top: parent.top
anchors.bottom: parent.bottom
contentHeight: additionalClientCommandsTextArea.implicitHeight
TextArea {
id: additionalClientCommandsTextArea
text: additionalClientCommands
placeholderText: qsTr("Commands:")
width: parent.width
anchors.topMargin: 16
anchors.bottomMargin: 16
topPadding: 16
leftPadding: 16
color: "#D7D8DB"
selectionColor: "#412102"
selectedTextColor: "#D7D8DB"
placeholderTextColor: "#878B91"
font.pixelSize: 16
font.weight: Font.Medium
font.family: "PT Root UI VF"
placeholderText: qsTr("Commands:")
text: additionalClientCommands
wrapMode: Text.Wrap
onEditingFinished: {
if (additionalClientCommands !== text) {
additionalClientCommands = text
}
}
onEditingFinished: {
if (additionalClientCommands !== text) {
additionalClientCommands = text
}
}
}
@ -359,50 +327,18 @@ PageType {
text: qsTr("Additional server configuration commands")
}
Rectangle {
TextAreaType {
Layout.fillWidth: true
Layout.topMargin: 16
height: 148
color: "#1C1D21"
border.width: 1
border.color: "#2C2D30"
radius: 16
visible: additionalServerCommandsSwitcher.checked
FlickableType {
anchors.top: parent.top
anchors.bottom: parent.bottom
contentHeight: additionalServerCommandsTextArea.implicitHeight
TextArea {
id: additionalServerCommandsTextArea
text: additionalServerCommands
placeholderText: qsTr("Commands:")
width: parent.width
anchors.topMargin: 16
anchors.bottomMargin: 16
topPadding: 16
leftPadding: 16
color: "#D7D8DB"
selectionColor: "#412102"
selectedTextColor: "#D7D8DB"
placeholderTextColor: "#878B91"
font.pixelSize: 16
font.weight: Font.Medium
font.family: "PT Root UI VF"
placeholderText: qsTr("Commands:")
text: additionalServerCommands
wrapMode: Text.Wrap
onEditingFinished: {
if (additionalServerCommands !== text) {
additionalServerCommands = text
}
}
onEditingFinished: {
if (additionalServerCommands !== text) {
additionalServerCommands = text
}
}
}

View file

@ -67,7 +67,7 @@ PageType {
Layout.fillWidth: true
text: qsTr("Logging")
descriptionText: SettingsController.isLoggingEnable ? qsTr("Enabled") : qsTr("Disabled")
descriptionText: SettingsController.isLoggingEnabled ? qsTr("Enabled") : qsTr("Disabled")
rightImageSource: "qrc:/images/controls/chevron-right.svg"
clickedFunction: function() {

View file

@ -41,6 +41,24 @@ PageType {
headerText: qsTr("Connection")
}
SwitcherType {
Layout.fillWidth: true
Layout.topMargin: 16
Layout.bottomMargin: 16
Layout.leftMargin: 16
Layout.rightMargin: 16
text: qsTr("Auto connect")
descriptionText: qsTr("Connect to VPN on app start")
checked: SettingsController.isAutoConnectEnabled()
onCheckedChanged: {
if (checked !== SettingsController.isAutoConnectEnabled()) {
SettingsController.toggleAutoConnect(checked)
}
}
}
SwitcherType {
Layout.fillWidth: true
Layout.topMargin: 16
@ -54,7 +72,7 @@ PageType {
checked: SettingsController.isAmneziaDnsEnabled()
onCheckedChanged: {
if (checked !== SettingsController.isAmneziaDnsEnabled()) {
SettingsController.setAmneziaDns(checked)
SettingsController.toggleAmneziaDns(checked)
}
}
}
@ -83,6 +101,7 @@ PageType {
rightImageSource: "qrc:/images/controls/chevron-right.svg"
clickedFunction: function() {
goToPage(PageEnum.PageSettingsSplitTunneling)
}
}

View file

@ -50,10 +50,10 @@ PageType {
text: qsTr("Save logs")
checked: SettingsController.isLoggingEnable
checked: SettingsController.isLoggingEnabled
onCheckedChanged: {
if (checked !== SettingsController.isLoggingEnable) {
SettingsController.isLoggingEnable = checked
if (checked !== SettingsController.isLoggingEnabled) {
SettingsController.isLoggingEnabled = checked
}
}
}

View file

@ -0,0 +1,377 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import SortFilterProxyModel 0.2
import PageEnum 1.0
import ProtocolEnum 1.0
import ContainerProps 1.0
import "./"
import "../Controls2"
import "../Controls2/TextTypes"
import "../Config"
import "../Components"
PageType {
id: root
Connections {
target: SitesController
function onFinished(message) {
PageController.showNotificationMessage(message)
}
function onErrorOccurred(errorMessage) {
PageController.showErrorMessage(errorMessage)
}
}
QtObject {
id: routeMode
property int allSites: 0
property int onlyForwardSites: 1
property int allExceptSites: 2
}
property list<QtObject> routeModesModel: [
onlyForwardSites,
allExceptSites
]
QtObject {
id: onlyForwardSites
property string name: qsTr("Addresses from the list should always open via VPN")
property int type: routeMode.onlyForwardSites
}
QtObject {
id: allExceptSites
property string name: qsTr("Addresses from the list should never be opened via VPN")
property int type: routeMode.allExceptSites
}
function getRouteModesModelIndex() {
var currentRouteMode = SitesModel.routeMode
if ((routeMode.onlyForwardSites === currentRouteMode) || (routeMode.allSites === currentRouteMode)) {
return 0
} else if (routeMode.allExceptSites === currentRouteMode) {
return 1
}
}
ColumnLayout {
id: header
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
anchors.topMargin: 20
BackButtonType {
}
RowLayout {
HeaderType {
Layout.fillWidth: true
Layout.leftMargin: 16
headerText: qsTr("Split site tunneling")
}
SwitcherType {
id: switcher
property int lastActiveRouteMode: routeMode.onlyForwardSites
Layout.fillWidth: true
Layout.rightMargin: 16
checked: SitesModel.routeMode !== routeMode.allSites
onToggled: {
if (checked) {
SitesModel.routeMode = lastActiveRouteMode
} else {
lastActiveRouteMode = SitesModel.routeMode
selector.text = root.routeModesModel[getRouteModesModelIndex()].name
SitesModel.routeMode = routeMode.allSites
}
}
}
}
DropDownType {
id: selector
Layout.fillWidth: true
Layout.topMargin: 32
Layout.leftMargin: 16
Layout.rightMargin: 16
drawerHeight: 0.4375
enabled: switcher.checked
headerText: qsTr("Mode")
listView: ListViewType {
rootWidth: root.width
model: root.routeModesModel
currentIndex: getRouteModesModelIndex()
clickedFunction: function() {
selector.text = selectedText
selector.menuVisible = false
if (SitesModel.routeMode !== root.routeModesModel[currentIndex].type) {
SitesModel.routeMode = root.routeModesModel[currentIndex].type
}
}
Component.onCompleted: {
if (root.routeModesModel[currentIndex].type === SitesModel.routeMode) {
selector.text = selectedText
} else {
selector.text = root.routeModesModel[0].name
}
}
Connections {
target: SitesModel
function onRouteModeChanged() {
currentIndex = getRouteModesModelIndex()
}
}
}
}
}
FlickableType {
anchors.top: header.bottom
anchors.topMargin: 16
contentHeight: col.implicitHeight + connectButton.implicitHeight + connectButton.anchors.bottomMargin + connectButton.anchors.topMargin
enabled: switcher.checked
Column {
id: col
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
ListView {
id: sites
width: parent.width
height: sites.contentItem.height
model: SitesModel
clip: true
interactive: false
delegate: Item {
implicitWidth: sites.width
implicitHeight: delegateContent.implicitHeight
ColumnLayout {
id: delegateContent
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
LabelWithButtonType {
Layout.fillWidth: true
text: url
descriptionText: ip
rightImageSource: "qrc:/images/controls/trash.svg"
rightImageColor: "#D7D8DB"
clickedFunction: function() {
questionDrawer.headerText = qsTr("Remove ") + url + "?"
questionDrawer.yesButtonText = qsTr("Continue")
questionDrawer.noButtonText = qsTr("Cancel")
questionDrawer.yesButtonFunction = function() {
questionDrawer.visible = false
SitesController.removeSite(index)
}
questionDrawer.noButtonFunction = function() {
questionDrawer.visible = false
}
questionDrawer.visible = true
}
}
DividerType {}
QuestionDrawer {
id: questionDrawer
}
}
}
}
}
}
RowLayout {
id: connectButton
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.right: parent.right
anchors.topMargin: 24
anchors.rightMargin: 16
anchors.leftMargin: 16
anchors.bottomMargin: 24
TextFieldWithHeaderType {
Layout.fillWidth: true
textFieldPlaceholderText: qsTr("Site or IP")
buttonImageSource: "qrc:/images/controls/plus.svg"
clickedFunc: function() {
SitesController.addSite(textFieldText)
textFieldText = ""
}
}
ImageButtonType {
implicitWidth: 56
implicitHeight: 56
image: "qrc:/images/controls/more-vertical.svg"
imageColor: "#D7D8DB"
onClicked: function () {
moreActionsDrawer.open()
}
}
}
DrawerType {
id: moreActionsDrawer
width: parent.width
height: parent.height * 0.4375
FlickableType {
anchors.fill: parent
contentHeight: moreActionsDrawerContent.height
ColumnLayout {
id: moreActionsDrawerContent
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
Header2Type {
Layout.fillWidth: true
Layout.margins: 16
headerText: qsTr("Import/Export Sites")
}
LabelWithButtonType {
Layout.fillWidth: true
text: qsTr("Import")
rightImageSource: "qrc:/images/controls/chevron-right.svg"
clickedFunction: function() {
importSitesDrawer.open()
}
}
DividerType {}
LabelWithButtonType {
Layout.fillWidth: true
text: qsTr("Save site list")
clickedFunction: function() {
SitesController.exportSites()
moreActionsDrawer.close()
}
}
DividerType {}
}
}
}
DrawerType {
id: importSitesDrawer
width: parent.width
height: parent.height * 0.4375
BackButtonType {
id: importSitesDrawerBackButton
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
anchors.topMargin: 16
backButtonFunction: function() {
importSitesDrawer.close()
}
}
FlickableType {
anchors.top: importSitesDrawerBackButton.bottom
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
contentHeight: importSitesDrawerContent.height
ColumnLayout {
id: importSitesDrawerContent
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
Header2Type {
Layout.fillWidth: true
Layout.margins: 16
headerText: qsTr("Import a list of sites")
}
LabelWithButtonType {
Layout.fillWidth: true
text: qsTr("Replace site list")
clickedFunction: function() {
SitesController.importSites(true)
importSitesDrawer.close()
moreActionsDrawer.close()
}
}
DividerType {}
LabelWithButtonType {
Layout.fillWidth: true
text: qsTr("Add imported sites to existing ones")
clickedFunction: function() {
SitesController.importSites(false)
importSitesDrawer.close()
moreActionsDrawer.close()
}
}
DividerType {}
}
}
}
}