add quick and dirty ports of nemo wireless settings

This commit is contained in:
Marco Martin 2014-11-27 17:40:27 +01:00
parent 16460460b0
commit 0bb4240b22
3 changed files with 766 additions and 0 deletions

View file

@ -41,3 +41,5 @@ install(DIRECTORY wallpaper/ DESTINATION "${WALLPAPER_INSTALL_DIR}/org.kde.satel
add_subdirectory(bin)
add_subdirectory(qmlcomponents)
add_subdirectory(services)
install(DIRECTORY settingsmodules DESTINATION ${DATA_INSTALL_DIR})

View file

@ -0,0 +1,548 @@
/*
* Copyright (C) 2013 Robin Burchell <robin+mer@viroteck.net>
* Copyright (C) 2012 Jolla Ltd. <dmitry.rozhkov@jollamobile.com>
*
* You may use this file under the terms of the BSD license as follows:
*
* "Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Nemo Mobile nor the names of its contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
*/
import QtQuick 2.0
import QtQuick.Layouts 1.1
import org.kde.plasma.components 2.0
import org.kde.plasma.extras 2.0 as PlasmaExtras
import MeeGo.Connman 0.2
Item {
id: sheet
property QtObject network
onNetworkChanged: {
proxyAutoUrl.checked = ! network.proxyConfig["URL"];
form.networkName = network.name;
form.ipv4 = network.ipv4;
form.nameservers = network.nameservers;
form.domains = network.domains;
form.proxy = network.proxy;
form.proxyConfig = network.proxyConfig;
}
RowLayout {
z: 2
anchors {
bottom: parent.bottom
horizontalCenter: parent.horizontalCenter
}
Button {
text: "Accept"
onClicked: {
var domains = [],
nameservers = [],
ipv4,
proxyconf,
proxy_server_text;
console.log("Accept");
// Domains
if (network.domains.join() !== domainsField.text) {
if (domainsField.text) {
domains = domainsField.text.split();
}
console.log("Update Domains: " + domains.join());
network.domainsConfig = domains;
}
// IPv4
ipv4 = network.ipv4;
if (ipv4["Method"] !== method.state) {
ipv4["Method"] = method.state;
if (method.state === "manual") {
ipv4["Address"] = address.text
ipv4["Netmask"] = netmask.text
ipv4["Gateway"] = gateway.text
}
network.ipv4Config = ipv4;
} else if (network.ipv4["Method"] === "manual") {
if (ipv4["Address"] !== address.text ||
ipv4["Netmask"] !== netmask.text ||
ipv4["Gateway"] !== gateway.text) {
ipv4["Address"] = address.text
ipv4["Netmask"] = netmask.text
ipv4["Gateway"] = gateway.text
network.ipv4Config = ipv4;
}
}
// Nameservers
if (method.state === "manual" &&
network.nameserversConfig.join() !== nameserversField.text) {
nameservers = nameserversField.text.split();
network.nameserversConfig = nameservers;
}
// Proxy
proxyconf = network.proxyConfig;
if (proxyconf["Method"] !== proxy.state) {
proxyconf["Method"] = proxy.state;
if (proxy.state === "auto") {
proxyconf["URL"] = proxyurl.text;
} else if (proxy.state === "manual") {
proxyconf["Servers"] = [proxyserver.text + ":" + proxyport.text];
}
network.proxyConfig = proxyconf;
} else if (proxy.state === "manual") {
proxy_server_text = proxyserver.text + ":" + proxyport.text;
if (proxyconf["Servers"].length === 0 || proxyconf["Servers"][0] !== proxy_server_text) {
proxyconf["Servers"] = [proxy_server_text];
network.proxyConfig = proxyconf;
}
} else if (proxy.state == "auto") {
if (proxyAutoUrl.checked && proxyconf["URL"]) {
// empty URL to use the provided by DHCP
proxyconf["URL"] = "";
network.proxyConfig = proxyconf;
} else if (! proxyAutoUrl.checked && proxyurl.text !== proxyconf["URL"]) {
// manual URL is used and it needs update
proxyconf["URL"] = proxyurl.text;
network.proxyConfig = proxyconf;
}
}
}
}
Button {
text: "Cancel"
onClicked: {
stackView.pop();
}
}
}
PlasmaExtras.ScrollArea {
anchors.fill: parent
Flickable {
id: form
anchors.fill: parent
anchors.leftMargin: 10
anchors.topMargin: 10
//contentWidth: mainColumn.width
contentHeight: mainColumn.height
flickableDirection: Flickable.VerticalFlick
property string networkName: "Error"
property variant ipv4: {"Method": "manual", "Address": "", "Netmask": "", "Gateway": ""}
property variant nameservers: []
property variant domains: []
property variant proxy: {"Method": "auto", "URL": ""}
property variant proxyConfig: {"Servers": []}
Column {
id: mainColumn
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
spacing: 10
Rectangle {
anchors { left: parent.left; right: parent.right }
height: 80
color: "transparent"
Image {
anchors { left: parent.left; verticalCenter: parent.verticalCenter }
source: "image://theme/icon-m-common-wlan-strength5"
width: 60
height: 60
}
Text {
anchors { left: parent.left; verticalCenter: parent.verticalCenter; leftMargin: 80 }
text: form.networkName
}
}
Rectangle {
anchors { left: parent.left; right: parent.right }
height: 100
color: "transparent"
Button {
id: disconnectButton
anchors {
horizontalCenter: parent.horizontalCenter
verticalCenter: parent.verticalCenter
}
text: "Disconnect"
onClicked: {
console.log("Disconnect clicked");
network.requestDisconnect();
sheet.close();
}
}
}
Item {
anchors { left: parent.left; right: parent.right }
height: 100
Text {
anchors { left: parent.left; leftMargin: 20 }
text: "Method"
}
ButtonRow {
id: method
anchors { left: parent.left; right: parent.right; top: parent.top; topMargin: 30; leftMargin: 10; rightMargin: 10 }
state: form.ipv4.Method
states: [
State {
name: "dhcp"
PropertyChanges {target: networkInfo; visible: true}
PropertyChanges {target: networkFields; visible: false}
},
State {
name: "manual"
PropertyChanges {target: networkInfo; visible: false}
PropertyChanges {target: networkFields; visible: true}
}
]
Button {
text: "DHCP"
checked: form.ipv4.Method == "dhcp"
onClicked: {
method.state = "dhcp"
}
}
Button {
text: "Static"
checked: form.ipv4.Method == "manual"
onClicked: {
method.state = "manual"
}
}
}
}
Item {
id: networkInfo
anchors { left: parent.left; right: parent.right }
height: 340
Column {
spacing: 50
Item {
height: 40
anchors { left: parent.left; right: parent.right }
Text {
anchors { left: parent.left; leftMargin: 20; top: parent.top }
text: "IP address"
}
Text {
anchors { left: parent.left; leftMargin: 20; top:parent.top; topMargin: 30 }
text: form.ipv4.Address
}
}
Item {
height: 40
anchors { left: parent.left; right: parent.right }
Text {
anchors { left: parent.left; leftMargin: 20; top: parent.top }
text: "Subnet mask"
}
Text {
anchors { left: parent.left; leftMargin: 20; top: parent.top; topMargin: 30 }
text: form.ipv4.Netmask
}
}
Item {
height: 40
anchors { left: parent.left; right: parent.right }
Text {
anchors { left: parent.left; leftMargin: 20; top: parent.top }
text: "Router"
}
Text {
anchors { left: parent.left; leftMargin: 20; top: parent.top; topMargin: 30 }
text: form.ipv4.Gateway
}
}
Item {
height: 40
anchors { left: parent.left; right: parent.right }
Text {
anchors { left: parent.left; leftMargin: 20; top: parent.top }
text: "DNS"
}
Text {
anchors { left: parent.left; leftMargin: 20; top: parent.top; topMargin: 30 }
text: form.nameservers.join()
}
}
}
}
Item {
id: networkFields
anchors { left: parent.left; right: parent.right }
height: 360
Column {
spacing: 50
Item {
height: 40
anchors { left: parent.left; right: parent.right }
Text {
anchors { left: parent.left; leftMargin: 20; top: parent.top }
text: "IP address"
}
TextField {
id: address
anchors { left: parent.left; leftMargin: 20; top:parent.top; topMargin: 30 }
width: 440
text: form.ipv4.Address
}
}
Item {
height: 40
anchors { left: parent.left; right: parent.right }
Text {
anchors { left: parent.left; leftMargin: 20; top: parent.top }
text: "Subnet mask"
}
TextField {
id: netmask
anchors { left: parent.left; leftMargin: 20; top: parent.top; topMargin: 30 }
width: 440
text: form.ipv4.Netmask
}
}
Item {
height: 40
anchors { left: parent.left; right: parent.right }
Text {
anchors { left: parent.left; leftMargin: 20; top: parent.top }
text: "Router"
}
TextField {
id: gateway
anchors { left: parent.left; leftMargin: 20; top: parent.top; topMargin: 30 }
width: 440
text: form.ipv4.Gateway
}
}
Item {
height: 40
anchors { left: parent.left; right: parent.right }
Text {
anchors { left: parent.left; leftMargin: 20; top: parent.top }
text: "DNS"
}
TextField {
id: nameserversField
anchors { left: parent.left; leftMargin: 20; top: parent.top; topMargin: 30 }
width: 440
text: {
var nservs = "";
if (sheet.network) {
nservs = sheet.network.nameserversConfig.join();
return nservs ? nservs : form.nameservers.join();
} else {
return "";
}
}
}
}
}
}
Item {
height: 100
anchors { left: parent.left; right: parent.right }
Text {
anchors { left: parent.left; leftMargin: 20; top: parent.top }
text: "Search domains"
}
TextField {
id: domainsField
anchors { left: parent.left; leftMargin: 20; top: parent.top; topMargin: 30 }
width: 440
text: form.domains.join()
}
}
Item {
anchors { left: parent.left; right: parent.right }
height: 100
Text {
anchors { left: parent.left; leftMargin: 20 }
text: "HTTP Proxy"
}
ButtonRow {
id: proxy
anchors { left: parent.left; right: parent.right; top: parent.top; topMargin: 30; leftMargin: 10; rightMargin: 10 }
state: form.proxy.Method
states: [
State {
name: "direct"
PropertyChanges {target: proxyManualFields; visible: false}
PropertyChanges {target: proxyAutoFields; visible: false}
PropertyChanges {target: directProxyButton; checked: true}
PropertyChanges {target: manualProxyButton; checked: false}
PropertyChanges {target: autoProxyButton; checked: false}
},
State {
name: "auto"
PropertyChanges {target: proxyManualFields; visible: false}
PropertyChanges {target: proxyAutoFields; visible: true}
PropertyChanges {target: directProxyButton; checked: false}
PropertyChanges {target: manualProxyButton; checked: false}
PropertyChanges {target: autoProxyButton; checked: true}
},
State {
name: "manual"
PropertyChanges {target: proxyManualFields; visible: true}
PropertyChanges {target: proxyAutoFields; visible: false}
PropertyChanges {target: directProxyButton; checked: false}
PropertyChanges {target: manualProxyButton; checked: true}
PropertyChanges {target: autoProxyButton; checked: false}
}
]
Button {
id: directProxyButton
text: "Off"
onClicked: {
proxy.state = "direct"
}
}
Button {
id: manualProxyButton
text: "Manual"
onClicked: {
proxy.state = "manual"
}
}
Button {
id: autoProxyButton
text: "Auto"
onClicked: {
proxy.state = "auto"
}
}
}
}
Item {
id: proxyManualFields
anchors { left: parent.left; right: parent.right }
height: 440
Column {
spacing: 50
Item {
height: 40
anchors { left: parent.left; right: parent.right }
Text {
anchors { left: parent.left; leftMargin: 20; top: parent.top }
text: "Server"
}
TextField {
id: proxyserver
anchors { left: parent.left; leftMargin: 20; top:parent.top; topMargin: 30 }
width: 440
text: form.proxyConfig.Servers ? form.proxyConfig.Servers[0].split(":")[0] : ""
}
}
Item {
height: 40
anchors { left: parent.left; right: parent.right }
Text {
anchors { left: parent.left; leftMargin: 20; top: parent.top }
text: "Port"
}
TextField {
id: proxyport
anchors { left: parent.left; leftMargin: 20; top: parent.top; topMargin: 30 }
width: 440
text: form.proxyConfig.Servers ? form.proxyConfig.Servers[0].split(":")[1] : ""
// TODO: validator
}
}
}
}
Item {
id: proxyAutoFields
anchors { left: parent.left; right: parent.right }
height: 440
Column {
spacing: 50
CheckBox {
id: proxyAutoUrl
text: "Use URL provided by DHCP server"
}
Item {
height: 40
visible: !proxyAutoUrl.checked
anchors { left: parent.left; right: parent.right }
Text {
anchors { left: parent.left; leftMargin: 20; top: parent.top }
text: "URL"
}
TextField {
id: proxyurl
anchors { left: parent.left; leftMargin: 20; top:parent.top; topMargin: 30 }
width: 440
readOnly: proxyAutoUrl.checked
text: form.proxy.URL
// TODO: validator
}
}
}
}
}
}
}
}

View file

@ -0,0 +1,216 @@
/*
* Copyright (C) 2013 Robin Burchell <robin+mer@viroteck.net>
* Copyright (C) 2012 Jolla Ltd. <dmitry.rozhkov@jollamobile.com>
*
* You may use this file under the terms of the BSD license as follows:
*
* "Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Nemo Mobile nor the names of its contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
*/
import QtQuick 2.0
import QtQuick.Layouts 1.1
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.components 2.0 as PlasmaComponents
import org.kde.plasma.extras 2.0 as PlasmaExtras
import MeeGo.Connman 0.2
import QtQuick.Controls 1.2
StackView {
id: stackView
initialItem: mainView
Component {
id: mainView
Item {
id: mainWindow
property Item tools: commonTools
Timer {
id: scanTimer
interval: 25000
running: networkingModel.powered
repeat: true
triggeredOnStart: true
onTriggered: networkingModel.requestScan();
}
TechnologyModel {
id: networkingModel
name: "wifi"
property bool sheetOpened
property string networkName
onTechnologiesChanged: {
scanTimer.running = networkingModel.powered;
}
onPoweredChanged: {
scanTimer.running = networkingModel.powered;
}
}
UserAgent {
id: userAgent
onUserInputRequested: {
scanTimer.running = false;
scanTimer.triggeredOnStart = false;
console.log("USER INPUT REQUESTED");
var view = {
"fields": []
};
for (var key in fields) {
view.fields.push({
"name": key,
"id": key.toLowerCase(),
"type": fields[key]["Type"],
"requirement": fields[key]["Requirement"]
});
console.log(key + ":");
for (var inkey in fields[key]) {
console.log(" " + inkey + ": " + fields[key][inkey]);
}
}
if (!networkingModel.sheetOpened) {
networkingModel.sheetOpened = true
var sheet = pageStack.openSheet(Qt.resolvedUrl("NetworkSettingsSheet.qml"), {
mustacheView: view,
networkName: networkingModel.networkName,
userAgent: userAgent,
scanTimer: scanTimer
})
sheet.accepted.connect(function() { networkingModel.sheetOpened = false })
sheet.rejected.connect(function() { networkingModel.sheetOpened = false })
// TODO: there was code that checked for pageStack.busy and
// didn't open if it was true. What was that about?
}
}
onErrorReported: {
console.log("Got error from model: " + error);
if (error == "invalid-key") {
mainpageNotificationBanner.text = "Incorrect value entered. Try again."
} else {
mainpageNotificationBanner.text = "Connect failed"
}
mainpageNotificationBanner.show()
}
}
PlasmaExtras.Heading {
visible: !networkingModel.available || networkList.count == 0
text: !networkingModel.available ? "Wireless networking unavailable" : "No wireless networks in range"
}
PlasmaExtras.ScrollArea {
anchors.fill: parent
ListView {
id: networkList
//header: WirelessApplet { }
anchors.margins: UiConstants.DefaultMargin
anchors.fill: parent
model: networkingModel
delegate: PlasmaComponents.ListItem {
PlasmaCore.IconItem {
anchors {
left: parent.left
top: parent.top
bottom: parent.bototm
}
width: height
source: {
var strength = modelData.strength;
var str_id = 0;
if (strength >= 100) {
str_id = 100;
} else if (strength >= 80) {
str_id = 80;
} else if (strength >= 60) {
str_id = 60;
} else if (strength >= 40) {
str_id = 40;
} else if (strength >= 20) {
str_id = 20;
}
return "network-wireless-" + str_id;
}
}
ColumnLayout {
anchors {
left: icon.right
top: parent.top
right: parent.right
bottom: parent.bottom
}
PlasmaExtras.Heading {
level: 2
text: modelData.name ? modelData.name : "(hidden network)"
}
PlasmaComponents.Label {
text: {
var state = modelData.state;
var security = modelData.security[0];
if ((state == "online") || (state == "ready")) {
return "connected";
} else if (state == "association" || state == "configuration") {
return "connecting...";
} else {
if (security == "none") {
return "open";
} else {
return "secure";
}
}
}
}
}
// TODO: subtitleColor / subtitleColorPressed bindings
// depending on state like in old delegate?
onClicked: {
console.log("clicked " + modelData.name);
if (modelData.state == "idle" || modelData.state == "failure") {
modelData.requestConnect();
networkingModel.networkName.text = modelData.name;
} else {
console.log("Show network status page");
for (var key in modelData.ipv4) {
console.log(key + " -> " + modelData.ipv4[key]);
}
stackView.push({item: Qt.resolvedUrl("SettingsSheet.qml"), properties: { network: modelData }})
}
}
}
}
}
}
}
}