Added tab navigation functional. (#721)
- Added tab navigation functional. - In basic types added parentFlickable property, which will help to ensure, that the item is visible within flickable parent during tab navigation. - Added focus state for some basic types. - In PageType qml file added lastItemTabClicked function, which will help to focus tab bar buttons when the last tab on the current page clicked. - Added Focus for back button for all pages and drawers. - Added scroll on tab for Servers ListView on PageHome.
This commit is contained in:
parent
d50e7dd3f4
commit
0e4ae26bae
66 changed files with 2269 additions and 143 deletions
|
@ -123,6 +123,9 @@ signals:
|
|||
void escapePressed();
|
||||
void closeTopDrawer();
|
||||
|
||||
void forceTabBarActiveFocus();
|
||||
void forceStackActiveFocus();
|
||||
|
||||
private:
|
||||
QSharedPointer<ServersModel> m_serversModel;
|
||||
|
||||
|
|
|
@ -49,10 +49,26 @@ Button {
|
|||
verticalOffset: 0
|
||||
radius: 10
|
||||
samples: 25
|
||||
color: "#FBB26A"
|
||||
color: root.activeFocus ? "#D7D8DB" : "#FBB26A"
|
||||
source: backgroundCircle
|
||||
}
|
||||
|
||||
ShapePath {
|
||||
fillColor: "transparent"
|
||||
strokeColor: "#D7D8DB"
|
||||
strokeWidth: root.activeFocus ? 1 : 0
|
||||
capStyle: ShapePath.RoundCap
|
||||
|
||||
PathAngleArc {
|
||||
centerX: backgroundCircle.width / 2
|
||||
centerY: backgroundCircle.height / 2
|
||||
radiusX: 94
|
||||
radiusY: 94
|
||||
startAngle: 0
|
||||
sweepAngle: 360
|
||||
}
|
||||
}
|
||||
|
||||
ShapePath {
|
||||
fillColor: "transparent"
|
||||
strokeColor: {
|
||||
|
@ -64,14 +80,14 @@ Button {
|
|||
return defaultButtonColor
|
||||
}
|
||||
}
|
||||
strokeWidth: 3
|
||||
strokeWidth: root.activeFocus ? 2 : 3
|
||||
capStyle: ShapePath.RoundCap
|
||||
|
||||
PathAngleArc {
|
||||
centerX: backgroundCircle.width / 2
|
||||
centerY: backgroundCircle.height / 2
|
||||
radiusX: 93
|
||||
radiusY: 93
|
||||
radiusX: 93 - (root.activeFocus ? 2 : 0)
|
||||
radiusY: 93 - (root.activeFocus ? 2 : 0)
|
||||
startAngle: 0
|
||||
sweepAngle: 360
|
||||
}
|
||||
|
@ -141,4 +157,7 @@ Button {
|
|||
ServersModel.setProcessedServerIndex(ServersModel.defaultIndex)
|
||||
ConnectionController.connectButtonClicked()
|
||||
}
|
||||
|
||||
Keys.onEnterPressed: this.clicked()
|
||||
Keys.onReturnPressed: this.clicked()
|
||||
}
|
||||
|
|
|
@ -26,6 +26,14 @@ DrawerType2 {
|
|||
root.expandedHeight = content.implicitHeight + 32
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: root
|
||||
enabled: !GC.isMobile()
|
||||
function onOpened() {
|
||||
focusItem.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
Header2Type {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 24
|
||||
|
@ -36,6 +44,11 @@ DrawerType2 {
|
|||
headerText: qsTr("Add new connection")
|
||||
}
|
||||
|
||||
Item {
|
||||
id: focusItem
|
||||
KeyNavigation.tab: ip.rightButton
|
||||
}
|
||||
|
||||
LabelWithButtonType {
|
||||
id: ip
|
||||
Layout.fillWidth: true
|
||||
|
@ -48,11 +61,14 @@ DrawerType2 {
|
|||
PageController.goToPage(PageEnum.PageSetupWizardCredentials)
|
||||
root.close()
|
||||
}
|
||||
|
||||
KeyNavigation.tab: qrCode.rightButton
|
||||
}
|
||||
|
||||
DividerType {}
|
||||
|
||||
LabelWithButtonType {
|
||||
id: qrCode
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: qsTr("Open config file, key or QR code")
|
||||
|
@ -62,6 +78,8 @@ DrawerType2 {
|
|||
PageController.goToPage(PageEnum.PageSetupWizardConfigSource)
|
||||
root.close()
|
||||
}
|
||||
|
||||
KeyNavigation.tab: focusItem
|
||||
}
|
||||
|
||||
DividerType {}
|
||||
|
|
|
@ -17,12 +17,56 @@ ListView {
|
|||
property var rootWidth
|
||||
property var selectedText
|
||||
|
||||
property bool a: true
|
||||
|
||||
width: rootWidth
|
||||
height: menuContent.contentItem.height
|
||||
|
||||
clip: true
|
||||
interactive: false
|
||||
|
||||
property FlickableType parentFlickable
|
||||
property var lastItemTabClicked
|
||||
|
||||
property int currentFocusIndex: 0
|
||||
|
||||
activeFocusOnTab: true
|
||||
onActiveFocusChanged: {
|
||||
if (activeFocus) {
|
||||
this.currentFocusIndex = 0
|
||||
this.itemAtIndex(currentFocusIndex).forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
Keys.onTabPressed: {
|
||||
if (currentFocusIndex < this.count - 1) {
|
||||
currentFocusIndex += 1
|
||||
this.itemAtIndex(currentFocusIndex).forceActiveFocus()
|
||||
} else {
|
||||
currentFocusIndex = 0
|
||||
if (lastItemTabClicked && typeof lastItemTabClicked === "function") {
|
||||
lastItemTabClicked()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onVisibleChanged: {
|
||||
if (visible) {
|
||||
currentFocusIndex = 0
|
||||
focusItem.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: focusItem
|
||||
}
|
||||
|
||||
onCurrentFocusIndexChanged: {
|
||||
if (parentFlickable) {
|
||||
parentFlickable.ensureVisible(this.itemAtIndex(currentFocusIndex))
|
||||
}
|
||||
}
|
||||
|
||||
ButtonGroup {
|
||||
id: containersRadioButtonGroup
|
||||
}
|
||||
|
@ -31,6 +75,12 @@ ListView {
|
|||
implicitWidth: rootWidth
|
||||
implicitHeight: content.implicitHeight
|
||||
|
||||
onActiveFocusChanged: {
|
||||
if (activeFocus) {
|
||||
containerRadioButton.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: content
|
||||
|
||||
|
@ -76,6 +126,19 @@ ListView {
|
|||
cursorShape: Qt.PointingHandCursor
|
||||
enabled: false
|
||||
}
|
||||
|
||||
Keys.onEnterPressed: {
|
||||
if (checkable) {
|
||||
checked = true
|
||||
}
|
||||
containerRadioButton.clicked()
|
||||
}
|
||||
Keys.onReturnPressed: {
|
||||
if (checkable) {
|
||||
checked = true
|
||||
}
|
||||
containerRadioButton.clicked()
|
||||
}
|
||||
}
|
||||
|
||||
DividerType {
|
||||
|
|
|
@ -24,6 +24,14 @@ DrawerType2 {
|
|||
anchors.right: parent.right
|
||||
spacing: 0
|
||||
|
||||
Connections {
|
||||
target: root
|
||||
enabled: !GC.isMobile()
|
||||
function onOpened() {
|
||||
focusItem.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
Header2Type {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 24
|
||||
|
@ -35,7 +43,13 @@ DrawerType2 {
|
|||
descriptionText: qsTr("Allows you to connect to some sites or applications through a VPN connection and bypass others")
|
||||
}
|
||||
|
||||
Item {
|
||||
id: focusItem
|
||||
KeyNavigation.tab: splitTunnelingSwitch.visible ? splitTunnelingSwitch : siteBasedSplitTunnelingSwitch.rightButton
|
||||
}
|
||||
|
||||
LabelWithButtonType {
|
||||
id: splitTunnelingSwitch
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 16
|
||||
|
||||
|
@ -45,6 +59,8 @@ DrawerType2 {
|
|||
descriptionText: qsTr("Enabled \nCan't be disabled for current server")
|
||||
rightImageSource: "qrc:/images/controls/chevron-right.svg"
|
||||
|
||||
KeyNavigation.tab: siteBasedSplitTunnelingSwitch.visible ? siteBasedSplitTunnelingSwitch.rightButton : focusItem
|
||||
|
||||
clickedFunction: function() {
|
||||
// PageController.goToPage(PageEnum.PageSettingsSplitTunneling)
|
||||
// root.close()
|
||||
|
@ -56,6 +72,7 @@ DrawerType2 {
|
|||
}
|
||||
|
||||
LabelWithButtonType {
|
||||
id: siteBasedSplitTunnelingSwitch
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 16
|
||||
|
||||
|
@ -63,6 +80,10 @@ DrawerType2 {
|
|||
descriptionText: enabled && SitesModel.isTunnelingEnabled ? qsTr("Enabled") : qsTr("Disabled")
|
||||
rightImageSource: "qrc:/images/controls/chevron-right.svg"
|
||||
|
||||
KeyNavigation.tab: appSplitTunnelingSwitch.visible ?
|
||||
appSplitTunnelingSwitch.rightButton :
|
||||
focusItem
|
||||
|
||||
clickedFunction: function() {
|
||||
PageController.goToPage(PageEnum.PageSettingsSplitTunneling)
|
||||
root.close()
|
||||
|
@ -73,6 +94,7 @@ DrawerType2 {
|
|||
}
|
||||
|
||||
LabelWithButtonType {
|
||||
id: appSplitTunnelingSwitch
|
||||
visible: isAppSplitTinnelingEnabled
|
||||
|
||||
Layout.fillWidth: true
|
||||
|
@ -81,6 +103,8 @@ DrawerType2 {
|
|||
descriptionText: AppSplitTunnelingModel.isTunnelingEnabled ? qsTr("Enabled") : qsTr("Disabled")
|
||||
rightImageSource: "qrc:/images/controls/chevron-right.svg"
|
||||
|
||||
KeyNavigation.tab: focusItem
|
||||
|
||||
clickedFunction: function() {
|
||||
PageController.goToPage(PageEnum.PageSettingsAppSplitTunneling)
|
||||
root.close()
|
||||
|
|
|
@ -5,6 +5,8 @@ import QtQuick.Layouts
|
|||
import "../Controls2"
|
||||
import "../Controls2/TextTypes"
|
||||
|
||||
import "../Config"
|
||||
|
||||
DrawerType2 {
|
||||
id: root
|
||||
|
||||
|
@ -29,6 +31,14 @@ DrawerType2 {
|
|||
root.expandedHeight = content.implicitHeight + 32
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: root
|
||||
enabled: !GC.isMobile()
|
||||
function onOpened() {
|
||||
focusItem.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
Header2TextType {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 16
|
||||
|
@ -47,7 +57,13 @@ DrawerType2 {
|
|||
text: descriptionText
|
||||
}
|
||||
|
||||
Item {
|
||||
id: focusItem
|
||||
KeyNavigation.tab: yesButton
|
||||
}
|
||||
|
||||
BasicButtonType {
|
||||
id: yesButton
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 16
|
||||
Layout.rightMargin: 16
|
||||
|
@ -60,9 +76,12 @@ DrawerType2 {
|
|||
yesButtonFunction()
|
||||
}
|
||||
}
|
||||
|
||||
KeyNavigation.tab: noButton
|
||||
}
|
||||
|
||||
BasicButtonType {
|
||||
id: noButton
|
||||
Layout.fillWidth: true
|
||||
Layout.rightMargin: 16
|
||||
Layout.leftMargin: 16
|
||||
|
@ -81,6 +100,8 @@ DrawerType2 {
|
|||
noButtonFunction()
|
||||
}
|
||||
}
|
||||
|
||||
KeyNavigation.tab: focusItem
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import QtQuick.Layouts
|
|||
|
||||
import "../Controls2"
|
||||
import "../Controls2/TextTypes"
|
||||
import "../Config"
|
||||
|
||||
DrawerType2 {
|
||||
id: root
|
||||
|
@ -17,8 +18,21 @@ DrawerType2 {
|
|||
root.expandedHeight = container.implicitHeight
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: root
|
||||
enabled: !GC.isMobile()
|
||||
function onOpened() {
|
||||
focusItem.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: focusItem
|
||||
KeyNavigation.tab: backButton
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: backButton
|
||||
id: backButtonLayout
|
||||
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
|
@ -26,15 +40,15 @@ DrawerType2 {
|
|||
anchors.topMargin: 16
|
||||
|
||||
BackButtonType {
|
||||
id: backButton
|
||||
backButtonImage: "qrc:/images/controls/arrow-left.svg"
|
||||
backButtonFunction: function() {
|
||||
root.close()
|
||||
}
|
||||
backButtonFunction: function() { root.close() }
|
||||
KeyNavigation.tab: listView
|
||||
}
|
||||
}
|
||||
|
||||
FlickableType {
|
||||
anchors.top: backButton.bottom
|
||||
anchors.top: backButtonLayout.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
|
@ -71,10 +85,50 @@ DrawerType2 {
|
|||
id: buttonGroup
|
||||
}
|
||||
|
||||
property int currentFocusIndex: 0
|
||||
|
||||
activeFocusOnTab: true
|
||||
onActiveFocusChanged: {
|
||||
if (activeFocus) {
|
||||
this.currentFocusIndex = 0
|
||||
this.itemAtIndex(currentFocusIndex).forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
Keys.onTabPressed: {
|
||||
if (currentFocusIndex < this.count - 1) {
|
||||
currentFocusIndex += 1
|
||||
this.itemAtIndex(currentFocusIndex).forceActiveFocus()
|
||||
} else {
|
||||
listViewFocusItem.forceActiveFocus()
|
||||
focusItem.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: listViewFocusItem
|
||||
Keys.onTabPressed: {
|
||||
root.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
onVisibleChanged: {
|
||||
if (visible) {
|
||||
listViewFocusItem.forceActiveFocus()
|
||||
focusItem.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
delegate: Item {
|
||||
implicitWidth: root.width
|
||||
implicitHeight: delegateContent.implicitHeight
|
||||
|
||||
onActiveFocusChanged: {
|
||||
if (activeFocus) {
|
||||
radioButton.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: delegateContent
|
||||
|
||||
|
@ -89,12 +143,18 @@ DrawerType2 {
|
|||
hoverEnabled: true
|
||||
|
||||
indicator: Rectangle {
|
||||
anchors.fill: parent
|
||||
width: parent.width - 1
|
||||
height: parent.height
|
||||
color: radioButton.hovered ? "#2C2D30" : "#1C1D21"
|
||||
border.color: radioButton.focus ? "#D7D8DB" : "transparent"
|
||||
border.width: radioButton.focus ? 1 : 0
|
||||
|
||||
Behavior on color {
|
||||
PropertyAnimation { duration: 200 }
|
||||
}
|
||||
Behavior on border.color {
|
||||
PropertyAnimation { duration: 200 }
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
|
@ -137,6 +197,9 @@ DrawerType2 {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
Keys.onEnterPressed: radioButton.clicked()
|
||||
Keys.onReturnPressed: radioButton.clicked()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,16 +22,52 @@ ListView {
|
|||
clip: true
|
||||
interactive: false
|
||||
|
||||
activeFocusOnTab: true
|
||||
Keys.onTabPressed: {
|
||||
if (currentIndex < this.count - 1) {
|
||||
this.incrementCurrentIndex()
|
||||
} else {
|
||||
currentIndex = 0
|
||||
lastItemTabClickedSignal()
|
||||
}
|
||||
}
|
||||
|
||||
onCurrentIndexChanged: {
|
||||
if (visible) {
|
||||
if (fl.contentHeight > fl.height) {
|
||||
var item = this.currentItem
|
||||
if (item.y < fl.height) {
|
||||
fl.contentY = item.y
|
||||
} else if (item.y + item.height > fl.contentY + fl.height) {
|
||||
fl.contentY = item.y + item.height - fl.height
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onVisibleChanged: {
|
||||
if (visible) {
|
||||
this.currentIndex = 0
|
||||
}
|
||||
}
|
||||
|
||||
delegate: Item {
|
||||
implicitWidth: root.width
|
||||
implicitHeight: delegateContent.implicitHeight
|
||||
|
||||
onActiveFocusChanged: {
|
||||
if (activeFocus) {
|
||||
containerRadioButton.rightButton.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: delegateContent
|
||||
|
||||
anchors.fill: parent
|
||||
|
||||
LabelWithButtonType {
|
||||
id: containerRadioButton
|
||||
implicitWidth: parent.width
|
||||
|
||||
text: name
|
||||
|
|
|
@ -121,6 +121,9 @@ DrawerType2 {
|
|||
text: qsTr("Copy")
|
||||
imageSource: "qrc:/images/controls/copy.svg"
|
||||
|
||||
Keys.onReturnPressed: { copyConfigTextButton.clicked() }
|
||||
Keys.onEnterPressed: { copyConfigTextButton.clicked() }
|
||||
|
||||
KeyNavigation.tab: copyNativeConfigStringButton.visible ? copyNativeConfigStringButton : showSettingsButton
|
||||
}
|
||||
|
||||
|
@ -174,11 +177,30 @@ DrawerType2 {
|
|||
anchors.fill: parent
|
||||
expandedHeight: parent.height * 0.9
|
||||
|
||||
onClosed: {
|
||||
if (!GC.isMobile()) {
|
||||
header.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
expandedContent: Item {
|
||||
id: configContentContainer
|
||||
|
||||
implicitHeight: configContentDrawer.expandedHeight
|
||||
|
||||
Connections {
|
||||
target: configContentDrawer
|
||||
enabled: !GC.isMobile()
|
||||
function onOpened() {
|
||||
focusItem.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: focusItem
|
||||
KeyNavigation.tab: backButton
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: copyNativeConfigStringButton
|
||||
function onClicked() {
|
||||
|
@ -196,6 +218,7 @@ DrawerType2 {
|
|||
configText.copy()
|
||||
configText.select(0, 0)
|
||||
PageController.showNotificationMessage(qsTr("Copied"))
|
||||
header.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -207,9 +230,9 @@ DrawerType2 {
|
|||
anchors.right: parent.right
|
||||
anchors.topMargin: 16
|
||||
|
||||
backButtonFunction: function() {
|
||||
configContentDrawer.close()
|
||||
}
|
||||
backButtonFunction: function() { configContentDrawer.close() }
|
||||
|
||||
KeyNavigation.tab: focusItem
|
||||
}
|
||||
|
||||
FlickableType {
|
||||
|
@ -256,6 +279,7 @@ DrawerType2 {
|
|||
height: 24
|
||||
|
||||
readOnly: true
|
||||
activeFocusOnTab: false
|
||||
|
||||
color: "#D7D8DB"
|
||||
selectionColor: "#633303"
|
||||
|
|
|
@ -17,12 +17,19 @@ Rectangle {
|
|||
color: "#1C1D21"
|
||||
radius: 16
|
||||
|
||||
onFocusChanged: {
|
||||
if (focus) {
|
||||
udpButton.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
id: transportProtoButtonGroup
|
||||
|
||||
spacing: 0
|
||||
|
||||
HorizontalRadioButton {
|
||||
id: udpButton
|
||||
checked: root.currentIndex === 0
|
||||
|
||||
hoverEnabled: root.enabled
|
||||
|
@ -30,12 +37,15 @@ Rectangle {
|
|||
implicitWidth: (rootWidth - 32) / 2
|
||||
text: "UDP"
|
||||
|
||||
KeyNavigation.tab: tcpButton
|
||||
|
||||
onClicked: {
|
||||
root.currentIndex = 0
|
||||
}
|
||||
}
|
||||
|
||||
HorizontalRadioButton {
|
||||
id: tcpButton
|
||||
checked: root.currentIndex === 1
|
||||
|
||||
hoverEnabled: root.enabled
|
||||
|
|
|
@ -13,6 +13,12 @@ Item {
|
|||
|
||||
visible: backButtonImage !== ""
|
||||
|
||||
onActiveFocusChanged: {
|
||||
if (activeFocus) {
|
||||
backButton.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
id: content
|
||||
|
||||
|
@ -20,6 +26,7 @@ Item {
|
|||
anchors.leftMargin: 8
|
||||
|
||||
ImageButtonType {
|
||||
id: backButton
|
||||
image: backButtonImage
|
||||
imageColor: "#D7D8DB"
|
||||
|
||||
|
@ -42,4 +49,7 @@ Item {
|
|||
color: "transparent"
|
||||
}
|
||||
}
|
||||
|
||||
Keys.onEnterPressed: backButton.clicked()
|
||||
Keys.onReturnPressed: backButton.clicked()
|
||||
}
|
||||
|
|
|
@ -26,18 +26,29 @@ Button {
|
|||
|
||||
property bool squareLeftSide: false
|
||||
|
||||
property FlickableType parentFlickable
|
||||
|
||||
property var clickedFunc
|
||||
|
||||
implicitHeight: 56
|
||||
|
||||
hoverEnabled: true
|
||||
focusPolicy: Qt.TabFocus
|
||||
|
||||
onFocusChanged: {
|
||||
if (root.activeFocus) {
|
||||
if (root.parentFlickable) {
|
||||
root.parentFlickable.ensureVisible(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
id: focusBorder
|
||||
|
||||
color: "transparent"
|
||||
border.color: root.activeFocus ? root.borderFocusedColor : "transparent"
|
||||
border.width: root.activeFocus ? root.borderFocusedWidth : "transparent"
|
||||
border.width: root.activeFocus ? root.borderFocusedWidth : 0
|
||||
|
||||
anchors.fill: parent
|
||||
|
||||
|
|
|
@ -23,6 +23,8 @@ CheckBox {
|
|||
property string checkedBorderColor: "#FBB26A"
|
||||
property string checkedBorderDisabledColor: "#402102"
|
||||
|
||||
property string borderFocusedColor: "#D7D8DB"
|
||||
|
||||
property string checkedImageColor: "#FBB26A"
|
||||
property string pressedImageColor: "#A85809"
|
||||
property string defaultImageColor: "transparent"
|
||||
|
@ -30,7 +32,24 @@ CheckBox {
|
|||
|
||||
property string imageSource: "qrc:/images/controls/check.svg"
|
||||
|
||||
property var parentFlickable
|
||||
onFocusChanged: {
|
||||
if (root.activeFocus) {
|
||||
if (root.parentFlickable) {
|
||||
root.parentFlickable.ensureVisible(root)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hoverEnabled: enabled ? true : false
|
||||
focusPolicy: Qt.NoFocus
|
||||
|
||||
background: Rectangle {
|
||||
color: "transparent"
|
||||
border.color: root.focus ? borderFocusedColor : "transparent"
|
||||
border.width: 1
|
||||
radius: 16
|
||||
}
|
||||
|
||||
indicator: Rectangle {
|
||||
id: background
|
||||
|
@ -59,7 +78,11 @@ CheckBox {
|
|||
width: 24
|
||||
height: 24
|
||||
color: "transparent"
|
||||
border.color: root.checked ? (root.enabled ? checkedBorderColor : checkedBorderDisabledColor) : defaultBorderColor
|
||||
border.color: root.checked ?
|
||||
(root.enabled ?
|
||||
checkedBorderColor :
|
||||
checkedBorderDisabledColor) :
|
||||
defaultBorderColor
|
||||
border.width: 1
|
||||
radius: 4
|
||||
|
||||
|
@ -130,6 +153,16 @@ CheckBox {
|
|||
cursorShape: Qt.PointingHandCursor
|
||||
enabled: false
|
||||
}
|
||||
|
||||
|
||||
Keys.onEnterPressed: {
|
||||
root.checked = !root.checked
|
||||
}
|
||||
|
||||
Keys.onReturnPressed: {
|
||||
root.checked = !root.checked
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ import QtQuick.Controls
|
|||
import QtQuick.Layouts
|
||||
|
||||
import "TextTypes"
|
||||
import "../Config"
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
@ -27,6 +28,9 @@ Item {
|
|||
property string rootButtonBackgroundHoveredColor: "#1C1D21"
|
||||
property string rootButtonBackgroundPressedColor: "#1C1D21"
|
||||
|
||||
property string borderFocusedColor: "#D7D8DB"
|
||||
property int borderFocusedWidth: 1
|
||||
|
||||
property string rootButtonHoveredBorderColor: "#494B50"
|
||||
property string rootButtonDefaultBorderColor: "#2C2D30"
|
||||
property string rootButtonPressedBorderColor: "#D7D8DB"
|
||||
|
@ -42,36 +46,61 @@ Item {
|
|||
signal open
|
||||
signal close
|
||||
|
||||
function popupClosedFunc() {
|
||||
if (!GC.isMobile()) {
|
||||
this.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
property var parentFlickable
|
||||
onFocusChanged: {
|
||||
if (root.activeFocus) {
|
||||
if (root.parentFlickable) {
|
||||
root.parentFlickable.ensureVisible(root)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
implicitWidth: rootButtonContent.implicitWidth
|
||||
implicitHeight: rootButtonContent.implicitHeight
|
||||
|
||||
onOpen: {
|
||||
menu.open()
|
||||
rootButtonBackground.border.color = rootButtonPressedBorderColor
|
||||
}
|
||||
|
||||
onClose: {
|
||||
menu.close()
|
||||
rootButtonBackground.border.color = rootButtonDefaultBorderColor
|
||||
}
|
||||
|
||||
onEnabledChanged: {
|
||||
if (enabled) {
|
||||
rootButtonBackground.color = rootButtonBackgroundColor
|
||||
rootButtonBackground.border.color = rootButtonDefaultBorderColor
|
||||
} else {
|
||||
rootButtonBackground.color = "transparent"
|
||||
rootButtonBackground.border.color = rootButtonHoveredBorderColor
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: rootButtonBackground
|
||||
anchors.fill: rootButtonContent
|
||||
id: focusBorder
|
||||
|
||||
color: "transparent"
|
||||
border.color: root.activeFocus ? root.borderFocusedColor : "transparent"
|
||||
border.width: root.activeFocus ? root.borderFocusedWidth : 0
|
||||
anchors.fill: rootButtonContent
|
||||
radius: 16
|
||||
color: root.enabled ? rootButtonBackgroundColor : "transparent"
|
||||
border.color: root.enabled ? rootButtonDefaultBorderColor : rootButtonHoveredBorderColor
|
||||
|
||||
|
||||
Rectangle {
|
||||
id: rootButtonBackground
|
||||
|
||||
anchors.fill: focusBorder
|
||||
anchors.margins: root.activeFocus ? 2 : 0
|
||||
radius: root.activeFocus ? 14 : 16
|
||||
|
||||
color: {
|
||||
if (root.enabled) {
|
||||
if (root.pressed) {
|
||||
return root.rootButtonBackgroundPressedColor
|
||||
}
|
||||
return root.hovered ? root.rootButtonBackgroundHoveredColor : root.rootButtonBackgroundColor
|
||||
} else {
|
||||
return "transparent"
|
||||
}
|
||||
}
|
||||
|
||||
border.color: rootButtonDefaultBorderColor
|
||||
border.width: 1
|
||||
|
||||
Behavior on border.color {
|
||||
|
@ -82,6 +111,7 @@ Item {
|
|||
PropertyAnimation { duration: 200 }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
id: rootButtonContent
|
||||
|
@ -107,6 +137,7 @@ Item {
|
|||
}
|
||||
|
||||
ButtonTextType {
|
||||
id: buttonText
|
||||
Layout.fillWidth: true
|
||||
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
|
@ -136,26 +167,6 @@ Item {
|
|||
cursorShape: Qt.PointingHandCursor
|
||||
hoverEnabled: root.enabled ? true : false
|
||||
|
||||
onEntered: {
|
||||
if (menu.isClosed) {
|
||||
rootButtonBackground.border.color = rootButtonHoveredBorderColor
|
||||
rootButtonBackground.color = rootButtonBackgroundHoveredColor
|
||||
}
|
||||
}
|
||||
|
||||
onExited: {
|
||||
if (menu.isClosed) {
|
||||
rootButtonBackground.border.color = rootButtonDefaultBorderColor
|
||||
rootButtonBackground.color = rootButtonBackgroundColor
|
||||
}
|
||||
}
|
||||
|
||||
onPressed: {
|
||||
if (menu.isClosed) {
|
||||
rootButtonBackground.color = pressed ? rootButtonBackgroundPressedColor : entered ? rootButtonHoveredBorderColor : rootButtonDefaultBorderColor
|
||||
}
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
if (rootButtonClickedFunction && typeof rootButtonClickedFunction === "function") {
|
||||
rootButtonClickedFunction()
|
||||
|
@ -173,11 +184,27 @@ Item {
|
|||
anchors.fill: parent
|
||||
expandedHeight: drawerParent.height * drawerHeight
|
||||
|
||||
onClosed: {
|
||||
root.popupClosedFunc()
|
||||
}
|
||||
|
||||
expandedContent: Item {
|
||||
id: container
|
||||
|
||||
implicitHeight: menu.expandedHeight
|
||||
|
||||
Connections {
|
||||
target: menu
|
||||
enabled: !GC.isMobile()
|
||||
function onOpened() {
|
||||
focusItem.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: focusItem
|
||||
KeyNavigation.tab: backButton
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: header
|
||||
|
||||
|
@ -187,14 +214,15 @@ Item {
|
|||
anchors.topMargin: 16
|
||||
|
||||
BackButtonType {
|
||||
id: backButton
|
||||
backButtonImage: root.headerBackButtonImage
|
||||
backButtonFunction: function() {
|
||||
menu.close()
|
||||
}
|
||||
backButtonFunction: function() { menu.close() }
|
||||
KeyNavigation.tab: listViewLoader.item
|
||||
}
|
||||
}
|
||||
|
||||
FlickableType {
|
||||
id: flickable
|
||||
anchors.top: header.bottom
|
||||
anchors.topMargin: 16
|
||||
contentHeight: col.implicitHeight
|
||||
|
@ -221,9 +249,28 @@ Item {
|
|||
Loader {
|
||||
id: listViewLoader
|
||||
sourceComponent: root.listView
|
||||
|
||||
onLoaded: {
|
||||
listViewLoader.item.parentFlickable = flickable
|
||||
listViewLoader.item.lastItemTabClicked = function() {
|
||||
focusItem.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Keys.onEnterPressed: {
|
||||
if (menu.isClosed) {
|
||||
menu.open()
|
||||
}
|
||||
}
|
||||
|
||||
Keys.onReturnPressed: {
|
||||
if (menu.isClosed) {
|
||||
menu.open()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,14 @@ import "../Config"
|
|||
Flickable {
|
||||
id: fl
|
||||
|
||||
function ensureVisible(item) {
|
||||
if (item.y < fl.contentY) {
|
||||
fl.contentY = item.y
|
||||
} else if (item.y + item.height > fl.contentY + fl.height) {
|
||||
fl.contentY = item.y + item.height - fl.height + 40 // 40 is a bottom margin
|
||||
}
|
||||
}
|
||||
|
||||
clip: true
|
||||
width: parent.width
|
||||
|
||||
|
|
|
@ -9,6 +9,8 @@ Item {
|
|||
property string actionButtonImage
|
||||
property var actionButtonFunction
|
||||
|
||||
property alias actionButton: headerActionButton
|
||||
|
||||
property string headerText
|
||||
property string descriptionText
|
||||
|
||||
|
@ -60,4 +62,16 @@ Item {
|
|||
visible: root.descriptionText !== ""
|
||||
}
|
||||
}
|
||||
|
||||
Keys.onEnterPressed: {
|
||||
if (actionButtonFunction && typeof actionButtonFunction === "function") {
|
||||
actionButtonFunction()
|
||||
}
|
||||
}
|
||||
|
||||
Keys.onReturnPressed: {
|
||||
if (actionButtonFunction && typeof actionButtonFunction === "function") {
|
||||
actionButtonFunction()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,12 +9,16 @@ Item {
|
|||
property string actionButtonImage
|
||||
property var actionButtonFunction
|
||||
|
||||
property alias actionButton: headerActionButton
|
||||
|
||||
property string headerText
|
||||
property int headerTextMaximumLineCount: 2
|
||||
property int headerTextElide: Qt.ElideRight
|
||||
|
||||
property string descriptionText
|
||||
|
||||
focus: true
|
||||
|
||||
implicitWidth: content.implicitWidth
|
||||
implicitHeight: content.implicitHeight
|
||||
|
||||
|
@ -67,4 +71,16 @@ Item {
|
|||
visible: root.descriptionText !== ""
|
||||
}
|
||||
}
|
||||
|
||||
Keys.onEnterPressed: {
|
||||
if (actionButtonFunction && typeof actionButtonFunction === "function") {
|
||||
actionButtonFunction()
|
||||
}
|
||||
}
|
||||
|
||||
Keys.onReturnPressed: {
|
||||
if (actionButtonFunction && typeof actionButtonFunction === "function") {
|
||||
actionButtonFunction()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ RadioButton {
|
|||
property string checkedBorderColor: "#FBB26A"
|
||||
property string defaultBodredColor: "transparent"
|
||||
property string checkedDisabledBorderColor: "#84603D"
|
||||
property string borderFocusedColor: "#D7D8DB"
|
||||
property int borderWidth: 0
|
||||
|
||||
implicitWidth: content.implicitWidth
|
||||
|
@ -47,6 +48,8 @@ RadioButton {
|
|||
return root.pressedBorderColor
|
||||
} else if (root.checked) {
|
||||
return root.checkedBorderColor
|
||||
} else if (root.activeFocus) {
|
||||
return root.borderFocusedColor
|
||||
}
|
||||
return root.defaultBodredColor
|
||||
} else {
|
||||
|
@ -58,7 +61,7 @@ RadioButton {
|
|||
}
|
||||
|
||||
border.width: {
|
||||
if(root.checked) {
|
||||
if(root.checked || root.activeFocus) {
|
||||
return 1
|
||||
}
|
||||
return root.pressed ? 1 : 0
|
||||
|
@ -97,4 +100,12 @@ RadioButton {
|
|||
cursorShape: Qt.PointingHandCursor
|
||||
enabled: false
|
||||
}
|
||||
|
||||
Keys.onEnterPressed: {
|
||||
this.clicked()
|
||||
}
|
||||
|
||||
Keys.onReturnPressed: {
|
||||
this.clicked()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,11 +18,26 @@ Button {
|
|||
property alias backgroundColor: background.color
|
||||
property alias backgroundRadius: background.radius
|
||||
|
||||
property string borderFocusedColor: "#D7D8DB"
|
||||
property int borderFocusedWidth: 1
|
||||
|
||||
hoverEnabled: true
|
||||
focus: true
|
||||
focusPolicy: Qt.TabFocus
|
||||
|
||||
icon.source: image
|
||||
icon.color: root.enabled ? imageColor : disableImageColor
|
||||
|
||||
property Flickable parentFlickable
|
||||
|
||||
onFocusChanged: {
|
||||
if (root.activeFocus) {
|
||||
if (root.parentFlickable) {
|
||||
root.parentFlickable.ensureVisible(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on icon.color {
|
||||
PropertyAnimation { duration: 200 }
|
||||
}
|
||||
|
@ -31,6 +46,9 @@ Button {
|
|||
id: background
|
||||
|
||||
anchors.fill: parent
|
||||
border.color: root.activeFocus ? root.borderFocusedColor : "transparent"
|
||||
border.width: root.activeFocus ? root.borderFocusedWidth : 0
|
||||
|
||||
color: {
|
||||
if (root.enabled) {
|
||||
if (root.pressed) {
|
||||
|
@ -44,6 +62,9 @@ Button {
|
|||
Behavior on color {
|
||||
PropertyAnimation { duration: 200 }
|
||||
}
|
||||
Behavior on border.color {
|
||||
PropertyAnimation { duration: 200 }
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
|
|
|
@ -19,12 +19,18 @@ Item {
|
|||
property string leftImageSource
|
||||
property bool isLeftImageHoverEnabled: true //todo separete this qml file to 3
|
||||
|
||||
property alias rightButton: rightImage
|
||||
property FlickableType parentFlickable
|
||||
|
||||
property string textColor: "#d7d8db"
|
||||
property string textDisabledColor: "#878B91"
|
||||
property string descriptionColor: "#878B91"
|
||||
property string descriptionDisabledColor: "#494B50"
|
||||
property real textOpacity: 1.0
|
||||
|
||||
property string borderFocusedColor: "#D7D8DB"
|
||||
property int borderFocusedWidth: 1
|
||||
|
||||
property string rightImageColor: "#d7d8db"
|
||||
|
||||
property bool descriptionOnTop: false
|
||||
|
@ -32,6 +38,25 @@ Item {
|
|||
implicitWidth: content.implicitWidth + content.anchors.topMargin + content.anchors.bottomMargin
|
||||
implicitHeight: content.implicitHeight + content.anchors.leftMargin + content.anchors.rightMargin
|
||||
|
||||
onFocusChanged: {
|
||||
if (root.activeFocus) {
|
||||
if (root.parentFlickable) {
|
||||
root.parentFlickable.ensureVisible(root)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: rightImage
|
||||
function onFocusChanged() {
|
||||
if (rightImage.activeFocus) {
|
||||
if (root.parentFlickable) {
|
||||
root.parentFlickable.ensureVisible(root)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
id: content
|
||||
anchors.fill: parent
|
||||
|
@ -163,6 +188,9 @@ Item {
|
|||
anchors.fill: root
|
||||
color: "transparent"
|
||||
|
||||
border.color: root.activeFocus ? root.borderFocusedColor : "transparent"
|
||||
border.width: root.activeFocus ? root.borderFocusedWidth : 0
|
||||
|
||||
|
||||
Behavior on color {
|
||||
PropertyAnimation { duration: 200 }
|
||||
|
@ -207,4 +235,16 @@ Item {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
Keys.onEnterPressed: {
|
||||
if (clickedFunction && typeof clickedFunction === "function") {
|
||||
clickedFunction()
|
||||
}
|
||||
}
|
||||
|
||||
Keys.onReturnPressed: {
|
||||
if (clickedFunction && typeof clickedFunction === "function") {
|
||||
clickedFunction()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,6 +26,47 @@ ListView {
|
|||
clip: true
|
||||
interactive: false
|
||||
|
||||
property FlickableType parentFlickable
|
||||
property var lastItemTabClicked
|
||||
|
||||
property int currentFocusIndex: 0
|
||||
|
||||
activeFocusOnTab: true
|
||||
onActiveFocusChanged: {
|
||||
if (activeFocus) {
|
||||
this.currentFocusIndex = 0
|
||||
this.itemAtIndex(currentFocusIndex).forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
Keys.onTabPressed: {
|
||||
if (currentFocusIndex < this.count - 1) {
|
||||
currentFocusIndex += 1
|
||||
} else {
|
||||
currentFocusIndex = 0
|
||||
}
|
||||
this.itemAtIndex(currentFocusIndex).forceActiveFocus()
|
||||
}
|
||||
|
||||
Item {
|
||||
id: focusItem
|
||||
Keys.onTabPressed: {
|
||||
root.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
onVisibleChanged: {
|
||||
if (visible) {
|
||||
focusItem.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
onCurrentFocusIndexChanged: {
|
||||
if (parentFlickable) {
|
||||
parentFlickable.ensureVisible(this.itemAtIndex(currentFocusIndex))
|
||||
}
|
||||
}
|
||||
|
||||
ButtonGroup {
|
||||
id: buttonGroup
|
||||
}
|
||||
|
@ -40,6 +81,12 @@ ListView {
|
|||
implicitWidth: rootWidth
|
||||
implicitHeight: content.implicitHeight
|
||||
|
||||
onActiveFocusChanged: {
|
||||
if (activeFocus) {
|
||||
radioButton.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: content
|
||||
|
||||
|
@ -54,12 +101,18 @@ ListView {
|
|||
hoverEnabled: true
|
||||
|
||||
indicator: Rectangle {
|
||||
anchors.fill: parent
|
||||
width: parent.width - 1
|
||||
height: parent.height
|
||||
color: radioButton.hovered ? "#2C2D30" : "#1C1D21"
|
||||
border.color: radioButton.focus ? "#D7D8DB" : "transparent"
|
||||
border.width: radioButton.focus ? 1 : 0
|
||||
|
||||
Behavior on color {
|
||||
PropertyAnimation { duration: 200 }
|
||||
}
|
||||
Behavior on border.color {
|
||||
PropertyAnimation { duration: 200 }
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
|
@ -117,5 +170,13 @@ ListView {
|
|||
root.selectedText = name
|
||||
}
|
||||
}
|
||||
|
||||
Keys.onReturnPressed: {
|
||||
radioButton.clicked()
|
||||
}
|
||||
|
||||
Keys.onEnterPressed: {
|
||||
radioButton.clicked()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,28 @@ Item {
|
|||
|
||||
property var defaultActiveFocusItem: null
|
||||
|
||||
onVisibleChanged: {
|
||||
if (visible && !GC.isMobile()) {
|
||||
timer.start()
|
||||
}
|
||||
}
|
||||
|
||||
function lastItemTabClicked(focusItem) {
|
||||
if (GC.isMobile()) {
|
||||
return
|
||||
}
|
||||
|
||||
if (focusItem) {
|
||||
focusItem.forceActiveFocus()
|
||||
PageController.forceTabBarActiveFocus()
|
||||
} else {
|
||||
if (defaultActiveFocusItem) {
|
||||
defaultActiveFocusItem.forceActiveFocus()
|
||||
}
|
||||
PageController.forceTabBarActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
// MouseArea {
|
||||
// id: globalMouseArea
|
||||
// z: 99
|
||||
|
|
|
@ -25,6 +25,14 @@ Popup {
|
|||
color: Qt.rgba(14/255, 14/255, 17/255, 0.8)
|
||||
}
|
||||
|
||||
onOpened: {
|
||||
focusItem.forceActiveFocus()
|
||||
}
|
||||
|
||||
onClosed: {
|
||||
PageController.forceStackActiveFocus()
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
anchors.fill: parent
|
||||
|
||||
|
@ -52,7 +60,13 @@ Popup {
|
|||
text: root.text
|
||||
}
|
||||
|
||||
Item {
|
||||
id: focusItem
|
||||
KeyNavigation.tab: closeButton
|
||||
}
|
||||
|
||||
BasicButtonType {
|
||||
id: closeButton
|
||||
visible: closeButtonVisible
|
||||
|
||||
implicitHeight: 32
|
||||
|
@ -66,6 +80,8 @@ Popup {
|
|||
borderWidth: 0
|
||||
|
||||
text: qsTr("Close")
|
||||
KeyNavigation.tab: focusItem
|
||||
|
||||
clickedFunc: function() {
|
||||
root.close()
|
||||
}
|
||||
|
|
|
@ -18,6 +18,9 @@ Switch {
|
|||
property string defaultIndicatorColor: "transparent"
|
||||
property string checkedDisabledIndicatorColor: "#402102"
|
||||
|
||||
property string borderFocusedColor: "#D7D8DB"
|
||||
property int borderFocusedWidth: 1
|
||||
|
||||
property string checkedIndicatorBorderColor: "#633303"
|
||||
property string defaultIndicatorBorderColor: "#494B50"
|
||||
property string checkedDisabledIndicatorBorderColor: "#402102"
|
||||
|
@ -31,6 +34,16 @@ Switch {
|
|||
property string defaultIndicatorBackgroundColor: "transparent"
|
||||
|
||||
hoverEnabled: enabled ? true : false
|
||||
focusPolicy: Qt.TabFocus
|
||||
|
||||
property FlickableType parentFlickable: null
|
||||
onFocusChanged: {
|
||||
if (root.activeFocus) {
|
||||
if (root.parentFlickable) {
|
||||
root.parentFlickable.ensureVisible(root)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
indicator: Rectangle {
|
||||
id: switcher
|
||||
|
@ -44,8 +57,9 @@ Switch {
|
|||
radius: 16
|
||||
color: root.checked ? (root.enabled ? root.checkedIndicatorColor : root.checkedDisabledIndicatorColor)
|
||||
: root.defaultIndicatorColor
|
||||
border.color: root.checked ? (root.enabled ? root.checkedIndicatorBorderColor : root.checkedDisabledIndicatorBorderColor)
|
||||
: root.defaultIndicatorBorderColor
|
||||
|
||||
border.color: root.activeFocus ? root.borderFocusedColor : (root.checked ? (root.enabled ? root.checkedIndicatorBorderColor : root.checkedDisabledIndicatorBorderColor)
|
||||
: root.defaultIndicatorBorderColor)
|
||||
|
||||
Behavior on color {
|
||||
PropertyAnimation { duration: 200 }
|
||||
|
@ -114,4 +128,14 @@ Switch {
|
|||
cursorShape: Qt.PointingHandCursor
|
||||
enabled: false
|
||||
}
|
||||
|
||||
Keys.onEnterPressed: {
|
||||
root.checked = !root.checked
|
||||
root.checkedChanged()
|
||||
}
|
||||
|
||||
Keys.onReturnPressed: {
|
||||
root.checked = !root.checked
|
||||
root.checkedChanged()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,11 +10,15 @@ TabButton {
|
|||
|
||||
property string textColor: "#D7D8DB"
|
||||
|
||||
property string borderFocusedColor: "#D7D8DB"
|
||||
property int borderFocusedWidth: 1
|
||||
|
||||
property bool isSelected: false
|
||||
|
||||
implicitHeight: 48
|
||||
|
||||
hoverEnabled: true
|
||||
focusPolicy: Qt.TabFocus
|
||||
|
||||
background: Rectangle {
|
||||
id: background
|
||||
|
@ -22,6 +26,9 @@ TabButton {
|
|||
anchors.fill: parent
|
||||
color: "transparent"
|
||||
|
||||
border.color: root.activeFocus ? root.borderFocusedColor : "transparent"
|
||||
border.width: root.activeFocus ? root.borderFocusedWidth : 0
|
||||
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: 1
|
||||
|
|
|
@ -12,7 +12,13 @@ TabButton {
|
|||
|
||||
property bool isSelected: false
|
||||
|
||||
property string borderFocusedColor: "#D7D8DB"
|
||||
property int borderFocusedWidth: 1
|
||||
|
||||
property var clickedFunc
|
||||
|
||||
hoverEnabled: true
|
||||
focusPolicy: Qt.TabFocus
|
||||
|
||||
icon.source: image
|
||||
icon.color: isSelected ? selectedColor : defaultColor
|
||||
|
@ -21,6 +27,11 @@ TabButton {
|
|||
id: background
|
||||
anchors.fill: parent
|
||||
color: "transparent"
|
||||
radius: 10
|
||||
|
||||
border.color: root.activeFocus ? root.borderFocusedColor : "transparent"
|
||||
border.width: root.activeFocus ? root.borderFocusedWidth : 0
|
||||
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
|
@ -28,4 +39,22 @@ TabButton {
|
|||
cursorShape: Qt.PointingHandCursor
|
||||
enabled: false
|
||||
}
|
||||
|
||||
Keys.onEnterPressed: {
|
||||
if (root.clickedFunc && typeof root.clickedFunc === "function") {
|
||||
root.clickedFunc()
|
||||
}
|
||||
}
|
||||
|
||||
Keys.onReturnPressed: {
|
||||
if (root.clickedFunc && typeof root.clickedFunc === "function") {
|
||||
root.clickedFunc()
|
||||
}
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
if (root.clickedFunc && typeof root.clickedFunc === "function") {
|
||||
root.clickedFunc()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,15 @@ Rectangle {
|
|||
border.color: getBorderColor(borderNormalColor)
|
||||
radius: 16
|
||||
|
||||
property FlickableType parentFlickable: null
|
||||
onFocusChanged: {
|
||||
if (root.activeFocus) {
|
||||
if (root.parentFlickable) {
|
||||
root.parentFlickable.ensureVisible(root)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: parentMouse
|
||||
anchors.fill: parent
|
||||
|
|
|
@ -13,6 +13,7 @@ Item {
|
|||
|
||||
property alias errorText: errorField.text
|
||||
property bool checkEmptyText: false
|
||||
property bool rightButtonClickedOnEnter: false
|
||||
|
||||
property string buttonText
|
||||
property string buttonImageSource
|
||||
|
@ -36,6 +37,18 @@ Item {
|
|||
implicitWidth: content.implicitWidth
|
||||
implicitHeight: content.implicitHeight
|
||||
|
||||
property FlickableType parentFlickable
|
||||
Connections {
|
||||
target: textField
|
||||
function onFocusChanged() {
|
||||
if (textField.activeFocus) {
|
||||
if (root.parentFlickable) {
|
||||
root.parentFlickable.ensureVisible(root)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: content
|
||||
anchors.fill: parent
|
||||
|
@ -188,10 +201,22 @@ Item {
|
|||
}
|
||||
|
||||
Keys.onEnterPressed: {
|
||||
if (root.rightButtonClickedOnEnter && root.clickedFunc && typeof root.clickedFunc === "function") {
|
||||
clickedFunc()
|
||||
}
|
||||
|
||||
if (KeyNavigation.tab) {
|
||||
KeyNavigation.tab.forceActiveFocus();
|
||||
}
|
||||
}
|
||||
|
||||
Keys.onReturnPressed: {
|
||||
if (root.rightButtonClickedOnEnter &&root.clickedFunc && typeof root.clickedFunc === "function") {
|
||||
clickedFunc()
|
||||
}
|
||||
|
||||
if (KeyNavigation.tab) {
|
||||
KeyNavigation.tab.forceActiveFocus();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,16 +20,23 @@ RadioButton {
|
|||
property string textColor: "#D7D8DB"
|
||||
property string selectedTextColor: "#FBB26A"
|
||||
|
||||
property string borderFocusedColor: "#D7D8DB"
|
||||
property int borderFocusedWidth: 1
|
||||
|
||||
property string imageSource
|
||||
property bool showImage
|
||||
|
||||
hoverEnabled: true
|
||||
focusPolicy: Qt.TabFocus
|
||||
|
||||
indicator: Rectangle {
|
||||
id: background
|
||||
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
border.color: root.focus ? root.borderFocusedColor : "transparent"
|
||||
border.width: root.focus ? root.borderFocusedWidth : 0
|
||||
|
||||
implicitWidth: 56
|
||||
implicitHeight: 56
|
||||
radius: 16
|
||||
|
@ -51,6 +58,10 @@ RadioButton {
|
|||
PropertyAnimation { duration: 200 }
|
||||
}
|
||||
|
||||
Behavior on border.color {
|
||||
PropertyAnimation { duration: 200 }
|
||||
}
|
||||
|
||||
Image {
|
||||
source: {
|
||||
if (showImage) {
|
||||
|
|
|
@ -18,6 +18,8 @@ import "../Components"
|
|||
PageType {
|
||||
id: root
|
||||
|
||||
defaultActiveFocusItem: focusItem
|
||||
|
||||
Connections {
|
||||
target: PageController
|
||||
|
||||
|
@ -38,7 +40,15 @@ PageType {
|
|||
anchors.topMargin: 34
|
||||
anchors.bottomMargin: 34
|
||||
|
||||
Item {
|
||||
id: focusItem
|
||||
KeyNavigation.tab: loggingButton.visible ?
|
||||
loggingButton :
|
||||
connectButton
|
||||
}
|
||||
|
||||
BasicButtonType {
|
||||
id: loggingButton
|
||||
property bool isLoggingEnabled: SettingsController.isLoggingEnabled
|
||||
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
|
@ -55,6 +65,11 @@ PageType {
|
|||
visible: isLoggingEnabled ? true : false
|
||||
text: qsTr("Logging enabled")
|
||||
|
||||
Keys.onEnterPressed: loggingButton.clicked()
|
||||
Keys.onReturnPressed: loggingButton.clicked()
|
||||
|
||||
KeyNavigation.tab: connectButton
|
||||
|
||||
onClicked: {
|
||||
PageController.goToPage(PageEnum.PageSettingsLogging)
|
||||
}
|
||||
|
@ -64,9 +79,11 @@ PageType {
|
|||
id: connectButton
|
||||
Layout.fillHeight: true
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
KeyNavigation.tab: splitTunnelingButton
|
||||
}
|
||||
|
||||
BasicButtonType {
|
||||
id: splitTunnelingButton
|
||||
Layout.alignment: Qt.AlignHCenter | Qt.AlignBottom
|
||||
Layout.bottomMargin: 34
|
||||
leftPadding: 16
|
||||
|
@ -90,6 +107,11 @@ PageType {
|
|||
imageSource: isSplitTunnelingEnabled ? "qrc:/images/controls/split-tunneling.svg" : ""
|
||||
rightImageSource: "qrc:/images/controls/chevron-down.svg"
|
||||
|
||||
Keys.onEnterPressed: splitTunnelingButton.clicked()
|
||||
Keys.onReturnPressed: splitTunnelingButton.clicked()
|
||||
|
||||
KeyNavigation.tab: drawer
|
||||
|
||||
onClicked: {
|
||||
homeSplitTunnelingDrawer.open()
|
||||
}
|
||||
|
@ -97,6 +119,12 @@ PageType {
|
|||
HomeSplitTunnelingDrawer {
|
||||
id: homeSplitTunnelingDrawer
|
||||
parent: root
|
||||
|
||||
onClosed: {
|
||||
if (!GC.isMobile()) {
|
||||
focusItem.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -107,11 +135,26 @@ PageType {
|
|||
id: drawer
|
||||
anchors.fill: parent
|
||||
|
||||
onClosed: {
|
||||
if (!GC.isMobile()) {
|
||||
focusItem.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
collapsedContent: Item {
|
||||
implicitHeight: Qt.platform.os !== "ios" ? root.height * 0.9 : screen.height * 0.77
|
||||
Component.onCompleted: {
|
||||
drawer.expandedHeight = implicitHeight
|
||||
}
|
||||
Connections {
|
||||
target: drawer
|
||||
enabled: !GC.isMobile()
|
||||
function onActiveFocusChanged() {
|
||||
if (drawer.activeFocus && !drawer.isOpened) {
|
||||
collapsedButtonChevron.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
}
|
||||
ColumnLayout {
|
||||
id: collapsed
|
||||
|
||||
|
@ -178,6 +221,8 @@ PageType {
|
|||
text: ServersModel.defaultServerName
|
||||
horizontalAlignment: Qt.AlignHCenter
|
||||
|
||||
KeyNavigation.tab: tabBar
|
||||
|
||||
Behavior on opacity {
|
||||
PropertyAnimation { duration: 200 }
|
||||
}
|
||||
|
@ -201,6 +246,11 @@ PageType {
|
|||
topPadding: 4
|
||||
bottomPadding: 3
|
||||
|
||||
Keys.onEnterPressed: collapsedButtonChevron.clicked()
|
||||
Keys.onReturnPressed: collapsedButtonChevron.clicked()
|
||||
Keys.onTabPressed: lastItemTabClicked()
|
||||
|
||||
|
||||
onClicked: {
|
||||
if (drawer.isCollapsed) {
|
||||
drawer.open()
|
||||
|
@ -217,6 +267,16 @@ PageType {
|
|||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: drawer
|
||||
enabled: !GC.isMobile()
|
||||
function onIsCollapsedChanged() {
|
||||
if (!drawer.isCollapsed) {
|
||||
focusItem1.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: serversMenuHeader
|
||||
|
||||
|
@ -230,6 +290,11 @@ PageType {
|
|||
|
||||
visible: !ServersModel.isDefaultServerFromApi
|
||||
|
||||
Item {
|
||||
id: focusItem1
|
||||
KeyNavigation.tab: containersDropDown
|
||||
}
|
||||
|
||||
DropDownType {
|
||||
id: containersDropDown
|
||||
|
||||
|
@ -252,9 +317,16 @@ PageType {
|
|||
}
|
||||
|
||||
drawerParent: root
|
||||
KeyNavigation.tab: serversMenuContent
|
||||
|
||||
listView: HomeContainersListView {
|
||||
id: containersListView
|
||||
rootWidth: root.width
|
||||
onVisibleChanged: {
|
||||
if (containersDropDown.visible && !GC.isMobile()) {
|
||||
focusItem1.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: ServersModel
|
||||
|
@ -317,9 +389,43 @@ PageType {
|
|||
policy: serversMenuContent.height >= serversMenuContent.contentHeight ? ScrollBar.AlwaysOff : ScrollBar.AlwaysOn
|
||||
}
|
||||
|
||||
|
||||
activeFocusOnTab: true
|
||||
focus: true
|
||||
|
||||
property int focusItemIndex: 0
|
||||
onActiveFocusChanged: {
|
||||
if (activeFocus) {
|
||||
serversMenuContent.focusItemIndex = 0
|
||||
serversMenuContent.itemAtIndex(focusItemIndex).forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
onFocusItemIndexChanged: {
|
||||
const focusedElement = serversMenuContent.itemAtIndex(focusItemIndex)
|
||||
if (focusedElement) {
|
||||
if (focusedElement.y + focusedElement.height > serversMenuContent.height) {
|
||||
serversMenuContent.contentY = focusedElement.y + focusedElement.height - serversMenuContent.height
|
||||
} else {
|
||||
serversMenuContent.contentY = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Keys.onUpPressed: scrollBar.decrease()
|
||||
Keys.onDownPressed: scrollBar.increase()
|
||||
|
||||
Connections {
|
||||
target: drawer
|
||||
enabled: !GC.isMobile()
|
||||
function onIsCollapsedChanged() {
|
||||
if (drawer.isCollapsed) {
|
||||
const item = serversMenuContent.itemAtIndex(serversMenuContent.focusItemIndex)
|
||||
if (item) { item.serverRadioButtonProperty.focus = false }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: ServersModel
|
||||
function onDefaultServerIndexChanged(serverIndex) {
|
||||
|
@ -333,10 +439,17 @@ PageType {
|
|||
id: menuContentDelegate
|
||||
|
||||
property variant delegateData: model
|
||||
property VerticalRadioButton serverRadioButtonProperty: serverRadioButton
|
||||
|
||||
implicitWidth: serversMenuContent.width
|
||||
implicitHeight: serverRadioButtonContent.implicitHeight
|
||||
|
||||
onActiveFocusChanged: {
|
||||
if (activeFocus) {
|
||||
serverRadioButton.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: serverRadioButtonContent
|
||||
|
||||
|
@ -377,9 +490,14 @@ PageType {
|
|||
cursorShape: Qt.PointingHandCursor
|
||||
enabled: false
|
||||
}
|
||||
|
||||
Keys.onTabPressed: serverInfoButton.forceActiveFocus()
|
||||
Keys.onEnterPressed: serverRadioButton.clicked()
|
||||
Keys.onReturnPressed: serverRadioButton.clicked()
|
||||
}
|
||||
|
||||
ImageButtonType {
|
||||
id: serverInfoButton
|
||||
image: "qrc:/images/controls/settings.svg"
|
||||
imageColor: "#D7D8DB"
|
||||
|
||||
|
@ -388,6 +506,18 @@ PageType {
|
|||
|
||||
z: 1
|
||||
|
||||
Keys.onTabPressed: {
|
||||
if (serversMenuContent.focusItemIndex < serversMenuContent.count - 1) {
|
||||
serversMenuContent.focusItemIndex++
|
||||
serversMenuContent.itemAtIndex(serversMenuContent.focusItemIndex).forceActiveFocus()
|
||||
} else {
|
||||
focusItem1.forceActiveFocus()
|
||||
serversMenuContent.contentY = 0
|
||||
}
|
||||
}
|
||||
Keys.onEnterPressed: serverInfoButton.clicked()
|
||||
Keys.onReturnPressed: serverInfoButton.clicked()
|
||||
|
||||
onClicked: function() {
|
||||
ServersModel.processedIndex = index
|
||||
PageController.goToPage(PageEnum.PageSettingsServerInfo)
|
||||
|
|
|
@ -18,8 +18,18 @@ PageType {
|
|||
|
||||
defaultActiveFocusItem: listview.currentItem.portTextField.textField
|
||||
|
||||
Item {
|
||||
id: focusItem
|
||||
onFocusChanged: {
|
||||
if (activeFocus) {
|
||||
fl.ensureVisible(focusItem)
|
||||
}
|
||||
}
|
||||
KeyNavigation.tab: backButton
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: backButton
|
||||
id: backButtonLayout
|
||||
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
|
@ -28,12 +38,14 @@ PageType {
|
|||
anchors.topMargin: 20
|
||||
|
||||
BackButtonType {
|
||||
id: backButton
|
||||
KeyNavigation.tab: listview.currentItem.portTextField.textField
|
||||
}
|
||||
}
|
||||
|
||||
FlickableType {
|
||||
id: fl
|
||||
anchors.top: backButton.bottom
|
||||
anchors.top: backButtonLayout.bottom
|
||||
anchors.bottom: parent.bottom
|
||||
contentHeight: content.implicitHeight
|
||||
|
||||
|
@ -47,8 +59,6 @@ PageType {
|
|||
enabled: ServersModel.isProcessedServerHasWriteAccess()
|
||||
|
||||
ListView {
|
||||
|
||||
|
||||
id: listview
|
||||
|
||||
width: parent.width
|
||||
|
@ -94,6 +104,7 @@ PageType {
|
|||
textFieldText: port
|
||||
textField.maximumLength: 5
|
||||
textField.validator: IntValidator { bottom: 1; top: 65535 }
|
||||
parentFlickable: fl
|
||||
|
||||
textField.onEditingFinished: {
|
||||
if (textFieldText !== port) {
|
||||
|
@ -103,7 +114,7 @@ PageType {
|
|||
|
||||
checkEmptyText: true
|
||||
|
||||
KeyNavigation.tab: junkPacketCountTextField.textField
|
||||
KeyNavigation.tab: mtuTextField.textField
|
||||
}
|
||||
|
||||
TextFieldWithHeaderType {
|
||||
|
@ -124,6 +135,7 @@ PageType {
|
|||
}
|
||||
}
|
||||
checkEmptyText: true
|
||||
KeyNavigation.tab: junkPacketCountTextField.textField
|
||||
}
|
||||
|
||||
TextFieldWithHeaderType {
|
||||
|
@ -134,6 +146,7 @@ PageType {
|
|||
headerText: "Jc - Junk packet count"
|
||||
textFieldText: junkPacketCount
|
||||
textField.validator: IntValidator { bottom: 0 }
|
||||
parentFlickable: fl
|
||||
|
||||
textField.onEditingFinished: {
|
||||
if (textFieldText === "") {
|
||||
|
@ -158,6 +171,7 @@ PageType {
|
|||
headerText: "Jmin - Junk packet minimum size"
|
||||
textFieldText: junkPacketMinSize
|
||||
textField.validator: IntValidator { bottom: 0 }
|
||||
parentFlickable: fl
|
||||
|
||||
textField.onEditingFinished: {
|
||||
if (textFieldText !== junkPacketMinSize) {
|
||||
|
@ -178,6 +192,7 @@ PageType {
|
|||
headerText: "Jmax - Junk packet maximum size"
|
||||
textFieldText: junkPacketMaxSize
|
||||
textField.validator: IntValidator { bottom: 0 }
|
||||
parentFlickable: fl
|
||||
|
||||
textField.onEditingFinished: {
|
||||
if (textFieldText !== junkPacketMaxSize) {
|
||||
|
@ -198,6 +213,7 @@ PageType {
|
|||
headerText: "S1 - Init packet junk size"
|
||||
textFieldText: initPacketJunkSize
|
||||
textField.validator: IntValidator { bottom: 0 }
|
||||
parentFlickable: fl
|
||||
|
||||
textField.onEditingFinished: {
|
||||
if (textFieldText !== initPacketJunkSize) {
|
||||
|
@ -218,6 +234,7 @@ PageType {
|
|||
headerText: "S2 - Response packet junk size"
|
||||
textFieldText: responsePacketJunkSize
|
||||
textField.validator: IntValidator { bottom: 0 }
|
||||
parentFlickable: fl
|
||||
|
||||
textField.onEditingFinished: {
|
||||
if (textFieldText !== responsePacketJunkSize) {
|
||||
|
@ -238,6 +255,7 @@ PageType {
|
|||
headerText: "H1 - Init packet magic header"
|
||||
textFieldText: initPacketMagicHeader
|
||||
textField.validator: IntValidator { bottom: 0 }
|
||||
parentFlickable: fl
|
||||
|
||||
textField.onEditingFinished: {
|
||||
if (textFieldText !== initPacketMagicHeader) {
|
||||
|
@ -258,6 +276,7 @@ PageType {
|
|||
headerText: "H2 - Response packet magic header"
|
||||
textFieldText: responsePacketMagicHeader
|
||||
textField.validator: IntValidator { bottom: 0 }
|
||||
parentFlickable: fl
|
||||
|
||||
textField.onEditingFinished: {
|
||||
if (textFieldText !== responsePacketMagicHeader) {
|
||||
|
@ -278,6 +297,7 @@ PageType {
|
|||
headerText: "H4 - Transport packet magic header"
|
||||
textFieldText: transportPacketMagicHeader
|
||||
textField.validator: IntValidator { bottom: 0 }
|
||||
parentFlickable: fl
|
||||
|
||||
textField.onEditingFinished: {
|
||||
if (textFieldText !== transportPacketMagicHeader) {
|
||||
|
@ -294,6 +314,7 @@ PageType {
|
|||
id: underloadPacketMagicHeaderTextField
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 16
|
||||
parentFlickable: fl
|
||||
|
||||
headerText: "H3 - Underload packet magic header"
|
||||
textFieldText: underloadPacketMagicHeader
|
||||
|
@ -312,6 +333,7 @@ PageType {
|
|||
|
||||
BasicButtonType {
|
||||
id: saveRestartButton
|
||||
parentFlickable: fl
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 24
|
||||
|
@ -330,7 +352,9 @@ PageType {
|
|||
|
||||
text: qsTr("Save")
|
||||
|
||||
onClicked: {
|
||||
Keys.onTabPressed: lastItemTabClicked(focusItem)
|
||||
|
||||
clickedFunc: function() {
|
||||
if (AwgConfigModel.isHeadersEqual(underloadPacketMagicHeaderTextField.textField.text,
|
||||
transportPacketMagicHeaderTextField.textField.text,
|
||||
responsePacketMagicHeaderTextField.textField.text,
|
||||
|
@ -362,6 +386,9 @@ PageType {
|
|||
InstallController.updateContainer(AwgConfigModel.getConfig())
|
||||
}
|
||||
var noButtonFunction = function() {
|
||||
if (!GC.isMobile()) {
|
||||
saveRestartButton.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
showQuestionDrawer(headerText, descriptionText, yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
|
||||
}
|
||||
|
|
|
@ -17,8 +17,13 @@ PageType {
|
|||
|
||||
defaultActiveFocusItem: listview.currentItem.trafficFromField.textField
|
||||
|
||||
Item {
|
||||
id: focusItem
|
||||
KeyNavigation.tab: backButton
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: backButton
|
||||
id: backButtonLayout
|
||||
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
|
@ -27,12 +32,14 @@ PageType {
|
|||
anchors.topMargin: 20
|
||||
|
||||
BackButtonType {
|
||||
id: backButton
|
||||
KeyNavigation.tab: listview.currentItem.trafficFromField.textField
|
||||
}
|
||||
}
|
||||
|
||||
FlickableType {
|
||||
id: fl
|
||||
anchors.top: backButton.bottom
|
||||
anchors.top: backButtonLayout.bottom
|
||||
anchors.bottom: parent.bottom
|
||||
contentHeight: content.implicitHeight
|
||||
|
||||
|
@ -123,7 +130,7 @@ PageType {
|
|||
}
|
||||
}
|
||||
|
||||
KeyNavigation.tab: saveRestartButton
|
||||
KeyNavigation.tab: cipherDropDown
|
||||
}
|
||||
|
||||
DropDownType {
|
||||
|
@ -135,6 +142,7 @@ PageType {
|
|||
headerText: qsTr("Cipher")
|
||||
|
||||
drawerParent: root
|
||||
KeyNavigation.tab: saveRestartButton
|
||||
|
||||
listView: ListViewWithRadioButtonType {
|
||||
id: cipherListView
|
||||
|
@ -175,6 +183,7 @@ PageType {
|
|||
Layout.bottomMargin: 24
|
||||
|
||||
text: qsTr("Save")
|
||||
Keys.onTabPressed: lastItemTabClicked(focusItem)
|
||||
|
||||
clickedFunc: function() {
|
||||
forceActiveFocus()
|
||||
|
|
|
@ -18,8 +18,18 @@ PageType {
|
|||
|
||||
defaultActiveFocusItem: listview.currentItem.vpnAddressSubnetTextField.textField
|
||||
|
||||
Item {
|
||||
id: focusItem
|
||||
KeyNavigation.tab: backButton
|
||||
onActiveFocusChanged: {
|
||||
if (activeFocus) {
|
||||
fl.ensureVisible(focusItem)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: backButton
|
||||
id: backButtonLayout
|
||||
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
|
@ -28,12 +38,14 @@ PageType {
|
|||
anchors.topMargin: 20
|
||||
|
||||
BackButtonType {
|
||||
id: backButton
|
||||
KeyNavigation.tab: listview.currentItem.vpnAddressSubnetTextField.textField
|
||||
}
|
||||
}
|
||||
|
||||
FlickableType {
|
||||
id: fl
|
||||
anchors.top: backButton.bottom
|
||||
anchors.top: backButtonLayout.bottom
|
||||
anchors.bottom: parent.bottom
|
||||
contentHeight: content.implicitHeight
|
||||
|
||||
|
@ -90,13 +102,14 @@ PageType {
|
|||
headerText: qsTr("VPN address subnet")
|
||||
textFieldText: subnetAddress
|
||||
|
||||
parentFlickable: fl
|
||||
KeyNavigation.tab: transportProtoSelector
|
||||
|
||||
textField.onEditingFinished: {
|
||||
if (textFieldText !== subnetAddress) {
|
||||
subnetAddress = textFieldText
|
||||
}
|
||||
}
|
||||
|
||||
KeyNavigation.tab: portTextField.enabled ? portTextField.textField : saveRestartButton
|
||||
}
|
||||
|
||||
ParagraphTextType {
|
||||
|
@ -107,6 +120,7 @@ PageType {
|
|||
}
|
||||
|
||||
TransportProtoSelector {
|
||||
id: transportProtoSelector
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 16
|
||||
rootWidth: root.width
|
||||
|
@ -117,6 +131,8 @@ PageType {
|
|||
return transportProto === "tcp" ? 1 : 0
|
||||
}
|
||||
|
||||
KeyNavigation.tab: portTextField.enabled ? portTextField.textField : autoNegotiateEncryprionSwitcher
|
||||
|
||||
onCurrentIndexChanged: {
|
||||
if (transportProto === "tcp" && currentIndex === 0) {
|
||||
transportProto = "udp"
|
||||
|
@ -131,6 +147,7 @@ PageType {
|
|||
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 40
|
||||
parentFlickable: fl
|
||||
|
||||
enabled: isPortEditable
|
||||
|
||||
|
@ -145,7 +162,7 @@ PageType {
|
|||
}
|
||||
}
|
||||
|
||||
KeyNavigation.tab: saveRestartButton
|
||||
KeyNavigation.tab: autoNegotiateEncryprionSwitcher
|
||||
}
|
||||
|
||||
SwitcherType {
|
||||
|
@ -153,6 +170,7 @@ PageType {
|
|||
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 24
|
||||
parentFlickable: fl
|
||||
|
||||
text: qsTr("Auto-negotiate encryption")
|
||||
checked: autoNegotiateEncryprion
|
||||
|
@ -162,6 +180,10 @@ PageType {
|
|||
autoNegotiateEncryprion = checked
|
||||
}
|
||||
}
|
||||
|
||||
KeyNavigation.tab: hashDropDown.enabled ?
|
||||
hashDropDown :
|
||||
tlsAuthCheckBox
|
||||
}
|
||||
|
||||
DropDownType {
|
||||
|
@ -175,6 +197,10 @@ PageType {
|
|||
headerText: qsTr("Hash")
|
||||
|
||||
drawerParent: root
|
||||
parentFlickable: fl
|
||||
KeyNavigation.tab: cipherDropDown.enabled ?
|
||||
cipherDropDown :
|
||||
tlsAuthCheckBox
|
||||
|
||||
listView: ListViewWithRadioButtonType {
|
||||
id: hashListView
|
||||
|
@ -223,6 +249,9 @@ PageType {
|
|||
headerText: qsTr("Cipher")
|
||||
|
||||
drawerParent: root
|
||||
parentFlickable: fl
|
||||
|
||||
KeyNavigation.tab: tlsAuthCheckBox
|
||||
|
||||
listView: ListViewWithRadioButtonType {
|
||||
id: cipherListView
|
||||
|
@ -261,24 +290,40 @@ PageType {
|
|||
}
|
||||
|
||||
Rectangle {
|
||||
id: contentRect
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 32
|
||||
Layout.preferredHeight: checkboxLayout.implicitHeight
|
||||
color: "#1C1D21"
|
||||
radius: 16
|
||||
|
||||
Connections {
|
||||
target: tlsAuthCheckBox
|
||||
enabled: !GC.isMobile()
|
||||
|
||||
function onFocusChanged() {
|
||||
if (tlsAuthCheckBox.activeFocus) {
|
||||
fl.ensureVisible(contentRect)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: checkboxLayout
|
||||
|
||||
anchors.fill: parent
|
||||
CheckBoxType {
|
||||
id: tlsAuthCheckBox
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: qsTr("TLS auth")
|
||||
checked: tlsAuth
|
||||
|
||||
KeyNavigation.tab: blockDnsCheckBox
|
||||
|
||||
onCheckedChanged: {
|
||||
if (checked !== tlsAuth) {
|
||||
console.log("tlsAuth changed to: " + checked)
|
||||
tlsAuth = checked
|
||||
}
|
||||
}
|
||||
|
@ -287,11 +332,14 @@ PageType {
|
|||
DividerType {}
|
||||
|
||||
CheckBoxType {
|
||||
id: blockDnsCheckBox
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: qsTr("Block DNS requests outside of VPN")
|
||||
checked: blockDns
|
||||
|
||||
KeyNavigation.tab: additionalClientCommandsSwitcher
|
||||
|
||||
onCheckedChanged: {
|
||||
if (checked !== blockDns) {
|
||||
blockDns = checked
|
||||
|
@ -305,6 +353,10 @@ PageType {
|
|||
id: additionalClientCommandsSwitcher
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 32
|
||||
parentFlickable: fl
|
||||
KeyNavigation.tab: additionalClientCommandsTextArea.visible ?
|
||||
additionalClientCommandsTextArea.textArea :
|
||||
additionalServerCommandsSwitcher
|
||||
|
||||
checked: additionalClientCommands !== ""
|
||||
|
||||
|
@ -318,10 +370,13 @@ PageType {
|
|||
}
|
||||
|
||||
TextAreaType {
|
||||
id: additionalClientCommandsTextArea
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 16
|
||||
|
||||
visible: additionalClientCommandsSwitcher.checked
|
||||
KeyNavigation.tab: additionalServerCommandsSwitcher
|
||||
parentFlickable: fl
|
||||
|
||||
textAreaText: additionalClientCommands
|
||||
placeholderText: qsTr("Commands:")
|
||||
|
@ -337,6 +392,10 @@ PageType {
|
|||
id: additionalServerCommandsSwitcher
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 16
|
||||
parentFlickable: fl
|
||||
KeyNavigation.tab: additionalServerCommandsTextArea.visible ?
|
||||
additionalServerCommandsTextArea.textArea :
|
||||
saveRestartButton
|
||||
|
||||
checked: additionalServerCommands !== ""
|
||||
|
||||
|
@ -350,6 +409,7 @@ PageType {
|
|||
}
|
||||
|
||||
TextAreaType {
|
||||
id: additionalServerCommandsTextArea
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 16
|
||||
|
||||
|
@ -357,7 +417,8 @@ PageType {
|
|||
|
||||
textAreaText: additionalServerCommands
|
||||
placeholderText: qsTr("Commands:")
|
||||
|
||||
parentFlickable: fl
|
||||
KeyNavigation.tab: saveRestartButton
|
||||
textArea.onEditingFinished: {
|
||||
if (additionalServerCommands !== textAreaText) {
|
||||
additionalServerCommands = textAreaText
|
||||
|
@ -373,6 +434,8 @@ PageType {
|
|||
Layout.bottomMargin: 24
|
||||
|
||||
text: qsTr("Save")
|
||||
parentFlickable: fl
|
||||
Keys.onTabPressed: lastItemTabClicked(focusItem)
|
||||
|
||||
clickedFunc: function() {
|
||||
forceActiveFocus()
|
||||
|
|
|
@ -18,6 +18,13 @@ import "../Components"
|
|||
PageType {
|
||||
id: root
|
||||
|
||||
defaultActiveFocusItem: focusItem
|
||||
|
||||
Item {
|
||||
id: focusItem
|
||||
KeyNavigation.tab: backButton
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: header
|
||||
|
||||
|
@ -28,6 +35,8 @@ PageType {
|
|||
anchors.topMargin: 20
|
||||
|
||||
BackButtonType {
|
||||
id: backButton
|
||||
KeyNavigation.tab: listView
|
||||
}
|
||||
|
||||
HeaderType {
|
||||
|
@ -55,16 +64,29 @@ PageType {
|
|||
anchors.topMargin: 32
|
||||
|
||||
ListView {
|
||||
id: listView
|
||||
width: parent.width
|
||||
height: contentItem.height
|
||||
clip: true
|
||||
interactive: false
|
||||
model: ProtocolsModel
|
||||
|
||||
activeFocusOnTab: true
|
||||
focus: true
|
||||
|
||||
onActiveFocusChanged: {
|
||||
if (focus) {
|
||||
listView.currentIndex = 0
|
||||
listView.currentItem.focusItem.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
delegate: Item {
|
||||
implicitWidth: parent.width
|
||||
implicitHeight: delegateContent.implicitHeight
|
||||
|
||||
property alias focusItem: button
|
||||
|
||||
ColumnLayout {
|
||||
id: delegateContent
|
||||
|
||||
|
@ -81,6 +103,8 @@ PageType {
|
|||
configContentDrawer.open()
|
||||
}
|
||||
|
||||
KeyNavigation.tab: removeButton
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: button
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
|
@ -95,14 +119,33 @@ PageType {
|
|||
|
||||
expandedHeight: root.height * 0.9
|
||||
|
||||
onClosed: {
|
||||
if (!GC.isMobile()) {
|
||||
defaultActiveFocusItem.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
parent: root
|
||||
anchors.fill: parent
|
||||
|
||||
expandedContent: Item {
|
||||
implicitHeight: configContentDrawer.expandedHeight
|
||||
|
||||
Connections {
|
||||
target: configContentDrawer
|
||||
enabled: !GC.isMobile()
|
||||
function onOpened() {
|
||||
focusItem1.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: focusItem1
|
||||
KeyNavigation.tab: backButton1
|
||||
}
|
||||
|
||||
BackButtonType {
|
||||
id: backButton
|
||||
id: backButton1
|
||||
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
|
@ -112,10 +155,12 @@ PageType {
|
|||
backButtonFunction: function() {
|
||||
configContentDrawer.close()
|
||||
}
|
||||
|
||||
KeyNavigation.tab: focusItem1
|
||||
}
|
||||
|
||||
FlickableType {
|
||||
anchors.top: backButton.bottom
|
||||
anchors.top: backButton1.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
|
@ -180,6 +225,7 @@ PageType {
|
|||
text: qsTr("Remove ") + ContainersModel.getProcessedContainerName()
|
||||
textColor: "#EB5757"
|
||||
|
||||
Keys.onTabPressed: lastItemTabClicked(focusItem)
|
||||
clickedFunction: function() {
|
||||
var headerText = qsTr("Remove %1 from server?").arg(ContainersModel.getProcessedContainerName())
|
||||
var descriptionText = qsTr("All users with whom you shared a connection with will no longer be able to connect to it.")
|
||||
|
@ -191,6 +237,9 @@ PageType {
|
|||
InstallController.removeProcessedContainer()
|
||||
}
|
||||
var noButtonFunction = function() {
|
||||
if (!GC.isMobile()) {
|
||||
focusItem.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
showQuestionDrawer(headerText, descriptionText, yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
|
||||
|
|
|
@ -15,10 +15,17 @@ import "../Components"
|
|||
PageType {
|
||||
id: root
|
||||
|
||||
defaultActiveFocusItem: listview.currentItem.portTextField.textField
|
||||
defaultActiveFocusItem: listview.currentItem.focusItemId.enabled ?
|
||||
listview.currentItem.focusItemId.textField :
|
||||
focusItem
|
||||
|
||||
Item {
|
||||
id: focusItem
|
||||
KeyNavigation.tab: backButton
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: backButton
|
||||
id: backButtonLayout
|
||||
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
|
@ -27,12 +34,16 @@ PageType {
|
|||
anchors.topMargin: 20
|
||||
|
||||
BackButtonType {
|
||||
id: backButton
|
||||
KeyNavigation.tab: listview.currentItem.focusItemId.enabled ?
|
||||
listview.currentItem.focusItemId.textField :
|
||||
focusItem
|
||||
}
|
||||
}
|
||||
|
||||
FlickableType {
|
||||
id: fl
|
||||
anchors.top: backButton.bottom
|
||||
anchors.top: backButtonLayout.bottom
|
||||
anchors.bottom: parent.bottom
|
||||
contentHeight: content.implicitHeight
|
||||
|
||||
|
@ -60,7 +71,11 @@ PageType {
|
|||
implicitWidth: listview.width
|
||||
implicitHeight: col.implicitHeight
|
||||
|
||||
property alias portTextField: portTextField
|
||||
property var focusItemId: portTextField.enabled ?
|
||||
portTextField :
|
||||
cipherDropDown.enabled ?
|
||||
cipherDropDown :
|
||||
saveRestartButton
|
||||
|
||||
ColumnLayout {
|
||||
id: col
|
||||
|
@ -99,7 +114,7 @@ PageType {
|
|||
}
|
||||
}
|
||||
|
||||
KeyNavigation.tab: saveRestartButton
|
||||
KeyNavigation.tab: cipherDropDown
|
||||
}
|
||||
|
||||
DropDownType {
|
||||
|
@ -113,6 +128,7 @@ PageType {
|
|||
headerText: qsTr("Cipher")
|
||||
|
||||
drawerParent: root
|
||||
KeyNavigation.tab: saveRestartButton
|
||||
|
||||
listView: ListViewWithRadioButtonType {
|
||||
id: cipherListView
|
||||
|
@ -155,6 +171,7 @@ PageType {
|
|||
enabled: isPortEditable | isCipherEditable
|
||||
|
||||
text: qsTr("Save")
|
||||
Keys.onTabPressed: lastItemTabClicked(focusItem)
|
||||
|
||||
clickedFunc: function() {
|
||||
forceActiveFocus()
|
||||
|
|
|
@ -15,8 +15,15 @@ import "../Components"
|
|||
PageType {
|
||||
id: root
|
||||
|
||||
defaultActiveFocusItem: listview
|
||||
|
||||
Item {
|
||||
id: focusItem
|
||||
KeyNavigation.tab: backButton
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: backButton
|
||||
id: backButtonLayout
|
||||
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
|
@ -25,12 +32,14 @@ PageType {
|
|||
anchors.topMargin: 20
|
||||
|
||||
BackButtonType {
|
||||
id: backButton
|
||||
KeyNavigation.tab: listview
|
||||
}
|
||||
}
|
||||
|
||||
FlickableType {
|
||||
id: fl
|
||||
anchors.top: backButton.bottom
|
||||
anchors.top: backButtonLayout.bottom
|
||||
anchors.bottom: parent.bottom
|
||||
contentHeight: content.implicitHeight
|
||||
|
||||
|
@ -54,7 +63,16 @@ PageType {
|
|||
|
||||
model: WireGuardConfigModel
|
||||
|
||||
activeFocusOnTab: true
|
||||
onActiveFocusChanged: {
|
||||
if (activeFocus) {
|
||||
listview.itemAtIndex(0)?.focusItemId.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
delegate: Item {
|
||||
property alias focusItemId: portTextField.textField
|
||||
|
||||
implicitWidth: listview.width
|
||||
implicitHeight: col.implicitHeight
|
||||
|
||||
|
@ -85,6 +103,8 @@ PageType {
|
|||
textField.maximumLength: 5
|
||||
textField.validator: IntValidator { bottom: 1; top: 65535 }
|
||||
|
||||
KeyNavigation.tab: mtuTextField.textField
|
||||
|
||||
textField.onEditingFinished: {
|
||||
if (textFieldText !== port) {
|
||||
port = textFieldText
|
||||
|
@ -103,6 +123,8 @@ PageType {
|
|||
textFieldText: mtu
|
||||
textField.validator: IntValidator { bottom: 576; top: 65535 }
|
||||
|
||||
KeyNavigation.tab: saveButton
|
||||
|
||||
textField.onEditingFinished: {
|
||||
if (textFieldText === "") {
|
||||
textFieldText = "0"
|
||||
|
@ -115,6 +137,7 @@ PageType {
|
|||
}
|
||||
|
||||
BasicButtonType {
|
||||
id: saveButton
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 24
|
||||
Layout.bottomMargin: 24
|
||||
|
@ -124,6 +147,8 @@ PageType {
|
|||
|
||||
text: qsTr("Save")
|
||||
|
||||
Keys.onTabPressed: lastItemTabClicked(focusItem)
|
||||
|
||||
onClicked: {
|
||||
forceActiveFocus()
|
||||
|
||||
|
@ -134,7 +159,11 @@ PageType {
|
|||
|
||||
PageController.goToPage(PageEnum.PageSetupWizardInstalling);
|
||||
InstallController.updateContainer(WireGuardConfigModel.getConfig())
|
||||
focusItem.forceActiveFocus()
|
||||
}
|
||||
|
||||
Keys.onEnterPressed: saveButton.clicked()
|
||||
Keys.onReturnPressed: saveButton.clicked()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,8 +16,15 @@ import "../Components"
|
|||
PageType {
|
||||
id: root
|
||||
|
||||
defaultActiveFocusItem: listview
|
||||
|
||||
Item {
|
||||
id: focusItem
|
||||
KeyNavigation.tab: backButton
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: backButton
|
||||
id: backButtonLayout
|
||||
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
|
@ -26,12 +33,14 @@ PageType {
|
|||
anchors.topMargin: 20
|
||||
|
||||
BackButtonType {
|
||||
id: backButton
|
||||
KeyNavigation.tab: listview
|
||||
}
|
||||
}
|
||||
|
||||
FlickableType {
|
||||
id: fl
|
||||
anchors.top: backButton.bottom
|
||||
anchors.top: backButtonLayout.bottom
|
||||
anchors.bottom: parent.bottom
|
||||
contentHeight: content.implicitHeight
|
||||
|
||||
|
@ -55,7 +64,16 @@ PageType {
|
|||
|
||||
model: XrayConfigModel
|
||||
|
||||
activeFocusOnTab: true
|
||||
onActiveFocusChanged: {
|
||||
if (activeFocus) {
|
||||
listview.itemAtIndex(0)?.focusItemId.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
delegate: Item {
|
||||
property alias focusItemId: textFieldWithHeaderType.textField
|
||||
|
||||
implicitWidth: listview.width
|
||||
implicitHeight: col.implicitHeight
|
||||
|
||||
|
@ -77,12 +95,15 @@ PageType {
|
|||
}
|
||||
|
||||
TextFieldWithHeaderType {
|
||||
id: textFieldWithHeaderType
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 32
|
||||
|
||||
headerText: qsTr("Disguised as traffic from")
|
||||
textFieldText: site
|
||||
|
||||
KeyNavigation.tab: basicButton
|
||||
|
||||
textField.onEditingFinished: {
|
||||
if (textFieldText !== site) {
|
||||
var tmpText = textFieldText
|
||||
|
@ -99,12 +120,15 @@ PageType {
|
|||
}
|
||||
|
||||
BasicButtonType {
|
||||
id: basicButton
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 24
|
||||
Layout.bottomMargin: 24
|
||||
|
||||
text: qsTr("Save")
|
||||
|
||||
Keys.onTabPressed: lastItemTabClicked(focusItem)
|
||||
|
||||
onClicked: {
|
||||
forceActiveFocus()
|
||||
|
||||
|
@ -115,7 +139,11 @@ PageType {
|
|||
|
||||
PageController.goToPage(PageEnum.PageSetupWizardInstalling);
|
||||
InstallController.updateContainer(XrayConfigModel.getConfig())
|
||||
focusItem.forceActiveFocus()
|
||||
}
|
||||
|
||||
Keys.onEnterPressed: basicButton.clicked()
|
||||
Keys.onReturnPressed: basicButton.clicked()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,8 +15,15 @@ import "../Components"
|
|||
PageType {
|
||||
id: root
|
||||
|
||||
defaultActiveFocusItem: focusItem
|
||||
|
||||
Item {
|
||||
id: focusItem
|
||||
KeyNavigation.tab: backButton
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: backButton
|
||||
id: backButtonLayout
|
||||
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
|
@ -25,12 +32,14 @@ PageType {
|
|||
anchors.topMargin: 20
|
||||
|
||||
BackButtonType {
|
||||
id: backButton
|
||||
KeyNavigation.tab: removeButton
|
||||
}
|
||||
}
|
||||
|
||||
FlickableType {
|
||||
id: fl
|
||||
anchors.top: backButton.bottom
|
||||
anchors.top: backButtonLayout.bottom
|
||||
anchors.bottom: parent.bottom
|
||||
contentHeight: content.implicitHeight
|
||||
|
||||
|
@ -62,6 +71,8 @@ PageType {
|
|||
text: qsTr("Remove ") + ContainersModel.getProcessedContainerName()
|
||||
textColor: "#EB5757"
|
||||
|
||||
Keys.onTabPressed: root.lastItemTabClicked()
|
||||
|
||||
clickedFunction: function() {
|
||||
var headerText = qsTr("Remove %1 from server?").arg(ContainersModel.getProcessedContainerName())
|
||||
var yesButtonText = qsTr("Continue")
|
||||
|
@ -78,6 +89,9 @@ PageType {
|
|||
}
|
||||
}
|
||||
var noButtonFunction = function() {
|
||||
if (!GC.isMobile()) {
|
||||
removeButton.rightButton.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
showQuestionDrawer(headerText, "", yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
|
||||
|
|
|
@ -15,6 +15,8 @@ import "../Components"
|
|||
PageType {
|
||||
id: root
|
||||
|
||||
defaultActiveFocusItem: focusItem
|
||||
|
||||
Connections {
|
||||
target: InstallController
|
||||
|
||||
|
@ -23,8 +25,13 @@ PageType {
|
|||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: focusItem
|
||||
KeyNavigation.tab: backButton
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: backButton
|
||||
id: backButtonLayout
|
||||
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
|
@ -33,12 +40,14 @@ PageType {
|
|||
anchors.topMargin: 20
|
||||
|
||||
BackButtonType {
|
||||
id: backButton
|
||||
KeyNavigation.tab: listview
|
||||
}
|
||||
}
|
||||
|
||||
FlickableType {
|
||||
id: fl
|
||||
anchors.top: backButton.bottom
|
||||
anchors.top: backButtonLayout.bottom
|
||||
anchors.bottom: parent.bottom
|
||||
contentHeight: content.implicitHeight
|
||||
|
||||
|
@ -62,10 +71,18 @@ PageType {
|
|||
|
||||
model: SftpConfigModel
|
||||
|
||||
onFocusChanged: {
|
||||
if (focus) {
|
||||
listview.currentItem.focusItem.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
delegate: Item {
|
||||
implicitWidth: listview.width
|
||||
implicitHeight: col.implicitHeight
|
||||
|
||||
property alias focusItem: hostLabel.rightButton
|
||||
|
||||
ColumnLayout {
|
||||
id: col
|
||||
|
||||
|
@ -84,9 +101,13 @@ PageType {
|
|||
}
|
||||
|
||||
LabelWithButtonType {
|
||||
id: hostLabel
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 32
|
||||
|
||||
parentFlickable: fl
|
||||
KeyNavigation.tab: portLabel.rightButton
|
||||
|
||||
text: qsTr("Host")
|
||||
descriptionText: ServersModel.getProcessedServerData("hostName")
|
||||
|
||||
|
@ -98,10 +119,14 @@ PageType {
|
|||
clickedFunction: function() {
|
||||
GC.copyToClipBoard(descriptionText)
|
||||
PageController.showNotificationMessage(qsTr("Copied"))
|
||||
if (!GC.isMobile()) {
|
||||
this.rightButton.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LabelWithButtonType {
|
||||
id: portLabel
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: qsTr("Port")
|
||||
|
@ -109,16 +134,23 @@ PageType {
|
|||
|
||||
descriptionOnTop: true
|
||||
|
||||
parentFlickable: fl
|
||||
KeyNavigation.tab: usernameLabel.rightButton
|
||||
|
||||
rightImageSource: "qrc:/images/controls/copy.svg"
|
||||
rightImageColor: "#D7D8DB"
|
||||
|
||||
clickedFunction: function() {
|
||||
GC.copyToClipBoard(descriptionText)
|
||||
PageController.showNotificationMessage(qsTr("Copied"))
|
||||
if (!GC.isMobile()) {
|
||||
this.rightButton.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LabelWithButtonType {
|
||||
id: usernameLabel
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: qsTr("User name")
|
||||
|
@ -126,16 +158,23 @@ PageType {
|
|||
|
||||
descriptionOnTop: true
|
||||
|
||||
parentFlickable: fl
|
||||
KeyNavigation.tab: passwordLabel.rightButton
|
||||
|
||||
rightImageSource: "qrc:/images/controls/copy.svg"
|
||||
rightImageColor: "#D7D8DB"
|
||||
|
||||
clickedFunction: function() {
|
||||
GC.copyToClipBoard(descriptionText)
|
||||
PageController.showNotificationMessage(qsTr("Copied"))
|
||||
if (!GC.isMobile()) {
|
||||
this.rightButton.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LabelWithButtonType {
|
||||
id: passwordLabel
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: qsTr("Password")
|
||||
|
@ -143,16 +182,29 @@ PageType {
|
|||
|
||||
descriptionOnTop: true
|
||||
|
||||
parentFlickable: fl
|
||||
Keys.onTabPressed: {
|
||||
if (mountButton.visible) {
|
||||
mountButton.forceActiveFocus()
|
||||
} else {
|
||||
detailedInstructionsButton.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
rightImageSource: "qrc:/images/controls/copy.svg"
|
||||
rightImageColor: "#D7D8DB"
|
||||
|
||||
clickedFunction: function() {
|
||||
GC.copyToClipBoard(descriptionText)
|
||||
PageController.showNotificationMessage(qsTr("Copied"))
|
||||
if (!GC.isMobile()) {
|
||||
this.rightButton.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BasicButtonType {
|
||||
id: mountButton
|
||||
visible: !GC.isMobile()
|
||||
|
||||
Layout.fillWidth: true
|
||||
|
@ -168,6 +220,9 @@ PageType {
|
|||
textColor: "#D7D8DB"
|
||||
borderWidth: 1
|
||||
|
||||
parentFlickable: fl
|
||||
KeyNavigation.tab: detailedInstructionsButton
|
||||
|
||||
text: qsTr("Mount folder on device")
|
||||
|
||||
clickedFunc: function() {
|
||||
|
@ -216,6 +271,7 @@ PageType {
|
|||
}
|
||||
|
||||
BasicButtonType {
|
||||
id: detailedInstructionsButton
|
||||
Layout.topMargin: 16
|
||||
Layout.bottomMargin: 16
|
||||
Layout.leftMargin: 8
|
||||
|
@ -229,12 +285,16 @@ PageType {
|
|||
|
||||
text: qsTr("Detailed instructions")
|
||||
|
||||
parentFlickable: fl
|
||||
KeyNavigation.tab: removeButton
|
||||
|
||||
clickedFunc: function() {
|
||||
// Qt.openUrlExternally("https://github.com/amnezia-vpn/desktop-client/releases/latest")
|
||||
}
|
||||
}
|
||||
|
||||
BasicButtonType {
|
||||
id: removeButton
|
||||
Layout.topMargin: 24
|
||||
Layout.bottomMargin: 16
|
||||
Layout.leftMargin: 8
|
||||
|
@ -245,6 +305,9 @@ PageType {
|
|||
pressedColor: Qt.rgba(1, 1, 1, 0.12)
|
||||
textColor: "#EB5757"
|
||||
|
||||
parentFlickable: fl
|
||||
Keys.onTabPressed: lastItemTabClicked()
|
||||
|
||||
text: qsTr("Remove SFTP and all data stored there")
|
||||
|
||||
clickedFunc: function() {
|
||||
|
@ -257,6 +320,9 @@ PageType {
|
|||
InstallController.removeProcessedContainer()
|
||||
}
|
||||
var noButtonFunction = function() {
|
||||
if (!GC.isMobile()) {
|
||||
removeButton.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
showQuestionDrawer(headerText, "", yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
|
||||
|
|
|
@ -16,6 +16,8 @@ import "../Components"
|
|||
PageType {
|
||||
id: root
|
||||
|
||||
defaultActiveFocusItem: focusItem
|
||||
|
||||
Connections {
|
||||
target: InstallController
|
||||
|
||||
|
@ -24,8 +26,13 @@ PageType {
|
|||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: focusItem
|
||||
KeyNavigation.tab: backButton
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: backButton
|
||||
id: backButtonLayout
|
||||
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
|
@ -34,12 +41,14 @@ PageType {
|
|||
anchors.topMargin: 20
|
||||
|
||||
BackButtonType {
|
||||
id: backButton
|
||||
KeyNavigation.tab: websiteName.rightButton
|
||||
}
|
||||
}
|
||||
|
||||
FlickableType {
|
||||
id: fl
|
||||
anchors.top: backButton.bottom
|
||||
anchors.top: backButtonLayout.bottom
|
||||
anchors.bottom: parent.bottom
|
||||
contentHeight: content.implicitHeight
|
||||
|
||||
|
@ -61,6 +70,7 @@ PageType {
|
|||
}
|
||||
|
||||
LabelWithButtonType {
|
||||
id: websiteName
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 32
|
||||
|
||||
|
@ -77,9 +87,14 @@ PageType {
|
|||
rightImageSource: "qrc:/images/controls/copy.svg"
|
||||
rightImageColor: "#D7D8DB"
|
||||
|
||||
KeyNavigation.tab: removeButton
|
||||
|
||||
clickedFunction: function() {
|
||||
GC.copyToClipBoard(descriptionText)
|
||||
PageController.showNotificationMessage(qsTr("Copied"))
|
||||
if (!GC.isMobile()) {
|
||||
this.rightButton.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -113,6 +128,7 @@ PageType {
|
|||
}
|
||||
|
||||
BasicButtonType {
|
||||
id: removeButton
|
||||
Layout.topMargin: 24
|
||||
Layout.bottomMargin: 16
|
||||
Layout.leftMargin: 8
|
||||
|
@ -125,6 +141,8 @@ PageType {
|
|||
|
||||
text: qsTr("Remove website")
|
||||
|
||||
Keys.onTabPressed: lastItemTabClicked(focusItem)
|
||||
|
||||
clickedFunc: function() {
|
||||
var headerText = qsTr("The site with all data will be removed from the tor network.")
|
||||
var yesButtonText = qsTr("Continue")
|
||||
|
@ -135,6 +153,9 @@ PageType {
|
|||
InstallController.removeProcessedContainer()
|
||||
}
|
||||
var noButtonFunction = function() {
|
||||
if (!GC.isMobile()) {
|
||||
removeButton.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
showQuestionDrawer(headerText, "", yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
|
||||
|
|
|
@ -13,6 +13,8 @@ import "../Config"
|
|||
PageType {
|
||||
id: root
|
||||
|
||||
defaultActiveFocusItem: header
|
||||
|
||||
FlickableType {
|
||||
id: fl
|
||||
anchors.top: parent.top
|
||||
|
@ -29,15 +31,19 @@ PageType {
|
|||
spacing: 0
|
||||
|
||||
HeaderType {
|
||||
id: header
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 24
|
||||
Layout.rightMargin: 16
|
||||
Layout.leftMargin: 16
|
||||
|
||||
headerText: qsTr("Settings")
|
||||
|
||||
KeyNavigation.tab: account.rightButton
|
||||
}
|
||||
|
||||
LabelWithButtonType {
|
||||
id: account
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 16
|
||||
|
||||
|
@ -48,11 +54,14 @@ PageType {
|
|||
clickedFunction: function() {
|
||||
PageController.goToPage(PageEnum.PageSettingsServersList)
|
||||
}
|
||||
|
||||
KeyNavigation.tab: connection.rightButton
|
||||
}
|
||||
|
||||
DividerType {}
|
||||
|
||||
LabelWithButtonType {
|
||||
id: connection
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: qsTr("Connection")
|
||||
|
@ -62,11 +71,14 @@ PageType {
|
|||
clickedFunction: function() {
|
||||
PageController.goToPage(PageEnum.PageSettingsConnection)
|
||||
}
|
||||
|
||||
KeyNavigation.tab: application.rightButton
|
||||
}
|
||||
|
||||
DividerType {}
|
||||
|
||||
LabelWithButtonType {
|
||||
id: application
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: qsTr("Application")
|
||||
|
@ -76,11 +88,14 @@ PageType {
|
|||
clickedFunction: function() {
|
||||
PageController.goToPage(PageEnum.PageSettingsApplication)
|
||||
}
|
||||
|
||||
KeyNavigation.tab: backup.rightButton
|
||||
}
|
||||
|
||||
DividerType {}
|
||||
|
||||
LabelWithButtonType {
|
||||
id: backup
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: qsTr("Backup")
|
||||
|
@ -90,6 +105,8 @@ PageType {
|
|||
clickedFunction: function() {
|
||||
PageController.goToPage(PageEnum.PageSettingsBackup)
|
||||
}
|
||||
|
||||
KeyNavigation.tab: about.rightButton
|
||||
}
|
||||
|
||||
DividerType {}
|
||||
|
@ -105,11 +122,14 @@ PageType {
|
|||
clickedFunction: function() {
|
||||
PageController.goToPage(PageEnum.PageSettingsAbout)
|
||||
}
|
||||
KeyNavigation.tab: close
|
||||
|
||||
}
|
||||
|
||||
DividerType {}
|
||||
|
||||
LabelWithButtonType {
|
||||
id: close
|
||||
visible: GC.isDesktop()
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: about.height
|
||||
|
@ -118,6 +138,8 @@ PageType {
|
|||
leftImageSource: "qrc:/images/controls/x-circle.svg"
|
||||
isLeftImageHoverEnabled: false
|
||||
|
||||
Keys.onTabPressed: lastItemTabClicked(header)
|
||||
|
||||
clickedFunction: function() {
|
||||
PageController.closeApplication()
|
||||
}
|
||||
|
|
|
@ -13,6 +13,19 @@ import "../Components"
|
|||
PageType {
|
||||
id: root
|
||||
|
||||
defaultActiveFocusItem: focusItem
|
||||
|
||||
Item {
|
||||
id: focusItem
|
||||
KeyNavigation.tab: backButton
|
||||
|
||||
onFocusChanged: {
|
||||
if (focusItem.activeFocus) {
|
||||
fl.contentY = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BackButtonType {
|
||||
id: backButton
|
||||
|
||||
|
@ -20,6 +33,8 @@ PageType {
|
|||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.topMargin: 20
|
||||
|
||||
KeyNavigation.tab: telegramButton
|
||||
}
|
||||
|
||||
FlickableType {
|
||||
|
@ -82,6 +97,7 @@ PageType {
|
|||
}
|
||||
|
||||
LabelWithButtonType {
|
||||
id: telegramButton
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 16
|
||||
|
||||
|
@ -89,6 +105,9 @@ PageType {
|
|||
descriptionText: qsTr("To discuss features")
|
||||
leftImageSource: "qrc:/images/controls/telegram.svg"
|
||||
|
||||
KeyNavigation.tab: mailButton
|
||||
parentFlickable: fl
|
||||
|
||||
clickedFunction: function() {
|
||||
Qt.openUrlExternally(qsTr("https://t.me/amnezia_vpn_en"))
|
||||
}
|
||||
|
@ -97,40 +116,55 @@ PageType {
|
|||
DividerType {}
|
||||
|
||||
LabelWithButtonType {
|
||||
id: mailButton
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: qsTr("Mail")
|
||||
descriptionText: qsTr("For reviews and bug reports")
|
||||
leftImageSource: "qrc:/images/controls/mail.svg"
|
||||
|
||||
KeyNavigation.tab: githubButton
|
||||
parentFlickable: fl
|
||||
|
||||
clickedFunction: function() {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
DividerType {}
|
||||
|
||||
LabelWithButtonType {
|
||||
id: githubButton
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: qsTr("Github")
|
||||
leftImageSource: "qrc:/images/controls/github.svg"
|
||||
|
||||
KeyNavigation.tab: websiteButton
|
||||
parentFlickable: fl
|
||||
|
||||
clickedFunction: function() {
|
||||
Qt.openUrlExternally(qsTr("https://github.com/amnezia-vpn/amnezia-client"))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
DividerType {}
|
||||
|
||||
LabelWithButtonType {
|
||||
id: websiteButton
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: qsTr("Website")
|
||||
leftImageSource: "qrc:/images/controls/amnezia.svg"
|
||||
|
||||
KeyNavigation.tab: checkUpdatesButton
|
||||
parentFlickable: fl
|
||||
|
||||
clickedFunction: function() {
|
||||
Qt.openUrlExternally(qsTr("https://amnezia.org"))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
DividerType {}
|
||||
|
@ -146,6 +180,7 @@ PageType {
|
|||
}
|
||||
|
||||
BasicButtonType {
|
||||
id: checkUpdatesButton
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.topMargin: 8
|
||||
Layout.bottomMargin: 16
|
||||
|
@ -159,12 +194,16 @@ PageType {
|
|||
|
||||
text: qsTr("Check for updates")
|
||||
|
||||
KeyNavigation.tab: privacyPolicyButton
|
||||
parentFlickable: fl
|
||||
|
||||
clickedFunc: function() {
|
||||
Qt.openUrlExternally("https://github.com/amnezia-vpn/desktop-client/releases/latest")
|
||||
}
|
||||
}
|
||||
|
||||
BasicButtonType {
|
||||
id: privacyPolicyButton
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.bottomMargin: 16
|
||||
Layout.topMargin: -15
|
||||
|
@ -178,6 +217,9 @@ PageType {
|
|||
|
||||
text: qsTr("Privacy Policy")
|
||||
|
||||
Keys.onTabPressed: lastItemTabClicked()
|
||||
parentFlickable: fl
|
||||
|
||||
clickedFunc: function() {
|
||||
Qt.openUrlExternally("https://amnezia.org/en/policy")
|
||||
}
|
||||
|
|
|
@ -20,6 +20,8 @@ import "../Components"
|
|||
PageType {
|
||||
id: root
|
||||
|
||||
defaultActiveFocusItem: focusItem
|
||||
|
||||
property bool pageEnabled
|
||||
|
||||
Component.onCompleted: {
|
||||
|
@ -63,6 +65,11 @@ PageType {
|
|||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: focusItem
|
||||
KeyNavigation.tab: backButton
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: header
|
||||
|
||||
|
@ -73,6 +80,8 @@ PageType {
|
|||
anchors.topMargin: 20
|
||||
|
||||
BackButtonType {
|
||||
id: backButton
|
||||
KeyNavigation.tab: switcher
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
|
@ -93,6 +102,10 @@ PageType {
|
|||
|
||||
enabled: root.pageEnabled
|
||||
|
||||
KeyNavigation.tab: selector.enabled ?
|
||||
selector :
|
||||
searchField.textField
|
||||
|
||||
checked: AppSplitTunnelingModel.isTunnelingEnabled
|
||||
onToggled: {
|
||||
AppSplitTunnelingModel.toggleSplitTunneling(checked)
|
||||
|
@ -116,6 +129,8 @@ PageType {
|
|||
|
||||
enabled: Qt.platform.os === "android" && root.pageEnabled
|
||||
|
||||
KeyNavigation.tab: searchField.textField
|
||||
|
||||
listView: ListViewWithRadioButtonType {
|
||||
rootWidth: root.width
|
||||
|
||||
|
@ -251,6 +266,9 @@ PageType {
|
|||
textFieldPlaceholderText: qsTr("application name")
|
||||
buttonImageSource: "qrc:/images/controls/plus.svg"
|
||||
|
||||
Keys.onTabPressed: lastItemTabClicked(focusItem)
|
||||
rightButtonClickedOnEnter: true
|
||||
|
||||
clickedFunc: function() {
|
||||
searchField.focus = false
|
||||
PageController.showBusyIndicator(true)
|
||||
|
|
|
@ -13,6 +13,53 @@ import "../Components"
|
|||
PageType {
|
||||
id: root
|
||||
|
||||
defaultActiveFocusItem: focusItem
|
||||
|
||||
function getNextComponentInFocusChain(componentId) {
|
||||
const componentsList = [focusItem,
|
||||
backButton,
|
||||
switcher,
|
||||
switcherAutoStart,
|
||||
switcherAutoConnect,
|
||||
switcherStartMinimized,
|
||||
labelWithButtonLanguage,
|
||||
labelWithButtonLogging,
|
||||
labelWithButtonReset,
|
||||
]
|
||||
|
||||
const idx = componentsList.indexOf(componentId)
|
||||
|
||||
if (idx === -1) {
|
||||
return null
|
||||
}
|
||||
|
||||
let nextIndex = idx + 1
|
||||
if (nextIndex >= componentsList.length) {
|
||||
nextIndex = 0
|
||||
}
|
||||
|
||||
if (componentsList[nextIndex].visible) {
|
||||
if ((nextIndex) >= 6) {
|
||||
return componentsList[nextIndex].rightButton
|
||||
} else {
|
||||
return componentsList[nextIndex]
|
||||
}
|
||||
} else {
|
||||
return getNextComponentInFocusChain(componentsList[nextIndex])
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: focusItem
|
||||
KeyNavigation.tab: root.getNextComponentInFocusChain(focusItem)
|
||||
|
||||
onFocusChanged: {
|
||||
if (focusItem.activeFocus) {
|
||||
fl.contentY = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BackButtonType {
|
||||
id: backButton
|
||||
|
||||
|
@ -20,6 +67,8 @@ PageType {
|
|||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.topMargin: 20
|
||||
|
||||
KeyNavigation.tab: root.getNextComponentInFocusChain(backButton)
|
||||
}
|
||||
|
||||
FlickableType {
|
||||
|
@ -44,6 +93,7 @@ PageType {
|
|||
}
|
||||
|
||||
SwitcherType {
|
||||
id: switcher
|
||||
visible: GC.isMobile()
|
||||
|
||||
Layout.fillWidth: true
|
||||
|
@ -57,6 +107,9 @@ PageType {
|
|||
SettingsController.toggleScreenshotsEnabled(checked)
|
||||
}
|
||||
}
|
||||
|
||||
KeyNavigation.tab: root.getNextComponentInFocusChain(switcher)
|
||||
parentFlickable: fl
|
||||
}
|
||||
|
||||
DividerType {
|
||||
|
@ -64,6 +117,7 @@ PageType {
|
|||
}
|
||||
|
||||
SwitcherType {
|
||||
id: switcherAutoStart
|
||||
visible: !GC.isMobile()
|
||||
|
||||
Layout.fillWidth: true
|
||||
|
@ -72,6 +126,9 @@ PageType {
|
|||
text: qsTr("Auto start")
|
||||
descriptionText: qsTr("Launch the application every time the device is starts")
|
||||
|
||||
KeyNavigation.tab: root.getNextComponentInFocusChain(switcherAutoStart)
|
||||
parentFlickable: fl
|
||||
|
||||
checked: SettingsController.isAutoStartEnabled()
|
||||
onCheckedChanged: {
|
||||
if (checked !== SettingsController.isAutoStartEnabled()) {
|
||||
|
@ -85,6 +142,7 @@ PageType {
|
|||
}
|
||||
|
||||
SwitcherType {
|
||||
id: switcherAutoConnect
|
||||
visible: !GC.isMobile()
|
||||
|
||||
Layout.fillWidth: true
|
||||
|
@ -93,6 +151,9 @@ PageType {
|
|||
text: qsTr("Auto connect")
|
||||
descriptionText: qsTr("Connect to VPN on app start")
|
||||
|
||||
KeyNavigation.tab: root.getNextComponentInFocusChain(switcherAutoConnect)
|
||||
parentFlickable: fl
|
||||
|
||||
checked: SettingsController.isAutoConnectEnabled()
|
||||
onCheckedChanged: {
|
||||
if (checked !== SettingsController.isAutoConnectEnabled()) {
|
||||
|
@ -106,6 +167,7 @@ PageType {
|
|||
}
|
||||
|
||||
SwitcherType {
|
||||
id: switcherStartMinimized
|
||||
visible: !GC.isMobile()
|
||||
|
||||
Layout.fillWidth: true
|
||||
|
@ -114,6 +176,9 @@ PageType {
|
|||
text: qsTr("Start minimized")
|
||||
descriptionText: qsTr("Launch application minimized")
|
||||
|
||||
KeyNavigation.tab: root.getNextComponentInFocusChain(switcherStartMinimized)
|
||||
parentFlickable: fl
|
||||
|
||||
checked: SettingsController.isStartMinimizedEnabled()
|
||||
onCheckedChanged: {
|
||||
if (checked !== SettingsController.isStartMinimizedEnabled()) {
|
||||
|
@ -127,12 +192,16 @@ PageType {
|
|||
}
|
||||
|
||||
LabelWithButtonType {
|
||||
id: labelWithButtonLanguage
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: qsTr("Language")
|
||||
descriptionText: LanguageModel.currentLanguageName
|
||||
rightImageSource: "qrc:/images/controls/chevron-right.svg"
|
||||
|
||||
KeyNavigation.tab: root.getNextComponentInFocusChain(labelWithButtonLanguage)
|
||||
parentFlickable: fl
|
||||
|
||||
clickedFunction: function() {
|
||||
selectLanguageDrawer.open()
|
||||
}
|
||||
|
@ -142,12 +211,16 @@ PageType {
|
|||
DividerType {}
|
||||
|
||||
LabelWithButtonType {
|
||||
id: labelWithButtonLogging
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: qsTr("Logging")
|
||||
descriptionText: SettingsController.isLoggingEnabled ? qsTr("Enabled") : qsTr("Disabled")
|
||||
rightImageSource: "qrc:/images/controls/chevron-right.svg"
|
||||
|
||||
KeyNavigation.tab: root.getNextComponentInFocusChain(labelWithButtonLogging)
|
||||
parentFlickable: fl
|
||||
|
||||
clickedFunction: function() {
|
||||
PageController.goToPage(PageEnum.PageSettingsLogging)
|
||||
}
|
||||
|
@ -156,12 +229,16 @@ PageType {
|
|||
DividerType {}
|
||||
|
||||
LabelWithButtonType {
|
||||
id: labelWithButtonReset
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: qsTr("Reset settings and remove all data from the application")
|
||||
rightImageSource: "qrc:/images/controls/chevron-right.svg"
|
||||
textColor: "#EB5757"
|
||||
|
||||
Keys.onTabPressed: lastItemTabClicked()
|
||||
parentFlickable: fl
|
||||
|
||||
clickedFunction: function() {
|
||||
var headerText = qsTr("Reset settings and remove all data from the application?")
|
||||
var descriptionText = qsTr("All settings will be reset to default. All installed AmneziaVPN services will still remain on the server.")
|
||||
|
@ -176,8 +253,15 @@ PageType {
|
|||
SettingsController.clearSettings()
|
||||
PageController.replaceStartPage()
|
||||
}
|
||||
|
||||
if (!GC.isMobile()) {
|
||||
root.defaultActiveFocusItem.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
var noButtonFunction = function() {
|
||||
if (!GC.isMobile()) {
|
||||
root.defaultActiveFocusItem.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
showQuestionDrawer(headerText, descriptionText, yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
|
||||
|
@ -193,5 +277,11 @@ PageType {
|
|||
|
||||
width: root.width
|
||||
height: root.height
|
||||
|
||||
onClosed: {
|
||||
if (!GC.isMobile()) {
|
||||
focusItem.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,8 @@ import "../Controls2/TextTypes"
|
|||
PageType {
|
||||
id: root
|
||||
|
||||
defaultActiveFocusItem: focusItem
|
||||
|
||||
Connections {
|
||||
target: SettingsController
|
||||
|
||||
|
@ -34,6 +36,11 @@ PageType {
|
|||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: focusItem
|
||||
KeyNavigation.tab: backButton
|
||||
}
|
||||
|
||||
BackButtonType {
|
||||
id: backButton
|
||||
|
||||
|
@ -41,6 +48,8 @@ PageType {
|
|||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.topMargin: 20
|
||||
|
||||
KeyNavigation.tab: makeBackupButton
|
||||
}
|
||||
|
||||
FlickableType {
|
||||
|
@ -102,9 +111,12 @@ PageType {
|
|||
PageController.showNotificationMessage(qsTr("Backup file saved"))
|
||||
}
|
||||
}
|
||||
|
||||
KeyNavigation.tab: restoreBackupButton
|
||||
}
|
||||
|
||||
BasicButtonType {
|
||||
id: restoreBackupButton
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: -8
|
||||
|
||||
|
@ -124,6 +136,8 @@ PageType {
|
|||
restoreBackup(filePath)
|
||||
}
|
||||
}
|
||||
|
||||
Keys.onTabPressed: lastItemTabClicked()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,8 +11,15 @@ import "../Config"
|
|||
PageType {
|
||||
id: root
|
||||
|
||||
defaultActiveFocusItem: focusItem
|
||||
|
||||
property bool isAppSplitTinnelingEnabled: Qt.platform.os === "windows" || Qt.platform.os === "android"
|
||||
|
||||
Item {
|
||||
id: focusItem
|
||||
KeyNavigation.tab: backButton
|
||||
}
|
||||
|
||||
BackButtonType {
|
||||
id: backButton
|
||||
|
||||
|
@ -20,6 +27,8 @@ PageType {
|
|||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.topMargin: 20
|
||||
|
||||
KeyNavigation.tab: amneziaDnsSwitch
|
||||
}
|
||||
|
||||
FlickableType {
|
||||
|
@ -44,6 +53,7 @@ PageType {
|
|||
}
|
||||
|
||||
SwitcherType {
|
||||
id: amneziaDnsSwitch
|
||||
Layout.fillWidth: true
|
||||
Layout.margins: 16
|
||||
|
||||
|
@ -56,11 +66,14 @@ PageType {
|
|||
SettingsController.toggleAmneziaDns(checked)
|
||||
}
|
||||
}
|
||||
|
||||
KeyNavigation.tab: dnsServersButton.rightButton
|
||||
}
|
||||
|
||||
DividerType {}
|
||||
|
||||
LabelWithButtonType {
|
||||
id: dnsServersButton
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: qsTr("DNS servers")
|
||||
|
@ -70,11 +83,14 @@ PageType {
|
|||
clickedFunction: function() {
|
||||
PageController.goToPage(PageEnum.PageSettingsDns)
|
||||
}
|
||||
|
||||
KeyNavigation.tab: splitTunnelingButton.rightButton
|
||||
}
|
||||
|
||||
DividerType {}
|
||||
|
||||
LabelWithButtonType {
|
||||
id: splitTunnelingButton
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: qsTr("Site-based split tunneling")
|
||||
|
@ -84,6 +100,10 @@ PageType {
|
|||
clickedFunction: function() {
|
||||
PageController.goToPage(PageEnum.PageSettingsSplitTunneling)
|
||||
}
|
||||
|
||||
Keys.onTabPressed: splitTunnelingButton2.visible ?
|
||||
splitTunnelingButton2.forceActiveFocus() :
|
||||
lastItemTabClicked()
|
||||
}
|
||||
|
||||
DividerType {
|
||||
|
@ -91,6 +111,7 @@ PageType {
|
|||
}
|
||||
|
||||
LabelWithButtonType {
|
||||
id: splitTunnelingButton2
|
||||
visible: root.isAppSplitTinnelingEnabled
|
||||
|
||||
Layout.fillWidth: true
|
||||
|
@ -102,6 +123,8 @@ PageType {
|
|||
clickedFunction: function() {
|
||||
PageController.goToPage(PageEnum.PageSettingsAppSplitTunneling)
|
||||
}
|
||||
|
||||
Keys.onTabPressed: lastItemTabClicked()
|
||||
}
|
||||
|
||||
DividerType {
|
||||
|
|
|
@ -15,6 +15,11 @@ PageType {
|
|||
|
||||
defaultActiveFocusItem: primaryDns.textField
|
||||
|
||||
Item {
|
||||
id: focusItem
|
||||
KeyNavigation.tab: backButton
|
||||
}
|
||||
|
||||
BackButtonType {
|
||||
id: backButton
|
||||
|
||||
|
@ -22,6 +27,8 @@ PageType {
|
|||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.topMargin: 20
|
||||
|
||||
KeyNavigation.tab: root.defaultActiveFocusItem
|
||||
}
|
||||
|
||||
FlickableType {
|
||||
|
@ -87,10 +94,11 @@ PageType {
|
|||
regularExpression: InstallController.ipAddressRegExp()
|
||||
}
|
||||
|
||||
KeyNavigation.tab: saveButton
|
||||
KeyNavigation.tab: restoreDefaultButton
|
||||
}
|
||||
|
||||
BasicButtonType {
|
||||
id: restoreDefaultButton
|
||||
Layout.fillWidth: true
|
||||
|
||||
defaultColor: "transparent"
|
||||
|
@ -113,12 +121,21 @@ PageType {
|
|||
SettingsController.secondaryDns = "1.0.0.1"
|
||||
secondaryDns.textFieldText = SettingsController.secondaryDns
|
||||
PageController.showNotificationMessage(qsTr("Settings have been reset"))
|
||||
|
||||
if (!GC.isMobile()) {
|
||||
defaultActiveFocusItem.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
var noButtonFunction = function() {
|
||||
if (!GC.isMobile()) {
|
||||
defaultActiveFocusItem.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
showQuestionDrawer(headerText, "", yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
|
||||
}
|
||||
|
||||
KeyNavigation.tab: saveButton
|
||||
}
|
||||
|
||||
BasicButtonType {
|
||||
|
@ -137,6 +154,8 @@ PageType {
|
|||
}
|
||||
PageController.showNotificationMessage(qsTr("Settings saved"))
|
||||
}
|
||||
|
||||
Keys.onTabPressed: lastItemTabClicked(focusItem)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,6 +27,13 @@ disabled after 14 days, and all log files will be deleted.")
|
|||
}
|
||||
}
|
||||
|
||||
defaultActiveFocusItem: focusItem
|
||||
|
||||
Item {
|
||||
id: focusItem
|
||||
KeyNavigation.tab: backButton
|
||||
}
|
||||
|
||||
BackButtonType {
|
||||
id: backButton
|
||||
|
||||
|
@ -34,6 +41,8 @@ disabled after 14 days, and all log files will be deleted.")
|
|||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.topMargin: 20
|
||||
|
||||
KeyNavigation.tab: switcher
|
||||
}
|
||||
|
||||
FlickableType {
|
||||
|
@ -62,12 +71,14 @@ disabled after 14 days, and all log files will be deleted.")
|
|||
}
|
||||
|
||||
SwitcherType {
|
||||
id: switcher
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 16
|
||||
|
||||
text: qsTr("Save logs")
|
||||
|
||||
checked: SettingsController.isLoggingEnabled
|
||||
KeyNavigation.tab: openFolderButton
|
||||
onCheckedChanged: {
|
||||
if (checked !== SettingsController.isLoggingEnabled) {
|
||||
SettingsController.isLoggingEnabled = checked
|
||||
|
@ -84,14 +95,18 @@ disabled after 14 days, and all log files will be deleted.")
|
|||
visible: !GC.isMobile()
|
||||
|
||||
ImageButtonType {
|
||||
id: openFolderButton
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
|
||||
implicitWidth: 56
|
||||
implicitHeight: 56
|
||||
|
||||
image: "qrc:/images/controls/folder-open.svg"
|
||||
KeyNavigation.tab: saveButton
|
||||
|
||||
onClicked: SettingsController.openLogsFolder()
|
||||
Keys.onReturnPressed: openFolderButton.clicked()
|
||||
Keys.onEnterPressed: openFolderButton.clicked()
|
||||
}
|
||||
|
||||
CaptionTextType {
|
||||
|
@ -108,13 +123,17 @@ disabled after 14 days, and all log files will be deleted.")
|
|||
Layout.preferredWidth: root.width / ( GC.isMobile() ? 2 : 3 )
|
||||
|
||||
ImageButtonType {
|
||||
id: saveButton
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
|
||||
implicitWidth: 56
|
||||
implicitHeight: 56
|
||||
|
||||
image: "qrc:/images/controls/save.svg"
|
||||
KeyNavigation.tab: clearButton
|
||||
|
||||
Keys.onReturnPressed: saveButton.clicked()
|
||||
Keys.onEnterPressed: saveButton.clicked()
|
||||
onClicked: {
|
||||
var fileName = ""
|
||||
if (GC.isMobile()) {
|
||||
|
@ -149,13 +168,17 @@ disabled after 14 days, and all log files will be deleted.")
|
|||
Layout.preferredWidth: root.width / ( GC.isMobile() ? 2 : 3 )
|
||||
|
||||
ImageButtonType {
|
||||
id: clearButton
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
|
||||
implicitWidth: 56
|
||||
implicitHeight: 56
|
||||
|
||||
image: "qrc:/images/controls/delete.svg"
|
||||
Keys.onTabPressed: lastItemTabClicked(focusItem)
|
||||
|
||||
Keys.onReturnPressed: clearButton.clicked()
|
||||
Keys.onEnterPressed: clearButton.clicked()
|
||||
onClicked: function() {
|
||||
var headerText = qsTr("Clear logs?")
|
||||
var yesButtonText = qsTr("Continue")
|
||||
|
@ -166,8 +189,14 @@ disabled after 14 days, and all log files will be deleted.")
|
|||
SettingsController.clearLogs()
|
||||
PageController.showBusyIndicator(false)
|
||||
PageController.showNotificationMessage(qsTr("Logs have been cleaned up"))
|
||||
if (!GC.isMobile()) {
|
||||
focusItem.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
var noButtonFunction = function() {
|
||||
if (!GC.isMobile()) {
|
||||
focusItem.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
showQuestionDrawer(headerText, "", yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
|
||||
|
|
|
@ -10,10 +10,17 @@ import ProtocolEnum 1.0
|
|||
import "../Controls2"
|
||||
import "../Controls2/TextTypes"
|
||||
import "../Components"
|
||||
import "../Config"
|
||||
|
||||
PageType {
|
||||
id: root
|
||||
|
||||
signal lastItemTabClickedSignal()
|
||||
|
||||
onFocusChanged: content.isServerWithWriteAccess ?
|
||||
labelWithButton.forceActiveFocus() :
|
||||
labelWithButton3.forceActiveFocus()
|
||||
|
||||
Connections {
|
||||
target: InstallController
|
||||
|
||||
|
@ -85,12 +92,15 @@ PageType {
|
|||
property bool isServerWithWriteAccess: ServersModel.isProcessedServerHasWriteAccess()
|
||||
|
||||
LabelWithButtonType {
|
||||
id: labelWithButton
|
||||
visible: content.isServerWithWriteAccess
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: qsTr("Check the server for previously installed Amnezia services")
|
||||
descriptionText: qsTr("Add them to the application if they were not displayed")
|
||||
|
||||
KeyNavigation.tab: labelWithButton2
|
||||
|
||||
clickedFunction: function() {
|
||||
PageController.showBusyIndicator(true)
|
||||
InstallController.scanServerForInstalledContainers()
|
||||
|
@ -103,12 +113,15 @@ PageType {
|
|||
}
|
||||
|
||||
LabelWithButtonType {
|
||||
id: labelWithButton2
|
||||
visible: content.isServerWithWriteAccess
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: qsTr("Reboot server")
|
||||
textColor: "#EB5757"
|
||||
|
||||
KeyNavigation.tab: labelWithButton3
|
||||
|
||||
clickedFunction: function() {
|
||||
var headerText = qsTr("Do you want to reboot the server?")
|
||||
var descriptionText = qsTr("The reboot process may take approximately 30 seconds. Are you sure you wish to proceed?")
|
||||
|
@ -123,8 +136,14 @@ PageType {
|
|||
InstallController.rebootProcessedServer()
|
||||
PageController.showBusyIndicator(false)
|
||||
}
|
||||
if (!GC.isMobile()) {
|
||||
labelWithButton5.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
var noButtonFunction = function() {
|
||||
if (!GC.isMobile()) {
|
||||
labelWithButton2.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
showQuestionDrawer(headerText, descriptionText, yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
|
||||
|
@ -136,11 +155,22 @@ PageType {
|
|||
}
|
||||
|
||||
LabelWithButtonType {
|
||||
id: labelWithButton3
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: qsTr("Remove server from application")
|
||||
textColor: "#EB5757"
|
||||
|
||||
Keys.onTabPressed: {
|
||||
if (content.isServerWithWriteAccess) {
|
||||
labelWithButton4.forceActiveFocus()
|
||||
} else {
|
||||
labelWithButton5.visible ?
|
||||
labelWithButton5.forceActiveFocus() :
|
||||
lastItemTabClickedSignal()
|
||||
}
|
||||
}
|
||||
|
||||
clickedFunction: function() {
|
||||
var headerText = qsTr("Do you want to remove the server from application?")
|
||||
var descriptionText = qsTr("All installed AmneziaVPN services will still remain on the server.")
|
||||
|
@ -155,8 +185,14 @@ PageType {
|
|||
InstallController.removeProcessedServer()
|
||||
PageController.showBusyIndicator(false)
|
||||
}
|
||||
if (!GC.isMobile()) {
|
||||
labelWithButton5.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
var noButtonFunction = function() {
|
||||
if (!GC.isMobile()) {
|
||||
labelWithButton3.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
showQuestionDrawer(headerText, descriptionText, yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
|
||||
|
@ -166,12 +202,17 @@ PageType {
|
|||
DividerType {}
|
||||
|
||||
LabelWithButtonType {
|
||||
id: labelWithButton4
|
||||
visible: content.isServerWithWriteAccess
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: qsTr("Clear server from Amnezia software")
|
||||
textColor: "#EB5757"
|
||||
|
||||
Keys.onTabPressed: labelWithButton5.visible ?
|
||||
labelWithButton5.forceActiveFocus() :
|
||||
root.lastItemTabClickedSignal()
|
||||
|
||||
clickedFunction: function() {
|
||||
var headerText = qsTr("Do you want to clear server from Amnezia software?")
|
||||
var descriptionText = qsTr("All users whom you shared a connection with will no longer be able to connect to it.")
|
||||
|
@ -185,8 +226,14 @@ PageType {
|
|||
PageController.goToPage(PageEnum.PageDeinstalling)
|
||||
InstallController.removeAllContainers()
|
||||
}
|
||||
if (!GC.isMobile()) {
|
||||
labelWithButton5.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
var noButtonFunction = function() {
|
||||
if (!GC.isMobile()) {
|
||||
labelWithButton4.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
showQuestionDrawer(headerText, descriptionText, yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
|
||||
|
@ -198,12 +245,15 @@ PageType {
|
|||
}
|
||||
|
||||
LabelWithButtonType {
|
||||
id: labelWithButton5
|
||||
visible: ServersModel.getProcessedServerData("isServerFromApi")
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: qsTr("Reset API config")
|
||||
textColor: "#EB5757"
|
||||
|
||||
Keys.onTabPressed: root.lastItemTabClickedSignal()
|
||||
|
||||
clickedFunction: function() {
|
||||
var headerText = qsTr("Do you want to reset API config?")
|
||||
var descriptionText = ""
|
||||
|
@ -218,8 +268,15 @@ PageType {
|
|||
InstallController.removeApiConfig(ServersModel.processedIndex)
|
||||
PageController.showBusyIndicator(false)
|
||||
}
|
||||
|
||||
if (!GC.isMobile()) {
|
||||
labelWithButton5.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
var noButtonFunction = function() {
|
||||
if (!GC.isMobile()) {
|
||||
labelWithButton5.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
showQuestionDrawer(headerText, descriptionText, yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
|
||||
|
|
|
@ -18,6 +18,8 @@ import "../Components"
|
|||
PageType {
|
||||
id: root
|
||||
|
||||
defaultActiveFocusItem: focusItem
|
||||
|
||||
Connections {
|
||||
target: PageController
|
||||
|
||||
|
@ -37,6 +39,11 @@ PageType {
|
|||
]
|
||||
}
|
||||
|
||||
Item {
|
||||
id: focusItem
|
||||
KeyNavigation.tab: header
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
|
||||
|
@ -46,15 +53,26 @@ PageType {
|
|||
id: header
|
||||
model: proxyServersModel
|
||||
|
||||
activeFocusOnTab: true
|
||||
onFocusChanged: {
|
||||
header.itemAt(0).focusItem.forceActiveFocus()
|
||||
}
|
||||
|
||||
delegate: ColumnLayout {
|
||||
|
||||
property alias focusItem: backButton
|
||||
|
||||
id: content
|
||||
|
||||
Layout.topMargin: 20
|
||||
|
||||
BackButtonType {
|
||||
id: backButton
|
||||
KeyNavigation.tab: headerContent.actionButton
|
||||
}
|
||||
|
||||
HeaderType {
|
||||
id: headerContent
|
||||
Layout.fillWidth: true
|
||||
Layout.leftMargin: 16
|
||||
Layout.rightMargin: 16
|
||||
|
@ -70,6 +88,8 @@ PageType {
|
|||
}
|
||||
}
|
||||
|
||||
KeyNavigation.tab: tabBar
|
||||
|
||||
actionButtonFunction: function() {
|
||||
serverNameEditDrawer.open()
|
||||
}
|
||||
|
@ -83,6 +103,12 @@ PageType {
|
|||
anchors.fill: parent
|
||||
expandedHeight: root.height * 0.35
|
||||
|
||||
onClosed: {
|
||||
if (!GC.isMobile()) {
|
||||
headerContent.actionButton.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
expandedContent: ColumnLayout {
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
|
@ -99,6 +125,11 @@ PageType {
|
|||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: focusItem1
|
||||
KeyNavigation.tab: serverName.textField
|
||||
}
|
||||
|
||||
TextFieldWithHeaderType {
|
||||
id: serverName
|
||||
|
||||
|
@ -117,6 +148,7 @@ PageType {
|
|||
Layout.fillWidth: true
|
||||
|
||||
text: qsTr("Save")
|
||||
KeyNavigation.tab: focusItem1
|
||||
|
||||
clickedFunc: function() {
|
||||
if (serverName.textFieldText === "") {
|
||||
|
@ -129,12 +161,6 @@ PageType {
|
|||
serverNameEditDrawer.close()
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
if (header.itemAt(0) && !GC.isMobile()) {
|
||||
defaultActiveFocusItem = serverName.textField
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -152,25 +178,52 @@ PageType {
|
|||
color: "transparent"
|
||||
}
|
||||
|
||||
activeFocusOnTab: true
|
||||
onFocusChanged: {
|
||||
if (activeFocus) {
|
||||
protocolsTab.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
TabButtonType {
|
||||
id: protocolsTab
|
||||
visible: protocolsPage.installedProtocolsCount
|
||||
width: protocolsPage.installedProtocolsCount ? undefined : 0
|
||||
isSelected: tabBar.currentIndex === 0
|
||||
text: qsTr("Protocols")
|
||||
|
||||
KeyNavigation.tab: servicesTab
|
||||
Keys.onReturnPressed: tabBar.currentIndex = 0
|
||||
Keys.onEnterPressed: tabBar.currentIndex = 0
|
||||
}
|
||||
TabButtonType {
|
||||
id: servicesTab
|
||||
visible: servicesPage.installedServicesCount
|
||||
width: servicesPage.installedServicesCount ? undefined : 0
|
||||
isSelected: tabBar.currentIndex === 1
|
||||
text: qsTr("Services")
|
||||
|
||||
KeyNavigation.tab: dataTab
|
||||
Keys.onReturnPressed: tabBar.currentIndex = 1
|
||||
Keys.onEnterPressed: tabBar.currentIndex = 1
|
||||
}
|
||||
TabButtonType {
|
||||
id: dataTab
|
||||
isSelected: tabBar.currentIndex === 2
|
||||
text: qsTr("Management")
|
||||
|
||||
Keys.onReturnPressed: tabBar.currentIndex = 2
|
||||
Keys.onEnterPressed: tabBar.currentIndex = 2
|
||||
KeyNavigation.tab: stackView.currentIndex === 0 ?
|
||||
protocolsPage :
|
||||
stackView.currentIndex === 1 ?
|
||||
servicesPage :
|
||||
dataPage
|
||||
}
|
||||
}
|
||||
|
||||
StackLayout {
|
||||
id: stackView
|
||||
Layout.preferredWidth: root.width
|
||||
Layout.preferredHeight: root.height - tabBar.implicitHeight - header.implicitHeight
|
||||
|
||||
|
@ -179,14 +232,22 @@ PageType {
|
|||
PageSettingsServerProtocols {
|
||||
id: protocolsPage
|
||||
stackView: root.stackView
|
||||
|
||||
onLastItemTabClickedSignal: lastItemTabClicked(focusItem)
|
||||
}
|
||||
PageSettingsServerServices {
|
||||
id: servicesPage
|
||||
stackView: root.stackView
|
||||
|
||||
onLastItemTabClickedSignal: lastItemTabClicked(focusItem)
|
||||
}
|
||||
PageSettingsServerData {
|
||||
id: dataPage
|
||||
stackView: root.stackView
|
||||
|
||||
onLastItemTabClickedSignal: lastItemTabClicked(focusItem)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,13 @@ import "../Components"
|
|||
PageType {
|
||||
id: root
|
||||
|
||||
defaultActiveFocusItem: focusItem
|
||||
|
||||
Item {
|
||||
id: focusItem
|
||||
KeyNavigation.tab: backButton
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: header
|
||||
|
||||
|
@ -28,6 +35,8 @@ PageType {
|
|||
anchors.topMargin: 20
|
||||
|
||||
BackButtonType {
|
||||
id: backButton
|
||||
KeyNavigation.tab: protocols
|
||||
}
|
||||
|
||||
HeaderType {
|
||||
|
@ -47,7 +56,28 @@ PageType {
|
|||
interactive: true
|
||||
model: ProtocolsModel
|
||||
|
||||
property int currentFocusIndex: 0
|
||||
|
||||
activeFocusOnTab: true
|
||||
onActiveFocusChanged: {
|
||||
if (activeFocus) {
|
||||
this.currentFocusIndex = 0
|
||||
protocols.itemAtIndex(currentFocusIndex).focusItem.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
Keys.onTabPressed: {
|
||||
if (currentFocusIndex < this.count - 1) {
|
||||
currentFocusIndex += 1
|
||||
protocols.itemAtIndex(currentFocusIndex).focusItem.forceActiveFocus()
|
||||
} else {
|
||||
clearCacheButton.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
delegate: Item {
|
||||
property var focusItem: button.rightButton
|
||||
|
||||
implicitWidth: protocols.width
|
||||
implicitHeight: delegateContent.implicitHeight
|
||||
|
||||
|
@ -95,6 +125,7 @@ PageType {
|
|||
Layout.fillWidth: true
|
||||
|
||||
visible: ServersModel.isProcessedServerHasWriteAccess()
|
||||
KeyNavigation.tab: removeButton
|
||||
|
||||
text: qsTr("Clear %1 profile").arg(ContainersModel.getProcessedContainerName())
|
||||
|
||||
|
@ -116,6 +147,9 @@ PageType {
|
|||
PageController.showBusyIndicator(false)
|
||||
}
|
||||
var noButtonFunction = function() {
|
||||
if (!GC.isMobile()) {
|
||||
focusItem.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
showQuestionDrawer(headerText, descriptionText, yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
|
||||
|
@ -142,6 +176,7 @@ PageType {
|
|||
Layout.fillWidth: true
|
||||
|
||||
visible: ServersModel.isProcessedServerHasWriteAccess()
|
||||
Keys.onTabPressed: lastItemTabClicked(focusItem)
|
||||
|
||||
text: qsTr("Remove ") + ContainersModel.getProcessedContainerName()
|
||||
textColor: "#EB5757"
|
||||
|
@ -163,6 +198,9 @@ PageType {
|
|||
}
|
||||
}
|
||||
var noButtonFunction = function() {
|
||||
if (!GC.isMobile()) {
|
||||
focusItem.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
showQuestionDrawer(headerText, descriptionText, yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
|
||||
|
@ -184,3 +222,4 @@ PageType {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,9 @@ PageType {
|
|||
|
||||
property var installedProtocolsCount
|
||||
|
||||
onFocusChanged: settingsContainersListView.forceActiveFocus()
|
||||
signal lastItemTabClickedSignal()
|
||||
|
||||
FlickableType {
|
||||
id: fl
|
||||
anchors.top: parent.top
|
||||
|
@ -35,6 +38,7 @@ PageType {
|
|||
|
||||
SettingsContainersListView {
|
||||
id: settingsContainersListView
|
||||
|
||||
Connections {
|
||||
target: ServersModel
|
||||
|
||||
|
|
|
@ -20,6 +20,9 @@ PageType {
|
|||
|
||||
property var installedServicesCount
|
||||
|
||||
onFocusChanged: settingsContainersListView.forceActiveFocus()
|
||||
signal lastItemTabClickedSignal()
|
||||
|
||||
FlickableType {
|
||||
id: fl
|
||||
anchors.top: parent.top
|
||||
|
@ -35,6 +38,7 @@ PageType {
|
|||
|
||||
SettingsContainersListView {
|
||||
id: settingsContainersListView
|
||||
|
||||
Connections {
|
||||
target: ServersModel
|
||||
|
||||
|
|
|
@ -17,6 +17,13 @@ import "../Components"
|
|||
PageType {
|
||||
id: root
|
||||
|
||||
defaultActiveFocusItem: focusItem
|
||||
|
||||
Item {
|
||||
id: focusItem
|
||||
KeyNavigation.tab: backButton
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: header
|
||||
|
||||
|
@ -27,6 +34,8 @@ PageType {
|
|||
anchors.topMargin: 20
|
||||
|
||||
BackButtonType {
|
||||
id: backButton
|
||||
KeyNavigation.tab: servers
|
||||
}
|
||||
|
||||
HeaderType {
|
||||
|
@ -39,6 +48,7 @@ PageType {
|
|||
}
|
||||
|
||||
FlickableType {
|
||||
id: fl
|
||||
anchors.top: header.bottom
|
||||
anchors.topMargin: 16
|
||||
contentHeight: col.implicitHeight
|
||||
|
@ -59,10 +69,36 @@ PageType {
|
|||
clip: true
|
||||
interactive: false
|
||||
|
||||
activeFocusOnTab: true
|
||||
focus: true
|
||||
Keys.onTabPressed: {
|
||||
if (currentIndex < servers.count - 1) {
|
||||
servers.incrementCurrentIndex()
|
||||
} else {
|
||||
servers.currentIndex = 0
|
||||
focusItem.forceActiveFocus()
|
||||
root.lastItemTabClicked()
|
||||
}
|
||||
|
||||
fl.ensureVisible(this.currentItem)
|
||||
}
|
||||
|
||||
onVisibleChanged: {
|
||||
if (visible) {
|
||||
currentIndex = 0
|
||||
}
|
||||
}
|
||||
|
||||
delegate: Item {
|
||||
implicitWidth: servers.width
|
||||
implicitHeight: delegateContent.implicitHeight
|
||||
|
||||
onFocusChanged: {
|
||||
if (focus) {
|
||||
server.rightButton.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: delegateContent
|
||||
|
||||
|
@ -75,6 +111,7 @@ PageType {
|
|||
Layout.fillWidth: true
|
||||
|
||||
text: name
|
||||
parentFlickable: fl
|
||||
descriptionText: {
|
||||
var servicesNameString = ""
|
||||
var servicesName = ServersModel.getAllInstalledServicesName(index)
|
||||
|
|
|
@ -24,6 +24,11 @@ PageType {
|
|||
|
||||
defaultActiveFocusItem: searchField.textField
|
||||
|
||||
Item {
|
||||
id: focusItem
|
||||
KeyNavigation.tab: backButton
|
||||
}
|
||||
|
||||
property bool pageEnabled
|
||||
|
||||
Component.onCompleted: {
|
||||
|
@ -92,6 +97,8 @@ PageType {
|
|||
anchors.topMargin: 20
|
||||
|
||||
BackButtonType {
|
||||
id: backButton
|
||||
KeyNavigation.tab: switcher
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
|
@ -112,11 +119,17 @@ PageType {
|
|||
Layout.fillWidth: true
|
||||
Layout.rightMargin: 16
|
||||
|
||||
checked: SitesModel.isTunnelingEnabled
|
||||
onToggled: {
|
||||
SitesModel.toggleSplitTunneling(checked)
|
||||
function onToggledFunc() {
|
||||
SitesModel.toggleSplitTunneling(this.checked)
|
||||
selector.text = root.routeModesModel[getRouteModesModelIndex()].name
|
||||
}
|
||||
|
||||
checked: SitesModel.isTunnelingEnabled
|
||||
onToggled: { onToggledFunc() }
|
||||
Keys.onEnterPressed: { onToggledFunc() }
|
||||
Keys.onReturnPressed: { onToggledFunc() }
|
||||
|
||||
KeyNavigation.tab: selector
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -165,10 +178,17 @@ PageType {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
KeyNavigation.tab: {
|
||||
return sites.count > 0 ?
|
||||
sites :
|
||||
searchField.textField
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FlickableType {
|
||||
id: fl
|
||||
anchors.top: header.bottom
|
||||
anchors.topMargin: 16
|
||||
contentHeight: col.implicitHeight + addSiteButton.implicitHeight + addSiteButton.anchors.bottomMargin + addSiteButton.anchors.topMargin
|
||||
|
@ -208,10 +228,29 @@ PageType {
|
|||
clip: true
|
||||
interactive: false
|
||||
|
||||
activeFocusOnTab: true
|
||||
focus: true
|
||||
Keys.onTabPressed: {
|
||||
if (currentIndex < this.count - 1) {
|
||||
this.incrementCurrentIndex()
|
||||
} else {
|
||||
currentIndex = 0
|
||||
searchField.textField.forceActiveFocus()
|
||||
}
|
||||
|
||||
fl.ensureVisible(currentItem)
|
||||
}
|
||||
|
||||
delegate: Item {
|
||||
implicitWidth: sites.width
|
||||
implicitHeight: delegateContent.implicitHeight
|
||||
|
||||
onActiveFocusChanged: {
|
||||
if (activeFocus) {
|
||||
site.rightButton.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: delegateContent
|
||||
|
||||
|
@ -220,6 +259,7 @@ PageType {
|
|||
anchors.right: parent.right
|
||||
|
||||
LabelWithButtonType {
|
||||
id: site
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: url
|
||||
|
@ -234,8 +274,14 @@ PageType {
|
|||
|
||||
var yesButtonFunction = function() {
|
||||
SitesController.removeSite(proxySitesModel.mapToSource(index))
|
||||
if (!GC.isMobile()) {
|
||||
site.rightButton.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
var noButtonFunction = function() {
|
||||
if (!GC.isMobile()) {
|
||||
site.rightButton.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
showQuestionDrawer(headerText, "", yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
|
||||
|
@ -246,6 +292,7 @@ PageType {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -273,9 +320,11 @@ PageType {
|
|||
id: searchField
|
||||
|
||||
Layout.fillWidth: true
|
||||
rightButtonClickedOnEnter: true
|
||||
|
||||
textFieldPlaceholderText: qsTr("website or IP")
|
||||
buttonImageSource: "qrc:/images/controls/plus.svg"
|
||||
KeyNavigation.tab: GC.isMobile() ? focusItem : addSiteButtonImage
|
||||
|
||||
clickedFunc: function() {
|
||||
PageController.showBusyIndicator(true)
|
||||
|
@ -286,6 +335,7 @@ PageType {
|
|||
}
|
||||
|
||||
ImageButtonType {
|
||||
id: addSiteButtonImage
|
||||
implicitWidth: 56
|
||||
implicitHeight: 56
|
||||
|
||||
|
@ -295,6 +345,11 @@ PageType {
|
|||
onClicked: function () {
|
||||
moreActionsDrawer.open()
|
||||
}
|
||||
|
||||
Keys.onReturnPressed: addSiteButtonImage.clicked()
|
||||
Keys.onEnterPressed: addSiteButtonImage.clicked()
|
||||
|
||||
Keys.onTabPressed: lastItemTabClicked(focusItem)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -304,6 +359,12 @@ PageType {
|
|||
anchors.fill: parent
|
||||
expandedHeight: parent.height * 0.4375
|
||||
|
||||
onClosed: {
|
||||
if (root.defaultActiveFocusItem && !GC.isMobile()) {
|
||||
root.defaultActiveFocusItem.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
expandedContent: ColumnLayout {
|
||||
id: moreActionsDrawerContent
|
||||
|
||||
|
@ -311,6 +372,25 @@ PageType {
|
|||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
|
||||
Connections {
|
||||
target: moreActionsDrawer
|
||||
|
||||
function onOpened() {
|
||||
focusItem1.forceActiveFocus()
|
||||
}
|
||||
|
||||
function onActiveFocusChanged() {
|
||||
if (!GC.isMobile()) {
|
||||
focusItem1.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: focusItem1
|
||||
KeyNavigation.tab: importSitesButton.rightButton
|
||||
}
|
||||
|
||||
Header2Type {
|
||||
Layout.fillWidth: true
|
||||
Layout.margins: 16
|
||||
|
@ -319,6 +399,7 @@ PageType {
|
|||
}
|
||||
|
||||
LabelWithButtonType {
|
||||
id: importSitesButton
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: qsTr("Import")
|
||||
|
@ -327,14 +408,19 @@ PageType {
|
|||
clickedFunction: function() {
|
||||
importSitesDrawer.open()
|
||||
}
|
||||
|
||||
KeyNavigation.tab: exportSitesButton
|
||||
}
|
||||
|
||||
DividerType {}
|
||||
|
||||
LabelWithButtonType {
|
||||
id: exportSitesButton
|
||||
Layout.fillWidth: true
|
||||
text: qsTr("Save site list")
|
||||
|
||||
KeyNavigation.tab: focusItem1
|
||||
|
||||
clickedFunction: function() {
|
||||
var fileName = ""
|
||||
if (GC.isMobile()) {
|
||||
|
@ -365,9 +451,28 @@ PageType {
|
|||
anchors.fill: parent
|
||||
expandedHeight: parent.height * 0.4375
|
||||
|
||||
onClosed: {
|
||||
if (!GC.isMobile()) {
|
||||
moreActionsDrawer.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
expandedContent: Item {
|
||||
implicitHeight: importSitesDrawer.expandedHeight
|
||||
|
||||
Connections {
|
||||
target: importSitesDrawer
|
||||
enabled: !GC.isMobile()
|
||||
function onOpened() {
|
||||
focusItem2.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: focusItem2
|
||||
KeyNavigation.tab: importSitesDrawerBackButton
|
||||
}
|
||||
|
||||
BackButtonType {
|
||||
id: importSitesDrawerBackButton
|
||||
|
||||
|
@ -376,6 +481,8 @@ PageType {
|
|||
anchors.right: parent.right
|
||||
anchors.topMargin: 16
|
||||
|
||||
KeyNavigation.tab: importSitesButton2
|
||||
|
||||
backButtonFunction: function() {
|
||||
importSitesDrawer.close()
|
||||
}
|
||||
|
@ -404,9 +511,11 @@ PageType {
|
|||
}
|
||||
|
||||
LabelWithButtonType {
|
||||
id: importSitesButton2
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: qsTr("Replace site list")
|
||||
KeyNavigation.tab: importSitesButton3
|
||||
|
||||
clickedFunction: function() {
|
||||
var fileName = SystemController.getFileName(qsTr("Open sites file"),
|
||||
|
@ -420,8 +529,10 @@ PageType {
|
|||
DividerType {}
|
||||
|
||||
LabelWithButtonType {
|
||||
id: importSitesButton3
|
||||
Layout.fillWidth: true
|
||||
text: qsTr("Add imported sites to existing ones")
|
||||
KeyNavigation.tab: focusItem2
|
||||
|
||||
clickedFunction: function() {
|
||||
var fileName = SystemController.getFileName(qsTr("Open sites file"),
|
||||
|
|
|
@ -22,6 +22,8 @@ PageType {
|
|||
}
|
||||
}
|
||||
|
||||
defaultActiveFocusItem: focusItem
|
||||
|
||||
FlickableType {
|
||||
id: fl
|
||||
anchors.top: parent.top
|
||||
|
@ -37,8 +39,15 @@ PageType {
|
|||
|
||||
spacing: 0
|
||||
|
||||
Item {
|
||||
id: focusItem
|
||||
KeyNavigation.tab: backButton
|
||||
}
|
||||
|
||||
BackButtonType {
|
||||
id: backButton
|
||||
Layout.topMargin: 20
|
||||
KeyNavigation.tab: fileButton.rightButton
|
||||
}
|
||||
|
||||
HeaderType {
|
||||
|
@ -61,6 +70,7 @@ PageType {
|
|||
}
|
||||
|
||||
LabelWithButtonType {
|
||||
id: fileButton
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 16
|
||||
|
||||
|
@ -68,6 +78,8 @@ PageType {
|
|||
rightImageSource: "qrc:/images/controls/chevron-right.svg"
|
||||
leftImageSource: "qrc:/images/controls/folder-open.svg"
|
||||
|
||||
KeyNavigation.tab: qrButton.visible ? qrButton.rightButton : textButton.rightButton
|
||||
|
||||
clickedFunction: function() {
|
||||
var nameFilter = !ServersModel.getServersCount() ? "Config or backup files (*.vpn *.ovpn *.conf *.json *.backup)" :
|
||||
"Config files (*.vpn *.ovpn *.conf *.json)"
|
||||
|
@ -83,6 +95,7 @@ PageType {
|
|||
DividerType {}
|
||||
|
||||
LabelWithButtonType {
|
||||
id: qrButton
|
||||
Layout.fillWidth: true
|
||||
visible: SettingsController.isCameraPresent()
|
||||
|
||||
|
@ -90,6 +103,8 @@ PageType {
|
|||
rightImageSource: "qrc:/images/controls/chevron-right.svg"
|
||||
leftImageSource: "qrc:/images/controls/qr-code.svg"
|
||||
|
||||
KeyNavigation.tab: textButton.rightButton
|
||||
|
||||
clickedFunction: function() {
|
||||
ImportController.startDecodingQr()
|
||||
if (Qt.platform.os === "ios") {
|
||||
|
@ -103,12 +118,15 @@ PageType {
|
|||
}
|
||||
|
||||
LabelWithButtonType {
|
||||
id: textButton
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: qsTr("Key as text")
|
||||
rightImageSource: "qrc:/images/controls/chevron-right.svg"
|
||||
leftImageSource: "qrc:/images/controls/text-cursor.svg"
|
||||
|
||||
Keys.onTabPressed: lastItemTabClicked(focusItem)
|
||||
|
||||
clickedFunction: function() {
|
||||
PageController.goToPage(PageEnum.PageSetupWizardTextKey)
|
||||
}
|
||||
|
|
|
@ -14,6 +14,11 @@ PageType {
|
|||
|
||||
defaultActiveFocusItem: hostname.textField
|
||||
|
||||
Item {
|
||||
id: focusItem
|
||||
KeyNavigation.tab: backButton
|
||||
}
|
||||
|
||||
BackButtonType {
|
||||
id: backButton
|
||||
|
||||
|
@ -21,6 +26,8 @@ PageType {
|
|||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.topMargin: 20
|
||||
|
||||
KeyNavigation.tab: hostname.textField
|
||||
}
|
||||
|
||||
FlickableType {
|
||||
|
@ -107,6 +114,8 @@ PageType {
|
|||
|
||||
text: qsTr("Continue")
|
||||
|
||||
Keys.onTabPressed: lastItemTabClicked(focusItem)
|
||||
|
||||
clickedFunc: function() {
|
||||
forceActiveFocus()
|
||||
if (!isCredentialsFilled()) {
|
||||
|
|
|
@ -16,6 +16,7 @@ PageType {
|
|||
id: root
|
||||
|
||||
property bool isEasySetup: true
|
||||
defaultActiveFocusItem: focusItem
|
||||
|
||||
SortFilterProxyModel {
|
||||
id: proxyContainersModel
|
||||
|
@ -32,6 +33,14 @@ PageType {
|
|||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: focusItem
|
||||
implicitWidth: 1
|
||||
implicitHeight: 54
|
||||
|
||||
KeyNavigation.tab: backButton
|
||||
}
|
||||
|
||||
BackButtonType {
|
||||
id: backButton
|
||||
|
||||
|
@ -39,6 +48,8 @@ PageType {
|
|||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.topMargin: 20
|
||||
|
||||
KeyNavigation.tab: continueButton
|
||||
}
|
||||
|
||||
FlickableType {
|
||||
|
@ -145,17 +156,14 @@ PageType {
|
|||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
implicitWidth: 1
|
||||
implicitHeight: 54
|
||||
}
|
||||
|
||||
BasicButtonType {
|
||||
id: continueButton
|
||||
|
||||
implicitWidth: parent.width
|
||||
|
||||
text: qsTr("Continue")
|
||||
KeyNavigation.tab: setupLaterButton
|
||||
parentFlickable: fl
|
||||
|
||||
clickedFunc: function() {
|
||||
if (root.isEasySetup) {
|
||||
|
@ -184,6 +192,9 @@ PageType {
|
|||
textColor: "#D7D8DB"
|
||||
borderWidth: 1
|
||||
|
||||
Keys.onTabPressed: lastItemTabClicked(focusItem)
|
||||
parentFlickable: fl
|
||||
|
||||
visible: {
|
||||
if (PageController.isTriggeredByConnectButton()) {
|
||||
PageController.setTriggeredByConnectButton(false)
|
||||
|
|
|
@ -61,12 +61,19 @@ PageType {
|
|||
anchors.rightMargin: 16
|
||||
anchors.leftMargin: 16
|
||||
|
||||
Item {
|
||||
id: focusItem
|
||||
KeyNavigation.tab: backButton
|
||||
}
|
||||
|
||||
BackButtonType {
|
||||
id: backButton
|
||||
|
||||
Layout.topMargin: 20
|
||||
Layout.rightMargin: -16
|
||||
Layout.leftMargin: -16
|
||||
|
||||
KeyNavigation.tab: showDetailsButton
|
||||
}
|
||||
|
||||
HeaderType {
|
||||
|
@ -93,6 +100,7 @@ PageType {
|
|||
textColor: "#FBB26A"
|
||||
|
||||
text: qsTr("More detailed")
|
||||
KeyNavigation.tab: transportProtoSelector
|
||||
|
||||
clickedFunc: function() {
|
||||
showDetailsDrawer.open()
|
||||
|
@ -102,12 +110,35 @@ PageType {
|
|||
DrawerType2 {
|
||||
id: showDetailsDrawer
|
||||
parent: root
|
||||
onClosed: {
|
||||
if (!GC.isMobile()) {
|
||||
defaultActiveFocusItem.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
anchors.fill: parent
|
||||
expandedHeight: parent.height * 0.9
|
||||
expandedContent: Item {
|
||||
Connections {
|
||||
target: showDetailsDrawer
|
||||
enabled: !GC.isMobile()
|
||||
function onOpened() {
|
||||
focusItem2.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
implicitHeight: showDetailsDrawer.expandedHeight
|
||||
|
||||
Item {
|
||||
id: focusItem2
|
||||
KeyNavigation.tab: showDetailsBackButton
|
||||
onFocusChanged: {
|
||||
if (focusItem2.activeFocus) {
|
||||
fl.contentY = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BackButtonType {
|
||||
id: showDetailsBackButton
|
||||
|
||||
|
@ -116,12 +147,15 @@ PageType {
|
|||
anchors.right: parent.right
|
||||
anchors.topMargin: 16
|
||||
|
||||
KeyNavigation.tab: showDetailsCloseButton
|
||||
|
||||
backButtonFunction: function() {
|
||||
showDetailsDrawer.close()
|
||||
}
|
||||
}
|
||||
|
||||
FlickableType {
|
||||
id: fl
|
||||
anchors.top: showDetailsBackButton.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
|
@ -158,17 +192,19 @@ PageType {
|
|||
textFormat: Text.MarkdownText
|
||||
}
|
||||
|
||||
|
||||
Rectangle {
|
||||
Layout.fillHeight: true
|
||||
color: "transparent"
|
||||
}
|
||||
|
||||
BasicButtonType {
|
||||
id: showDetailsCloseButton
|
||||
Layout.fillWidth: true
|
||||
Layout.bottomMargin: 32
|
||||
parentFlickable: fl
|
||||
|
||||
text: qsTr("Close")
|
||||
Keys.onTabPressed: lastItemTabClicked(focusItem2)
|
||||
|
||||
clickedFunc: function() {
|
||||
showDetailsDrawer.close()
|
||||
|
@ -192,6 +228,8 @@ PageType {
|
|||
|
||||
Layout.fillWidth: true
|
||||
rootWidth: root.width
|
||||
|
||||
KeyNavigation.tab: (port.visible && port.enabled) ? port.textField : installButton
|
||||
}
|
||||
|
||||
TextFieldWithHeaderType {
|
||||
|
@ -220,6 +258,8 @@ PageType {
|
|||
|
||||
text: qsTr("Install")
|
||||
|
||||
Keys.onTabPressed: lastItemTabClicked(focusItem)
|
||||
|
||||
clickedFunc: function() {
|
||||
PageController.goToPage(PageEnum.PageSetupWizardInstalling);
|
||||
InstallController.install(dockerContainer, port.textFieldText, transportProtoSelector.currentIndex)
|
||||
|
@ -241,7 +281,10 @@ PageType {
|
|||
transportProtoSelector.visible = protocolSelectorVisible
|
||||
transportProtoHeader.visible = protocolSelectorVisible
|
||||
|
||||
if (port.visible && port.enabled)
|
||||
defaultActiveFocusItem = port.textField
|
||||
else
|
||||
defaultActiveFocusItem = focusItem
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,6 +14,13 @@ import "../Config"
|
|||
PageType {
|
||||
id: root
|
||||
|
||||
defaultActiveFocusItem: focusItem
|
||||
|
||||
Item {
|
||||
id: focusItem
|
||||
KeyNavigation.tab: backButton
|
||||
}
|
||||
|
||||
SortFilterProxyModel {
|
||||
id: proxyContainersModel
|
||||
sourceModel: ContainersModel
|
||||
|
@ -30,7 +37,7 @@ PageType {
|
|||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: backButton
|
||||
id: backButtonLayout
|
||||
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
|
@ -39,12 +46,14 @@ PageType {
|
|||
anchors.topMargin: 20
|
||||
|
||||
BackButtonType {
|
||||
id: backButton
|
||||
KeyNavigation.tab: containers
|
||||
}
|
||||
}
|
||||
|
||||
FlickableType {
|
||||
id: fl
|
||||
anchors.top: backButton.bottom
|
||||
anchors.top: backButtonLayout.bottom
|
||||
anchors.bottom: parent.bottom
|
||||
contentHeight: content.implicitHeight + content.anchors.topMargin + content.anchors.bottomMargin
|
||||
|
||||
|
@ -79,15 +88,49 @@ PageType {
|
|||
id: containers
|
||||
width: parent.width
|
||||
height: containers.contentItem.height
|
||||
currentIndex: -1
|
||||
// currentIndex: -1
|
||||
clip: true
|
||||
interactive: false
|
||||
model: proxyContainersModel
|
||||
|
||||
function ensureCurrentItemVisible() {
|
||||
if (currentIndex >= 0) {
|
||||
if (currentItem.y < fl.contentY) {
|
||||
fl.contentY = currentItem.y
|
||||
} else if (currentItem.y + currentItem.height + header.height > fl.contentY + fl.height) {
|
||||
fl.contentY = currentItem.y + currentItem.height + header.height - fl.height + 40 // 40 is a bottom margin
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
activeFocusOnTab: true
|
||||
Keys.onTabPressed: {
|
||||
if (currentIndex < this.count - 1) {
|
||||
this.incrementCurrentIndex()
|
||||
} else {
|
||||
this.currentIndex = 0
|
||||
focusItem.forceActiveFocus()
|
||||
}
|
||||
|
||||
ensureCurrentItemVisible()
|
||||
}
|
||||
|
||||
onVisibleChanged: {
|
||||
if (visible) {
|
||||
currentIndex = 0
|
||||
}
|
||||
}
|
||||
|
||||
delegate: Item {
|
||||
implicitWidth: containers.width
|
||||
implicitHeight: delegateContent.implicitHeight
|
||||
|
||||
onActiveFocusChanged: {
|
||||
if (activeFocus) {
|
||||
container.rightButton.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: delegateContent
|
||||
|
||||
|
|
|
@ -15,6 +15,8 @@ PageType {
|
|||
|
||||
property bool isControlsDisabled: false
|
||||
|
||||
defaultActiveFocusItem: focusItem
|
||||
|
||||
Connections {
|
||||
target: PageController
|
||||
|
||||
|
@ -136,7 +138,13 @@ PageType {
|
|||
qsTr(" Helps you access blocked content without revealing your privacy, even to VPN providers.")
|
||||
}
|
||||
|
||||
Item {
|
||||
id: focusItem
|
||||
KeyNavigation.tab: startButton
|
||||
}
|
||||
|
||||
BasicButtonType {
|
||||
id: startButton
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 32
|
||||
Layout.leftMargin: 16
|
||||
|
@ -147,9 +155,12 @@ PageType {
|
|||
clickedFunc: function() {
|
||||
connectionTypeSelection.open()
|
||||
}
|
||||
|
||||
KeyNavigation.tab: startButton2
|
||||
}
|
||||
|
||||
BasicButtonType {
|
||||
id: startButton2
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 8
|
||||
Layout.leftMargin: 16
|
||||
|
@ -167,11 +178,18 @@ PageType {
|
|||
clickedFunc: function() {
|
||||
Qt.openUrlExternally(qsTr("https://amnezia.org/instructions/0_starter-guide"))
|
||||
}
|
||||
|
||||
Keys.onTabPressed: lastItemTabClicked(focusItem)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ConnectionTypeSelectionDrawer {
|
||||
id: connectionTypeSelection
|
||||
|
||||
onClosed: {
|
||||
PageController.forceTabBarActiveFocus()
|
||||
root.defaultActiveFocusItem.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,6 +14,12 @@ PageType {
|
|||
|
||||
defaultActiveFocusItem: textKey.textField
|
||||
|
||||
|
||||
Item {
|
||||
id: focusItem
|
||||
KeyNavigation.tab: backButton
|
||||
}
|
||||
|
||||
FlickableType {
|
||||
id: fl
|
||||
anchors.top: parent.top
|
||||
|
@ -30,7 +36,9 @@ PageType {
|
|||
spacing: 16
|
||||
|
||||
BackButtonType {
|
||||
id: backButton
|
||||
Layout.topMargin: 20
|
||||
KeyNavigation.tab: textKey.textField
|
||||
}
|
||||
|
||||
HeaderType {
|
||||
|
@ -75,6 +83,7 @@ PageType {
|
|||
anchors.bottomMargin: 32
|
||||
|
||||
text: qsTr("Continue")
|
||||
Keys.onTabPressed: lastItemTabClicked(focusItem)
|
||||
|
||||
clickedFunc: function() {
|
||||
if (ImportController.extractConfigFromData(textKey.textFieldText)) {
|
||||
|
|
|
@ -15,6 +15,24 @@ PageType {
|
|||
|
||||
property bool showContent: false
|
||||
|
||||
defaultActiveFocusItem: focusItem
|
||||
|
||||
Item {
|
||||
id: focusItem
|
||||
KeyNavigation.tab: backButton
|
||||
}
|
||||
|
||||
BackButtonType {
|
||||
id: backButton
|
||||
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.topMargin: 20
|
||||
|
||||
KeyNavigation.tab: showContentButton
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: ImportController
|
||||
|
||||
|
@ -39,15 +57,6 @@ PageType {
|
|||
}
|
||||
}
|
||||
|
||||
BackButtonType {
|
||||
id: backButton
|
||||
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.topMargin: 20
|
||||
}
|
||||
|
||||
FlickableType {
|
||||
id: fl
|
||||
anchors.top: backButton.bottom
|
||||
|
@ -88,6 +97,7 @@ PageType {
|
|||
}
|
||||
|
||||
BasicButtonType {
|
||||
id: showContentButton
|
||||
Layout.topMargin: 16
|
||||
Layout.leftMargin: -8
|
||||
implicitHeight: 32
|
||||
|
@ -99,6 +109,7 @@ PageType {
|
|||
textColor: "#FBB26A"
|
||||
|
||||
text: showContent ? qsTr("Collapse content") : qsTr("Show content")
|
||||
KeyNavigation.tab: connectButton
|
||||
|
||||
clickedFunc: function() {
|
||||
showContent = !showContent
|
||||
|
@ -138,15 +149,16 @@ PageType {
|
|||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: connectButton
|
||||
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 16
|
||||
anchors.leftMargin: 16
|
||||
|
||||
Keys.onTabPressed: lastItemTabClicked(focusItem)
|
||||
|
||||
BasicButtonType {
|
||||
id: connectButton
|
||||
Layout.fillWidth: true
|
||||
Layout.bottomMargin: 32
|
||||
|
||||
|
|
|
@ -152,6 +152,8 @@ PageType {
|
|||
}
|
||||
|
||||
FlickableType {
|
||||
id: a
|
||||
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
contentHeight: content.height + 10
|
||||
|
@ -168,7 +170,18 @@ PageType {
|
|||
|
||||
spacing: 0
|
||||
|
||||
Item {
|
||||
id: focusItem
|
||||
KeyNavigation.tab: header.actionButton
|
||||
onFocusChanged: {
|
||||
if (focusItem.activeFocus) {
|
||||
a.contentY = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HeaderType {
|
||||
id: header
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 24
|
||||
|
||||
|
@ -179,6 +192,8 @@ PageType {
|
|||
shareFullAccessDrawer.open()
|
||||
}
|
||||
|
||||
KeyNavigation.tab: connectionRadioButton
|
||||
|
||||
DrawerType2 {
|
||||
id: shareFullAccessDrawer
|
||||
|
||||
|
@ -186,6 +201,11 @@ PageType {
|
|||
|
||||
anchors.fill: parent
|
||||
expandedHeight: root.height * 0.45
|
||||
onClosed: {
|
||||
if (!GC.isMobile()) {
|
||||
clientNameTextField.textField.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
expandedContent: ColumnLayout {
|
||||
anchors.top: parent.top
|
||||
|
@ -195,6 +215,14 @@ PageType {
|
|||
|
||||
spacing: 0
|
||||
|
||||
Connections {
|
||||
target: shareFullAccessDrawer
|
||||
enabled: !GC.isMobile()
|
||||
function onOpened() {
|
||||
focusItem.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
Header2Type {
|
||||
Layout.fillWidth: true
|
||||
Layout.bottomMargin: 16
|
||||
|
@ -205,17 +233,24 @@ PageType {
|
|||
descriptionText: qsTr("Use for your own devices, or share with those you trust to manage the server.")
|
||||
}
|
||||
|
||||
Item {
|
||||
id: focusItem
|
||||
KeyNavigation.tab: shareFullAccessButton.rightButton
|
||||
}
|
||||
|
||||
LabelWithButtonType {
|
||||
id: shareFullAccessButton
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: qsTr("Share")
|
||||
rightImageSource: "qrc:/images/controls/chevron-right.svg"
|
||||
KeyNavigation.tab: focusItem
|
||||
|
||||
clickedFunction: function() {
|
||||
PageController.goToPage(PageEnum.PageShareFullAccess)
|
||||
shareFullAccessDrawer.close()
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -240,28 +275,38 @@ PageType {
|
|||
spacing: 0
|
||||
|
||||
HorizontalRadioButton {
|
||||
id: connectionRadioButton
|
||||
checked: accessTypeSelector.currentIndex === 0
|
||||
|
||||
implicitWidth: (root.width - 32) / 2
|
||||
text: qsTr("Connection")
|
||||
|
||||
KeyNavigation.tab: usersRadioButton
|
||||
|
||||
onClicked: {
|
||||
accessTypeSelector.currentIndex = 0
|
||||
if (!GC.isMobile()) {
|
||||
clientNameTextField.textField.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HorizontalRadioButton {
|
||||
id: usersRadioButton
|
||||
checked: accessTypeSelector.currentIndex === 1
|
||||
|
||||
implicitWidth: (root.width - 32) / 2
|
||||
text: qsTr("Users")
|
||||
|
||||
KeyNavigation.tab: accessTypeSelector.currentIndex === 0 ? clientNameTextField.textField : serverSelector
|
||||
|
||||
onClicked: {
|
||||
accessTypeSelector.currentIndex = 1
|
||||
PageController.showBusyIndicator(true)
|
||||
ExportController.updateClientManagementModel(ContainersModel.getProcessedContainerIndex(),
|
||||
ServersModel.getProcessedServerCredentials())
|
||||
PageController.showBusyIndicator(false)
|
||||
focusItem.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -291,7 +336,8 @@ PageType {
|
|||
|
||||
checkEmptyText: true
|
||||
|
||||
KeyNavigation.tab: shareButton
|
||||
KeyNavigation.tab: serverSelector
|
||||
|
||||
}
|
||||
|
||||
DropDownType {
|
||||
|
@ -311,7 +357,6 @@ PageType {
|
|||
|
||||
listView: ListViewWithRadioButtonType {
|
||||
id: serverSelectorListView
|
||||
|
||||
rootWidth: root.width
|
||||
imageSource: "qrc:/images/controls/check.svg"
|
||||
|
||||
|
@ -356,6 +401,8 @@ PageType {
|
|||
ServersModel.processedIndex = proxyServersModel.mapToSource(currentIndex)
|
||||
}
|
||||
}
|
||||
|
||||
KeyNavigation.tab: protocolSelector
|
||||
}
|
||||
|
||||
DropDownType {
|
||||
|
@ -454,6 +501,12 @@ PageType {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
KeyNavigation.tab: accessTypeSelector.currentIndex === 0 ?
|
||||
exportTypeSelector :
|
||||
isSearchBarVisible ?
|
||||
searchTextField.textField :
|
||||
usersHeader.actionButton
|
||||
}
|
||||
|
||||
DropDownType {
|
||||
|
@ -497,6 +550,9 @@ PageType {
|
|||
exportTypeSelector.currentIndex = currentIndex
|
||||
}
|
||||
}
|
||||
|
||||
KeyNavigation.tab: shareButton
|
||||
|
||||
}
|
||||
|
||||
BasicButtonType {
|
||||
|
@ -512,14 +568,20 @@ PageType {
|
|||
text: qsTr("Share")
|
||||
imageSource: "qrc:/images/controls/share-2.svg"
|
||||
|
||||
Keys.onTabPressed: lastItemTabClicked(focusItem)
|
||||
|
||||
parentFlickable: a
|
||||
|
||||
clickedFunc: function(){
|
||||
if (clientNameTextField.textFieldText !== "") {
|
||||
ExportController.generateConfig(root.connectionTypesModel[exportTypeSelector.currentIndex].type)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Header2Type {
|
||||
id: usersHeader
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 24
|
||||
Layout.bottomMargin: 16
|
||||
|
@ -531,6 +593,11 @@ PageType {
|
|||
actionButtonFunction: function() {
|
||||
root.isSearchBarVisible = true
|
||||
}
|
||||
|
||||
Keys.onTabPressed: clientsListView.model.count > 0 ?
|
||||
clientsListView.forceActiveFocus() :
|
||||
lastItemTabClicked(focusItem)
|
||||
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
|
@ -543,19 +610,69 @@ PageType {
|
|||
Layout.fillWidth: true
|
||||
|
||||
textFieldPlaceholderText: qsTr("Search")
|
||||
|
||||
Connections {
|
||||
target: root
|
||||
function onIsSearchBarVisibleChanged() {
|
||||
if (root.isSearchBarVisible) {
|
||||
searchTextField.textField.forceActiveFocus()
|
||||
} else {
|
||||
searchTextField.textFieldText = ""
|
||||
if (!GC.isMobile()) {
|
||||
usersHeader.actionButton.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Keys.onEscapePressed: {
|
||||
root.isSearchBarVisible = false
|
||||
}
|
||||
|
||||
function navigateTo() {
|
||||
if (GC.isMobile()) {
|
||||
focusItem.forceActiveFocus()
|
||||
return;
|
||||
}
|
||||
|
||||
if (searchTextField.textFieldText === "") {
|
||||
root.isSearchBarVisible = false
|
||||
usersHeader.actionButton.forceActiveFocus()
|
||||
} else {
|
||||
closeSearchButton.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
Keys.onTabPressed: { navigateTo() }
|
||||
Keys.onEnterPressed: { navigateTo() }
|
||||
Keys.onReturnPressed: { navigateTo() }
|
||||
}
|
||||
|
||||
ImageButtonType {
|
||||
id: closeSearchButton
|
||||
image: "qrc:/images/controls/close.svg"
|
||||
imageColor: "#D7D8DB"
|
||||
|
||||
onClicked: function() {
|
||||
root.isSearchBarVisible = false
|
||||
searchTextField.textFieldText = ""
|
||||
Keys.onTabPressed: {
|
||||
if (!GC.isMobile()) {
|
||||
if (clientsListView.model.count > 0) {
|
||||
clientsListView.forceActiveFocus()
|
||||
} else {
|
||||
lastItemTabClicked(focusItem)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function clickedFunc() {
|
||||
root.isSearchBarVisible = false
|
||||
}
|
||||
|
||||
onClicked: clickedFunc()
|
||||
Keys.onEnterPressed: clickedFunc()
|
||||
Keys.onReturnPressed: clickedFunc()
|
||||
}
|
||||
}
|
||||
|
||||
ListView {
|
||||
id: clientsListView
|
||||
Layout.fillWidth: true
|
||||
|
@ -576,10 +693,43 @@ PageType {
|
|||
clip: true
|
||||
interactive: false
|
||||
|
||||
activeFocusOnTab: true
|
||||
focus: true
|
||||
Keys.onTabPressed: {
|
||||
if (!GC.isMobile()) {
|
||||
if (currentIndex < this.count - 1) {
|
||||
this.incrementCurrentIndex()
|
||||
currentItem.focusItem.forceActiveFocus()
|
||||
} else {
|
||||
this.currentIndex = 0
|
||||
lastItemTabClicked(focusItem)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onActiveFocusChanged: {
|
||||
if (focus && !GC.isMobile()) {
|
||||
currentIndex = 0
|
||||
currentItem.focusItem.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
onCurrentIndexChanged: {
|
||||
if (currentItem) {
|
||||
if (currentItem.y < a.contentY) {
|
||||
a.contentY = currentItem.y
|
||||
} else if (currentItem.y + currentItem.height + clientsListView.y > a.contentY + a.height) {
|
||||
a.contentY = currentItem.y + clientsListView.y + currentItem.height - a.height
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delegate: Item {
|
||||
implicitWidth: clientsListView.width
|
||||
implicitHeight: delegateContent.implicitHeight
|
||||
|
||||
property alias focusItem: clientFocusItem.rightButton
|
||||
|
||||
ColumnLayout {
|
||||
id: delegateContent
|
||||
|
||||
|
@ -591,6 +741,7 @@ PageType {
|
|||
anchors.leftMargin: -16
|
||||
|
||||
LabelWithButtonType {
|
||||
id: clientFocusItem
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: clientName
|
||||
|
@ -608,6 +759,12 @@ PageType {
|
|||
|
||||
parent: root
|
||||
|
||||
onClosed: {
|
||||
if (!GC.isMobile()) {
|
||||
focusItem.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
anchors.fill: parent
|
||||
expandedHeight: root.height * 0.5
|
||||
|
||||
|
@ -621,6 +778,14 @@ PageType {
|
|||
|
||||
spacing: 8
|
||||
|
||||
Connections {
|
||||
target: clientInfoDrawer
|
||||
enabled: !GC.isMobile()
|
||||
function onOpened() {
|
||||
focusItem1.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
Header2Type {
|
||||
Layout.fillWidth: true
|
||||
Layout.bottomMargin: 24
|
||||
|
@ -629,7 +794,13 @@ PageType {
|
|||
descriptionText: qsTr("Creation date: ") + creationDate
|
||||
}
|
||||
|
||||
Item {
|
||||
id: focusItem1
|
||||
KeyNavigation.tab: renameButton
|
||||
}
|
||||
|
||||
BasicButtonType {
|
||||
id: renameButton
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 24
|
||||
|
||||
|
@ -642,6 +813,8 @@ PageType {
|
|||
|
||||
text: qsTr("Rename")
|
||||
|
||||
KeyNavigation.tab: revokeButton
|
||||
|
||||
clickedFunc: function() {
|
||||
clientNameEditDrawer.open()
|
||||
}
|
||||
|
@ -654,6 +827,12 @@ PageType {
|
|||
anchors.fill: parent
|
||||
expandedHeight: root.height * 0.35
|
||||
|
||||
onClosed: {
|
||||
if (!GC.isMobile()) {
|
||||
focusItem1.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
expandedContent: ColumnLayout {
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
|
@ -670,6 +849,11 @@ PageType {
|
|||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: focusItem2
|
||||
KeyNavigation.tab: clientNameEditor.textField
|
||||
}
|
||||
|
||||
TextFieldWithHeaderType {
|
||||
id: clientNameEditor
|
||||
Layout.fillWidth: true
|
||||
|
@ -687,6 +871,7 @@ PageType {
|
|||
Layout.fillWidth: true
|
||||
|
||||
text: qsTr("Save")
|
||||
KeyNavigation.tab: focusItem2
|
||||
|
||||
clickedFunc: function() {
|
||||
if (clientNameEditor.textFieldText === "") {
|
||||
|
@ -709,6 +894,7 @@ PageType {
|
|||
}
|
||||
|
||||
BasicButtonType {
|
||||
id: revokeButton
|
||||
Layout.fillWidth: true
|
||||
|
||||
defaultColor: "transparent"
|
||||
|
@ -719,6 +905,7 @@ PageType {
|
|||
borderWidth: 1
|
||||
|
||||
text: qsTr("Revoke")
|
||||
KeyNavigation.tab: focusItem1
|
||||
|
||||
clickedFunc: function() {
|
||||
var headerText = qsTr("Revoke the config for a user - %1?").arg(clientName)
|
||||
|
@ -731,6 +918,9 @@ PageType {
|
|||
root.revokeConfig(index)
|
||||
}
|
||||
var noButtonFunction = function() {
|
||||
if (!GC.isMobile()) {
|
||||
focusItem1.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
showQuestionDrawer(headerText, descriptionText, yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
|
||||
|
@ -748,6 +938,11 @@ PageType {
|
|||
id: shareConnectionDrawer
|
||||
|
||||
anchors.fill: parent
|
||||
onClosed: {
|
||||
if (!GC.isMobile()) {
|
||||
clientNameTextField.textField.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
|
|
|
@ -12,10 +12,18 @@ import "./"
|
|||
import "../Controls2"
|
||||
import "../Controls2/TextTypes"
|
||||
import "../Components"
|
||||
import "../Config"
|
||||
|
||||
PageType {
|
||||
id: root
|
||||
|
||||
defaultActiveFocusItem: focusItem
|
||||
|
||||
Item {
|
||||
id: focusItem
|
||||
KeyNavigation.tab: backButton
|
||||
}
|
||||
|
||||
BackButtonType {
|
||||
id: backButton
|
||||
|
||||
|
@ -23,6 +31,8 @@ PageType {
|
|||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.topMargin: 20
|
||||
|
||||
KeyNavigation.tab: serverSelector
|
||||
}
|
||||
|
||||
FlickableType {
|
||||
|
@ -74,6 +84,8 @@ PageType {
|
|||
descriptionText: qsTr("Server")
|
||||
headerText: qsTr("Server")
|
||||
|
||||
KeyNavigation.tab: shareButton
|
||||
|
||||
listView: ListViewWithRadioButtonType {
|
||||
id: serverSelectorListView
|
||||
|
||||
|
@ -100,7 +112,7 @@ PageType {
|
|||
|
||||
shareConnectionDrawer.headerText = qsTr("Accessing ") + serverSelector.text
|
||||
shareConnectionDrawer.configContentHeaderText = qsTr("File with accessing settings to ") + serverSelector.text
|
||||
serverSelector.close()
|
||||
// serverSelector.close()
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
|
@ -117,12 +129,15 @@ PageType {
|
|||
}
|
||||
|
||||
BasicButtonType {
|
||||
id: shareButton
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 40
|
||||
|
||||
text: qsTr("Share")
|
||||
imageSource: "qrc:/images/controls/share-2.svg"
|
||||
|
||||
Keys.onTabPressed: lastItemTabClicked(focusItem)
|
||||
|
||||
clickedFunc: function() {
|
||||
shareConnectionDrawer.headerText = qsTr("Connection to ") + serverSelector.text
|
||||
shareConnectionDrawer.configContentHeaderText = qsTr("File with connection settings to ") + serverSelector.text
|
||||
|
@ -149,5 +164,10 @@ PageType {
|
|||
id: shareConnectionDrawer
|
||||
|
||||
anchors.fill: parent
|
||||
onClosed: {
|
||||
if (!GC.isMobile()) {
|
||||
focusItem.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,6 +14,8 @@ import "../Components"
|
|||
PageType {
|
||||
id: root
|
||||
|
||||
defaultActiveFocusItem: homeTabButton
|
||||
|
||||
property bool isControlsDisabled: false
|
||||
property bool isTabBarDisabled: false
|
||||
|
||||
|
@ -82,6 +84,16 @@ PageType {
|
|||
PageController.closePage()
|
||||
}
|
||||
}
|
||||
|
||||
function onForceTabBarActiveFocus() {
|
||||
homeTabButton.focus = true
|
||||
tabBar.forceActiveFocus()
|
||||
}
|
||||
|
||||
function onForceStackActiveFocus() {
|
||||
homeTabButton.focus = true
|
||||
tabBarStackView.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
|
@ -211,13 +223,19 @@ PageType {
|
|||
}
|
||||
|
||||
TabImageButtonType {
|
||||
id: homeTabButton
|
||||
isSelected: tabBar.currentIndex === 0
|
||||
image: "qrc:/images/controls/home.svg"
|
||||
onClicked: {
|
||||
clickedFunc: function () {
|
||||
tabBarStackView.goToTabBarPage(PageEnum.PageHome)
|
||||
ServersModel.processedIndex = ServersModel.defaultIndex
|
||||
tabBar.currentIndex = 0
|
||||
tabBar.previousIndex = 0
|
||||
}
|
||||
|
||||
KeyNavigation.tab: shareTabButton
|
||||
Keys.onEnterPressed: this.clicked()
|
||||
Keys.onReturnPressed: this.clicked()
|
||||
}
|
||||
|
||||
TabImageButtonType {
|
||||
|
@ -238,27 +256,37 @@ PageType {
|
|||
|
||||
isSelected: tabBar.currentIndex === 1
|
||||
image: "qrc:/images/controls/share-2.svg"
|
||||
onClicked: {
|
||||
clickedFunc: function () {
|
||||
tabBarStackView.goToTabBarPage(PageEnum.PageShare)
|
||||
tabBar.currentIndex = 1
|
||||
tabBar.previousIndex = 1
|
||||
}
|
||||
|
||||
KeyNavigation.tab: settingsTabButton
|
||||
}
|
||||
|
||||
TabImageButtonType {
|
||||
id: settingsTabButton
|
||||
isSelected: tabBar.currentIndex === 2
|
||||
image: "qrc:/images/controls/settings-2.svg"
|
||||
onClicked: {
|
||||
clickedFunc: function () {
|
||||
tabBarStackView.goToTabBarPage(PageEnum.PageSettings)
|
||||
tabBar.currentIndex = 2
|
||||
tabBar.previousIndex = 2
|
||||
}
|
||||
|
||||
KeyNavigation.tab: plusTabButton
|
||||
}
|
||||
|
||||
TabImageButtonType {
|
||||
id: plusTabButton
|
||||
isSelected: tabBar.currentIndex === 3
|
||||
image: "qrc:/images/controls/plus.svg"
|
||||
onClicked: {
|
||||
clickedFunc: function () {
|
||||
connectionTypeSelection.open()
|
||||
}
|
||||
|
||||
Keys.onTabPressed: PageController.forceStackActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -266,6 +294,7 @@ PageType {
|
|||
id: connectionTypeSelection
|
||||
|
||||
onAboutToHide: {
|
||||
PageController.forceTabBarActiveFocus()
|
||||
tabBar.setCurrentIndex(tabBar.previousIndex)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue