Merge lp:~unity-api-team/ubuntu-system-settings/morenetworks into lp:ubuntu-system-settings

Proposed by Antti Kaijanmäki
Status: Merged
Approved by: Charles Kerr
Approved revision: 755
Merged at revision: 750
Proposed branch: lp:~unity-api-team/ubuntu-system-settings/morenetworks
Merge into: lp:ubuntu-system-settings
Diff against target: 1586 lines (+1371/-71)
17 files modified
.bzrignore (+3/-0)
plugins/wifi/CMakeLists.txt (+10/-0)
plugins/wifi/NetworkDetails.qml (+99/-0)
plugins/wifi/OtherNetwork.qml (+129/-0)
plugins/wifi/PageComponent.qml (+93/-71)
plugins/wifi/PreviousNetworks.qml (+45/-0)
plugins/wifi/nm-manager-introspection.xml (+79/-0)
plugins/wifi/nm-settings-connection-introspection.xml (+22/-0)
plugins/wifi/nm-settings-introspection.xml (+26/-0)
plugins/wifi/nm_manager_proxy.h (+207/-0)
plugins/wifi/nm_settings_connection_proxy.h (+74/-0)
plugins/wifi/nm_settings_proxy.h (+84/-0)
plugins/wifi/plugin.cpp (+20/-0)
plugins/wifi/previousnetworkmodel.cpp (+72/-0)
plugins/wifi/previousnetworkmodel.h (+47/-0)
plugins/wifi/wifidbushelper.cpp (+318/-0)
plugins/wifi/wifidbushelper.h (+43/-0)
To merge this branch: bzr merge lp:~unity-api-team/ubuntu-system-settings/morenetworks
Reviewer Review Type Date Requested Status
PS Jenkins bot continuous-integration Approve
Charles Kerr (community) Approve
Brendan Donegan (community) Approve
Jussi Pakkanen (community) Approve
Review via email: mp+220422@code.launchpad.net

Commit message

Wifi:
  * Connecto to Other (hidden) Network
  * Previous Networks

Description of the change

 * Is your branch in sync with latest trunk (e.g. bzr pull lp:trunk -> no changes)

Should be.

 * Did you build your software in a clean sbuild/pbuilder chroot or ppa?

Nope. I let the machines do it for me.

 * Has your component "TestPlan” been executed successfully on emulator, N4?

Yes.

 * Has a 5 minute exploratory testing run been executed on N4?

Yep.

 * If you changed the packaging (debian), did you subscribe a core-dev to this MP?

Did not touch it.

 * If you changed the UI, did you subscribe the design-reviewers to this MP?

We have an agreement with the design.

 * What components might get impacted by your changes?

None.

 * Have you requested review by the teams of these owning components?

Yep.

To post a comment you must log in.
Revision history for this message
Brendan Donegan (brendan-donegan) wrote :

I know this is a work in progress, but can you think about adding some tests in here as well? At least some autopilot functional tests, but some unit tests for the plugin code would be appreciated as well.

750. By Antti Kaijanmäki

Revert any Hotspot related changes.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:749
http://jenkins.qa.ubuntu.com/job/ubuntu-system-settings-ci/881/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-utopic-touch/1009
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-utopic/909
    SUCCESS: http://jenkins.qa.ubuntu.com/job/ubuntu-system-settings-utopic-amd64-ci/73
    SUCCESS: http://jenkins.qa.ubuntu.com/job/ubuntu-system-settings-utopic-armhf-ci/73
        deb: http://jenkins.qa.ubuntu.com/job/ubuntu-system-settings-utopic-armhf-ci/73/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/ubuntu-system-settings-utopic-i386-ci/73
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-mako/1392
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-utopic-armhf/1779
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-utopic-armhf/1779/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/8593
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/autopilot-testrunner-otto-utopic/785
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-utopic-amd64/1051
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-utopic-amd64/1051/artifact/work/output/*zip*/output.zip

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/ubuntu-system-settings-ci/881/rebuild

review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:750
http://jenkins.qa.ubuntu.com/job/ubuntu-system-settings-ci/882/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-utopic-touch/1012
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-utopic/913
    SUCCESS: http://jenkins.qa.ubuntu.com/job/ubuntu-system-settings-utopic-amd64-ci/74
    SUCCESS: http://jenkins.qa.ubuntu.com/job/ubuntu-system-settings-utopic-armhf-ci/74
        deb: http://jenkins.qa.ubuntu.com/job/ubuntu-system-settings-utopic-armhf-ci/74/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/ubuntu-system-settings-utopic-i386-ci/74
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-mako/1393
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-utopic-armhf/1783
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-utopic-armhf/1783/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/8596
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/autopilot-testrunner-otto-utopic/788
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-utopic-amd64/1055
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-utopic-amd64/1055/artifact/work/output/*zip*/output.zip

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/ubuntu-system-settings-ci/882/rebuild

review: Needs Fixing (continuous-integration)
Revision history for this message
Jussi Pakkanen (jpakkane) wrote :

Looks good to me, but I wrote most of it, so take it with sufficient amounts of salt.

The testing bit is not in the best possible form. Unfortunately this is one of those bits where testing is quite hard. All these pieces of code do is mediate info between NM dbus services and the Qml widgets. In order to meaningfully test this, we would need to write a fake NetworkManager, and all the surrounding work that requires (custom dbus bus etc) which is a huge amount of work.

review: Approve
751. By Antti Kaijanmäki

Fix PageComponent flickable.

Revision history for this message
Brendan Donegan (brendan-donegan) wrote :

To say the testing is not in the best possible form is a bit of an understatement. We need to have something here. This is two major features landing in one branch without so much as a single test. I will need to think a bit more about how to solve the unit testing problem. But definitely some high-level tests can be written with autopilot. I appreciate you guys might not have the experience with this, so I will look at contributing some myself.

review: Needs Fixing
Revision history for this message
Antti Kaijanmäki (kaijanmaki) wrote :

> To say the testing is not in the best possible form is a bit of an
> understatement. We need to have something here. This is two major features
> landing in one branch without so much as a single test. I will need to think a
> bit more about how to solve the unit testing problem. But definitely some
> high-level tests can be written with autopilot. I appreciate you guys might
> not have the experience with this, so I will look at contributing some myself.

The problem is that we don't have a comprehensive "mock" of NetworkManager which would implement the NM API close enough functionality wise to actual NM and we can't use actual NM as it deals with hardware directly and we can't set up a testing hardware environment.

This is a known problem and we need to tackle it at some point, but right now the effort required to do such meaningful mocking far exceeds the complexity of the code under testing and would take weeks to complete.

I will augment the system-settings manual test list to cover these cases so we get at least manual testing for them.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

PASSED: Continuous integration, rev:751
http://jenkins.qa.ubuntu.com/job/ubuntu-system-settings-ci/885/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-utopic-touch/1085
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-utopic/972
    SUCCESS: http://jenkins.qa.ubuntu.com/job/ubuntu-system-settings-utopic-amd64-ci/77
    SUCCESS: http://jenkins.qa.ubuntu.com/job/ubuntu-system-settings-utopic-armhf-ci/77
        deb: http://jenkins.qa.ubuntu.com/job/ubuntu-system-settings-utopic-armhf-ci/77/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/ubuntu-system-settings-utopic-i386-ci/77
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-mako/1456
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-utopic-armhf/1903
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-utopic-armhf/1903/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/8713
    SUCCESS: http://jenkins.qa.ubuntu.com/job/autopilot-testrunner-otto-utopic/837
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-utopic-amd64/1115
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-utopic-amd64/1115/artifact/work/output/*zip*/output.zip

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/ubuntu-system-settings-ci/885/rebuild

review: Approve (continuous-integration)
752. By Antti Kaijanmäki

Don't ask for secrects on a connection that has never been activated properly.

753. By Antti Kaijanmäki

Add progression indicators to the PreviousNetworks items.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:752
http://jenkins.qa.ubuntu.com/job/ubuntu-system-settings-ci/888/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-utopic-touch/1113
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-utopic/993/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/ubuntu-system-settings-utopic-amd64-ci/80
    SUCCESS: http://jenkins.qa.ubuntu.com/job/ubuntu-system-settings-utopic-armhf-ci/80
        deb: http://jenkins.qa.ubuntu.com/job/ubuntu-system-settings-utopic-armhf-ci/80/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/ubuntu-system-settings-utopic-i386-ci/80
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-mako/1480
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-utopic-armhf/1938
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-utopic-armhf/1938/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/8743
    FAILURE: http://jenkins.qa.ubuntu.com/job/autopilot-testrunner-otto-utopic/845/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-utopic-amd64/1136
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-utopic-amd64/1136/artifact/work/output/*zip*/output.zip

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/ubuntu-system-settings-ci/888/rebuild

review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

PASSED: Continuous integration, rev:753
http://jenkins.qa.ubuntu.com/job/ubuntu-system-settings-ci/889/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-utopic-touch/1118
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-utopic/996
    SUCCESS: http://jenkins.qa.ubuntu.com/job/ubuntu-system-settings-utopic-amd64-ci/81
    SUCCESS: http://jenkins.qa.ubuntu.com/job/ubuntu-system-settings-utopic-armhf-ci/81
        deb: http://jenkins.qa.ubuntu.com/job/ubuntu-system-settings-utopic-armhf-ci/81/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/ubuntu-system-settings-utopic-i386-ci/81
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-mako/1484
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-utopic-armhf/1948
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-utopic-armhf/1948/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/8750
    SUCCESS: http://jenkins.qa.ubuntu.com/job/autopilot-testrunner-otto-utopic/847
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-utopic-amd64/1139
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-utopic-amd64/1139/artifact/work/output/*zip*/output.zip

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/ubuntu-system-settings-ci/889/rebuild

review: Approve (continuous-integration)
Revision history for this message
Brendan Donegan (brendan-donegan) wrote :

In this case I'll have a look at the branch and check the test cases you added and approve this soon, if no issues are found.

> > To say the testing is not in the best possible form is a bit of an
> > understatement. We need to have something here. This is two major features
> > landing in one branch without so much as a single test. I will need to think
> a
> > bit more about how to solve the unit testing problem. But definitely some
> > high-level tests can be written with autopilot. I appreciate you guys might
> > not have the experience with this, so I will look at contributing some
> myself.
>
> The problem is that we don't have a comprehensive "mock" of NetworkManager
> which would implement the NM API close enough functionality wise to actual NM
> and we can't use actual NM as it deals with hardware directly and we can't set
> up a testing hardware environment.
>
> This is a known problem and we need to tackle it at some point, but right now
> the effort required to do such meaningful mocking far exceeds the complexity
> of the code under testing and would take weeks to complete.
>
> I will augment the system-settings manual test list to cover these cases so we
> get at least manual testing for them.

Revision history for this message
Brendan Donegan (brendan-donegan) wrote :

Some stuff I noticed:

1.) Previous networks remembers networks I only tried to connect to. If I select a network and then cancel the password entry then it appears in Previous networks with a 'Last connected' value of 'Never'. Not sure if this is expected behaviour or not.

2.) Show password in Network details has tiny text. If I check 'Show password' in the Network details screen of a network I entered a password for, then the password text is very small, compared to the rest of the text.

3.) Selecting 'Password visible' on the 'Other network' screen is difficult. When entering a password on the Other network screen, the keyboard covers the 'Password visible' toggle button (also why the different phrasing for different screens - i.e. Show password vs. Password visible?). Also it's effectively impossible to test Other network manually because the keyboard can't be hidden due to a current bug, and I can never click Connect. Obviously this is not system-settings fault, but it's not ideal that we can't test it. I could try on the desktop, but it's not the same thing.

review: Needs Information
Revision history for this message
Jussi Pakkanen (jpakkane) wrote :

1) We only report what NetworkManager tells us. If the network should not appear if you cancel the request, then the password request window (snap decision?) needs to be changed to tell NM to forget the connection. That is a completely separate issue that does not affect this MR. I personally would keep the current behaviour because that network is something the user has actively tried to interact with so it should be listed.

2) I noticed this too, but I can't see what could be causing it. The widget is a bog standard TextInput with no styling applied whatsoever.

3) To get the keyboard go away, swipe from the left to get to the main screen and then tap on the open app. As far as the password text goes, different documents and different people say different things. I'll be glad to standardise on one phrase once someone makes a binding decision what that should be.

Revision history for this message
Brendan Donegan (brendan-donegan) wrote :

Thanks - I'll report bugs for these issues and they can be taken care of as appropriate. Otherwise, +1

review: Approve
Revision history for this message
Charles Kerr (charlesk) wrote :

Added some inline comments for code-level issues.

Some of these comments -- eg bounds checking, testing bus replies for validity, accidentally leaking the variable 's' into libUbuntuWifiPanel.so -- should fixed before landing.

Other comments, like cleaning up the debug statements and error logging, don't need to block and if time is short I'd be okay with deferring that kind of stuff to a followup MR.

754. By Jussi Pakkanen

Fix simple issues raised in review.

755. By Jussi Pakkanen

Validate all dbus query statuses.

Revision history for this message
Jussi Pakkanen (jpakkane) wrote :

Fixed issues apart from these two that are the work of Antti and the correct thing to do was not immediately obvious:

I think the second argument is redundant here, since locale.dateFormat() and locale.toString(QDateTime) will both default to use LongFormat

and

// intentionally left blank

Revision history for this message
Jussi Pakkanen (jpakkane) wrote :

Oh, and the reason that one class is not using QScopedPointer is mostly stylistic. I'm an #include minimalist and don't like to use things unless they are absolutely needed. In this case the life cycle is straightforward so I just did it manually. If you feel that QScopedPointer is warranted then I'll add it in.

Revision history for this message
Charles Kerr (charlesk) wrote :

Jussi, thanks for the fixes and the tweaks. Looks good; Approve.

"// intentionally left blank" -- I'm not requesting a code change, just asking about the empty else { }" clause in the code there. Since it doesn't do anything, I was wondering if it kept as an oversight or if it was an intentional hint that other cases would be added there in the future -- and if the latter, maybe it would be better to insert a comment saying so.

About the QScopedPointer or std::unique_ptr... it's not a blocker by any stretch. For the sake of discussion, though, is the extra #include hit really that expensive? Since you're the can-we-build-it-faster man, I suspect you already know exactly how many things are getting #included... :-)

review: Approve
Revision history for this message
Jussi Pakkanen (jpakkane) wrote :

The build speed difference is probably unmeasurably tiny in this particular case. This is mostly a question of personal principle and OCD. ;-)

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Charles Kerr (charlesk) wrote :

I've run the Silo 7 build on a fresh r99 install and have confirmed the WiFi tests listed at <https://wiki.ubuntu.com/Process/Merges/TestPlan/ubuntu-system-settings> all still pass.

Revision history for this message
Charles Kerr (charlesk) wrote :

The formal report as per <https://wiki.ubuntu.com/Process/Merges/Checklists/ubuntu-system-settings>:

> * Are any changes against your component pending/needed to land the MP under review in a functional state and are those called out explicitly by the submitter?

No other changes needed.

> * Did you do exploratory testing related to the component you own with the MP changeset included?

Yes, although I'm not the owner.

> * Has the submitter requested review by all the relevant teams/reviewers?

Yes.

> If you are the reviewer owning the component the MP is against, have you checked that submitter has accurately filled out the submitter checklist and has taken no shortcut?

Yes, although I'm not the owner.

Revision history for this message
Antti Kaijanmäki (kaijanmaki) wrote :

> Yes, although I'm not the owner.

Just to clarify. Charles was explicitly asked to do the review by the owner, so we are all good here.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file '.bzrignore'
2--- .bzrignore 2014-01-09 13:03:17 +0000
3+++ .bzrignore 2014-06-26 07:31:08 +0000
4@@ -16,3 +16,6 @@
5 /debian/tmp/
6 /debian/ubuntu-system-settings/
7 /debian/ubuntu-system-settings-example/
8+.cproject
9+.project
10+.settings
11
12=== modified file 'plugins/wifi/CMakeLists.txt'
13--- plugins/wifi/CMakeLists.txt 2013-10-22 14:44:44 +0000
14+++ plugins/wifi/CMakeLists.txt 2014-06-26 07:31:08 +0000
15@@ -6,7 +6,10 @@
16 HLine.qml
17 IndicatorBase.qml
18 MenuItemFactory.qml
19+NetworkDetails.qml
20+OtherNetwork.qml
21 PageComponent.qml
22+PreviousNetworks.qml
23 RemoveBackground.qml
24 SectionMenuItem.qml
25 StandardMenuItem.qml
26@@ -14,10 +17,17 @@
27 )
28
29 add_library(UbuntuWifiPanel MODULE
30+ wifidbushelper.cpp
31 plugin.cpp
32 unitymenumodelstack.cpp
33+ previousnetworkmodel.cpp
34+ wifidbushelper.h
35 plugin.h
36 unitymenumodelstack.h
37+ previousnetworkmodel.h
38+ nm_manager_proxy.h
39+ nm_settings_proxy.h
40+ nm_settings_connection_proxy.h
41 ${QML_SOURCES}
42 )
43 qt5_use_modules(UbuntuWifiPanel Qml Quick DBus)
44
45=== added file 'plugins/wifi/NetworkDetails.qml'
46--- plugins/wifi/NetworkDetails.qml 1970-01-01 00:00:00 +0000
47+++ plugins/wifi/NetworkDetails.qml 2014-06-26 07:31:08 +0000
48@@ -0,0 +1,99 @@
49+/*
50+ * This file is part of system-settings
51+ *
52+ * Copyright (C) 2013 Canonical Ltd.
53+ *
54+ * Contact: Iain Lane <iain.lane@canonical.com>
55+ *
56+ * This program is free software: you can redistribute it and/or modify it
57+ * under the terms of the GNU General Public License version 3, as published
58+ * by the Free Software Foundation.
59+ *
60+ * This program is distributed in the hope that it will be useful, but
61+ * WITHOUT ANY WARRANTY; without even the implied warranties of
62+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
63+ * PURPOSE. See the GNU General Public License for more details.
64+ *
65+ * You should have received a copy of the GNU General Public License along
66+ * with this program. If not, see <http://www.gnu.org/licenses/>.
67+ */
68+
69+import QtQuick 2.0
70+import QtQuick.Layouts 1.1
71+import SystemSettings 1.0
72+import Ubuntu.Components 0.1
73+import Ubuntu.Components.ListItems 0.1 as ListItem
74+import Ubuntu.SystemSettings.Phone 1.0
75+import Ubuntu.SystemSettings.Wifi 1.0
76+
77+ItemPage {
78+
79+ id: networkDetails
80+ property string networkName
81+ property string password
82+ property string lastUsed
83+ property string dbusPath
84+
85+ title: i18n.tr("Network details")
86+
87+ Column {
88+
89+ anchors.fill: parent
90+
91+ ListItem.Standard {
92+ text: i18n.tr("Name")
93+ control: Label {
94+ text: networkName
95+ }
96+ }
97+
98+ ListItem.Standard {
99+ id: lastLabel
100+ text: i18n.tr("Last connected")
101+ control: Label {
102+ id: lastField
103+
104+ text: networkDetails.lastUsed.length !== 0 ? networkDetails.lastUsed : i18n.tr("Never")
105+ }
106+ }
107+
108+ ListItem.Standard {
109+ id: passwordLabel
110+ text: i18n.tr("Password")
111+ visible: networkDetails.password.length !== 0
112+ control: TextInput {
113+ id: passwordField
114+ readOnly: true
115+ text: networkDetails.password
116+ echoMode: passwordVisibleSwitch.checked ? TextInput.Normal : TextInput.Password
117+ }
118+ }
119+
120+ ListItem.Standard {
121+ id: passwordVisible
122+ text: i18n.tr("Show password")
123+ visible: networkDetails.password.length !== 0
124+ control: Switch {
125+ id: passwordVisibleSwitch
126+ }
127+ }
128+
129+ ListItem.Divider {}
130+
131+ Button {
132+ text : i18n.tr("Forget network")
133+ anchors {
134+ left: parent.left
135+ right: parent.right
136+ margins: units.gu(2)
137+ }
138+ onClicked : {
139+ DbusHelper.forgetConnection(dbusPath)
140+ pageStack.pop()
141+ // Go back two steps so we don't have to update the model.
142+ // If the user goes back to network list, the model is rebuilt.
143+ pageStack.pop()
144+ }
145+ }
146+ }
147+}
148
149=== added file 'plugins/wifi/OtherNetwork.qml'
150--- plugins/wifi/OtherNetwork.qml 1970-01-01 00:00:00 +0000
151+++ plugins/wifi/OtherNetwork.qml 2014-06-26 07:31:08 +0000
152@@ -0,0 +1,129 @@
153+/*
154+ * Copyright 2013 Canonical Ltd.
155+ *
156+ * This program is free software; you can redistribute it and/or modify
157+ * it under the terms of the GNU General Public License as published by
158+ * the Free Software Foundation; version 3.
159+ *
160+ * This program is distributed in the hope that it will be useful,
161+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
162+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
163+ * GNU General Public License for more details.
164+ *
165+ * You should have received a copy of the GNU General Public License
166+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
167+ */
168+
169+import QtQuick 2.0
170+import QtQuick.Layouts 1.1
171+import SystemSettings 1.0
172+import Ubuntu.Components 0.1
173+import Ubuntu.Components.ListItems 0.1 as ListItem
174+import Ubuntu.SystemSettings.Wifi 1.0
175+import QMenuModel 0.1
176+
177+ItemPage {
178+ id: othernetwork
179+ title: i18n.tr("Other network")
180+
181+ function settingsValid() {
182+ if(networkname.length == 0) {
183+ return false;
184+ }
185+ if(securityList.selectedIndex == 0) {
186+ return true
187+ }
188+ if(securityList.selectedIndex == 1) {
189+ return password.length >= 8
190+ }
191+ // WEP
192+ return password.length === 5 ||
193+ password.length === 10 ||
194+ password.length === 13 ||
195+ password.length === 26;
196+ }
197+
198+
199+ Column {
200+ id : otherview
201+ anchors {
202+ top: parent.top
203+ left: parent.left
204+ right: parent.right
205+ }
206+
207+ ListItem.Standard {
208+ text : i18n.tr("Network name")
209+ }
210+
211+ TextField {
212+ id : networkname
213+ width: parent.width
214+ }
215+
216+ ListItem.ItemSelector {
217+ id: securityList
218+ text: i18n.tr("Security")
219+ model: [i18n.tr("None"), // index: 0
220+ i18n.tr("WPA & WPA2 Personal"), // index: 1
221+ i18n.tr("WEP"), // index: 2
222+ ]
223+ }
224+
225+ ListItem.Standard {
226+ id: passwordList
227+ visible: securityList.selectedIndex !== 0
228+ text: i18n.tr("Password")
229+ control : TextInput {
230+ }
231+ }
232+
233+ TextField {
234+ id : password
235+ visible: securityList.selectedIndex !== 0
236+ width: parent.width
237+ echoMode: passwordVisibleSwitch.checked ? TextInput.Normal : TextInput.Password
238+ }
239+
240+ ListItem.Standard {
241+ text: i18n.tr("Password visible")
242+ visible: securityList.selectedIndex !== 0
243+ id: passwordVisible
244+ control: Switch {
245+ id: passwordVisibleSwitch
246+ }
247+ }
248+ }
249+
250+ RowLayout {
251+ id: buttonRow
252+
253+ anchors {
254+ bottom: parent.bottom
255+ left: parent.left
256+ right: parent.right
257+ margins: units.gu(2)
258+ }
259+ spacing: units.gu(2)
260+
261+ Button {
262+ id: cancelButton
263+ Layout.fillWidth: true
264+ text: i18n.tr("Cancel")
265+ onClicked: {
266+ pageStack.pop()
267+ }
268+ }
269+
270+ Button {
271+ id: connectButton
272+ Layout.fillWidth: true
273+ text: i18n.tr("Connect")
274+ enabled: settingsValid()
275+ onClicked: {
276+ DbusHelper.connect(networkname.text, securityList.selectedIndex, password.text)
277+ pageStack.pop()
278+ }
279+ }
280+ }
281+}
282
283=== modified file 'plugins/wifi/PageComponent.qml'
284--- plugins/wifi/PageComponent.qml 2013-10-15 15:10:01 +0000
285+++ plugins/wifi/PageComponent.qml 2014-06-26 07:31:08 +0000
286@@ -21,14 +21,9 @@
287 import Ubuntu.SystemSettings.Wifi 1.0
288 import QMenuModel 0.1
289
290-
291-IndicatorBase {
292+ItemPage {
293 id: wifibase
294 title: i18n.tr("Wi-Fi")
295- busName: "com.canonical.indicator.network"
296- actionsObjectPath: "/com/canonical/indicator/network"
297- menuObjectPaths: {"phone_wifi_settings": "/com/canonical/indicator/network/phone_wifi_settings"}
298- active: true
299
300 UnityMenuModel {
301 id: menuModel
302@@ -39,84 +34,111 @@
303 menuStack.head = menuModel;
304 }
305 }
306-
307+ UnityMenuModelStack {
308+ id: menuStack
309+ }
310 MenuItemFactory {
311 id: menuFactory
312 model: mainMenu.model
313 }
314
315- UnityMenuModelStack {
316- id: menuStack
317+ // workaround of getting the following error on startup:
318+ // WARNING - file:///usr/..../wifi/PageComponent.qml:24:1: QML Page: Binding loop detected for property "flickable"
319+ flickable: null
320+ Component.onCompleted: {
321+ flickable = pageFlickable
322 }
323
324- ListView {
325- id: mainMenu
326- model: menuStack.tail ? menuStack.tail : null
327-
328- anchors {
329- fill: parent
330- bottomMargin: Qt.inputMethod.visible ? (Qt.inputMethod.keyboardRectangle.height - main.anchors.bottomMargin) : 0
331-
332- Behavior on bottomMargin {
333- NumberAnimation {
334- duration: 175
335- easing.type: Easing.OutQuad
336+ Flickable {
337+ id: pageFlickable
338+ anchors.fill: parent
339+
340+ contentWidth: parent.width
341+ contentHeight: contentItem.childrenRect.height
342+
343+
344+ Column {
345+ anchors {
346+ left: parent.left
347+ right: parent.right
348+ top: parent.top
349+ }
350+
351+ Repeater {
352+ id: mainMenu
353+ model: menuStack.tail ? menuStack.tail : null
354+ delegate: Item {
355+ id: menuDelegate
356+
357+ anchors {
358+ left: parent.left
359+ right: parent.right
360+ }
361+ height: loader.height
362+ visible: height > 0
363+
364+ Loader {
365+ id: loader
366+ asynchronous: true
367+
368+ property int modelIndex: index
369+
370+ anchors {
371+ left: parent.left
372+ right: parent.right
373+ }
374+
375+ sourceComponent: menuFactory.load(model)
376+
377+ onLoaded: {
378+ if (model.type === "com.canonical.indicator.root") {
379+ menuStack.push(mainMenu.model.submenu(index));
380+ }
381+
382+ if (item.hasOwnProperty("menuActivated")) {
383+ item.menuActivated = Qt.binding(function() { return ListView.isCurrentItem; });
384+ item.selectMenu.connect(function() { ListView.view.currentIndex = index });
385+ item.deselectMenu.connect(function() { ListView.view.currentIndex = -1 });
386+ }
387+ if (item.hasOwnProperty("menu")) {
388+ item.menu = Qt.binding(function() { return model; });
389+ }
390+ }
391+ }
392 }
393 }
394- // TODO - does ever frame.
395- onBottomMarginChanged: {
396- mainMenu.positionViewAtIndex(mainMenu.currentIndex, ListView.End)
397- }
398- }
399-
400- // Ensure all delegates are cached in order to improve smoothness of scrolling
401- cacheBuffer: 10000
402+
403+ ListItem.Divider {}
404+
405+ ListItem.SingleValue {
406+ text: i18n.tr("Previous networks")
407+ progression: true
408+ onClicked: pageStack.push(Qt.resolvedUrl("PreviousNetworks.qml"))
409+ }
410+
411+ ListItem.SingleValue {
412+ text: i18n.tr("Other network")
413+ progression: true
414+ onClicked: pageStack.push(Qt.resolvedUrl("OtherNetwork.qml"))
415+ }
416+ }
417+
418+ bottomMargin: Qt.inputMethod.visible ? (Qt.inputMethod.keyboardRectangle.height - main.anchors.bottomMargin) : 0
419+
420+ Behavior on bottomMargin {
421+ NumberAnimation {
422+ duration: 175
423+ easing.type: Easing.OutQuad
424+ }
425+ }
426+ // TODO - does ever frame.
427+ onBottomMarginChanged: {
428+ mainMenu.positionViewAtIndex(mainMenu.currentIndex, ListView.End)
429+ }
430
431 // Only allow flicking if the content doesn't fit on the page
432- contentHeight: contentItem.childrenRect.height
433 boundsBehavior: (contentHeight > wifibase.height) ?
434 Flickable.DragAndOvershootBounds :
435 Flickable.StopAtBounds
436-
437- currentIndex: -1
438- delegate: Item {
439- id: menuDelegate
440-
441- anchors {
442- left: parent.left
443- right: parent.right
444- }
445- height: loader.height
446- visible: height > 0
447-
448- Loader {
449- id: loader
450- asynchronous: true
451-
452- property int modelIndex: index
453-
454- anchors {
455- left: parent.left
456- right: parent.right
457- }
458-
459- sourceComponent: menuFactory.load(model)
460-
461- onLoaded: {
462- if (model.type === rootMenuType) {
463- menuStack.push(mainMenu.model.submenu(index));
464- }
465-
466- if (item.hasOwnProperty("menuActivated")) {
467- item.menuActivated = Qt.binding(function() { return ListView.isCurrentItem; });
468- item.selectMenu.connect(function() { ListView.view.currentIndex = index });
469- item.deselectMenu.connect(function() { ListView.view.currentIndex = -1 });
470- }
471- if (item.hasOwnProperty("menu")) {
472- item.menu = Qt.binding(function() { return model; });
473- }
474- }
475- }
476- }
477 }
478 }
479
480=== added file 'plugins/wifi/PreviousNetworks.qml'
481--- plugins/wifi/PreviousNetworks.qml 1970-01-01 00:00:00 +0000
482+++ plugins/wifi/PreviousNetworks.qml 2014-06-26 07:31:08 +0000
483@@ -0,0 +1,45 @@
484+/*
485+ * Copyright 2013 Canonical Ltd.
486+ *
487+ * This program is free software; you can redistribute it and/or modify
488+ * it under the terms of the GNU General Public License as published by
489+ * the Free Software Foundation; version 3.
490+ *
491+ * This program is distributed in the hope that it will be useful,
492+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
493+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
494+ * GNU General Public License for more details.
495+ *
496+ * You should have received a copy of the GNU General Public License
497+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
498+ */
499+
500+import QtQuick 2.0
501+import SystemSettings 1.0
502+import Ubuntu.Components 0.1
503+import Ubuntu.Components.ListItems 0.1 as ListItem
504+import Ubuntu.SystemSettings.Wifi 1.0
505+import QMenuModel 0.1
506+
507+ItemPage {
508+ id: othernetwork
509+ title: i18n.tr("Previous networks")
510+
511+ PreviousNetworkModel {
512+ id: pnmodel
513+ }
514+
515+ ListView {
516+ anchors.fill : parent
517+ model: pnmodel
518+ delegate: ListItem.Standard {
519+ text: name
520+ progression: true
521+ onClicked: {
522+ pageStack.push(Qt.resolvedUrl("NetworkDetails.qml"),
523+ {networkName : name, password : password, lastUsed : lastUsed,
524+ dbusPath : objectPath})
525+ }
526+ }
527+ }
528+}
529
530=== added file 'plugins/wifi/nm-manager-introspection.xml'
531--- plugins/wifi/nm-manager-introspection.xml 1970-01-01 00:00:00 +0000
532+++ plugins/wifi/nm-manager-introspection.xml 2014-06-26 07:31:08 +0000
533@@ -0,0 +1,79 @@
534+ <interface name="org.freedesktop.NetworkManager">
535+ <method name="state">
536+ <arg name="state" type="u" direction="out"/>
537+ </method>
538+ <method name="CheckConnectivity">
539+ <arg name="connectivity" type="u" direction="out"/>
540+ </method>
541+ <method name="GetLogging">
542+ <arg name="level" type="s" direction="out"/>
543+ <arg name="domains" type="s" direction="out"/>
544+ </method>
545+ <method name="SetLogging">
546+ <arg name="level" type="s" direction="in"/>
547+ <arg name="domains" type="s" direction="in"/>
548+ </method>
549+ <method name="GetPermissions">
550+ <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QMap&lt;QString, QString&gt;"/>
551+ <arg name="permissions" type="a{ss}" direction="out"/>
552+ </method>
553+ <method name="Enable">
554+ <arg name="enable" type="b" direction="in"/>
555+ </method>
556+ <method name="Sleep">
557+ <arg name="sleep" type="b" direction="in"/>
558+ </method>
559+ <method name="DeactivateConnection">
560+ <arg name="active_connection" type="o" direction="in"/>
561+ </method>
562+ <method name="AddAndActivateConnection">
563+ <annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="QMap&lt;QString, QVariantMap&gt;"/>
564+ <arg name="connection" type="a{sa{sv}}" direction="in"/>
565+ <arg name="device" type="o" direction="in"/>
566+ <arg name="specific_object" type="o" direction="in"/>
567+ <arg name="path" type="o" direction="out"/>
568+ <arg name="active_connection" type="o" direction="out"/>
569+ </method>
570+ <method name="ActivateConnection">
571+ <arg name="connection" type="o" direction="in"/>
572+ <arg name="device" type="o" direction="in"/>
573+ <arg name="specific_object" type="o" direction="in"/>
574+ <arg name="active_connection" type="o" direction="out"/>
575+ </method>
576+ <method name="GetDeviceByIpIface">
577+ <arg name="iface" type="s" direction="in"/>
578+ <arg name="device" type="o" direction="out"/>
579+ </method>
580+ <method name="GetDevices">
581+ <arg name="devices" type="ao" direction="out"/>
582+ </method>
583+ <signal name="DeviceRemoved">
584+ <arg type="o"/>
585+ </signal>
586+ <signal name="DeviceAdded">
587+ <arg type="o"/>
588+ </signal>
589+ <signal name="PropertiesChanged">
590+ <annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="QVariantMap"/>
591+ <arg type="a{sv}"/>
592+ </signal>
593+ <signal name="StateChanged">
594+ <arg type="u"/>
595+ </signal>
596+ <signal name="CheckPermissions">
597+ </signal>
598+ <property name="Connectivity" type="u" access="read"/>
599+ <property name="State" type="u" access="read"/>
600+ <property name="Version" type="s" access="read"/>
601+ <property name="ActivatingConnection" type="o" access="read"/>
602+ <property name="PrimaryConnection" type="o" access="read"/>
603+ <property name="ActiveConnections" type="ao" access="read"/>
604+ <property name="WimaxHardwareEnabled" type="b" access="read"/>
605+ <property name="WimaxEnabled" type="b" access="readwrite"/>
606+ <property name="WwanHardwareEnabled" type="b" access="read"/>
607+ <property name="WwanEnabled" type="b" access="readwrite"/>
608+ <property name="WirelessHardwareEnabled" type="b" access="read"/>
609+ <property name="WirelessEnabled" type="b" access="readwrite"/>
610+ <property name="NetworkingEnabled" type="b" access="read"/>
611+ </interface>
612+
613
614=== added file 'plugins/wifi/nm-settings-connection-introspection.xml'
615--- plugins/wifi/nm-settings-connection-introspection.xml 1970-01-01 00:00:00 +0000
616+++ plugins/wifi/nm-settings-connection-introspection.xml 2014-06-26 07:31:08 +0000
617@@ -0,0 +1,22 @@
618+ <interface name="org.freedesktop.NetworkManager.Settings.Connection">
619+ <method name="GetSecrets">
620+ <arg name="setting_name" type="s" direction="in"/>
621+ <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QMap&lt;QString, QVariantMap&gt;"/>
622+ <arg name="secrets" type="a{sa{sv}}" direction="out"/>
623+ </method>
624+ <method name="GetSettings">
625+ <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QMap&lt;QString, QVariantMap&gt;"/>
626+ <arg name="settings" type="a{sa{sv}}" direction="out"/>
627+ </method>
628+ <method name="Delete">
629+ </method>
630+ <method name="Update">
631+ <annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="QMap&lt;QString, QVariantMap&gt;"/>
632+ <arg name="properties" type="a{sa{sv}}" direction="in"/>
633+ </method>
634+ <signal name="Removed">
635+ </signal>
636+ <signal name="Updated">
637+ </signal>
638+ </interface>
639+
640
641=== added file 'plugins/wifi/nm-settings-introspection.xml'
642--- plugins/wifi/nm-settings-introspection.xml 1970-01-01 00:00:00 +0000
643+++ plugins/wifi/nm-settings-introspection.xml 2014-06-26 07:31:08 +0000
644@@ -0,0 +1,26 @@
645+ <interface name="org.freedesktop.NetworkManager.Settings">
646+ <method name="SaveHostname">
647+ <arg name="hostname" type="s" direction="in"/>
648+ </method>
649+ <method name="AddConnection">
650+ <annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="QMap&lt;QString, QVariantMap&gt;"/>
651+ <arg name="connection" type="a{sa{sv}}" direction="in"/>
652+ <arg name="path" type="o" direction="out"/>
653+ </method>
654+ <method name="GetConnectionByUuid">
655+ <arg name="uuid" type="s" direction="in"/>
656+ <arg name="connection" type="o" direction="out"/>
657+ </method>
658+ <method name="ListConnections">
659+ <arg name="connections" type="ao" direction="out"/>
660+ </method>
661+ <signal name="NewConnection">
662+ <arg type="o"/>
663+ </signal>
664+ <signal name="PropertiesChanged">
665+ <annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="QVariantMap"/>
666+ <arg type="a{sv}"/>
667+ </signal>
668+ <property name="CanModify" type="b" access="read"/>
669+ <property name="Hostname" type="s" access="read"/>
670+ </interface>
671
672=== added file 'plugins/wifi/nm_manager_proxy.h'
673--- plugins/wifi/nm_manager_proxy.h 1970-01-01 00:00:00 +0000
674+++ plugins/wifi/nm_manager_proxy.h 2014-06-26 07:31:08 +0000
675@@ -0,0 +1,207 @@
676+/*
677+ * This file was generated by qdbusxml2cpp version 0.8
678+ * Command line was: qdbusxml2cpp -N -p nm_manager_proxy.h -v nm-manager-introspection.xml
679+ *
680+ * qdbusxml2cpp is Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
681+ *
682+ * This is an auto-generated file.
683+ * Do not edit! All changes made to it will be lost.
684+ */
685+
686+#ifndef NM_MANAGER_PROXY_H_1403027877
687+#define NM_MANAGER_PROXY_H_1403027877
688+
689+#include <QtCore/QObject>
690+#include <QtCore/QByteArray>
691+#include <QtCore/QList>
692+#include <QtCore/QMap>
693+#include <QtCore/QString>
694+#include <QtCore/QStringList>
695+#include <QtCore/QVariant>
696+#include <QtDBus/QtDBus>
697+
698+/*
699+ * Proxy class for interface org.freedesktop.NetworkManager
700+ */
701+class OrgFreedesktopNetworkManagerInterface: public QDBusAbstractInterface
702+{
703+ Q_OBJECT
704+public:
705+ static inline const char *staticInterfaceName()
706+ { return "org.freedesktop.NetworkManager"; }
707+
708+public:
709+ OrgFreedesktopNetworkManagerInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0)
710+ : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent)
711+ {}
712+
713+ ~OrgFreedesktopNetworkManagerInterface()
714+ {}
715+
716+ Q_PROPERTY(QDBusObjectPath ActivatingConnection READ activatingConnection)
717+ inline QDBusObjectPath activatingConnection() const
718+ { return qvariant_cast< QDBusObjectPath >(property("ActivatingConnection")); }
719+
720+ Q_PROPERTY(QList<QDBusObjectPath> ActiveConnections READ activeConnections)
721+ inline QList<QDBusObjectPath> activeConnections() const
722+ { return qvariant_cast< QList<QDBusObjectPath> >(property("ActiveConnections")); }
723+
724+ Q_PROPERTY(uint Connectivity READ connectivity)
725+ inline uint connectivity() const
726+ { return qvariant_cast< uint >(property("Connectivity")); }
727+
728+ Q_PROPERTY(bool NetworkingEnabled READ networkingEnabled)
729+ inline bool networkingEnabled() const
730+ { return qvariant_cast< bool >(property("NetworkingEnabled")); }
731+
732+ Q_PROPERTY(QDBusObjectPath PrimaryConnection READ primaryConnection)
733+ inline QDBusObjectPath primaryConnection() const
734+ { return qvariant_cast< QDBusObjectPath >(property("PrimaryConnection")); }
735+
736+ Q_PROPERTY(uint State READ state)
737+ inline uint state() const
738+ { return qvariant_cast< uint >(property("State")); }
739+
740+ Q_PROPERTY(QString Version READ version)
741+ inline QString version() const
742+ { return qvariant_cast< QString >(property("Version")); }
743+
744+ Q_PROPERTY(bool WimaxEnabled READ wimaxEnabled WRITE setWimaxEnabled)
745+ inline bool wimaxEnabled() const
746+ { return qvariant_cast< bool >(property("WimaxEnabled")); }
747+ inline void setWimaxEnabled(bool value)
748+ { setProperty("WimaxEnabled", QVariant::fromValue(value)); }
749+
750+ Q_PROPERTY(bool WimaxHardwareEnabled READ wimaxHardwareEnabled)
751+ inline bool wimaxHardwareEnabled() const
752+ { return qvariant_cast< bool >(property("WimaxHardwareEnabled")); }
753+
754+ Q_PROPERTY(bool WirelessEnabled READ wirelessEnabled WRITE setWirelessEnabled)
755+ inline bool wirelessEnabled() const
756+ { return qvariant_cast< bool >(property("WirelessEnabled")); }
757+ inline void setWirelessEnabled(bool value)
758+ { setProperty("WirelessEnabled", QVariant::fromValue(value)); }
759+
760+ Q_PROPERTY(bool WirelessHardwareEnabled READ wirelessHardwareEnabled)
761+ inline bool wirelessHardwareEnabled() const
762+ { return qvariant_cast< bool >(property("WirelessHardwareEnabled")); }
763+
764+ Q_PROPERTY(bool WwanEnabled READ wwanEnabled WRITE setWwanEnabled)
765+ inline bool wwanEnabled() const
766+ { return qvariant_cast< bool >(property("WwanEnabled")); }
767+ inline void setWwanEnabled(bool value)
768+ { setProperty("WwanEnabled", QVariant::fromValue(value)); }
769+
770+ Q_PROPERTY(bool WwanHardwareEnabled READ wwanHardwareEnabled)
771+ inline bool wwanHardwareEnabled() const
772+ { return qvariant_cast< bool >(property("WwanHardwareEnabled")); }
773+
774+public Q_SLOTS: // METHODS
775+ inline QDBusPendingReply<QDBusObjectPath> ActivateConnection(const QDBusObjectPath &connection, const QDBusObjectPath &device, const QDBusObjectPath &specific_object)
776+ {
777+ QList<QVariant> argumentList;
778+ argumentList << QVariant::fromValue(connection) << QVariant::fromValue(device) << QVariant::fromValue(specific_object);
779+ return asyncCallWithArgumentList(QLatin1String("ActivateConnection"), argumentList);
780+ }
781+
782+ inline QDBusPendingReply<QDBusObjectPath, QDBusObjectPath> AddAndActivateConnection(const QMap<QString, QVariantMap> &connection, const QDBusObjectPath &device, const QDBusObjectPath &specific_object)
783+ {
784+ QList<QVariant> argumentList;
785+ argumentList << QVariant::fromValue(connection) << QVariant::fromValue(device) << QVariant::fromValue(specific_object);
786+ return asyncCallWithArgumentList(QLatin1String("AddAndActivateConnection"), argumentList);
787+ }
788+ inline QDBusReply<QDBusObjectPath> AddAndActivateConnection(const QMap<QString, QVariantMap> &connection, const QDBusObjectPath &device, const QDBusObjectPath &specific_object, QDBusObjectPath &active_connection)
789+ {
790+ QList<QVariant> argumentList;
791+ argumentList << QVariant::fromValue(connection) << QVariant::fromValue(device) << QVariant::fromValue(specific_object);
792+ QDBusMessage reply = callWithArgumentList(QDBus::Block, QLatin1String("AddAndActivateConnection"), argumentList);
793+ if (reply.type() == QDBusMessage::ReplyMessage && reply.arguments().count() == 2) {
794+ active_connection = qdbus_cast<QDBusObjectPath>(reply.arguments().at(1));
795+ }
796+ return reply;
797+ }
798+
799+ inline QDBusPendingReply<uint> CheckConnectivity()
800+ {
801+ QList<QVariant> argumentList;
802+ return asyncCallWithArgumentList(QLatin1String("CheckConnectivity"), argumentList);
803+ }
804+
805+ inline QDBusPendingReply<> DeactivateConnection(const QDBusObjectPath &active_connection)
806+ {
807+ QList<QVariant> argumentList;
808+ argumentList << QVariant::fromValue(active_connection);
809+ return asyncCallWithArgumentList(QLatin1String("DeactivateConnection"), argumentList);
810+ }
811+
812+ inline QDBusPendingReply<> Enable(bool enable)
813+ {
814+ QList<QVariant> argumentList;
815+ argumentList << QVariant::fromValue(enable);
816+ return asyncCallWithArgumentList(QLatin1String("Enable"), argumentList);
817+ }
818+
819+ inline QDBusPendingReply<QDBusObjectPath> GetDeviceByIpIface(const QString &iface)
820+ {
821+ QList<QVariant> argumentList;
822+ argumentList << QVariant::fromValue(iface);
823+ return asyncCallWithArgumentList(QLatin1String("GetDeviceByIpIface"), argumentList);
824+ }
825+
826+ inline QDBusPendingReply<QList<QDBusObjectPath> > GetDevices()
827+ {
828+ QList<QVariant> argumentList;
829+ return asyncCallWithArgumentList(QLatin1String("GetDevices"), argumentList);
830+ }
831+
832+ inline QDBusPendingReply<QString, QString> GetLogging()
833+ {
834+ QList<QVariant> argumentList;
835+ return asyncCallWithArgumentList(QLatin1String("GetLogging"), argumentList);
836+ }
837+ inline QDBusReply<QString> GetLogging(QString &domains)
838+ {
839+ QList<QVariant> argumentList;
840+ QDBusMessage reply = callWithArgumentList(QDBus::Block, QLatin1String("GetLogging"), argumentList);
841+ if (reply.type() == QDBusMessage::ReplyMessage && reply.arguments().count() == 2) {
842+ domains = qdbus_cast<QString>(reply.arguments().at(1));
843+ }
844+ return reply;
845+ }
846+
847+ inline QDBusPendingReply<QMap<QString, QString> > GetPermissions()
848+ {
849+ QList<QVariant> argumentList;
850+ return asyncCallWithArgumentList(QLatin1String("GetPermissions"), argumentList);
851+ }
852+
853+ inline QDBusPendingReply<> SetLogging(const QString &level, const QString &domains)
854+ {
855+ QList<QVariant> argumentList;
856+ argumentList << QVariant::fromValue(level) << QVariant::fromValue(domains);
857+ return asyncCallWithArgumentList(QLatin1String("SetLogging"), argumentList);
858+ }
859+
860+ inline QDBusPendingReply<> Sleep(bool sleep)
861+ {
862+ QList<QVariant> argumentList;
863+ argumentList << QVariant::fromValue(sleep);
864+ return asyncCallWithArgumentList(QLatin1String("Sleep"), argumentList);
865+ }
866+
867+ inline QDBusPendingReply<uint> state()
868+ {
869+ QList<QVariant> argumentList;
870+ return asyncCallWithArgumentList(QLatin1String("state"), argumentList);
871+ }
872+
873+Q_SIGNALS: // SIGNALS
874+ void CheckPermissions();
875+ void DeviceAdded(const QDBusObjectPath &in0);
876+ void DeviceRemoved(const QDBusObjectPath &in0);
877+ void PropertiesChanged(const QVariantMap &in0);
878+ void StateChanged(uint in0);
879+};
880+
881+#endif
882+
883
884=== added file 'plugins/wifi/nm_settings_connection_proxy.h'
885--- plugins/wifi/nm_settings_connection_proxy.h 1970-01-01 00:00:00 +0000
886+++ plugins/wifi/nm_settings_connection_proxy.h 2014-06-26 07:31:08 +0000
887@@ -0,0 +1,74 @@
888+/*
889+ * This file was generated by qdbusxml2cpp version 0.8
890+ * Command line was: qdbusxml2cpp -N -p nm_settings_connection_proxy.h -v nm-settings-connection-introspection.xml
891+ *
892+ * qdbusxml2cpp is Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
893+ *
894+ * This is an auto-generated file.
895+ * Do not edit! All changes made to it will be lost.
896+ */
897+
898+#ifndef NM_SETTINGS_CONNECTION_PROXY_H_1402664031
899+#define NM_SETTINGS_CONNECTION_PROXY_H_1402664031
900+
901+#include <QtCore/QObject>
902+#include <QtCore/QByteArray>
903+#include <QtCore/QList>
904+#include <QtCore/QMap>
905+#include <QtCore/QString>
906+#include <QtCore/QStringList>
907+#include <QtCore/QVariant>
908+#include <QtDBus/QtDBus>
909+
910+/*
911+ * Proxy class for interface org.freedesktop.NetworkManager.Settings.Connection
912+ */
913+class OrgFreedesktopNetworkManagerSettingsConnectionInterface: public QDBusAbstractInterface
914+{
915+ Q_OBJECT
916+public:
917+ static inline const char *staticInterfaceName()
918+ { return "org.freedesktop.NetworkManager.Settings.Connection"; }
919+
920+public:
921+ OrgFreedesktopNetworkManagerSettingsConnectionInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0)
922+ : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent)
923+ {}
924+
925+
926+ ~OrgFreedesktopNetworkManagerSettingsConnectionInterface()
927+ {}
928+
929+public Q_SLOTS: // METHODS
930+ inline QDBusPendingReply<> Delete()
931+ {
932+ QList<QVariant> argumentList;
933+ return asyncCallWithArgumentList(QLatin1String("Delete"), argumentList);
934+ }
935+
936+ inline QDBusPendingReply<QMap<QString, QVariantMap> > GetSecrets(const QString &setting_name)
937+ {
938+ QList<QVariant> argumentList;
939+ argumentList << QVariant::fromValue(setting_name);
940+ return asyncCallWithArgumentList(QLatin1String("GetSecrets"), argumentList);
941+ }
942+
943+ inline QDBusPendingReply<QMap<QString, QVariantMap> > GetSettings()
944+ {
945+ QList<QVariant> argumentList;
946+ return asyncCallWithArgumentList(QLatin1String("GetSettings"), argumentList);
947+ }
948+
949+ inline QDBusPendingReply<> Update(const QMap<QString, QVariantMap> &properties)
950+ {
951+ QList<QVariant> argumentList;
952+ argumentList << QVariant::fromValue(properties);
953+ return asyncCallWithArgumentList(QLatin1String("Update"), argumentList);
954+ }
955+
956+Q_SIGNALS: // SIGNALS
957+ void Removed();
958+ void Updated();
959+};
960+
961+#endif
962
963=== added file 'plugins/wifi/nm_settings_proxy.h'
964--- plugins/wifi/nm_settings_proxy.h 1970-01-01 00:00:00 +0000
965+++ plugins/wifi/nm_settings_proxy.h 2014-06-26 07:31:08 +0000
966@@ -0,0 +1,84 @@
967+/*
968+ * This file was generated by qdbusxml2cpp version 0.8
969+ * Command line was: qdbusxml2cpp -N -p nm_settings_proxy.h -v nm-settings-introspection.xml
970+ *
971+ * qdbusxml2cpp is Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
972+ *
973+ * This is an auto-generated file.
974+ * Do not edit! All changes made to it will be lost.
975+ */
976+
977+#ifndef NM_SETTINGS_PROXY_H_1402663916
978+#define NM_SETTINGS_PROXY_H_1402663916
979+
980+#include <QtCore/QObject>
981+#include <QtCore/QByteArray>
982+#include <QtCore/QList>
983+#include <QtCore/QMap>
984+#include <QtCore/QString>
985+#include <QtCore/QStringList>
986+#include <QtCore/QVariant>
987+#include <QtDBus/QtDBus>
988+
989+/*
990+ * Proxy class for interface org.freedesktop.NetworkManager.Settings
991+ */
992+class OrgFreedesktopNetworkManagerSettingsInterface: public QDBusAbstractInterface
993+{
994+ Q_OBJECT
995+public:
996+ static inline const char *staticInterfaceName()
997+ { return "org.freedesktop.NetworkManager.Settings"; }
998+
999+public:
1000+ OrgFreedesktopNetworkManagerSettingsInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0)
1001+ : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent)
1002+ {}
1003+
1004+ ~OrgFreedesktopNetworkManagerSettingsInterface()
1005+ {}
1006+
1007+ Q_PROPERTY(bool CanModify READ canModify)
1008+ inline bool canModify() const
1009+ { return qvariant_cast< bool >(property("CanModify")); }
1010+
1011+ Q_PROPERTY(QString Hostname READ hostname)
1012+ inline QString hostname() const
1013+ { return qvariant_cast< QString >(property("Hostname")); }
1014+
1015+public Q_SLOTS: // METHODS
1016+ inline QDBusPendingReply<QDBusObjectPath> AddConnection(const QMap<QString, QVariantMap> &connection)
1017+ {
1018+ QList<QVariant> argumentList;
1019+ argumentList << QVariant::fromValue(connection);
1020+ return asyncCallWithArgumentList(QLatin1String("AddConnection"), argumentList);
1021+ }
1022+
1023+ inline QDBusPendingReply<QDBusObjectPath> GetConnectionByUuid(const QString &uuid)
1024+ {
1025+ QList<QVariant> argumentList;
1026+ argumentList << QVariant::fromValue(uuid);
1027+ return asyncCallWithArgumentList(QLatin1String("GetConnectionByUuid"), argumentList);
1028+ }
1029+
1030+ inline QDBusPendingReply<QList<QDBusObjectPath> > ListConnections()
1031+ {
1032+ QList<QVariant> argumentList;
1033+ return asyncCallWithArgumentList(QLatin1String("ListConnections"), argumentList);
1034+ }
1035+
1036+ inline QDBusPendingReply<> SaveHostname(const QString &hostname)
1037+ {
1038+ QList<QVariant> argumentList;
1039+ argumentList << QVariant::fromValue(hostname);
1040+ return asyncCallWithArgumentList(QLatin1String("SaveHostname"), argumentList);
1041+ }
1042+
1043+Q_SIGNALS: // SIGNALS
1044+ void NewConnection(const QDBusObjectPath &in0);
1045+ void PropertiesChanged(const QVariantMap &in0);
1046+};
1047+
1048+#endif
1049+
1050+
1051
1052=== modified file 'plugins/wifi/plugin.cpp'
1053--- plugins/wifi/plugin.cpp 2013-09-13 21:50:25 +0000
1054+++ plugins/wifi/plugin.cpp 2014-06-26 07:31:08 +0000
1055@@ -19,11 +19,31 @@
1056 #include <QtQml/QQmlContext>
1057 #include "plugin.h"
1058 #include "unitymenumodelstack.h"
1059+#include "wifidbushelper.h"
1060+#include "previousnetworkmodel.h"
1061+
1062+namespace {
1063+
1064+WifiDbusHelper *s = nullptr;
1065+
1066+QObject* dbusProvider(QQmlEngine* engine, QJSEngine* /* scriptEngine */)
1067+{
1068+ // Why are we not using static WifiDbusHelper here, you ask?
1069+ // Because I'm not sure if the Qml engine tries to delete the
1070+ // pointer we return when it is shuts down.
1071+ if(!s)
1072+ s = new WifiDbusHelper(engine);
1073+ return s;
1074+}
1075+
1076+}
1077
1078 void BackendPlugin::registerTypes(const char *uri)
1079 {
1080 Q_ASSERT(uri == QLatin1String("Ubuntu.SystemSettings.Wifi"));
1081 qmlRegisterType<UnityMenuModelStack>(uri, 1, 0, "UnityMenuModelStack");
1082+ qmlRegisterSingletonType<WifiDbusHelper>(uri, 1, 0, "DbusHelper", dbusProvider);
1083+ qmlRegisterType<PreviousNetworkModel>(uri, 1, 0, "PreviousNetworkModel");
1084 }
1085
1086 void BackendPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
1087
1088=== added file 'plugins/wifi/previousnetworkmodel.cpp'
1089--- plugins/wifi/previousnetworkmodel.cpp 1970-01-01 00:00:00 +0000
1090+++ plugins/wifi/previousnetworkmodel.cpp 2014-06-26 07:31:08 +0000
1091@@ -0,0 +1,72 @@
1092+/*
1093+ * Copyright (C) 2014 Canonical, Ltd.
1094+ *
1095+ * Authors:
1096+ * Jussi Pakkanen <jussi.pakkanen@canonical.com>
1097+ *
1098+ * This program is free software: you can redistribute it and/or modify it
1099+ * under the terms of the GNU General Public License version 3, as published
1100+ * by the Free Software Foundation.
1101+ *
1102+ * This library is distributed in the hope that it will be useful, but WITHOUT
1103+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1104+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
1105+ * details.
1106+ *
1107+ * You should have received a copy of the GNU General Public License
1108+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1109+ */
1110+
1111+#include "previousnetworkmodel.h"
1112+#include "wifidbushelper.h"
1113+#include<QVariant>
1114+
1115+struct PreviousNetworkModel::Private {
1116+ QList<QStringList> data;
1117+};
1118+
1119+PreviousNetworkModel::PreviousNetworkModel(QObject *parent) : QAbstractListModel(parent) {
1120+ p = new PreviousNetworkModel::Private();
1121+
1122+ WifiDbusHelper h;
1123+ auto networks = h.getPreviouslyConnectedWifiNetworks();
1124+
1125+ p->data = networks;
1126+}
1127+
1128+PreviousNetworkModel::~PreviousNetworkModel() {
1129+ delete p;
1130+}
1131+
1132+QHash<int, QByteArray> PreviousNetworkModel::roleNames() const {
1133+ QHash<int, QByteArray> roles;
1134+ roles[NameRole] = "name";
1135+ roles[ObjectPathRole] = "objectPath";
1136+ roles[PasswordRole] = "password";
1137+ roles[LastUsedRole] = "lastUsed";
1138+ return roles;
1139+}
1140+
1141+int PreviousNetworkModel::rowCount(const QModelIndex &/*parent*/) const {
1142+ return p->data.size();
1143+}
1144+
1145+QVariant PreviousNetworkModel::data(const QModelIndex & index, int role) const {
1146+ if(!index.isValid() || index.row() >= p->data.size()) {
1147+ return QVariant();
1148+ }
1149+
1150+ const auto &row = p->data[index.row()];
1151+
1152+ switch(role) {
1153+
1154+ case NameRole : return QVariant(row[0]);
1155+ case ObjectPathRole : return QVariant(row[1]);
1156+ case PasswordRole : return QVariant(row[2]);
1157+ case LastUsedRole : return QVariant(row[3]);
1158+
1159+ default : return QVariant();
1160+
1161+ }
1162+
1163+}
1164
1165=== added file 'plugins/wifi/previousnetworkmodel.h'
1166--- plugins/wifi/previousnetworkmodel.h 1970-01-01 00:00:00 +0000
1167+++ plugins/wifi/previousnetworkmodel.h 2014-06-26 07:31:08 +0000
1168@@ -0,0 +1,47 @@
1169+/*
1170+ * Copyright (C) 2014 Canonical, Ltd.
1171+ *
1172+ * Authors:
1173+ * Jussi Pakkanen <jussi.pakkanen@canonical.com>
1174+ *
1175+ * This program is free software: you can redistribute it and/or modify it
1176+ * under the terms of the GNU General Public License version 3, as published
1177+ * by the Free Software Foundation.
1178+ *
1179+ * This library is distributed in the hope that it will be useful, but WITHOUT
1180+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1181+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
1182+ * details.
1183+ *
1184+ * You should have received a copy of the GNU General Public License
1185+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1186+ */
1187+
1188+#ifndef PREVIOUSNETWORKMODEL_H
1189+#define PREVIOUSNETWORKMODEL_H
1190+
1191+#include<QAbstractListModel>
1192+
1193+class PreviousNetworkModel : public QAbstractListModel
1194+{
1195+ Q_OBJECT
1196+public:
1197+ enum PreviousNetworkRoles {
1198+ NameRole = Qt::UserRole + 1,
1199+ ObjectPathRole,
1200+ PasswordRole,
1201+ LastUsedRole,
1202+ };
1203+
1204+ PreviousNetworkModel(QObject *parent = 0);
1205+ virtual ~PreviousNetworkModel();
1206+ QHash<int, QByteArray> roleNames() const;
1207+ int rowCount(const QModelIndex &parent) const;
1208+ QVariant data(const QModelIndex & index, int role) const;
1209+
1210+private:
1211+ struct Private;
1212+ Private *p;
1213+};
1214+
1215+#endif
1216
1217=== added file 'plugins/wifi/wifidbushelper.cpp'
1218--- plugins/wifi/wifidbushelper.cpp 1970-01-01 00:00:00 +0000
1219+++ plugins/wifi/wifidbushelper.cpp 2014-06-26 07:31:08 +0000
1220@@ -0,0 +1,318 @@
1221+/*
1222+ * Copyright (C) 2014 Canonical, Ltd.
1223+ *
1224+ * Authors:
1225+ * Jussi Pakkanen <jussi.pakkanen@canonical.com>
1226+ *
1227+ * This program is free software: you can redistribute it and/or modify it
1228+ * under the terms of the GNU General Public License version 3, as published
1229+ * by the Free Software Foundation.
1230+ *
1231+ * This library is distributed in the hope that it will be useful, but WITHOUT
1232+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1233+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
1234+ * details.
1235+ *
1236+ * You should have received a copy of the GNU General Public License
1237+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1238+ */
1239+
1240+#include "wifidbushelper.h"
1241+#include <QStringList>
1242+#include <QDBusReply>
1243+#include <QtDebug>
1244+#include <QDBusInterface>
1245+#include <algorithm>
1246+
1247+#include "nm_manager_proxy.h"
1248+#include "nm_settings_proxy.h"
1249+#include "nm_settings_connection_proxy.h"
1250+
1251+typedef QMap<QString,QVariantMap> ConfigurationData;
1252+Q_DECLARE_METATYPE(ConfigurationData)
1253+
1254+WifiDbusHelper::WifiDbusHelper(QObject *parent) : QObject(parent)
1255+{
1256+ qDBusRegisterMetaType<ConfigurationData>();
1257+}
1258+
1259+void WifiDbusHelper::connect(QString ssid, int security, QString password)
1260+{
1261+ if(security<0 || security>2) {
1262+ qWarning() << "Qml and C++ have gotten out of sync. Can't connect.\n";
1263+ return;
1264+ }
1265+
1266+ OrgFreedesktopNetworkManagerInterface mgr("org.freedesktop.NetworkManager",
1267+ "/org/freedesktop/NetworkManager",
1268+ QDBusConnection::systemBus());
1269+
1270+ QMap<QString, QVariantMap> configuration;
1271+
1272+ QVariantMap connection;
1273+ connection["type"] = QStringLiteral("802-11-wireless");
1274+ configuration["connection"] = connection;
1275+
1276+ QVariantMap wireless;
1277+ wireless["ssid"] = ssid.toLatin1();
1278+
1279+ // security:
1280+ // 0: None
1281+ // 1: WPA & WPA2 Personal
1282+ // 2: WEP
1283+ if (security != 0) {
1284+ wireless["security"] = QStringLiteral("802-11-wireless-security");
1285+
1286+ QVariantMap wireless_security;
1287+
1288+ if (security == 1) {
1289+ wireless_security["key-mgmt"] = QStringLiteral("wpa-psk");
1290+ wireless_security["psk"] = password;
1291+ } else if (security == 2) {
1292+ wireless_security["key-mgmt"] = QStringLiteral("none");
1293+ wireless_security["auth-alg"] = QStringLiteral("open");
1294+ wireless_security["wep-key0"] = password;
1295+ wireless_security["wep-key-type"] = QVariant(uint(1));
1296+ }
1297+ configuration["802-11-wireless-security"] = wireless_security;
1298+ }
1299+
1300+ configuration["802-11-wireless"] = wireless;
1301+
1302+
1303+ // find the first wlan adapter for now
1304+ auto reply1 = mgr.GetDevices();
1305+ reply1.waitForFinished();
1306+ if(!reply1.isValid()) {
1307+ qWarning() << "Could not get network device: " << reply1.error().message() << "\n";
1308+ return;
1309+ }
1310+ auto devices = reply1.value();
1311+
1312+ QDBusObjectPath dev;
1313+ for (const auto &d : devices) {
1314+ QDBusInterface iface("org.freedesktop.NetworkManager",
1315+ d.path(),
1316+ "org.freedesktop.NetworkManager.Device",
1317+ QDBusConnection::systemBus());
1318+
1319+ auto type_v = iface.property("DeviceType");
1320+ if (type_v.toUInt() == 2 /* NM_DEVICE_TYPE_WIFI */) {
1321+ dev = d;
1322+ break;
1323+ }
1324+ }
1325+
1326+ if (dev.path().isEmpty()) {
1327+ // didn't find a wifi device
1328+ return;
1329+ }
1330+
1331+ QDBusObjectPath tmp;
1332+ auto reply2 = mgr.AddAndActivateConnection(configuration,
1333+ dev,
1334+ QDBusObjectPath("/"),
1335+ tmp);
1336+}
1337+
1338+struct Network : public QObject
1339+{
1340+ struct DontCare : public std::exception {};
1341+
1342+ QString id;
1343+
1344+ enum class Mode {
1345+ infrastructure,
1346+ adhoc,
1347+ unknown
1348+ };
1349+ Mode mode;
1350+
1351+ enum class Type {
1352+ wireless,
1353+ other
1354+ };
1355+ Type type;
1356+
1357+ qulonglong timestamp;
1358+
1359+ bool isValid;
1360+ QString path;
1361+
1362+ enum class Security
1363+ {
1364+ open,
1365+ secured
1366+ };
1367+ Security security;
1368+ QString password;
1369+
1370+ void parseConnection()
1371+ {
1372+ if (!settings.contains("connection"))
1373+ throw DontCare();
1374+
1375+ auto connection = settings["connection"];
1376+ id = connection["id"].toString();
1377+
1378+ // we only care about wifi
1379+ auto type_str = connection["type"].toString();
1380+ if (type_str != "802-11-wireless")
1381+ throw DontCare();
1382+ type = Type::wireless;
1383+
1384+ auto match = connection.find("timestamp");
1385+ if (match == connection.end()) {
1386+ timestamp = 0;
1387+ } else {
1388+ timestamp = (*match).toULongLong();
1389+ }
1390+ }
1391+
1392+ void parseWireless()
1393+ {
1394+ if (!settings.contains("802-11-wireless"))
1395+ throw DontCare();
1396+
1397+ auto wireless = settings["802-11-wireless"];
1398+
1399+ auto mode_str = wireless["mode"];
1400+ if (mode_str == "infrastructure")
1401+ mode = Mode::infrastructure;
1402+ else if (mode_str == "adhoc")
1403+ mode = Mode::adhoc;
1404+ else
1405+ mode = Mode::unknown;
1406+
1407+ auto match = wireless.find("security");
1408+ if (match != wireless.end())
1409+ {
1410+ auto security_str = *match;
1411+ if (security_str != "802-11-wireless-security")
1412+ throw DontCare();
1413+ security = Security::secured;
1414+ parseWirelessSecurity();
1415+ } else {
1416+ security = Security::open;
1417+ }
1418+ }
1419+
1420+ void parseWirelessSecurity()
1421+ {
1422+ if (!settings.contains("802-11-wireless-security"))
1423+ return;
1424+
1425+ auto security = settings["802-11-wireless-security"];
1426+ auto keymgmt = security["key-mgmt"];
1427+ auto authalg = security["auth-alg"];
1428+
1429+ // If the connection has never been activated succesfully there is a
1430+ // high chance that it has no stored secrects.
1431+ if (timestamp != 0) {
1432+ auto reply = m_iface.GetSecrets("802-11-wireless-security");
1433+ reply.waitForFinished();
1434+ if(!reply.isValid()) {
1435+ qWarning() << "Error querying secrects: " << reply.error().message() << "\n";
1436+ return;
1437+ }
1438+ auto secrects = reply.value();
1439+
1440+ auto match = secrects.find("802-11-wireless-security");
1441+ if (match != secrects.end()) {
1442+ auto secrects_security = *match;
1443+
1444+ if (keymgmt == "none") {
1445+ password = secrects_security["wep-key0"].toString();
1446+ } else if (keymgmt == "wpa-psk" && authalg == "open") {
1447+ password = secrects_security["psk"].toString();
1448+ } else {
1449+ }
1450+ }
1451+ }
1452+ }
1453+
1454+ Network() = delete;
1455+ Network(QString path)
1456+ : path{path},
1457+ m_iface("org.freedesktop.NetworkManager",
1458+ path,
1459+ QDBusConnection::systemBus())
1460+ {
1461+ auto reply = m_iface.GetSettings();
1462+ reply.waitForFinished();
1463+ if(!reply.isValid()) {
1464+ qWarning() << "Error getting network info: " << reply.error().message() << "\n";
1465+ throw DontCare();
1466+ }
1467+ settings = reply.value();
1468+
1469+ try {
1470+ parseConnection();
1471+ } catch (const DontCare &) {
1472+ qDebug() << "Ignoring a network based on connection block.\n";
1473+ throw;
1474+ }
1475+
1476+ if (type == Type::wireless) {
1477+ try {
1478+ parseWireless();
1479+ } catch (const DontCare &) {
1480+ qDebug() << "Ignoring a network based on wireless block. " << qPrintable(m_iface.path()) << "\n";
1481+ throw;
1482+ }
1483+ }
1484+ }
1485+
1486+ OrgFreedesktopNetworkManagerSettingsConnectionInterface m_iface;
1487+ QMap<QString, QVariantMap> settings;
1488+};
1489+
1490+QList<QStringList> WifiDbusHelper::getPreviouslyConnectedWifiNetworks() {
1491+ QList<QStringList> networks;
1492+
1493+ OrgFreedesktopNetworkManagerSettingsInterface foo
1494+ ("org.freedesktop.NetworkManager",
1495+ "/org/freedesktop/NetworkManager/Settings",
1496+ QDBusConnection::systemBus());
1497+ auto reply = foo.ListConnections();
1498+ reply.waitForFinished();
1499+ if (reply.isValid()) {
1500+ for(const auto &c: reply.value()) {
1501+ try {
1502+ Network network(c.path());
1503+ QStringList tmp;
1504+ tmp.push_back(network.id);
1505+ tmp.push_back(network.path);
1506+ tmp.push_back(network.password);
1507+ QString lastConnected = "";
1508+ QLocale locale;
1509+ if (network.timestamp != 0) {
1510+ lastConnected = locale.toString(QDateTime::fromMSecsSinceEpoch(network.timestamp*1000), locale.dateFormat());
1511+ }
1512+ tmp.push_back(lastConnected);
1513+ networks.push_back(tmp);
1514+ } catch (const Network::DontCare &) {
1515+ continue;
1516+ }
1517+ }
1518+ } else {
1519+ qWarning() << "ERROR " << reply.error().message() << "\n";
1520+ }
1521+
1522+ std::sort(networks.begin(), networks.end(), [](const QStringList &a, const QStringList &b){
1523+ return a[0].toLower() < b[0].toLower();
1524+ });
1525+ return networks;
1526+}
1527+
1528+void WifiDbusHelper::forgetConnection(const QString dbus_path) {
1529+ OrgFreedesktopNetworkManagerSettingsConnectionInterface bar
1530+ ("org.freedesktop.NetworkManager",
1531+ dbus_path,
1532+ QDBusConnection::systemBus());
1533+ auto reply = bar.Delete();
1534+ reply.waitForFinished();
1535+ if(!reply.isValid()) {
1536+ qWarning() << "Error forgetting network: " << reply.error().message() << "\n";
1537+ }
1538+}
1539
1540=== added file 'plugins/wifi/wifidbushelper.h'
1541--- plugins/wifi/wifidbushelper.h 1970-01-01 00:00:00 +0000
1542+++ plugins/wifi/wifidbushelper.h 2014-06-26 07:31:08 +0000
1543@@ -0,0 +1,43 @@
1544+/*
1545+ * Copyright (C) 2014 Canonical, Ltd.
1546+ *
1547+ * Authors:
1548+ * Jussi Pakkanen <jussi.pakkanen@canonical.com>
1549+ *
1550+ * This program is free software: you can redistribute it and/or modify it
1551+ * under the terms of the GNU General Public License version 3, as published
1552+ * by the Free Software Foundation.
1553+ *
1554+ * This library is distributed in the hope that it will be useful, but WITHOUT
1555+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1556+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
1557+ * details.
1558+ *
1559+ * You should have received a copy of the GNU General Public License
1560+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1561+ */
1562+
1563+#ifndef WIFI_DBUS_HELPER
1564+#define WIFI_DBUS_HELPER
1565+
1566+#include <QObject>
1567+
1568+/**
1569+ * For sending specific dbus messages from QML.
1570+ */
1571+
1572+class WifiDbusHelper final : public QObject {
1573+ Q_OBJECT
1574+
1575+public:
1576+ WifiDbusHelper(QObject *parent = nullptr);
1577+ ~WifiDbusHelper() {};
1578+
1579+ Q_INVOKABLE void connect(QString ssid, int security, QString password);
1580+ Q_INVOKABLE QList<QStringList> getPreviouslyConnectedWifiNetworks();
1581+ Q_INVOKABLE void forgetConnection(const QString dbus_path);
1582+
1583+};
1584+
1585+
1586+#endif

Subscribers

People subscribed via source and target branches