Merge lp:~unity-api-team/ubuntu-system-settings/morenetworks into lp:ubuntu-system-settings
- morenetworks
- Merge into trunk
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 |
Related bugs: |
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.
Brendan Donegan (brendan-donegan) wrote : | # |
- 750. By Antti Kaijanmäki
-
Revert any Hotspot related changes.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:749
http://
Executed test runs:
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:750
http://
Executed test runs:
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
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.
- 751. By Antti Kaijanmäki
-
Fix PageComponent flickable.
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.
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.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:751
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
- 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.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:752
http://
Executed test runs:
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:753
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
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.
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.
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.
Brendan Donegan (brendan-donegan) wrote : | # |
Thanks - I'll report bugs for these issues and they can be taken care of as appropriate. Otherwise, +1
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 libUbuntuWifiPa
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.
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.
and
// intentionally left blank
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.
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-
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. ;-)
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:754
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
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:/
Charles Kerr (charlesk) wrote : | # |
The formal report as per <https:/
> * 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.
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
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<QString, QString>"/> |
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<QString, QVariantMap>"/> |
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<QString, QVariantMap>"/> |
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<QString, QVariantMap>"/> |
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<QString, QVariantMap>"/> |
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<QString, QVariantMap>"/> |
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 |
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.