Merge lp:~jonas-drange/ubuntu-system-settings/1357393-fix into lp:ubuntu-system-settings

Proposed by Jonas G. Drange
Status: Merged
Approved by: Ken VanDine
Approved revision: 922
Merged at revision: 932
Proposed branch: lp:~jonas-drange/ubuntu-system-settings/1357393-fix
Merge into: lp:ubuntu-system-settings
Prerequisite: lp:~jonas-drange/ubuntu-system-settings/1355053-fix-2g-bug
Diff against target: 1330 lines (+695/-218)
16 files modified
plugins/cellular/CMakeLists.txt (+1/-0)
plugins/cellular/Components/CMakeLists.txt (+4/-1)
plugins/cellular/Components/CellularMultiSim.qml (+16/-18)
plugins/cellular/Components/CellularSingleSim.qml (+13/-14)
plugins/cellular/Components/DefaultSim.qml (+3/-4)
plugins/cellular/Components/MultiSim.qml (+120/-0)
plugins/cellular/Components/NoSim.qml (+51/-0)
plugins/cellular/Components/Sim.qml (+2/-0)
plugins/cellular/Components/SimEditor.qml (+8/-8)
plugins/cellular/Components/SingleSim.qml (+76/-0)
plugins/cellular/PageChooseCarriers.qml (+9/-10)
plugins/cellular/PageComponent.qml (+42/-159)
plugins/cellular/sims.js (+34/-0)
tests/autopilot/ubuntu_system_settings/tests/__init__.py (+5/-3)
tests/autopilot/ubuntu_system_settings/tests/ofono.py (+215/-0)
tests/autopilot/ubuntu_system_settings/tests/test_cellular.py (+96/-1)
To merge this branch: bzr merge lp:~jonas-drange/ubuntu-system-settings/1357393-fix
Reviewer Review Type Date Requested Status
Ken VanDine Approve
PS Jenkins bot continuous-integration Approve
Review via email: mp+231347@code.launchpad.net

This proposal supersedes a proposal from 2014-08-17.

Commit message

[cellular] displays cellular UIs based on how many SIMs are present.

Description of the change

Hi,

this creates three states for the cellular UI to be in:

* noSim
* singleSim
* multiSim

It also adds some logic for an arbitrary number of SIMs, however, the multiSim UI currently only supports two.

In addition to all of the above, this branch will be ready for SIM hotswapping, even though re-inserting SIMs currently does not work (broken at lower levels).

Thanks

 * Is your branch in sync with latest trunk (e.g. bzr pull lp:trunk -> no changes)
    yes
 * Did you build your software in a clean sbuild/pbuilder chroot or ppa?
    jenkins
 * Did you build your software in a clean sbuild/pbuilder armhf chroot or ppa?
    jenkins
 * Has your component "TestPlan” been executed successfully on emulator, N4?
    n4 and other device
 * Has a 5 minute exploratory testing run been executed on N4?
    no/jenkins?
 * If you changed the packaging (debian), did you subscribe a core-dev to this MP?
    N/A
 * If you changed the UI, did you subscribe the design-reviewers to this MP?
    How?
 * What components might get impacted by your changes?
    USS Phone panel
 * Have you requested review by the teams of these owning components?
    Yes

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal

FAILED: Continuous integration, rev:913
No commit message was specified in the merge proposal. Click on the following link and set the commit message (if you want a jenkins rebuild you need to trigger it yourself):
https://code.launchpad.net/~jonas-drange/ubuntu-system-settings/1357393-fix/+merge/231136/+edit-commit-message

http://jenkins.qa.ubuntu.com/job/ubuntu-system-settings-ci/1243/
Executed test runs:
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-utopic-touch/3725
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-utopic/2870
    SUCCESS: http://jenkins.qa.ubuntu.com/job/ubuntu-system-settings-utopic-amd64-ci/436
    SUCCESS: http://jenkins.qa.ubuntu.com/job/ubuntu-system-settings-utopic-armhf-ci/432
        deb: http://jenkins.qa.ubuntu.com/job/ubuntu-system-settings-utopic-armhf-ci/432/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/ubuntu-system-settings-utopic-i386-ci/435
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-mako/3601
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-utopic-armhf/4972
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-utopic-armhf/4972/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/11690
    SUCCESS: http://jenkins.qa.ubuntu.com/job/autopilot-testrunner-otto-utopic/2330
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-utopic-amd64/3154
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-utopic-amd64/3154/artifact/work/output/*zip*/output.zip

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

review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal

FAILED: Continuous integration, rev:917
No commit message was specified in the merge proposal. Click on the following link and set the commit message (if you want a jenkins rebuild you need to trigger it yourself):
https://code.launchpad.net/~jonas-drange/ubuntu-system-settings/1357393-fix/+merge/231136/+edit-commit-message

http://jenkins.qa.ubuntu.com/job/ubuntu-system-settings-ci/1245/
Executed test runs:
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-utopic-touch/3767
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-utopic/2897
    SUCCESS: http://jenkins.qa.ubuntu.com/job/ubuntu-system-settings-utopic-amd64-ci/438
    SUCCESS: http://jenkins.qa.ubuntu.com/job/ubuntu-system-settings-utopic-armhf-ci/434
        deb: http://jenkins.qa.ubuntu.com/job/ubuntu-system-settings-utopic-armhf-ci/434/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/ubuntu-system-settings-utopic-i386-ci/437
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-mako/3636
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-utopic-armhf/5014
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-utopic-armhf/5014/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/11736
    SUCCESS: http://jenkins.qa.ubuntu.com/job/autopilot-testrunner-otto-utopic/2352
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-utopic-amd64/3181
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-utopic-amd64/3181/artifact/work/output/*zip*/output.zip

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

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

FAILED: Continuous integration, rev:918
No commit message was specified in the merge proposal. Click on the following link and set the commit message (if you want a jenkins rebuild you need to trigger it yourself):
https://code.launchpad.net/~jonas-drange/ubuntu-system-settings/1357393-fix/+merge/231347/+edit-commit-message

http://jenkins.qa.ubuntu.com/job/ubuntu-system-settings-ci/1247/
Executed test runs:
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-utopic-touch/3770
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-utopic/2900
    SUCCESS: http://jenkins.qa.ubuntu.com/job/ubuntu-system-settings-utopic-amd64-ci/440
    SUCCESS: http://jenkins.qa.ubuntu.com/job/ubuntu-system-settings-utopic-armhf-ci/436
        deb: http://jenkins.qa.ubuntu.com/job/ubuntu-system-settings-utopic-armhf-ci/436/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/ubuntu-system-settings-utopic-i386-ci/439
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-mako/3637
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-utopic-armhf/5017
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-utopic-armhf/5017/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/11737
    SUCCESS: http://jenkins.qa.ubuntu.com/job/autopilot-testrunner-otto-utopic/2354
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-utopic-amd64/3184
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-utopic-amd64/3184/artifact/work/output/*zip*/output.zip

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

review: Needs Fixing (continuous-integration)
919. By Jonas G. Drange

fix small rendering issues

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

PASSED: Continuous integration, rev:919
http://jenkins.qa.ubuntu.com/job/ubuntu-system-settings-ci/1253/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-utopic-touch/3806
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-utopic/2924
    SUCCESS: http://jenkins.qa.ubuntu.com/job/ubuntu-system-settings-utopic-amd64-ci/446
    SUCCESS: http://jenkins.qa.ubuntu.com/job/ubuntu-system-settings-utopic-armhf-ci/442
        deb: http://jenkins.qa.ubuntu.com/job/ubuntu-system-settings-utopic-armhf-ci/442/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/ubuntu-system-settings-utopic-i386-ci/445
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-mako/3668
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-utopic-armhf/5053
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-utopic-armhf/5053/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/11774
    SUCCESS: http://jenkins.qa.ubuntu.com/job/autopilot-testrunner-otto-utopic/2376
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-utopic-amd64/3208
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-utopic-amd64/3208/artifact/work/output/*zip*/output.zip

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

review: Approve (continuous-integration)
920. By Jonas G. Drange

merge trunk

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Ken VanDine (ken-vandine) wrote :

Works well on my dual sim device. One small nit pick thing inlineh

review: Needs Fixing
921. By Jonas G. Drange

merge trunk

922. By Jonas G. Drange

cleanup of extra lines

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Ken VanDine (ken-vandine) wrote :

Thanks!

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-07-17 20:59:15 +0000
3+++ plugins/cellular/CMakeLists.txt 2014-08-22 10:53:29 +0000
4@@ -9,6 +9,7 @@
5 PageComponent.qml
6 Hotspot.qml
7 HotspotSetup.qml
8+ sims.js
9 )
10
11
12
13=== modified file 'plugins/cellular/Components/CMakeLists.txt'
14--- plugins/cellular/Components/CMakeLists.txt 2014-07-31 20:10:40 +0000
15+++ plugins/cellular/Components/CMakeLists.txt 2014-08-22 10:53:29 +0000
16@@ -1,6 +1,9 @@
17 set(QML_SOURCES
18+ NoSim.qml
19+ SingleSim.qml
20+ MultiSim.qml
21 CellularSingleSim.qml
22- CellularDualSim.qml
23+ CellularMultiSim.qml
24 data-helpers.js
25 DefaultSim.qml
26 Sim.qml
27
28=== renamed file 'plugins/cellular/Components/CellularDualSim.qml' => 'plugins/cellular/Components/CellularMultiSim.qml'
29--- plugins/cellular/Components/CellularDualSim.qml 2014-08-14 13:59:57 +0000
30+++ plugins/cellular/Components/CellularMultiSim.qml 2014-08-22 10:53:29 +0000
31@@ -24,20 +24,18 @@
32
33 Column {
34 id: root
35- property var sim1
36- property var sim2
37 property var selector: selector
38 property var prefMap: ['gsm', 'umts']
39
40 function getNameFromIndex (index) {
41- return [i18n.tr("Off"), sim1.title, sim2.title][index];
42+ return [i18n.tr("Off"), sims[0].title, sims[1].title][index];
43 }
44
45 function getUsedSim () {
46 if (state === "sim1Online") {
47- return sim1;
48+ return sims[0];
49 } else if (state === "sim2Online") {
50- return sim2;
51+ return sims[1];
52 } else {
53 return null;
54 }
55@@ -47,7 +45,7 @@
56 states: [
57 State {
58 name: "sim1Online"
59- when: sim1.connMan.powered && !sim2.connMan.powered
60+ when: sims[0].connMan.powered && !sims[1].connMan.powered
61 StateChangeScript { script: {
62 selector.selectedIndex =
63 DataHelpers.dualSimKeyToIndex(
64@@ -56,7 +54,7 @@
65 },
66 State {
67 name: "sim2Online"
68- when: sim2.connMan.powered && !sim1.connMan.powered
69+ when: sims[1].connMan.powered && !sims[0].connMan.powered
70 StateChangeScript { script: {
71 selector.selectedIndex =
72 DataHelpers.dualSimKeyToIndex(
73@@ -65,9 +63,9 @@
74 },
75 State {
76 name: "bothOnline"
77- when: sim1.connMan.powered && sim2.connMan.powered
78+ when: sims[0].connMan.powered && sims[1].connMan.powered
79 StateChangeScript { script: {
80- sim2.connMan.powered = false;
81+ sims[1].connMan.powered = false;
82 }}
83 }
84 ]
85@@ -82,16 +80,16 @@
86 objectName: "use" + modelData
87 text: getNameFromIndex(index)
88 }
89- selectedIndex: [true, sim1.connMan.powered, sim2.connMan.powered]
90+ selectedIndex: [true, sims[0].connMan.powered, sims[1].connMan.powered]
91 .lastIndexOf(true)
92 onDelegateClicked: {
93- sim1.connMan.powered = (index === 1)
94- sim2.connMan.powered = (index === 2)
95+ sims[0].connMan.powered = (index === 1)
96+ sims[1].connMan.powered = (index === 2)
97 }
98 }
99
100 Connections {
101- target: sim1.connMan
102+ target: sims[0].connMan
103 onPoweredChanged: {
104 if (powered) {
105 use.selectedIndex = 1;
106@@ -100,7 +98,7 @@
107 }
108
109 Connections {
110- target: sim2.connMan
111+ target: sims[1].connMan
112 onPoweredChanged: {
113 if (powered) {
114 use.selectedIndex = 2;
115@@ -124,9 +122,9 @@
116 }
117
118 Connections {
119- target: sim1.radioSettings
120+ target: sims[0].radioSettings
121 onTechnologyPreferenceChanged: {
122- if (sim1.connMan.powered) {
123+ if (sims[0].connMan.powered) {
124 selector.selectedIndex =
125 DataHelpers.dualSimKeyToIndex(preference);
126 }
127@@ -134,9 +132,9 @@
128 }
129
130 Connections {
131- target: sim2.radioSettings
132+ target: sims[1].radioSettings
133 onTechnologyPreferenceChanged: {
134- if (sim2.connMan.powered) {
135+ if (sims[1].connMan.powered) {
136 selector.selectedIndex =
137 DataHelpers.dualSimKeyToIndex(preference);
138 }
139
140=== modified file 'plugins/cellular/Components/CellularSingleSim.qml'
141--- plugins/cellular/Components/CellularSingleSim.qml 2014-08-14 13:59:57 +0000
142+++ plugins/cellular/Components/CellularSingleSim.qml 2014-08-22 10:53:29 +0000
143@@ -25,7 +25,6 @@
144 Column {
145 height: childrenRect.height
146
147- property var sim1
148 property var selector: selector
149
150 ListItem.ItemSelector {
151@@ -33,15 +32,15 @@
152 objectName: "technologyPreferenceSelector"
153 text: i18n.tr("Cellular data:")
154 expanded: true
155- enabled: sim1.radioSettings.technologyPreference !== ""
156+ enabled: sim.radioSettings.technologyPreference !== ""
157 model: [
158 i18n.tr("Off"),
159 i18n.tr("2G only (saves battery)"),
160 i18n.tr("2G/3G/4G (faster)")]
161 selectedIndex: {
162- if (sim1.connMan.powered) {
163+ if (sim.connMan.powered) {
164 return DataHelpers.singleSimKeyToIndex(
165- sim1.radioSettings.technologyPreference);
166+ sim.radioSettings.technologyPreference);
167 } else {
168 return 0;
169 }
170@@ -52,20 +51,20 @@
171 id: dataRoamingItem
172 objectName: "dataRoamingSwitch"
173 text: i18n.tr("Data roaming")
174- enabled: sim1.connMan.powered
175+ enabled: sim.connMan.powered
176 control: Switch {
177 id: dataRoamingControl
178- checked: sim1.connMan.roamingAllowed
179- onClicked: sim1.connMan.roamingAllowed = checked
180+ checked: sim.connMan.roamingAllowed
181+ onClicked: sim.connMan.roamingAllowed = checked
182 }
183 }
184
185 Connections {
186- target: sim1.connMan
187+ target: sim.connMan
188 onPoweredChanged: {
189 if (powered) {
190 selector.selectedIndex = DataHelpers.singleSimKeyToIndex(
191- sim1.radioSettings.technologyPreference);
192+ sim.radioSettings.technologyPreference);
193 } else {
194 selector.selectedIndex = 0;
195 }
196@@ -73,24 +72,24 @@
197 }
198
199 Connections {
200- target: sim1.radioSettings
201+ target: sim.radioSettings
202 onTechnologyPreferenceChanged: {
203 var selIndex = selector.selectedIndex;
204 if (selIndex > 0) {
205- sim1.radioSettings.technologyPreference =
206+ sim.radioSettings.technologyPreference =
207 DataHelpers.singleSimIndexToKey(selIndex);
208 }
209 }
210 }
211
212 Binding {
213- target: sim1.connMan
214+ target: sim.connMan
215 property: "powered"
216 value: selector.selectedIndex !== 0
217 }
218
219 Binding {
220- target: sim1.radioSettings
221+ target: sim.radioSettings
222 property: "technologyPreference"
223 value: {
224 var i = selector.selectedIndex;
225@@ -99,7 +98,7 @@
226 } else if (i === 2) {
227 return 'umts';
228 } else {
229- return sim1.radioSettings.technologyPreference
230+ return sim.radioSettings.technologyPreference
231 }
232 }
233 }
234
235=== modified file 'plugins/cellular/Components/DefaultSim.qml'
236--- plugins/cellular/Components/DefaultSim.qml 2014-08-14 09:59:56 +0000
237+++ plugins/cellular/Components/DefaultSim.qml 2014-08-22 10:53:29 +0000
238@@ -23,10 +23,10 @@
239
240 Column {
241
242- property var m: ["ask", sim1.path, sim2.path]
243+ property var m: ["ask", sims[0].path, sims[1].path]
244
245 function getNameFromIndex (index) {
246- return [i18n.tr("Ask me each time"), sim1.title, sim2.title][index];
247+ return [i18n.tr("Ask me each time"), sims[0].title, sims[1].title][index];
248 }
249
250 ListItem.ItemSelector {
251@@ -45,8 +45,7 @@
252 }
253
254 ListItem.Caption {
255- text: i18n.tr("You can change the SIM for individual calls,
256- or for contacts in the address book.")
257+ text: i18n.tr("You can change the SIM for individual calls, or for contacts in the address book.")
258 }
259
260 ListItem.Divider {}
261
262=== added file 'plugins/cellular/Components/MultiSim.qml'
263--- plugins/cellular/Components/MultiSim.qml 1970-01-01 00:00:00 +0000
264+++ plugins/cellular/Components/MultiSim.qml 2014-08-22 10:53:29 +0000
265@@ -0,0 +1,120 @@
266+/*
267+ * Copyright (C) 2014 Canonical Ltd
268+ *
269+ * This program is free software: you can redistribute it and/or modify
270+ * it under the terms of the GNU General Public License version 3 as
271+ * published by the Free Software Foundation.
272+ *
273+ * This program is distributed in the hope that it will be useful,
274+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
275+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
276+ * GNU General Public License for more details.
277+ *
278+ * You should have received a copy of the GNU General Public License
279+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
280+ *
281+ * Authors:
282+ * Jonas G. Drange <jonas.drange@canonical.com>
283+ *
284+*/
285+import QtQuick 2.0
286+import GSettings 1.0
287+import Ubuntu.Components 0.1
288+import Ubuntu.Components.ListItems 0.1 as ListItem
289+
290+Column {
291+
292+ objectName: "multiSim"
293+
294+ property var sims
295+ property var modems
296+
297+ // make settings available to all children of root
298+ property var settings: phoneSettings
299+
300+ CellularMultiSim {
301+ anchors { left: parent.left; right: parent.right }
302+ }
303+
304+ ListItem.Divider {}
305+
306+ ListItem.SingleValue {
307+ text : i18n.tr("Hotspot disabled because Wi-Fi is off.")
308+ visible: showAllUI && !hotspotItem.visible
309+ }
310+
311+ ListItem.SingleValue {
312+ id: hotspotItem
313+ text: i18n.tr("Wi-Fi hotspot")
314+ progression: true
315+ onClicked: {
316+ pageStack.push(Qt.resolvedUrl("Hotspot.qml"))
317+ }
318+ visible: showAllUI && (actionGroup.actionObject.valid ? actionGroup.actionObject.state : false)
319+ }
320+
321+ ListItem.Standard {
322+ id: dataUsage
323+ text: i18n.tr("Data usage statistics")
324+ progression: true
325+ visible: showAllUI
326+ }
327+
328+ ListItem.Divider {
329+ visible: hotspotItem.visible || dataUsage.visible
330+ }
331+
332+ ListItem.SingleValue {
333+ text: i18n.tr("Carriers")
334+ id: chooseCarrier
335+ objectName: "chooseCarrier"
336+ progression: enabled
337+ onClicked: {
338+ pageStack.push(Qt.resolvedUrl("../PageChooseCarriers.qml"), {
339+ sims: sims
340+ });
341+ }
342+ }
343+
344+ ListItem.Divider {}
345+
346+ SimEditor {
347+ anchors { left: parent.left; right: parent.right }
348+ }
349+
350+ ListItem.Divider {}
351+
352+ DefaultSim {
353+ anchors { left: parent.left; right: parent.right }
354+ }
355+
356+ GSettings {
357+ id: phoneSettings
358+ schema.id: "com.ubuntu.phone"
359+ Component.onCompleted: {
360+ // set default names
361+ var simNames = phoneSettings.simNames;
362+ var m0 = modems[0];
363+ var m1 = modems[1];
364+ if (!simNames[m0]) {
365+ simNames[m0] = "SIM 1";
366+ }
367+ if (!simNames[m1]) {
368+ simNames[m1] = "SIM 2";
369+ }
370+ phoneSettings.simNames = simNames;
371+ }
372+ }
373+
374+ Binding {
375+ target: sims[0]
376+ property: "name"
377+ value: phoneSettings.simNames[modems[0]]
378+ }
379+
380+ Binding {
381+ target: sims[1]
382+ property: "name"
383+ value: phoneSettings.simNames[modems[1]]
384+ }
385+}
386
387=== added file 'plugins/cellular/Components/NoSim.qml'
388--- plugins/cellular/Components/NoSim.qml 1970-01-01 00:00:00 +0000
389+++ plugins/cellular/Components/NoSim.qml 2014-08-22 10:53:29 +0000
390@@ -0,0 +1,51 @@
391+/*
392+ * Copyright (C) 2014 Canonical Ltd
393+ *
394+ * This program is free software: you can redistribute it and/or modify
395+ * it under the terms of the GNU General Public License version 3 as
396+ * published by the Free Software Foundation.
397+ *
398+ * This program is distributed in the hope that it will be useful,
399+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
400+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
401+ * GNU General Public License for more details.
402+ *
403+ * You should have received a copy of the GNU General Public License
404+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
405+ *
406+ * Authors:
407+ * Jonas G. Drange <jonas.drange@canonical.com>
408+ *
409+*/
410+import QtQuick 2.0
411+import Ubuntu.Components 0.1
412+import Ubuntu.Components.ListItems 0.1 as ListItem
413+
414+Column {
415+
416+ objectName: "noSim"
417+
418+ ListItem.ItemSelector {
419+ text: i18n.tr("Cellular data:")
420+ expanded: true
421+ enabled: false
422+ model: [i18n.tr("Off"), i18n.tr("2G only (saves battery)"), i18n.tr("2G/3G/4G (faster)")]
423+ selectedIndex: -1
424+ }
425+
426+ ListItem.Standard {
427+ text: i18n.tr("Data roaming")
428+ enabled: false
429+ control: Switch {
430+ checked: false
431+ }
432+ }
433+
434+ ListItem.Divider {}
435+
436+ ListItem.SingleValue {
437+ text: i18n.tr("Carrier");
438+ value: i18n.tr("N/A")
439+ enabled: false
440+ }
441+}
442
443=== modified file 'plugins/cellular/Components/Sim.qml'
444--- plugins/cellular/Components/Sim.qml 2014-07-25 13:33:36 +0000
445+++ plugins/cellular/Components/Sim.qml 2014-08-22 10:53:29 +0000
446@@ -21,12 +21,14 @@
447 import MeeGo.QOfono 0.2
448
449 Item {
450+ id: root
451 property alias modem: modem
452 property alias netReg: netReg
453 property alias radioSettings: radioSettings
454 property alias simMng: simMng
455 property alias connMan: connMan
456
457+ property alias present: simMng.present
458 property string path
459 property string name
460 property string title: {
461
462=== modified file 'plugins/cellular/Components/SimEditor.qml'
463--- plugins/cellular/Components/SimEditor.qml 2014-08-15 19:58:34 +0000
464+++ plugins/cellular/Components/SimEditor.qml 2014-08-22 10:53:29 +0000
465@@ -44,7 +44,7 @@
466 name: "editingSim1"
467 PropertyChanges {
468 target: nameField
469- text: sim1.name
470+ text: sims[0].name
471 }
472 ParentChange {
473 target: editor
474@@ -60,7 +60,7 @@
475 name: "editingSim2"
476 PropertyChanges {
477 target: nameField
478- text: sim2.name
479+ text: sims[1].name
480 }
481 ParentChange {
482 target: editor
483@@ -108,7 +108,7 @@
484 right: parent.right
485 verticalCenter: parent.verticalCenter
486 }
487- text: sim1.title
488+ text: sims[0].title
489 }
490 }
491 Column {
492@@ -144,7 +144,7 @@
493 right: parent.right
494 verticalCenter: parent.verticalCenter
495 }
496- text: sim2.title
497+ text: sims[1].title
498 }
499 }
500 Column {
501@@ -213,11 +213,11 @@
502 onTriggered: {
503 var tmpSimNames = {};
504 if (simList.state === "editingSim1") {
505- tmpSimNames[sim1.path] = nameField.text;
506- tmpSimNames[sim2.path] = sim2.name;
507+ tmpSimNames[sims[0].path] = nameField.text;
508+ tmpSimNames[sims[1].path] = sims[1].name;
509 } else if (simList.state === "editingSim2") {
510- tmpSimNames[sim1.path] = sim1.name;
511- tmpSimNames[sim2.path] = nameField.text;
512+ tmpSimNames[sims[0].path] = sims[0].name;
513+ tmpSimNames[sims[1].path] = nameField.text;
514 }
515 phoneSettings.simNames = tmpSimNames;
516 simList.state = "";
517
518=== added file 'plugins/cellular/Components/SingleSim.qml'
519--- plugins/cellular/Components/SingleSim.qml 1970-01-01 00:00:00 +0000
520+++ plugins/cellular/Components/SingleSim.qml 2014-08-22 10:53:29 +0000
521@@ -0,0 +1,76 @@
522+/*
523+ * Copyright (C) 2014 Canonical Ltd
524+ *
525+ * This program is free software: you can redistribute it and/or modify
526+ * it under the terms of the GNU General Public License version 3 as
527+ * published by the Free Software Foundation.
528+ *
529+ * This program is distributed in the hope that it will be useful,
530+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
531+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
532+ * GNU General Public License for more details.
533+ *
534+ * You should have received a copy of the GNU General Public License
535+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
536+ *
537+ * Authors:
538+ * Jonas G. Drange <jonas.drange@canonical.com>
539+ *
540+*/
541+import QtQuick 2.0
542+import Ubuntu.Components 0.1
543+import Ubuntu.Components.ListItems 0.1 as ListItem
544+
545+Column {
546+
547+ objectName: "singleSim"
548+
549+ property var sim
550+
551+ CellularSingleSim {
552+ anchors { left: parent.left; right: parent.right }
553+ }
554+
555+ ListItem.Divider {}
556+
557+ ListItem.SingleValue {
558+ text : i18n.tr("Hotspot disabled because Wi-Fi is off.")
559+ visible: showAllUI && !hotspotItem.visible
560+ }
561+
562+ ListItem.SingleValue {
563+ id: hotspotItem
564+ text: i18n.tr("Wi-Fi hotspot")
565+ progression: true
566+ onClicked: {
567+ pageStack.push(Qt.resolvedUrl("Hotspot.qml"))
568+ }
569+ visible: showAllUI && (actionGroup.actionObject.valid ? actionGroup.actionObject.state : false)
570+ }
571+
572+ ListItem.Standard {
573+ text: i18n.tr("Data usage statistics")
574+ progression: true
575+ visible: showAllUI
576+ }
577+
578+ ListItem.SingleValue {
579+ text: i18n.tr("Carrier");
580+ id: chooseCarrier
581+ objectName: "chooseCarrier"
582+ progression: enabled
583+ value: sim.netReg.name || i18n.tr("N/A")
584+ onClicked: {
585+ pageStack.push(Qt.resolvedUrl("../PageChooseCarrier.qml"), {
586+ netReg: sim.netReg,
587+ title: i18n.tr("Carrier")
588+ })
589+ }
590+ }
591+
592+ ListItem.Standard {
593+ text: i18n.tr("APN")
594+ progression: true
595+ visible: showAllUI
596+ }
597+}
598
599=== modified file 'plugins/cellular/PageChooseCarriers.qml'
600--- plugins/cellular/PageChooseCarriers.qml 2014-07-24 19:00:45 +0000
601+++ plugins/cellular/PageChooseCarriers.qml 2014-08-22 10:53:29 +0000
602@@ -28,8 +28,7 @@
603 title: i18n.tr("Carriers")
604 objectName: "chooseCarriersPage"
605
606- property var sim1
607- property var sim2
608+ property var sims
609
610 Flickable {
611 anchors.fill: parent
612@@ -42,33 +41,33 @@
613 anchors.right: parent.right
614
615 ListItem.Standard {
616- text: sim1.title
617+ text: sims[0].title
618 }
619
620 ListItem.SingleValue {
621 objectName: "chooseCarrierSim1"
622- value: sim1.netReg.name ? sim1.netReg.name : i18n.tr("N/A")
623+ value: sims[0].netReg.name ? sims[0].netReg.name : i18n.tr("N/A")
624 progression: true
625 onClicked: {
626 pageStack.push(Qt.resolvedUrl("PageChooseCarrier.qml"), {
627- netReg: sim1.netReg,
628- title: sim1.title
629+ netReg: sims[0].netReg,
630+ title: sims[0].title
631 })
632 }
633 }
634
635 ListItem.Standard {
636- text: sim2.title
637+ text: sims[1].title
638 }
639
640 ListItem.SingleValue {
641 objectName: "chooseCarrierSim2"
642- value: sim2.netReg.name ? sim2.netReg.name : i18n.tr("N/A")
643+ value: sims[1].netReg.name ? sims[1].netReg.name : i18n.tr("N/A")
644 progression: true
645 onClicked: {
646 pageStack.push(Qt.resolvedUrl("PageChooseCarrier.qml"), {
647- netReg: sim2.netReg,
648- title: sim2.title
649+ netReg: sims[1].netReg,
650+ title: sims[1].title
651 })
652 }
653 }
654
655=== modified file 'plugins/cellular/PageComponent.qml'
656--- plugins/cellular/PageComponent.qml 2014-08-12 16:25:26 +0000
657+++ plugins/cellular/PageComponent.qml 2014-08-22 10:53:29 +0000
658@@ -19,53 +19,69 @@
659 */
660
661 import QtQuick 2.0
662-import GSettings 1.0
663 import SystemSettings 1.0
664 import Ubuntu.Components 0.1
665 import Ubuntu.Components.ListItems 0.1 as ListItem
666 import MeeGo.QOfono 0.2
667 import QMenuModel 0.1
668-import "Components"
669+import "Components" as LocalComponents
670+import "sims.js" as Sims
671
672 ItemPage {
673 id: root
674 title: i18n.tr("Cellular")
675 objectName: "cellularPage"
676
677- // pointers to sim 1 and 2, lazy loaded
678- property alias sim1: simOneLoader.item
679- property alias sim2: simTwoLoader.item
680 property var modemsSorted: manager.modems.slice(0).sort()
681+ property int simsLoaded: 0
682
683 states: [
684 State {
685+ name: "noSim"
686+ when: (simsLoaded === 0) || (Sims.getPresentCount() === 0)
687+ StateChangeScript {
688+ script: loader.source = "Components/NoSim.qml"
689+ }
690+ },
691+ State {
692 name: "singleSim"
693 StateChangeScript {
694- name: "loadSim"
695- script: {
696- var p = modemsSorted[0];
697- simOneLoader.setSource("Components/Sim.qml", {
698- path: p
699- });
700- }
701+ script: loader.setSource("Components/SingleSim.qml", {
702+ sim: Sims.get(0)
703+ })
704 }
705+ when: simsLoaded && (Sims.getPresentCount() === 1)
706 },
707 State {
708- name: "dualSim"
709- extend: "singleSim"
710+ name: "multiSim"
711 StateChangeScript {
712- name: "loadSecondSim"
713- script: {
714- var p = modemsSorted[1];
715- simTwoLoader.setSource("Components/Sim.qml", {
716- path: p
717- });
718- defaultSimLoader.source = "Components/DefaultSim.qml";
719- }
720+ script: loader.setSource("Components/MultiSim.qml", {
721+ sims: Sims.getAll(),
722+ modems: modemsSorted
723+ })
724 }
725+ when: simsLoaded && (Sims.getPresentCount() > 1)
726 }
727 ]
728
729+ OfonoManager {
730+ id: manager
731+ Component.onCompleted: {
732+ var component = Qt.createComponent("Components/Sim.qml");
733+ modemsSorted.forEach(function (path) {
734+ console.warn('creating sim object for', path)
735+ var sim = component.createObject(root, {
736+ path: path
737+ });
738+ if (sim === null) {
739+ console.warn('failed to create sim object');
740+ } else {
741+ Sims.add(sim);
742+ }
743+ });
744+ }
745+ }
746+
747 QDBusActionGroup {
748 id: actionGroup
749 busType: 1
750@@ -78,42 +94,6 @@
751 start()
752 }
753 }
754-
755- OfonoManager {
756- id: manager
757- Component.onCompleted: {
758- if (modems.length === 1) {
759- root.state = "singleSim";
760- } else if (modems.length === 2) {
761- root.state = "dualSim";
762- }
763- }
764- }
765-
766- Loader {
767- id: simOneLoader
768- onLoaded: {
769- if (parent.state === "singleSim") {
770- cellData.setSource("Components/CellularSingleSim.qml", {
771- sim1: sim1
772- });
773- }
774- }
775- }
776-
777- Loader {
778- id: simTwoLoader
779- onLoaded: {
780- // unload any single sim setup
781- cellData.source = "";
782- cellData.setSource("Components/CellularDualSim.qml", {
783- sim1: sim1,
784- sim2: sim2
785- });
786- simEditorLoader.source = "Components/SimEditor.qml";
787- }
788- }
789-
790 Flickable {
791 anchors.fill: parent
792 contentWidth: parent.width
793@@ -124,106 +104,9 @@
794 anchors { left: parent.left; right: parent.right }
795
796 Loader {
797- id: cellData
798- anchors { left: parent.left; right: parent.right }
799- }
800-
801- ListItem.SingleValue {
802- text : i18n.tr("Hotspot disabled because Wi-Fi is off.")
803- visible: showAllUI && !hotspotItem.visible
804- }
805-
806- ListItem.SingleValue {
807- id: hotspotItem
808- text: i18n.tr("Wi-Fi hotspot")
809- progression: true
810- onClicked: {
811- pageStack.push(Qt.resolvedUrl("Hotspot.qml"))
812- }
813- visible: showAllUI && (actionGroup.actionObject.valid ? actionGroup.actionObject.state : false)
814- }
815-
816- ListItem.Standard {
817- text: i18n.tr("Data usage statistics")
818- progression: true
819- visible: showAllUI
820- }
821-
822- ListItem.SingleValue {
823- text: i18n.tr("Carrier", "Carriers", manager.modems.length);
824- id: chooseCarrier
825- objectName: "chooseCarrier"
826- progression: enabled
827- onClicked: {
828- if (root.state === 'singleSim') {
829- pageStack.push(Qt.resolvedUrl("PageChooseCarrier.qml"), {
830- netReg: sim1.netReg,
831- title: i18n.tr("Carrier")
832- })
833- } else if (root.state === 'dualSim') {
834- pageStack.push(Qt.resolvedUrl("PageChooseCarriers.qml"), {
835- sim1: sim1,
836- sim2: sim2
837- });
838- }
839- }
840- }
841-
842- Binding {
843- target: chooseCarrier
844- property: "value"
845- value: sim1.netReg.name || i18n.tr("N/A")
846- when: (simOneLoader.status === Loader.Ready) && root.state === "singleSim"
847- }
848-
849- ListItem.Standard {
850- text: i18n.tr("APN")
851- progression: true
852- visible: showAllUI
853- }
854-
855- Loader {
856- id: simEditorLoader
857- anchors { left: parent.left; right: parent.right }
858- }
859-
860- ListItem.Divider {}
861-
862- Loader {
863- id: defaultSimLoader
864- anchors.left: parent.left
865- anchors.right: parent.right
866- }
867- }
868- }
869-
870- GSettings {
871- id: phoneSettings
872- schema.id: "com.ubuntu.phone"
873- Component.onCompleted: {
874- // set default names
875- var simNames = phoneSettings.simNames;
876- var m0 = modemsSorted[0];
877- var m1 = modemsSorted[1];
878- if (!simNames[m0]) {
879- simNames[m0] = "SIM 1";
880- }
881- if (!simNames[m1]) {
882- simNames[m1] = "SIM 2";
883- }
884- phoneSettings.simNames = simNames;
885- }
886- }
887-
888- Binding {
889- target: sim1
890- property: "name"
891- value: phoneSettings.simNames[modemsSorted[0]]
892- }
893-
894- Binding {
895- target: sim2
896- property: "name"
897- value: phoneSettings.simNames[modemsSorted[1]]
898+ id: loader
899+ anchors { left: parent.left; right: parent.right }
900+ }
901+ }
902 }
903 }
904
905=== added file 'plugins/cellular/sims.js'
906--- plugins/cellular/sims.js 1970-01-01 00:00:00 +0000
907+++ plugins/cellular/sims.js 2014-08-22 10:53:29 +0000
908@@ -0,0 +1,34 @@
909+var sims = [];
910+
911+function add (sim) {
912+ sims.push(sim);
913+ root.simsLoaded++;
914+}
915+
916+function getAll () {
917+ return sims;
918+}
919+
920+function get (n) {
921+ return getAll()[n];
922+}
923+
924+function getCount () {
925+ return getAll().length;
926+}
927+
928+function getPresent () {
929+ var present = [];
930+ getAll().forEach(function (sim) {
931+ if (sim.present) {
932+ present.push(sim);
933+ } else {
934+ return;
935+ }
936+ });
937+ return present;
938+}
939+
940+function getPresentCount () {
941+ return getPresent().length;
942+}
943
944=== modified file 'tests/autopilot/ubuntu_system_settings/tests/__init__.py'
945--- tests/autopilot/ubuntu_system_settings/tests/__init__.py 2014-08-19 15:26:07 +0000
946+++ tests/autopilot/ubuntu_system_settings/tests/__init__.py 2014-08-22 10:53:29 +0000
947@@ -125,7 +125,7 @@
948 'for m in objects if "%s/operator/" in m]' % name
949
950 def mock_connection_manager(self, modem):
951- modem.AddProperty(CONNMAN_IFACE, 'Powered', True)
952+ modem.AddProperty(CONNMAN_IFACE, 'Powered', dbus.Boolean(1))
953 modem.AddProperty(CONNMAN_IFACE, 'RoamingAllowed', False)
954 modem.AddMethods(
955 CONNMAN_IFACE,
956@@ -194,6 +194,7 @@
957 'SubscriberNumbers': ['123456', '234567']
958 }
959 modem.AddProperties(SIM_IFACE, properties)
960+ modem.AddProperty(SIM_IFACE, 'Present', True)
961 modem.AddMethods(
962 SIM_IFACE,
963 [('GetProperties', '', 'a{sv}',
964@@ -208,7 +209,6 @@
965 # create modem_0 proxy
966 self.modem_0 = self.dbus_con.get_object('org.ofono', '/ril_0')
967
968- # Add an available carrier
969 self.mock_carriers('ril_0')
970
971 self.mock_radio_settings(self.modem_0)
972@@ -232,6 +232,7 @@
973 self.dbusmock.AddModem(second_modem, {'Powered': True})
974 self.modem_1 = self.dbus_con.get_object(
975 'org.ofono', '/%s' % second_modem)
976+
977 self.modem_1.AddMethods(NETREG_IFACE, [
978 ('GetProperties', '', 'a{sv}',
979 'ret = self.GetAll("org.ofono.NetworkRegistration")'),
980@@ -253,9 +254,10 @@
981 def setUpClass(cls):
982 cls.start_system_bus()
983 cls.dbus_con = cls.get_dbus(True)
984+ template = os.path.join(os.path.dirname(__file__), 'ofono.py')
985 # Add a mock Ofono environment so we get consistent results
986 (cls.p_mock, cls.obj_ofono) = cls.spawn_server_template(
987- 'ofono', stdout=subprocess.PIPE)
988+ template, stdout=subprocess.PIPE)
989 cls.dbusmock = dbus.Interface(cls.obj_ofono, dbusmock.MOCK_IFACE)
990
991 def setUp(self, panel=None):
992
993=== added file 'tests/autopilot/ubuntu_system_settings/tests/ofono.py'
994--- tests/autopilot/ubuntu_system_settings/tests/ofono.py 1970-01-01 00:00:00 +0000
995+++ tests/autopilot/ubuntu_system_settings/tests/ofono.py 2014-08-22 10:53:29 +0000
996@@ -0,0 +1,215 @@
997+'''ofonod D-BUS mock template'''
998+
999+# This program is free software; you can redistribute it and/or modify it under
1000+# the terms of the GNU Lesser General Public License as published by the Free
1001+# Software Foundation; either version 3 of the License, or (at your option) any
1002+# later version. See http://www.gnu.org/copyleft/lgpl.html for the full text
1003+# of the license.
1004+
1005+__author__ = 'Martin Pitt'
1006+__email__ = 'martin.pitt@ubuntu.com'
1007+__copyright__ = '(c) 2013 Canonical Ltd.'
1008+__license__ = 'LGPL 3+'
1009+
1010+
1011+import dbus
1012+
1013+import dbusmock
1014+
1015+BUS_NAME = 'org.ofono'
1016+MAIN_OBJ = '/'
1017+MAIN_IFACE = 'org.ofono.Manager'
1018+SYSTEM_BUS = True
1019+
1020+NOT_IMPLEMENTED = '''raise dbus.exceptions.DBusException(
1021+ "org.ofono.Error.NotImplemented")'''
1022+
1023+_parameters = {}
1024+
1025+
1026+def load(mock, parameters):
1027+ global _parameters
1028+ mock.modems = [] # object paths
1029+ _parameters = parameters
1030+ mock.AddMethod(MAIN_IFACE, 'GetModems', '', 'a(oa{sv})',
1031+ 'ret = [(m, objects[m].GetAll(\
1032+ "org.ofono.Modem")) for m in self.modems]')
1033+
1034+ if not parameters.get('no_modem', False):
1035+ mock.AddModem(parameters.get('ModemName', 'ril_0'), {})
1036+
1037+
1038+@dbus.service.method(dbusmock.MOCK_IFACE,
1039+ in_signature='sa{sv}', out_signature='s')
1040+def AddModem(self, name, properties):
1041+ '''Convenience method to add a modem
1042+
1043+ You have to specify a device name which must be a valid part of an object
1044+ path, e. g. "mock_ac". For future extensions you can specify a "properties"
1045+ array, but no extra properties are supported for now.
1046+
1047+ Returns the new object path.
1048+ '''
1049+ path = '/' + name
1050+ self.AddObject(
1051+ path,
1052+ 'org.ofono.Modem',
1053+ {
1054+ 'Online': dbus.Boolean(True, variant_level=1),
1055+ 'Powered': dbus.Boolean(True, variant_level=1),
1056+ 'Lockdown': dbus.Boolean(False, variant_level=1),
1057+ 'Emergency': dbus.Boolean(False, variant_level=1),
1058+ 'Manufacturer': dbus.String('Fakesys', variant_level=1),
1059+ 'Model': dbus.String('Mock Modem', variant_level=1),
1060+ 'Revision': dbus.String('0815.42', variant_level=1),
1061+ 'Type': dbus.String('hardware', variant_level=1),
1062+ 'Interfaces': [
1063+ 'org.ofono.CallVolume',
1064+ 'org.ofono.VoiceCallManager',
1065+ 'org.ofono.NetworkRegistration',
1066+ 'org.ofono.SimManager'],
1067+ 'Features': ['gprs', 'net'],
1068+ },
1069+ [
1070+ ('GetProperties', '', 'a{sv}',
1071+ 'ret = self.GetAll("org.ofono.Modem")'),
1072+ (
1073+ 'SetProperty', 'sv', '',
1074+ 'self.Set("org.ofono.Modem", args[0], args[1]); '
1075+ 'self.EmitSignal("org.ofono.Modem", "PropertyChanged",'
1076+ '"sv", [args[0], args[1]])'),
1077+ ])
1078+ obj = dbusmock.mockobject.objects[path]
1079+ obj.name = name
1080+ add_voice_call_api(obj)
1081+ add_netreg_api(obj)
1082+ self.modems.append(path)
1083+ props = obj.GetAll('org.ofono.Modem', dbus_interface=dbus.PROPERTIES_IFACE)
1084+ self.EmitSignal(MAIN_IFACE, 'ModemAdded', 'oa{sv}', [path, props])
1085+ return path
1086+
1087+
1088+def add_voice_call_api(mock):
1089+ '''Add org.ofono.VoiceCallManager API to a mock'''
1090+
1091+ # also add an emergency number which is not a real one, in case one runs a
1092+ # test case against a production ofono :-)
1093+ mock.AddProperty(
1094+ 'org.ofono.VoiceCallManager', 'EmergencyNumbers', ['911', '13373'])
1095+
1096+ mock.calls = [] # object paths
1097+
1098+ mock.AddMethods('org.ofono.VoiceCallManager', [
1099+ (
1100+ 'GetProperties', '', 'a{sv}',
1101+ 'ret = self.GetAll("org.ofono.VoiceCallManager")'),
1102+ ('Transfer', '', '', ''),
1103+ ('SwapCalls', '', '', ''),
1104+ ('ReleaseAndAnswer', '', '', ''),
1105+ ('ReleaseAndSwap', '', '', ''),
1106+ ('HoldAndAnswer', '', '', ''),
1107+ ('SendTones', 's', '', ''),
1108+ ('PrivateChat', 'o', 'ao', NOT_IMPLEMENTED),
1109+ ('CreateMultiparty', '', 'o', NOT_IMPLEMENTED),
1110+ ('HangupMultiparty', '', '', NOT_IMPLEMENTED),
1111+ (
1112+ 'GetCalls', '', 'a(oa{sv})',
1113+ 'ret = [(c, objects[c].GetAll("org.ofono.VoiceCall"))\
1114+ for c in self.calls]')
1115+ ])
1116+
1117+
1118+@dbus.service.method('org.ofono.VoiceCallManager',
1119+ in_signature='ss', out_signature='s')
1120+def Dial(self, number, hide_callerid):
1121+ path = self._object_path + '/voicecall%02i' % (len(self.calls) + 1)
1122+ self.AddObject(
1123+ path, 'org.ofono.VoiceCall',
1124+ {
1125+ 'State': dbus.String('dialing', variant_level=1),
1126+ 'LineIdentification': dbus.String(number, variant_level=1),
1127+ 'Name': dbus.String('', variant_level=1),
1128+ 'Multiparty': dbus.Boolean(False, variant_level=1),
1129+ 'Multiparty': dbus.Boolean(False, variant_level=1),
1130+ 'RemoteHeld': dbus.Boolean(False, variant_level=1),
1131+ 'RemoteMultiparty': dbus.Boolean(False, variant_level=1),
1132+ 'Emergency': dbus.Boolean(False, variant_level=1),
1133+ },
1134+ [
1135+ (
1136+ 'GetProperties', '', 'a{sv}',
1137+ 'ret = self.GetAll("org.ofono.VoiceCall")'),
1138+ ('Deflect', 's', '', NOT_IMPLEMENTED),
1139+ (
1140+ 'Hangup', '', '',
1141+ 'self.parent.calls.remove(self._object_path);'
1142+ 'self.parent.RemoveObject(self._object_path);'
1143+ 'self.EmitSignal("org.ofono.VoiceCallManager",\
1144+ "CallRemoved", "o", [self._object_path])'),
1145+ ('Answer', '', '', NOT_IMPLEMENTED),
1146+ ])
1147+ obj = dbusmock.mockobject.objects[path]
1148+ obj.parent = self
1149+ self.calls.append(path)
1150+ self.EmitSignal('org.ofono.VoiceCallManager', 'CallAdded', 'oa{sv}',
1151+ [path, obj.GetProperties()])
1152+ return path
1153+
1154+
1155+@dbus.service.method('org.ofono.VoiceCallManager',
1156+ in_signature='', out_signature='')
1157+def HangupAll(self):
1158+ print('XXX HangupAll', self.calls)
1159+ for c in list(self.calls): # needs a copy
1160+ dbusmock.mockobject.objects[c].Hangup()
1161+ assert self.calls == []
1162+
1163+
1164+def get_all_operators(mock):
1165+ return 'ret = [(m, objects[m].GetAll("org.ofono.NetworkOperator")) ' \
1166+ 'for m in objects if "%s/operator/" in m]' % mock.name
1167+
1168+
1169+def add_netreg_api(mock):
1170+ '''Add org.ofono.NetworkRegistration API to a mock'''
1171+
1172+ # also add an emergency number which is not a real one, in case one runs a
1173+ # test case against a production ofono :-)
1174+ mock.AddProperties('org.ofono.NetworkRegistration', {
1175+ 'Mode': 'auto',
1176+ 'Status': 'registered',
1177+ 'LocationAreaCode': _parameters.get('LocationAreaCode', 987),
1178+ 'CellId': _parameters.get('CellId', 10203),
1179+ 'MobileCountryCode': _parameters.get('MobileCountryCode', '777'),
1180+ 'MobileNetworkCode': _parameters.get('MobileNetworkCode', '11'),
1181+ 'Technology': _parameters.get('Technology', 'gsm'),
1182+ 'Name': _parameters.get('Name', 'fake.tel'),
1183+ 'Strength': _parameters.get('Strength', dbus.Byte(80)),
1184+ 'BaseStation': _parameters.get('BaseStation', ''),
1185+ })
1186+
1187+ mock.AddObject(
1188+ '/%s/operator/op1' % mock.name,
1189+ 'org.ofono.NetworkOperator',
1190+ {
1191+ 'Name': _parameters.get('Name', 'fake.tel'),
1192+ 'Status': 'current',
1193+ 'MobileCountryCode': _parameters.get('MobileCountryCode', '777'),
1194+ 'MobileNetworkCode': _parameters.get('MobileNetworkCode', '11'),
1195+ 'Technologies': [_parameters.get('Technology', 'gsm')],
1196+ },
1197+ [
1198+ (
1199+ 'GetProperties', '', 'a{sv}',
1200+ 'ret = self.GetAll("org.ofono.NetworkOperator")'),
1201+ ('Register', '', '', ''),
1202+ ])
1203+
1204+ mock.AddMethods('org.ofono.NetworkRegistration', [
1205+ (
1206+ 'GetProperties', '', 'a{sv}',
1207+ 'ret = self.GetAll("org.ofono.NetworkRegistration")'),
1208+ ('Register', '', '', ''),
1209+ ('GetOperators', '', 'a(oa{sv})', get_all_operators(mock)),
1210+ ('Scan', '', 'a(oa{sv})', get_all_operators(mock)),
1211+ ])
1212
1213=== modified file 'tests/autopilot/ubuntu_system_settings/tests/test_cellular.py'
1214--- tests/autopilot/ubuntu_system_settings/tests/test_cellular.py 2014-08-14 14:18:17 +0000
1215+++ tests/autopilot/ubuntu_system_settings/tests/test_cellular.py 2014-08-22 10:53:29 +0000
1216@@ -15,7 +15,7 @@
1217 from unittest import skip
1218
1219 from ubuntu_system_settings.tests import (
1220- CellularBaseTestCase, CONNMAN_IFACE, RDO_IFACE)
1221+ CellularBaseTestCase, CONNMAN_IFACE, RDO_IFACE, SIM_IFACE)
1222 from ubuntu_system_settings.utils.i18n import ugettext as _
1223
1224 from ubuntuuitoolkit import emulators as toolkit_emulators
1225@@ -92,6 +92,14 @@
1226 Equals(_('Cellular'))
1227 )
1228
1229+ def test_single_sim_layout(self):
1230+ self.system_settings.main_view.cellular_page.\
1231+ select_single(objectName="singleSim")
1232+ self.assertThat(lambda: self.system_settings.main_view.select_single(
1233+ objectName='multiSim'), raises(StateNotFoundError))
1234+ self.assertThat(lambda: self.system_settings.main_view.select_single(
1235+ objectName='noSim'), raises(StateNotFoundError))
1236+
1237 def test_current_network(self):
1238 """ Tests whether the current network is visible and selected """
1239 self.navigate_to_carrier_page()
1240@@ -592,3 +600,90 @@
1241 self.assertEqual(
1242 gsettings.get_value('default-sim-for-messages').get_string(),
1243 '/ril_1')
1244+
1245+ def test_multi_sim_layout(self):
1246+ self.system_settings.main_view.cellular_page.\
1247+ select_single(objectName="multiSim")
1248+ self.assertThat(lambda: self.system_settings.main_view.select_single(
1249+ objectName='singleSim'), raises(StateNotFoundError))
1250+ self.assertThat(lambda: self.system_settings.main_view.select_single(
1251+ objectName='noSim'), raises(StateNotFoundError))
1252+
1253+ def test_remove_one_sim(self):
1254+ self.modem_0.EmitSignal(
1255+ SIM_IFACE,
1256+ 'PropertyChanged',
1257+ 'sv',
1258+ ['Present', 'False'])
1259+
1260+ self.system_settings.main_view.cellular_page.\
1261+ select_single(objectName="singleSim")
1262+ self.assertThat(lambda: self.system_settings.main_view.select_single(
1263+ objectName='multiSim'), raises(StateNotFoundError))
1264+ self.assertThat(lambda: self.system_settings.main_view.select_single(
1265+ objectName='noSim'), raises(StateNotFoundError))
1266+
1267+ def test_remove_two_sims(self):
1268+ self.modem_0.EmitSignal(
1269+ SIM_IFACE,
1270+ 'PropertyChanged',
1271+ 'sv',
1272+ ['Present', 'False'])
1273+
1274+ self.modem_1.EmitSignal(
1275+ SIM_IFACE,
1276+ 'PropertyChanged',
1277+ 'sv',
1278+ ['Present', 'False'])
1279+
1280+ self.system_settings.main_view.cellular_page.\
1281+ wait_select_single(objectName="noSim")
1282+ self.assertThat(
1283+ lambda: self.system_settings.main_view.select_single(
1284+ objectName='multiSim'), raises(StateNotFoundError))
1285+ self.assertThat(
1286+ lambda: self.system_settings.main_view.select_single(
1287+ objectName='singleSim'), raises(StateNotFoundError))
1288+
1289+ def test_remove_and_insert_sims(self):
1290+ self.modem_0.EmitSignal(
1291+ SIM_IFACE,
1292+ 'PropertyChanged',
1293+ 'sv',
1294+ ['Present', 'False'])
1295+
1296+ self.modem_1.EmitSignal(
1297+ SIM_IFACE,
1298+ 'PropertyChanged',
1299+ 'sv',
1300+ ['Present', 'False'])
1301+
1302+ self.system_settings.main_view.cellular_page.\
1303+ wait_select_single(objectName="noSim")
1304+ self.assertThat(
1305+ lambda: self.system_settings.main_view.select_single(
1306+ objectName='multiSim'), raises(StateNotFoundError))
1307+ self.assertThat(
1308+ lambda: self.system_settings.main_view.select_single(
1309+ objectName='singleSim'), raises(StateNotFoundError))
1310+
1311+ self.modem_0.EmitSignal(
1312+ SIM_IFACE,
1313+ 'PropertyChanged',
1314+ 'sv',
1315+ ['Present', 'True'])
1316+
1317+ self.modem_1.EmitSignal(
1318+ SIM_IFACE,
1319+ 'PropertyChanged',
1320+ 'sv',
1321+ ['Present', 'True'])
1322+
1323+ self.system_settings.main_view.cellular_page.\
1324+ wait_select_single(objectName="multiSim")
1325+ self.assertThat(
1326+ lambda: self.system_settings.main_view.select_single(
1327+ objectName='noSim'), raises(StateNotFoundError))
1328+ self.assertThat(
1329+ lambda: self.system_settings.main_view.select_single(
1330+ objectName='singleSim'), raises(StateNotFoundError))

Subscribers

People subscribed via source and target branches