Merge lp:~ken-vandine/ubuntu-system-settings/rtm-1388044 into lp:ubuntu-system-settings/rtm-14.09
- rtm-1388044
- Merge into rtm-14.09
Proposed by
Ken VanDine
Status: | Merged |
---|---|
Approved by: | Jonas G. Drange |
Approved revision: | 951 |
Merged at revision: | 967 |
Proposed branch: | lp:~ken-vandine/ubuntu-system-settings/rtm-1388044 |
Merge into: | lp:ubuntu-system-settings/rtm-14.09 |
Diff against target: |
987 lines (+495/-272) 9 files modified
plugins/cellular/CMakeLists.txt (+3/-1) plugins/cellular/Components/MultiSim.qml (+3/-2) plugins/cellular/Components/RadioSingleSim.qml (+5/-5) plugins/cellular/Components/SingleSim.qml (+18/-24) plugins/cellular/PageCarrierAndApn.qml (+67/-0) plugins/cellular/PageCarriersAndApns.qml (+41/-20) plugins/cellular/PageChooseCarrier.qml (+201/-179) plugins/cellular/carriers.js (+106/-0) tests/autopilot/ubuntu_system_settings/__init__.py (+51/-41) |
To merge this branch: | bzr merge lp:~ken-vandine/ubuntu-system-settings/rtm-1388044 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Jonas G. Drange (community) | Approve | ||
PS Jenkins bot | continuous-integration | Approve | |
Review via email: mp+244878@code.launchpad.net |
Commit message
[cellular/carriers] new Carrier & APN entry, as well as a major refactor of carrier selection code warranted by the design change.
Description of the change
[cellular/carriers] new Carrier & APN entry, as well as a major refactor of carrier selection code warranted by the design change.
To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : | # |
review:
Approve
(continuous-integration)
Revision history for this message
Jonas G. Drange (jonas-drange) wrote : | # |
Thanks, Ken!
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'plugins/cellular/CMakeLists.txt' |
2 | --- plugins/cellular/CMakeLists.txt 2014-08-27 09:17:50 +0000 |
3 | +++ plugins/cellular/CMakeLists.txt 2014-12-16 16:24:38 +0000 |
4 | @@ -4,10 +4,12 @@ |
5 | install(FILES settings-cellular.svg DESTINATION ${PLUGIN_MANIFEST_DIR}/icons) |
6 | |
7 | set(QML_SOURCES |
8 | + carriers.js |
9 | CustomApnEditor.qml |
10 | PageChooseApn.qml |
11 | PageChooseCarrier.qml |
12 | - PageChooseCarriers.qml |
13 | + PageCarrierAndApn.qml |
14 | + PageCarriersAndApns.qml |
15 | PageComponent.qml |
16 | Hotspot.qml |
17 | HotspotSetup.qml |
18 | |
19 | === modified file 'plugins/cellular/Components/MultiSim.qml' |
20 | --- plugins/cellular/Components/MultiSim.qml 2014-12-08 16:01:29 +0000 |
21 | +++ plugins/cellular/Components/MultiSim.qml 2014-12-16 16:24:38 +0000 |
22 | @@ -43,6 +43,7 @@ |
23 | anchors { left: parent.left; right: parent.right } |
24 | } |
25 | |
26 | + |
27 | ListItem.SingleValue { |
28 | text : i18n.tr("Hotspot disabled because Wi-Fi is off.") |
29 | visible: showAllUI && !hotspotItem.visible |
30 | @@ -70,11 +71,11 @@ |
31 | ListItem.SingleValue { |
32 | text: i18n.tr("Carriers") |
33 | id: chooseCarrier |
34 | - objectName: "carriers" |
35 | + objectName: "carrierApnEntry" |
36 | progression: enabled |
37 | showDivider: false |
38 | onClicked: { |
39 | - pageStack.push(Qt.resolvedUrl("../PageChooseCarriers.qml"), { |
40 | + pageStack.push(Qt.resolvedUrl("../PageCarriersAndApns.qml"), { |
41 | sims: sims |
42 | }); |
43 | } |
44 | |
45 | === modified file 'plugins/cellular/Components/RadioSingleSim.qml' |
46 | --- plugins/cellular/Components/RadioSingleSim.qml 2014-11-18 20:13:35 +0000 |
47 | +++ plugins/cellular/Components/RadioSingleSim.qml 2014-12-16 16:24:38 +0000 |
48 | @@ -24,7 +24,7 @@ |
49 | Column { |
50 | height: childrenRect.height |
51 | |
52 | - property alias selector: selector |
53 | + property bool enabled: sim.radioSettings.technologyPreference !== "" |
54 | |
55 | ListItem.ItemSelector { |
56 | id: selector |
57 | @@ -34,8 +34,8 @@ |
58 | |
59 | // an empty string is not a valid preference, which means |
60 | // we disregard the interace and disable the selector |
61 | - enabled: sim.radioSettings.technologyPreference !== "" |
62 | - model: sim.radioSettings.modemTechnologies |
63 | + enabled: parent.enabled |
64 | + model: sim.radioSettings.modemTechnologies || [] |
65 | |
66 | delegate: OptionSelectorDelegate { |
67 | objectName: sim.path + "_radio_" + modelData |
68 | @@ -48,10 +48,10 @@ |
69 | } |
70 | showDivider: false |
71 | } |
72 | - selectedIndex: model.indexOf(sim.radioSettings.technologyPreference) |
73 | + selectedIndex: model.length ? |
74 | + model.indexOf(sim.radioSettings.technologyPreference) : -1 |
75 | onDelegateClicked: { |
76 | sim.radioSettings.technologyPreference = model[index]; |
77 | } |
78 | } |
79 | - |
80 | } |
81 | |
82 | === modified file 'plugins/cellular/Components/SingleSim.qml' |
83 | --- plugins/cellular/Components/SingleSim.qml 2014-11-18 20:13:35 +0000 |
84 | +++ plugins/cellular/Components/SingleSim.qml 2014-12-16 16:24:38 +0000 |
85 | @@ -18,6 +18,7 @@ |
86 | * |
87 | */ |
88 | import QtQuick 2.0 |
89 | +import SystemSettings 1.0 |
90 | import Ubuntu.Components 0.1 |
91 | import Ubuntu.Components.ListItems 0.1 as ListItem |
92 | |
93 | @@ -33,8 +34,10 @@ |
94 | control: Switch { |
95 | id: dataControl |
96 | objectName: 'data' |
97 | - checked: sim.connMan.powered |
98 | - onClicked: sim.connMan.powered = checked |
99 | + property bool serverChecked: sim.connMan.powered |
100 | + onServerCheckedChanged: checked = serverChecked |
101 | + Component.onCompleted: checked = serverChecked |
102 | + onTriggered: sim.connMan.powered = checked |
103 | } |
104 | } |
105 | |
106 | @@ -46,8 +49,10 @@ |
107 | control: Switch { |
108 | id: dataRoamingControl |
109 | objectName: "roaming" |
110 | - checked: sim.connMan.roamingAllowed |
111 | - onClicked: sim.connMan.roamingAllowed = checked |
112 | + property bool serverChecked: sim.connMan.roamingAllowed |
113 | + onServerCheckedChanged: checked = serverChecked |
114 | + Component.onCompleted: checked = serverChecked |
115 | + onTriggered: sim.connMan.roamingAllowed = checked |
116 | } |
117 | } |
118 | |
119 | @@ -72,36 +77,25 @@ |
120 | visible: showAllUI |
121 | } |
122 | |
123 | - ListItem.Divider { |
124 | - visible: radio.selector.model.length |
125 | + ListItem.Divider { |
126 | + visible: radio.visible |
127 | } |
128 | |
129 | RadioSingleSim { |
130 | id: radio |
131 | - anchors { left: parent.left; right: parent.right } |
132 | - visible: radio.selector.model.length |
133 | + anchors { left: parent.left; right: parent.right } |
134 | + visible: radio.enabled |
135 | } |
136 | |
137 | - ListItem.Divider {} |
138 | + ListItem.Divider {} |
139 | |
140 | ListItem.SingleValue { |
141 | text: i18n.tr("Carrier"); |
142 | id: chooseCarrier |
143 | - objectName: "carrier" |
144 | + objectName: "carrierApnEntry" |
145 | progression: enabled |
146 | - value: sim.netReg.name || i18n.tr("N/A") |
147 | - enabled: sim.netReg.status !== "" |
148 | - onClicked: { |
149 | - pageStack.push(Qt.resolvedUrl("../PageChooseCarrier.qml"), { |
150 | - sim: sim, |
151 | - title: i18n.tr("Carrier") |
152 | - }) |
153 | - } |
154 | - } |
155 | - |
156 | - ListItem.Standard { |
157 | - text: i18n.tr("APN") |
158 | - progression: true |
159 | - visible: showAllUI |
160 | + onClicked: pageStack.push(Qt.resolvedUrl("../PageCarrierAndApn.qml"), { |
161 | + sim: sim |
162 | + }) |
163 | } |
164 | } |
165 | |
166 | === added file 'plugins/cellular/PageCarrierAndApn.qml' |
167 | --- plugins/cellular/PageCarrierAndApn.qml 1970-01-01 00:00:00 +0000 |
168 | +++ plugins/cellular/PageCarrierAndApn.qml 2014-12-16 16:24:38 +0000 |
169 | @@ -0,0 +1,67 @@ |
170 | +/* |
171 | + * Copyright (C) 2014 Canonical Ltd |
172 | + * |
173 | + * This program is free software: you can redistribute it and/or modify |
174 | + * it under the terms of the GNU General Public License version 3 as |
175 | + * published by the Free Software Foundation. |
176 | + * |
177 | + * This program is distributed in the hope that it will be useful, |
178 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
179 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
180 | + * GNU General Public License for more details. |
181 | + * |
182 | + * You should have received a copy of the GNU General Public License |
183 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
184 | + * |
185 | + * Authors: |
186 | + * Jonas G. Drange <jonas.drange@canonical.com> |
187 | + * |
188 | +*/ |
189 | +import QtQuick 2.0 |
190 | +import SystemSettings 1.0 |
191 | +import Ubuntu.Components 0.1 |
192 | +import Ubuntu.Components.ListItems 0.1 as ListItem |
193 | + |
194 | +ItemPage { |
195 | + id: root |
196 | + title: i18n.tr("Carrier") |
197 | + objectName: "carrierApnPage" |
198 | + flickable: null |
199 | + |
200 | + property var sim |
201 | + |
202 | + Flickable { |
203 | + anchors.fill: parent |
204 | + contentWidth: parent.width |
205 | + contentHeight: contentItem.childrenRect.height |
206 | + boundsBehavior: (contentHeight > root.height) ? Flickable.DragAndOvershootBounds : Flickable.StopAtBounds |
207 | + |
208 | + Column { |
209 | + anchors.left: parent.left |
210 | + anchors.right: parent.right |
211 | + |
212 | + ListItem.SingleValue { |
213 | + text: i18n.tr("Carrier") |
214 | + objectName: "carrier" |
215 | + value: sim.netReg.name ? sim.netReg.name : i18n.tr("None") |
216 | + enabled: (sim.netReg.status !== "") && |
217 | + (sim.netReg.mode !== "auto-only") |
218 | + progression: enabled |
219 | + onClicked: pageStack.push(Qt.resolvedUrl("PageChooseCarrier.qml"), { |
220 | + sim: sim, |
221 | + title: i18n.tr("Carrier") |
222 | + }) |
223 | + } |
224 | + |
225 | + ListItem.Standard { |
226 | + text: i18n.tr("APN") |
227 | + objectName: "apn" |
228 | + progression: enabled |
229 | + enabled: sim.connMan.powered |
230 | + onClicked: pageStack.push(Qt.resolvedUrl("PageChooseApn.qml"), { |
231 | + sim: sim |
232 | + }) |
233 | + } |
234 | + } |
235 | + } |
236 | +} |
237 | |
238 | === renamed file 'plugins/cellular/PageChooseCarriers.qml' => 'plugins/cellular/PageCarriersAndApns.qml' |
239 | --- plugins/cellular/PageChooseCarriers.qml 2014-11-18 20:13:35 +0000 |
240 | +++ plugins/cellular/PageCarriersAndApns.qml 2014-12-16 16:24:38 +0000 |
241 | @@ -25,7 +25,8 @@ |
242 | ItemPage { |
243 | id: root |
244 | title: i18n.tr("Carriers") |
245 | - objectName: "chooseCarriersPage" |
246 | + objectName: "carrierApnPage" |
247 | + flickable: null |
248 | |
249 | property var sims |
250 | |
251 | @@ -39,38 +40,58 @@ |
252 | anchors.left: parent.left |
253 | anchors.right: parent.right |
254 | |
255 | - ListItem.Standard { |
256 | + SettingsItemTitle { |
257 | text: sims[0].title |
258 | } |
259 | |
260 | ListItem.SingleValue { |
261 | + text: i18n.tr("Carrier") |
262 | objectName: sims[0].path + "_carriers" |
263 | - value: sims[0].netReg.name ? sims[0].netReg.name : i18n.tr("N/A") |
264 | - enabled: sims[0].netReg.status !== "" |
265 | - progression: true |
266 | - onClicked: { |
267 | - pageStack.push(Qt.resolvedUrl("PageChooseCarrier.qml"), { |
268 | - sim: sims[0], |
269 | - title: sims[0].title |
270 | - }) |
271 | - } |
272 | + value: sims[0].netReg.name ? sims[0].netReg.name : |
273 | + i18n.tr("None") |
274 | + enabled: (sims[0].netReg.status !== "") && |
275 | + (sims[0].netReg.mode !== "auto-only") |
276 | + progression: enabled |
277 | + onClicked: pageStack.push(Qt.resolvedUrl("PageChooseCarrier.qml"), { |
278 | + sim: sims[0], |
279 | + title: sims[0].title |
280 | + }) |
281 | } |
282 | |
283 | ListItem.Standard { |
284 | + text: i18n.tr("APN") |
285 | + progression: enabled |
286 | + enabled: sims[0].connMan.powered |
287 | + onClicked: pageStack.push(Qt.resolvedUrl("PageChooseApn.qml"), { |
288 | + sim: sims[0] |
289 | + }) |
290 | + } |
291 | + |
292 | + SettingsItemTitle { |
293 | text: sims[1].title |
294 | } |
295 | |
296 | ListItem.SingleValue { |
297 | + text: i18n.tr("Carrier") |
298 | objectName: sims[1].path + "_carriers" |
299 | - value: sims[1].netReg.name ? sims[1].netReg.name : i18n.tr("N/A") |
300 | - enabled: sims[1].netReg.status !== "" |
301 | - progression: true |
302 | - onClicked: { |
303 | - pageStack.push(Qt.resolvedUrl("PageChooseCarrier.qml"), { |
304 | - sim: sims[1], |
305 | - title: sims[1].title |
306 | - }) |
307 | - } |
308 | + value: sims[1].netReg.name ? sims[1].netReg.name : |
309 | + i18n.tr("None") |
310 | + enabled: (sims[1].netReg.status !== "") && |
311 | + (sims[1].netReg.mode !== "auto-only") |
312 | + progression: enabled |
313 | + onClicked: pageStack.push(Qt.resolvedUrl("PageChooseCarrier.qml"), { |
314 | + sim: sims[1], |
315 | + title: sims[1].title |
316 | + }) |
317 | + } |
318 | + |
319 | + ListItem.Standard { |
320 | + text: i18n.tr("APN") |
321 | + progression: enabled |
322 | + enabled: sims[1].connMan.powered |
323 | + onClicked: pageStack.push(Qt.resolvedUrl("PageChooseApn.qml"), { |
324 | + sim: sims[1] |
325 | + }) |
326 | } |
327 | } |
328 | } |
329 | |
330 | === modified file 'plugins/cellular/PageChooseCarrier.qml' |
331 | --- plugins/cellular/PageChooseCarrier.qml 2014-11-18 20:13:35 +0000 |
332 | +++ plugins/cellular/PageChooseCarrier.qml 2014-12-16 16:24:38 +0000 |
333 | @@ -4,6 +4,7 @@ |
334 | * Copyright (C) 2013 Canonical Ltd. |
335 | * |
336 | * Contact: Iain Lane <iain.lane@canonical.com> |
337 | + * Jonas G. Drange <jonas.drange@canonical.com> |
338 | * |
339 | * This program is free software: you can redistribute it and/or modify it |
340 | * under the terms of the GNU General Public License version 3, as published |
341 | @@ -24,214 +25,235 @@ |
342 | import Ubuntu.Components 1.1 |
343 | import Ubuntu.Components.ListItems 1.0 as ListItem |
344 | import MeeGo.QOfono 0.2 |
345 | +import "carriers.js" as CHelper |
346 | |
347 | ItemPage { |
348 | id: root |
349 | title: i18n.tr("Carrier") |
350 | - |
351 | objectName: "chooseCarrierPage" |
352 | + flickable: null |
353 | |
354 | property var sim |
355 | - |
356 | - property variant operatorNames |
357 | - property int mode |
358 | - |
359 | - QtObject { |
360 | - id: d |
361 | - property bool __suppressActivation : true; |
362 | - } |
363 | - |
364 | - Component.onCompleted: { |
365 | - updateNetworkOperators(); |
366 | - } |
367 | - |
368 | - Connections { |
369 | - target: sim.netReg |
370 | - onNetworkOperatorsChanged: updateNetworkOperators(); |
371 | - onCurrentOperatorPathChanged: buildLists(); |
372 | - } |
373 | - |
374 | - // map of operatorPath : netOp |
375 | - property var operators: ({}) |
376 | - function updateNetworkOperators() |
377 | - { |
378 | - var tmp = sim.netReg.networkOperators; |
379 | - var added = tmp.filter(function(i) { |
380 | - return operators[i] === undefined; |
381 | - }); |
382 | - var removed = Object.keys(operators).filter(function(i) { |
383 | - return tmp.indexOf(i) === -1; |
384 | - }) |
385 | - |
386 | - removed.forEach(function(currentValue, index, array) { |
387 | - // just asserting to verify the logic |
388 | - // remove once proven functional |
389 | - if (operators[currentValue] === undefined) { |
390 | - throw "updateNetworkOperators: removed is broken"; |
391 | - } |
392 | - |
393 | - operators[currentValue].destroy(); |
394 | - delete operators[currentValue]; |
395 | - }); |
396 | - |
397 | - added.forEach(function(currentValue, index, array) { |
398 | - // just asserting to verify the logic |
399 | - // remove once proven functional |
400 | - if (operators[currentValue] !== undefined) { |
401 | - throw "updateNetworkOperators: added is broken"; |
402 | - } |
403 | - |
404 | - operators[currentValue] = netOp.createObject(parent, |
405 | - { |
406 | - "operatorPath": currentValue |
407 | - }); |
408 | - }); |
409 | - |
410 | - // just asserting to verify the logic |
411 | - // remove once proven functional |
412 | - if (Object.keys(operators).length !== tmp.length) { |
413 | - throw "Object.keys(operators).length !== tmp.length"; |
414 | - } |
415 | - tmp.forEach(function(currentValue, index, array) { |
416 | - if (operators[currentValue] === undefined) |
417 | - throw "operators[currentValue] === undefined"; |
418 | - }); |
419 | - |
420 | - buildLists(); |
421 | - } |
422 | - |
423 | - function buildLists() |
424 | - { |
425 | - d.__suppressActivation = true; |
426 | - var oN = new Array(); |
427 | - |
428 | - for (var i in operators) { |
429 | - var tempOp = operators[i]; |
430 | - if (tempOp.status === "forbidden") |
431 | - continue |
432 | - oN.push(tempOp.name); |
433 | - } |
434 | - operatorNames = oN; |
435 | - |
436 | - var cur = operators[sim.netReg.currentOperatorPath]; |
437 | - carrierSelector.selectedIndex = cur === undefined ? -1 : operatorNames.indexOf(cur.name); |
438 | - d.__suppressActivation = false; |
439 | - } |
440 | + property bool scanning: true |
441 | + property bool working: false |
442 | + |
443 | + states: [ |
444 | + State { |
445 | + name: "auto" |
446 | + when: sim.netReg.mode === "auto" |
447 | + PropertyChanges { |
448 | + target: otherOperators |
449 | + selectedIndex: -1 |
450 | + } |
451 | + PropertyChanges { |
452 | + target: allOperators |
453 | + height: 0 |
454 | + opacity: 0 |
455 | + } |
456 | + }, |
457 | + State { |
458 | + name: "manual" |
459 | + when: sim.netReg.mode === "manual" |
460 | + PropertyChanges { |
461 | + target: otherOperators |
462 | + height: 0 |
463 | + opacity: 0 |
464 | + } |
465 | + } |
466 | + /* Note that we do not consider auto-only since this page is not |
467 | + reachable in that case (see Carrier & APN page). */ |
468 | + ] |
469 | |
470 | Component { |
471 | id: netOp |
472 | OfonoNetworkOperator { |
473 | onRegisterComplete: { |
474 | - if (error === OfonoNetworkOperator.InProgressError) { |
475 | - console.warn("registerComplete failed with error: " + errorString); |
476 | - } else if (error !== OfonoNetworkOperator.NoError) { |
477 | - console.warn("registerComplete failed with error: " + errorString + " Falling back to default"); |
478 | + if (error !== OfonoNetworkOperator.NoError) { |
479 | + console.warn("Register complete:", errorString); |
480 | + console.warn("Falling back to default operator."); |
481 | sim.netReg.registration(); |
482 | } |
483 | - } |
484 | - onNameChanged: buildLists(); |
485 | - onStatusChanged: buildLists(); |
486 | - } |
487 | - } |
488 | + working = false; |
489 | + } |
490 | + } |
491 | + } |
492 | + |
493 | + Connections { |
494 | + /* The following is a hack: If a scan is in progress and we call |
495 | + scan() on netReg, it emits a scanError _and_ scanFinished. |
496 | + We look at the scanError message, set this property to true if |
497 | + it says a scan is in progress. This way we can ignore the bad |
498 | + scanFinished signal. Filed bug against libqofono[1]. |
499 | + [1] https://github.com/nemomobile/libqofono/issues/52 |
500 | + */ |
501 | + property bool __scanInProgress: false |
502 | + |
503 | + target: sim.netReg |
504 | + onScanFinished: { |
505 | + if (scanning && !__scanInProgress) { |
506 | + scanning = false; |
507 | + } |
508 | + __scanInProgress = false; |
509 | + } |
510 | + onScanError: { |
511 | + if (message === "Operation already in progress") { |
512 | + console.warn('A scan was already in progress.'); |
513 | + __scanInProgress = true; |
514 | + } else { |
515 | + scanning = false; |
516 | + __scanInProgress = false; |
517 | + console.warn("onScanError: " + message); |
518 | + } |
519 | + } |
520 | + onModeChanged: modeSelector.selectedIndex = (mode === "auto") ? 0 : -1 |
521 | + } |
522 | + |
523 | + Component.onCompleted: sim.netReg.scan() |
524 | |
525 | Flickable { |
526 | id: scrollWidget |
527 | anchors.fill: parent |
528 | contentWidth: parent.width |
529 | - contentHeight: parent.height |
530 | - boundsBehavior: (contentHeight > parent.height) ? Flickable.DragAndOvershootBounds : Flickable.StopAtBounds |
531 | + contentHeight: contentItem.childrenRect.height |
532 | + boundsBehavior: (contentHeight > root.height) ? |
533 | + Flickable.DragAndOvershootBounds : Flickable.StopAtBounds |
534 | |
535 | - ColumnLayout { |
536 | + Column { |
537 | anchors { |
538 | left: parent.left |
539 | right: parent.right |
540 | } |
541 | + spacing: 0 |
542 | + |
543 | + SettingsItemTitle { |
544 | + text: i18n.tr("Carrier") |
545 | + |
546 | + ActivityIndicator { |
547 | + anchors { |
548 | + right: parent.right |
549 | + top: parent.top |
550 | + margins: units.gu(1.5) |
551 | + } |
552 | + running: true |
553 | + opacity: scanning || working ? 1 : 0 |
554 | + Behavior on opacity { |
555 | + NumberAnimation { |
556 | + duration: UbuntuAnimation.SnapDuration |
557 | + } |
558 | + } |
559 | + } |
560 | + } |
561 | |
562 | ListItem.ItemSelector { |
563 | - id: chooseCarrier |
564 | + id: modeSelector |
565 | objectName: "mode" |
566 | expanded: true |
567 | - enabled: sim.netReg.mode !== "auto-only" |
568 | - text: i18n.tr("Choose carrier:") |
569 | - model: [i18n.tr("Automatically"), i18n.tr("Manually")] |
570 | - |
571 | - delegate: OptionSelectorDelegate { showDivider: false } |
572 | - selectedIndex: sim.netReg.mode === "manual" ? 1 : 0 |
573 | - |
574 | - // we only want to do this per user input |
575 | + enabled: !scanning && !working |
576 | + opacity: enabled ? 1 : 0.5 |
577 | + model: [i18n.tr("Automatically")] |
578 | + delegate: OptionSelectorDelegate { |
579 | + text: { |
580 | + // modelData is "Automatically" |
581 | + if (sim.netReg.mode === "auto") { |
582 | + return sim.netReg.name ? |
583 | + modelData + " [ " + sim.netReg.name + " ]" : |
584 | + modelData |
585 | + } else { |
586 | + return modelData; |
587 | + } |
588 | + } |
589 | + showDivider: false |
590 | + } |
591 | + selectedIndex: sim.netReg.mode === "auto" ? 0 : -1 |
592 | + |
593 | + /* When registration() fails, the UI state may end up in an |
594 | + undefined state. Issue[1] has been filed against libqofono. |
595 | + [1] https://github.com/nemomobile/libqofono/issues/54 |
596 | + */ |
597 | + onDelegateClicked: sim.netReg.registration() |
598 | + } |
599 | + |
600 | + // In manual mode, all non-forbidden operators are shown. |
601 | + ListItem.ItemSelector { |
602 | + id: allOperators |
603 | + objectName: "allOperators" |
604 | + expanded: true |
605 | + enabled: !scanning && !working |
606 | + opacity: enabled ? 1 : 0.5 |
607 | + model: CHelper.getOps(sim.netReg.networkOperators) |
608 | + delegate: OptionSelectorDelegate { |
609 | + objectName: "carrier" |
610 | + showDivider: false |
611 | + text: modelData.name |
612 | + } |
613 | + onDelegateClicked: { |
614 | + CHelper.setOp(model[index].operatorPath); |
615 | + working = true; |
616 | + } |
617 | + selectedIndex: { |
618 | + var curop = sim.netReg.currentOperatorPath; |
619 | + return model.indexOf(CHelper.getOrCreateOpQml(curop)); |
620 | + } |
621 | + |
622 | + Behavior on height { |
623 | + NumberAnimation { |
624 | + duration: UbuntuAnimation.SnapDuration |
625 | + } |
626 | + } |
627 | + |
628 | + Behavior on opacity { |
629 | + NumberAnimation { |
630 | + duration: UbuntuAnimation.SnapDuration |
631 | + } |
632 | + } |
633 | + } |
634 | + |
635 | + /* When registration mode is "Automatic", this list contains all |
636 | + the non-forbidden operators except the current one. When the user |
637 | + taps one of the elements in this selector, it will be hidden, |
638 | + and the mode will switch to "Manual". */ |
639 | + ListItem.ItemSelector { |
640 | + id: otherOperators |
641 | + objectName: "otherOperators" |
642 | + expanded: true |
643 | + enabled: !scanning && !working |
644 | + opacity: enabled ? 1 : 0.5 |
645 | + model: CHelper.getOps(sim.netReg.networkOperators, |
646 | + [sim.netReg.currentOperatorPath]) |
647 | + delegate: OptionSelectorDelegate { |
648 | + objectName: "carrier" |
649 | + showDivider: false |
650 | + text: modelData.name |
651 | + } |
652 | + onDelegateClicked: { |
653 | + var clickedOp = model[index].operatorPath; |
654 | + CHelper.setOp(clickedOp); |
655 | + |
656 | + // Update immediately and do not wait for netReg |
657 | + allOperators.selectedIndex = allOperators.model.indexOf( |
658 | + CHelper.getOrCreateOpQml(clickedOp)); |
659 | + working = true; |
660 | + } |
661 | onSelectedIndexChanged: { |
662 | - if (selectedIndex === -1 || d.__suppressActivation) |
663 | - return; |
664 | - |
665 | - if (selectedIndex === 0) { |
666 | - sim.netReg.registration(); |
667 | - } else if (selectedIndex === 1) { |
668 | - if (sim.netReg.status !== "searching") |
669 | - sim.netReg.scan(); |
670 | - } |
671 | - } |
672 | - } |
673 | - |
674 | - ListItem.SingleControl { |
675 | - enabled: chooseCarrier.selectedIndex === 1 |
676 | - anchors { |
677 | - left: parent.left |
678 | - leftMargin: units.gu(0) |
679 | - } |
680 | - control: ColumnLayout { |
681 | - id: child |
682 | - width: parent.width - units.gu(4) |
683 | - anchors.left: parent.left |
684 | - RowLayout { |
685 | - id: searchingRow |
686 | - spacing: units.gu(1) |
687 | - |
688 | - visible: sim.netReg.status === "searching" |
689 | - ActivityIndicator { |
690 | - id: activityIndicator |
691 | - anchors.verticalCenter: parent.verticalCenter |
692 | - running: parent.visible |
693 | - } |
694 | - Label { |
695 | - anchors.verticalCenter: parent.verticalCenter |
696 | - text: i18n.tr("Searching for carriers…") |
697 | - } |
698 | - } |
699 | - ListItem.ItemSelector { |
700 | - id: carrierSelector |
701 | - objectName: "carriers" |
702 | - expanded: true |
703 | - enabled: sim.netReg.status !== "searching" && chooseCarrier.selectedIndex === 1 |
704 | - // work around ItemSelector not having a visual change depending on being disabled |
705 | - opacity: enabled ? 1.0 : 0.5 |
706 | - width: parent.width |
707 | - model: operatorNames |
708 | - delegate: OptionSelectorDelegate { enabled: carrierSelector.enabled; showDivider: false } |
709 | - onSelectedIndexChanged: { |
710 | - if (selectedIndex === -1 || d.__suppressActivation) |
711 | - return; |
712 | - |
713 | - // this assumes operator names are unique, |
714 | - // revise if not so |
715 | - for (var op in operators) { |
716 | - if (operators[op].name === operatorNames[selectedIndex]) { |
717 | - operators[op].registerOperator(); |
718 | - return; |
719 | - } |
720 | - } |
721 | - // just asserting to verify the logic |
722 | - // remove once proven functional |
723 | - throw "should not be reached."; |
724 | - } |
725 | - } |
726 | - } |
727 | - } |
728 | - ListItem.Standard { |
729 | - text: i18n.tr("APN") |
730 | - progression: true |
731 | - enabled: sim.connMan.powered |
732 | - onClicked: { |
733 | - pageStack.push(Qt.resolvedUrl("PageChooseApn.qml"), {sim: sim}) |
734 | + /* When e.g. the model changes, the selectedIndex is set to |
735 | + 0. Ignore this, since we never want the selectedIndex to be |
736 | + anything other than -1. This component is shown only when |
737 | + registration is "Automatic". */ |
738 | + if (selectedIndex >= 0) { |
739 | + selectedIndex = -1; |
740 | + } |
741 | + } |
742 | + |
743 | + Behavior on height { |
744 | + NumberAnimation { |
745 | + duration: UbuntuAnimation.SnapDuration |
746 | + } |
747 | + } |
748 | + |
749 | + Behavior on opacity { |
750 | + NumberAnimation { |
751 | + duration: UbuntuAnimation.SnapDuration |
752 | + } |
753 | } |
754 | } |
755 | } |
756 | |
757 | === added file 'plugins/cellular/carriers.js' |
758 | --- plugins/cellular/carriers.js 1970-01-01 00:00:00 +0000 |
759 | +++ plugins/cellular/carriers.js 2014-12-16 16:24:38 +0000 |
760 | @@ -0,0 +1,106 @@ |
761 | +// Map of path to OfonoNetworkOperator objects |
762 | +var _pathToQml = {} |
763 | + |
764 | +/* |
765 | +Given an array of paths, it will create and associate |
766 | +an OfonoNetworkOperator QML object for each new path. |
767 | + |
768 | +It will also delete any QML that is not in given list of paths. |
769 | + |
770 | +@param {Array} paths - Array of operator paths |
771 | +@return {undefined} |
772 | +*/ |
773 | +function updateOperatorQML (paths) { |
774 | + _garbageCollect(paths); |
775 | + _createQml(paths); |
776 | +} |
777 | + |
778 | +function _garbageCollect (paths) { |
779 | + var path; |
780 | + for (path in _pathToQml) { |
781 | + if (_pathToQml.hasOwnProperty(path)) { |
782 | + if (paths.indexOf(path) === -1) { |
783 | + _pathToQml[path].destroy(); |
784 | + delete _pathToQml[path]; |
785 | + } |
786 | + } |
787 | + } |
788 | +} |
789 | + |
790 | +function _createQml (paths) { |
791 | + paths.forEach(function (path, i) { |
792 | + if (!_pathToQml.hasOwnProperty(path)) { |
793 | + _pathToQml[path] = netOp.createObject(root, { |
794 | + 'operatorPath': path |
795 | + }); |
796 | + } |
797 | + }); |
798 | +} |
799 | + |
800 | +/* |
801 | +Takes a list of paths and returns |
802 | +OfonoNetworkOperator objects for each path. |
803 | + |
804 | +This function will create OfonoNetworkOperator |
805 | +objects. |
806 | + |
807 | +@param {Array} paths - Array of operator paths |
808 | +@param {Array} ignore - Array of operator paths to ignore |
809 | +@return {Array} of OfonoNetworkOperators |
810 | +*/ |
811 | +function getOps (paths, ignore) { |
812 | + var ret = []; |
813 | + ignore = ignore || []; |
814 | + paths.forEach(function (op) { |
815 | + var ofonoOp = getOrCreateOpQml(op); |
816 | + if (ignore.indexOf(op) >= 0) { |
817 | + return; |
818 | + } else if (ofonoOp.status === "forbidden") { |
819 | + return; |
820 | + } |
821 | + ret.push(ofonoOp); |
822 | + }); |
823 | + return ret; |
824 | +} |
825 | + |
826 | +/* |
827 | +@param path String an operator path |
828 | +@return {Object|null} OfonoNetworkOperator|null - null if no QML exist for path |
829 | +*/ |
830 | +function getOp (path) { |
831 | + if (_pathToQml.hasOwnProperty(path)) { |
832 | + return _pathToQml[path]; |
833 | + } else { |
834 | + return null; |
835 | + } |
836 | +} |
837 | + |
838 | +/* |
839 | +Returns an operator. Before returning it sees |
840 | +if we have created QML for this operator path |
841 | +before. QML is created if not. |
842 | + |
843 | +It is guaranteed that a QML object will be returned. |
844 | + |
845 | +@param {String} path - an operator path |
846 | +@return {Object} OfonoNetworkOperator - the created qml |
847 | +*/ |
848 | +function getOrCreateOpQml (path) { |
849 | + if (getOp(path)) { |
850 | + return getOp(path); |
851 | + } else { |
852 | + _createQml([path]); |
853 | + return getOp(path); |
854 | + } |
855 | +} |
856 | + |
857 | +/* |
858 | +Registers operator on path |
859 | + |
860 | +@param {String} path - operator to register |
861 | +@return {undefined} |
862 | +*/ |
863 | +function setOp (path) { |
864 | + var op = getOrCreateOpQml(path); |
865 | + op.registerOperator(); |
866 | +} |
867 | |
868 | === modified file 'tests/autopilot/ubuntu_system_settings/__init__.py' |
869 | --- tests/autopilot/ubuntu_system_settings/__init__.py 2014-11-18 20:13:35 +0000 |
870 | +++ tests/autopilot/ubuntu_system_settings/__init__.py 2014-12-16 16:24:38 +0000 |
871 | @@ -277,28 +277,16 @@ |
872 | |
873 | @autopilot.logging.log_action(logger.debug) |
874 | def change_carrier(self, carrier, sim=None): |
875 | - if sim: |
876 | - carriersPage = self._click_carriers() |
877 | - carrierPage = carriersPage.select_sim(sim) |
878 | - else: |
879 | - carrierPage = self._click_carrier() |
880 | - |
881 | - carrierPage.set_manual() |
882 | - carrierPage.set_carrier(carrier) |
883 | - |
884 | - @autopilot.logging.log_action(logger.debug) |
885 | - def _click_carrier(self): |
886 | - item = self.select_single(objectName='carrier') |
887 | - self.pointing_device.click_object(item) |
888 | - return self.get_root_instance().wait_select_single( |
889 | - objectName='chooseCarrierPage') |
890 | - |
891 | - @autopilot.logging.log_action(logger.debug) |
892 | - def _click_carriers(self): |
893 | - item = self.select_single(objectName='carriers') |
894 | - self.pointing_device.click_object(item) |
895 | - return self.get_root_instance().wait_select_single( |
896 | - objectName='chooseCarriersPage') |
897 | + carrierApnPage = self._click_carrier_apn() |
898 | + chooseCarrierPage = carrierApnPage.open_carrier(sim) |
899 | + chooseCarrierPage.set_carrier(carrier) |
900 | + |
901 | + @autopilot.logging.log_action(logger.debug) |
902 | + def _click_carrier_apn(self): |
903 | + item = self.select_single(objectName='carrierApnEntry') |
904 | + self.pointing_device.click_object(item) |
905 | + return self.get_root_instance().wait_select_single( |
906 | + objectName='carrierApnPage') |
907 | |
908 | @autopilot.logging.log_action(logger.debug) |
909 | def select_sim_for_data(self, sim): |
910 | @@ -340,30 +328,42 @@ |
911 | self.pointing_device.click_object(ok) |
912 | |
913 | |
914 | -class PageChooseCarriers(ubuntuuitoolkit.UbuntuUIToolkitCustomProxyObjectBase): |
915 | - |
916 | - """Autopilot helper for carrier selection page (multisim).""" |
917 | - |
918 | - @autopilot.logging.log_action(logger.debug) |
919 | - def select_sim(self, sim): |
920 | - return self._select_sim(sim) |
921 | - |
922 | - @autopilot.logging.log_action(logger.debug) |
923 | - def _select_sim(self, sim): |
924 | - item = self.select_single(objectName='%s_carriers' % sim) |
925 | - self.pointing_device.click_object(item) |
926 | +class PageCarrierAndApn(ubuntuuitoolkit.UbuntuUIToolkitCustomProxyObjectBase): |
927 | + |
928 | + """Autopilot helper for carrier/apn entry page (singlesim).""" |
929 | + @autopilot.logging.log_action(logger.debug) |
930 | + def open_carrier(self, sim): |
931 | + return self._click_carrier(sim) |
932 | + |
933 | + @autopilot.logging.log_action(logger.debug) |
934 | + def _click_carrier(self, sim): |
935 | + obj = self.select_single( |
936 | + objectName='carrier') |
937 | + self.pointing_device.click_object(obj) |
938 | + return self.get_root_instance().wait_select_single( |
939 | + objectName='chooseCarrierPage') |
940 | + |
941 | + |
942 | +class PageCarriersAndApns( |
943 | + ubuntuuitoolkit.UbuntuUIToolkitCustomProxyObjectBase): |
944 | + """Autopilot helper for carrier/apn entry page (multisim).""" |
945 | + """Autopilot helper for carrier/apn entry page (singlesim).""" |
946 | + @autopilot.logging.log_action(logger.debug) |
947 | + def open_carrier(self, sim): |
948 | + return self._click_carrier(sim) |
949 | + |
950 | + @autopilot.logging.log_action(logger.debug) |
951 | + def _click_carrier(self, sim): |
952 | + obj = self.select_single( |
953 | + objectName='%s_carriers' % sim) |
954 | + self.pointing_device.click_object(obj) |
955 | return self.get_root_instance().wait_select_single( |
956 | objectName='chooseCarrierPage') |
957 | |
958 | |
959 | class PageChooseCarrier(ubuntuuitoolkit.UbuntuUIToolkitCustomProxyObjectBase): |
960 | |
961 | - """Autopilot helper for carrier selection page (singlesim).""" |
962 | - |
963 | - @autopilot.logging.log_action(logger.debug) |
964 | - def set_manual(self): |
965 | - item = self.select_single(text='Manually') |
966 | - self.pointing_device.click_object(item) |
967 | + """Autopilot helper for carrier selection page""" |
968 | |
969 | @autopilot.logging.log_action(logger.debug) |
970 | def set_automatic(self): |
971 | @@ -374,7 +374,17 @@ |
972 | # wait for animation, since page.animationRunning.wait_for(False) |
973 | # does not work? |
974 | sleep(0.5) |
975 | - item = self.select_single(text=carrier) |
976 | + allOperators = self.select_single(objectName="allOperators") |
977 | + otherOperators = self.select_single(objectName="otherOperators") |
978 | + |
979 | + if allOperators.visible: |
980 | + opList = allOperators |
981 | + elif otherOperators.visible: |
982 | + opList = otherOperators |
983 | + else: |
984 | + raise Exception("No operator list visible.") |
985 | + |
986 | + item = opList.select_single(text=carrier, objectName="carrier") |
987 | self.pointing_device.click_object(item) |
988 | |
989 |
PASSED: Continuous integration, rev:951 jenkins. qa.ubuntu. com/job/ ubuntu- system- settings- rtm-14. 09-ci/19/ jenkins. qa.ubuntu. com/job/ ubuntu- system- settings- rtm-14. 09-14.09- armhf-ci/ 20 jenkins. qa.ubuntu. com/job/ ubuntu- system- settings- rtm-14. 09-14.09- armhf-ci/ 20/artifact/ work/output/ *zip*/output. zip
http://
Executed test runs:
SUCCESS: http://
deb: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/ubuntu- system- settings- rtm-14. 09-ci/19/ rebuild
http://