summaryrefslogtreecommitdiff
path: root/gui
diff options
context:
space:
mode:
authorkali kaneko (leap communications) <kali@leap.se>2021-05-31 01:49:43 +0200
committerkali kaneko (leap communications) <kali@leap.se>2021-06-01 12:34:03 +0200
commit00be891d3b0cb401e642a5331aedcc399641b8ef (patch)
tree19303b892d9bcae3f30cf6dae68af7f7324c1481 /gui
parent1bd2637e3133d895d1e73931f8b3466a5761d9ef (diff)
[refactor] unclutter main qml
Diffstat (limited to 'gui')
-rw-r--r--gui/gui.qrc6
-rw-r--r--gui/qml/BackgroundImage.qml15
-rw-r--r--gui/qml/BridgesItem.qml58
-rw-r--r--gui/qml/LocationText.qml8
-rw-r--r--gui/qml/MainBar.qml16
-rw-r--r--gui/qml/VPNSwitch.qml64
-rw-r--r--gui/qml/VpnState.qml42
-rw-r--r--gui/qml/logic.js39
-rw-r--r--gui/qml/main.qml156
9 files changed, 253 insertions, 151 deletions
diff --git a/gui/gui.qrc b/gui/gui.qrc
index be0d3e9..3099727 100644
--- a/gui/gui.qrc
+++ b/gui/gui.qrc
@@ -8,6 +8,12 @@
<file>qml/LoginDialog.qml</file>
<file>qml/LoginOKDialog.qml</file>
<file>qml/FailDialog.qml</file>
+ <file>qml/MainBar.qml</file>
+ <file>qml/BackgroundImage.qml</file>
+ <file>qml/LocationText.qml</file>
+ <file>qml/VPNSwitch.qml</file>
+ <file>qml/BridgesItem.qml</file>
+ <file>qml/logic.js</file>
<file>assets/icon/png/black/vpn_off.png</file>
<file>assets/icon/png/black/vpn_on.png</file>
diff --git a/gui/qml/BackgroundImage.qml b/gui/qml/BackgroundImage.qml
new file mode 100644
index 0000000..86b8cba
--- /dev/null
+++ b/gui/qml/BackgroundImage.qml
@@ -0,0 +1,15 @@
+import QtQuick 2.9
+import QtQuick.Controls 2.4
+
+Rectangle {
+
+ anchors.fill: parent;
+ anchors.topMargin: 40;
+
+ Image {
+ source: "qrc:/assets/img/bird.jpg";
+ fillMode: Image.PreserveAspectCrop;
+ anchors.fill: parent;
+ opacity: 0.8;
+ }
+}
diff --git a/gui/qml/BridgesItem.qml b/gui/qml/BridgesItem.qml
new file mode 100644
index 0000000..1cf152c
--- /dev/null
+++ b/gui/qml/BridgesItem.qml
@@ -0,0 +1,58 @@
+import QtQuick 2.9
+import QtQuick.Layouts 1.12
+import QtQuick.Controls 2.4
+
+import "logic.js" as Logic
+
+Item {
+
+ anchors.centerIn: parent
+ width: parent.width
+ property alias displayReconnect: bridgeReconnect.visible
+
+ Column {
+
+ anchors.centerIn: parent
+ spacing: 10
+ width: parent.width
+
+ CheckBox {
+ id: bridgeCheck
+ checked: false
+ text: qsTr("Use obfs4 bridges")
+ font.pixelSize: 14
+ anchors.horizontalCenter: parent.horizontalCenter
+ onClicked: {
+ if (checked) {
+ Logic.setNeedsReconnect(true);
+ bridgeReconnect.visible = true;
+ } else {
+ // This would also need a "needs reconnect" for de-selecting bridges the next time.
+ // better to wait and see the new connection widgets though
+ Logic.setNeedsReconnect(false);
+ bridgeReconnect.visible = false;
+ }
+ }
+ }
+
+ Text {
+ id: bridgesInfo
+ width: 250
+ color: "grey"
+ text: qsTr("Select a bridge only if you know that you need it to evade censorship in your country or local network.")
+ anchors.horizontalCenter: parent.horizontalCenter
+ wrapMode: Text.WordWrap
+ }
+
+ Text {
+ id: bridgeReconnect
+ width: 250
+ font.pixelSize: 12
+ color: "red"
+ text: qsTr("We will attempt to connect to a bridge the next time you connect to the VPN.")
+ anchors.horizontalCenter: parent.horizontalCenter
+ wrapMode: Text.WordWrap
+ visible: false;
+ }
+ }
+}
diff --git a/gui/qml/LocationText.qml b/gui/qml/LocationText.qml
new file mode 100644
index 0000000..883a8a4
--- /dev/null
+++ b/gui/qml/LocationText.qml
@@ -0,0 +1,8 @@
+import QtQuick 2.9
+
+Text {
+ font.pixelSize: 10
+ color: "black"
+ text: qsTr("Location has been manually set.")
+ anchors.horizontalCenter: parent.horizontalCenter
+}
diff --git a/gui/qml/MainBar.qml b/gui/qml/MainBar.qml
new file mode 100644
index 0000000..1f28bac
--- /dev/null
+++ b/gui/qml/MainBar.qml
@@ -0,0 +1,16 @@
+import QtQuick 2.9
+import QtQuick.Controls 2.4
+
+TabBar {
+ //id: bar
+ width: parent.width
+ TabButton {
+ text: qsTr("Status")
+ }
+ TabButton {
+ text: qsTr("Location")
+ }
+ TabButton {
+ text: qsTr("Bridges")
+ }
+}
diff --git a/gui/qml/VPNSwitch.qml b/gui/qml/VPNSwitch.qml
new file mode 100644
index 0000000..14b3734
--- /dev/null
+++ b/gui/qml/VPNSwitch.qml
@@ -0,0 +1,64 @@
+import QtQuick 2.9
+import QtQuick.Layouts 1.12
+import QtQuick.Controls 2.4
+
+
+SwitchDelegate {
+
+ //id: vpntoggle
+
+ text: qsTr("")
+ checked: false
+ anchors.horizontalCenter: parent.horizontalCenter
+
+ /*
+ Connections {
+ function onCheckedChanged() {
+ if (vpntoggle.checked == true
+ && ctx.status == "off") {
+ backend.switchOn()
+ }
+ if (vpntoggle.checked === false
+ && ctx.status == "on") {
+ backend.switchOff()
+ }
+ }
+ }
+ */
+
+ contentItem: Text {
+ rightPadding: vpntoggle.indicator.width + vpntoggle.spacing
+ text: vpntoggle.text
+ font: vpntoggle.font
+ opacity: enabled ? 1.0 : 0.5
+ color: vpntoggle.down ? "#17a81a" : "#21be2b"
+ elide: Text.ElideRight
+ verticalAlignment: Text.AlignVCenter
+ }
+
+ indicator: Rectangle {
+ implicitWidth: 48
+ implicitHeight: 26
+ x: vpntoggle.width - width - vpntoggle.rightPadding
+ y: parent.height / 2 - height / 2
+ radius: 13
+ color: vpntoggle.checked ? "#17a81a" : "transparent"
+ border.color: vpntoggle.checked ? "#17a81a" : "#cccccc"
+
+ Rectangle {
+ x: vpntoggle.checked ? parent.width - width : 0
+ width: 26
+ height: 26
+ radius: 13
+ color: vpntoggle.down ? "#cccccc" : "#ffffff"
+ border.color: vpntoggle.checked ? (vpntoggle.down ? "#17a81a" : "#21be2b") : "#999999"
+ }
+ }
+
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ visible: vpntoggle.down || vpntoggle.highlighted
+ color: vpntoggle.down ? "#17a81a" : "#eeeeee"
+ }
+} // end switchdelegate
diff --git a/gui/qml/VpnState.qml b/gui/qml/VpnState.qml
index e1a183c..332dcaa 100644
--- a/gui/qml/VpnState.qml
+++ b/gui/qml/VpnState.qml
@@ -1,6 +1,8 @@
import QtQuick 2.0
import QtQuick.Controls 2.12
+import "logic.js" as Logic
+
StateGroup {
state: ctx ? ctx.status : ""
@@ -11,9 +13,12 @@ StateGroup {
},
State {
name: "off"
+ StateChangeScript {
+ script: Logic.setStatus("off");
+ }
PropertyChanges {
target: systray
- tooltip: toHuman("off")
+ tooltip: Logic.toHuman("off")
icon.source: icons["off"]
}
PropertyChanges {
@@ -22,15 +27,15 @@ StateGroup {
}
PropertyChanges {
target: statusItem
- text: toHuman("off")
+ text: Logic.toHuman("off")
}
PropertyChanges {
target: autoSelectionItem
- text: qsTr("Best")
+ text: qsTr("Recommended")
}
PropertyChanges {
target: mainStatus
- text: toHuman("off")
+ text: Logic.toHuman("off")
}
PropertyChanges {
target: mainCurrentGateway
@@ -39,9 +44,16 @@ StateGroup {
},
State {
name: "on"
+ StateChangeScript {
+ script: {
+ Logic.setNeedsReconnect(false);
+ brReconnect = false;
+ }
+
+ }
PropertyChanges {
target: systray
- tooltip: toHuman("on")
+ tooltip: Logic.toHuman("on")
icon.source: icons["on"]
}
PropertyChanges {
@@ -50,7 +62,7 @@ StateGroup {
}
PropertyChanges {
target: statusItem
- text: toHuman("on")
+ text: Logic.toHuman("on")
}
PropertyChanges {
target: autoSelectionItem
@@ -65,7 +77,7 @@ StateGroup {
}
PropertyChanges {
target: mainStatus
- text: toHuman("on")
+ text: Logic.toHuman("on")
}
PropertyChanges {
target: mainCurrentGateway
@@ -77,12 +89,12 @@ StateGroup {
name: "starting"
PropertyChanges {
target: systray
- tooltip: toHuman("connecting")
+ tooltip: Logic.toHuman("connecting")
icon.source: icons["wait"]
}
PropertyChanges {
target: statusItem
- text: toHuman("connecting")
+ text: Logic.toHuman("connecting")
}
PropertyChanges {
target: autoSelectionItem
@@ -108,12 +120,12 @@ StateGroup {
name: "stopping"
PropertyChanges {
target: systray
- tooltip: toHuman("stopping")
+ tooltip: Logic.toHuman("stopping")
icon.source: icons["wait"]
}
PropertyChanges {
target: statusItem
- text: toHuman("stopping")
+ text: Logic.toHuman("stopping")
}
PropertyChanges {
target: autoSelectionItem
@@ -121,7 +133,7 @@ StateGroup {
}
PropertyChanges {
target: mainStatus
- text: toHuman("stopping")
+ text: Logic.toHuman("stopping")
}
PropertyChanges {
target: mainCurrentGateway
@@ -132,12 +144,12 @@ StateGroup {
name: "failed"
PropertyChanges {
target: systray
- tooltip: toHuman("failed")
+ tooltip: Logic.toHuman("failed")
icon.source: icons["wait"]
}
PropertyChanges {
target: statusItem
- text: toHuman("failed")
+ text: Logic.toHuman("failed")
}
PropertyChanges {
target: autoSelectionItem
@@ -145,7 +157,7 @@ StateGroup {
}
PropertyChanges {
target: mainStatus
- text: toHuman("failed")
+ text: Logic.toHuman("failed")
}
PropertyChanges {
target: mainCurrentGateway
diff --git a/gui/qml/logic.js b/gui/qml/logic.js
new file mode 100644
index 0000000..4fdbb99
--- /dev/null
+++ b/gui/qml/logic.js
@@ -0,0 +1,39 @@
+let status = 'off';
+let needsReconnect = false;
+
+function setStatus(st) {
+ status = st;
+}
+
+function getStatus() {
+ return status;
+}
+
+function setNeedsReconnect(val) {
+ needsReconnect = val;
+}
+
+function getNeedsReconnect() {
+ return needsReconnect;
+}
+
+function toHuman(st) {
+ switch (st) {
+ case "off":
+ //: %1 -> application name
+ return qsTr("%1 off").arg(ctx.appName)
+ case "on":
+ //: %1 -> application name
+ return qsTr("%1 on").arg(ctx.appName)
+ case "connecting":
+ //: %1 -> application name
+ return qsTr("Connecting to %1").arg(ctx.appName)
+ case "stopping":
+ //: %1 -> application name
+ return qsTr("Stopping %1").arg(ctx.appName)
+ case "failed":
+ //: %1 -> application name
+ return qsTr("%1 blocking internet").arg(
+ ctx.appName) // TODO failed is not handed yet
+ }
+}
diff --git a/gui/qml/main.qml b/gui/qml/main.qml
index 7048a81..f75a121 100644
--- a/gui/qml/main.qml
+++ b/gui/qml/main.qml
@@ -5,6 +5,8 @@ import QtQuick.Controls 2.4
import Qt.labs.platform 1.0
+import "logic.js" as Logic
+
ApplicationWindow {
id: app
visible: true
@@ -18,26 +20,16 @@ ApplicationWindow {
property var ctx
property var loginDone
property var allowEmptyPass
+ property var needsRestart
+
onSceneGraphError: function(error, msg) {
console.debug("ERROR while initializing scene")
console.debug(msg)
}
- // TODO refactor into discrete components.
-
- TabBar {
+ MainBar {
id: bar
- width: parent.width
- TabButton {
- text: qsTr("Status")
- }
- TabButton {
- text: qsTr("Location")
- }
- TabButton {
- text: qsTr("Bridges")
- }
}
StackLayout {
@@ -50,17 +42,8 @@ ApplicationWindow {
id: infoTab
anchors.centerIn: parent
- Rectangle {
+ BackgroundImage {
id: background
- anchors.fill: parent;
- anchors.topMargin: 40;
-
- Image {
- source: "qrc:/assets/img/bird.jpg";
- fillMode: Image.PreserveAspectCrop;
- anchors.fill: parent;
- opacity: 0.8;
- }
}
Item {
@@ -96,14 +79,9 @@ ApplicationWindow {
anchors.horizontalCenter: parent.horizontalCenter
}
- SwitchDelegate {
-
+ VPNSwitch {
id: vpntoggle
- text: qsTr("")
- checked: false
- anchors.horizontalCenter: parent.horizontalCenter
-
Connections {
function onCheckedChanged() {
if (vpntoggle.checked == true
@@ -116,50 +94,10 @@ ApplicationWindow {
}
}
}
+ }
- contentItem: Text {
- rightPadding: vpntoggle.indicator.width + vpntoggle.spacing
- text: vpntoggle.text
- font: vpntoggle.font
- opacity: enabled ? 1.0 : 0.5
- color: vpntoggle.down ? "#17a81a" : "#21be2b"
- elide: Text.ElideRight
- verticalAlignment: Text.AlignVCenter
- }
-
- indicator: Rectangle {
- implicitWidth: 48
- implicitHeight: 26
- x: vpntoggle.width - width - vpntoggle.rightPadding
- y: parent.height / 2 - height / 2
- radius: 13
- color: vpntoggle.checked ? "#17a81a" : "transparent"
- border.color: vpntoggle.checked ? "#17a81a" : "#cccccc"
-
- Rectangle {
- x: vpntoggle.checked ? parent.width - width : 0
- width: 26
- height: 26
- radius: 13
- color: vpntoggle.down ? "#cccccc" : "#ffffff"
- border.color: vpntoggle.checked ? (vpntoggle.down ? "#17a81a" : "#21be2b") : "#999999"
- }
- }
-
- background: Rectangle {
- implicitWidth: 100
- implicitHeight: 40
- visible: vpntoggle.down || vpntoggle.highlighted
- color: vpntoggle.down ? "#17a81a" : "#eeeeee"
- }
- } // end switchdelegate
-
- Text {
+ LocationText {
id: manualOverrideWarning
- font.pixelSize: 10
- color: "grey"
- text: qsTr("Location has been manually set.")
- anchors.horizontalCenter: parent.horizontalCenter
visible: isManualLocation()
}
} // end column
@@ -200,7 +138,6 @@ ApplicationWindow {
backend.useLocation(currentText.toString())
}
-
delegate: ItemDelegate {
// TODO: we could use icons
// https://doc.qt.io/qt-5/qml-qtquick-controls2-abstractbutton.html#icon-prop
@@ -232,44 +169,10 @@ ApplicationWindow {
} // end column
} // end item
- Item {
-
+ BridgesItem {
id: bridgesTab
- anchors.centerIn: parent
- width: parent.width
-
- Column {
-
- anchors.centerIn: parent
- spacing: 10
- width: parent.width
+ }
- CheckBox {
- checked: false
- text: qsTr("Use obfs4 bridges")
- font.pixelSize: 14
- anchors.horizontalCenter: parent.horizontalCenter
- }
- Text {
- id: bridgesInfo
- width: 250
- color: "grey"
- text: qsTr("Select a bridge only if you know that you need it to evade censorship in your country or local network.")
- anchors.horizontalCenter: parent.horizontalCenter
- wrapMode: Text.WordWrap
- }
- Text {
- id: bridgeReconnect
- width: 250
- font.pixelSize: 12
- color: "red"
- text: qsTr("The change will take effect next time you connect to the VPN.")
- anchors.horizontalCenter: parent.horizontalCenter
- wrapMode: Text.WordWrap
- visible: true
- }
- } // end column
- } // end item
} // end stacklayout
Connections {
@@ -374,36 +277,13 @@ ApplicationWindow {
console.debug("DEBUG: Pre-seeded providers:")
console.debug(providers.getJson())
allowEmptyPass = shouldAllowEmptyPass()
+ needsRestart = false;
/* TODO get appVisible flag from backend */
app.visible = true
app.raise()
}
- function toHuman(st) {
- switch (st) {
- case "off":
- //: %1 -> application name
- return qsTr("%1 off").arg(ctx.appName)
- case "on":
- //: %1 -> application name
- return qsTr("%1 on").arg(ctx.appName)
- case "connecting":
- //: %1 -> application name
- return qsTr("Connecting to %1").arg(ctx.appName)
- case "stopping":
- //: %1 -> application name
- return qsTr("Stopping %1").arg(ctx.appName)
- case "failed":
- //: %1 -> application name
- return qsTr("%1 blocking internet").arg(
- ctx.appName) // TODO failed is not handed yet
- }
- }
-
- function locationStr() {
- return ctx.currentLocation + ", " + ctx.currentCountry
- }
property var icons: {
"off": "qrc:/assets/icon/png/white/vpn_off.png",
@@ -557,10 +437,8 @@ ApplicationWindow {
systray.icon.source = icons["off"]
tooltip = qsTr("Checking status…")
console.debug("systray init completed")
- //hide()
if (systrayVisible) {
console.log("show systray")
- //show()
if (Qt.platform.os === "windows") {
let appname = ctx ? ctx.appName : "VPN"
showNotification(
@@ -570,6 +448,7 @@ ApplicationWindow {
}
}
+ // TODO move to logic, pass ctx
// Helper to show notification messages
function showNotification(msg) {
console.log("Going to show notification message: ", msg)
@@ -604,7 +483,6 @@ ApplicationWindow {
MessageDialog {
id: errorStartingVPN
- //buttons: MessageDialog.Ok
modality: Qt.NonModal
title: qsTr("Error starting VPN")
text: ""
@@ -614,7 +492,6 @@ ApplicationWindow {
MessageDialog {
id: authAgent
- //buttons: MessageDialog.Ok
modality: Qt.NonModal
title: qsTr("Missing authentication agent")
text: qsTr("Could not find a polkit authentication agent. Please run one and try again.")
@@ -625,4 +502,11 @@ ApplicationWindow {
id: initFailure
visible: false
}
+
+ function locationStr() {
+ return ctx.currentLocation + ", " + ctx.currentCountry
+ }
+
+ property alias brReconnect:bridgesTab.displayReconnect
+
}