Merge lp:~nik90/ubuntu-clock-app/performance-patch-1 into lp:ubuntu-clock-app/saucy

Proposed by Nekhelesh Ramananthan on 2014-02-19
Status: Merged
Approved by: Nekhelesh Ramananthan on 2014-02-19
Approved revision: 350
Merged at revision: 347
Proposed branch: lp:~nik90/ubuntu-clock-app/performance-patch-1
Merge into: lp:ubuntu-clock-app/saucy
Diff against target: 394 lines (+119/-46)
7 files modified
alarm/AlarmPage.qml (+3/-1)
clock/ClockPage.qml (+6/-6)
clock/WorldClock.qml (+2/-2)
common/SettingsPage.qml (+24/-3)
stopwatch/StopwatchPage.qml (+5/-1)
timer/TimerPage.qml (+5/-1)
ubuntu-clock-app.qml (+74/-32)
To merge this branch: bzr merge lp:~nik90/ubuntu-clock-app/performance-patch-1
Reviewer Review Type Date Requested Status
Riccardo Padovani Approve on 2014-02-19
Alan Pope 🍺🐧🐱 πŸ¦„ 2014-02-19 Approve on 2014-02-19
Ubuntu Phone Apps Jenkins Bot continuous-integration Approve on 2014-02-19
Review via email: mp+207119@code.launchpad.net

Commit message

Improved the IDLE performance of the clock app. Added a settings option to hide/show the seconds hand.

Description of the change

Dynamically loads tabs using QML Loaders ensuring there is only one tab in memory at any time. This has improve the IDLE performance of the clock app significantly. It has resulted in the IDLE CPU usage reduction from 2.6-4.0% to 0%.

It also adds an settings option to show/hide the seconds hand.

To post a comment you must log in.
350. By Nekhelesh Ramananthan on 2014-02-19

Fixed invalid call to clock page

Looks good.

review: Approve
Riccardo Padovani (rpadovani) wrote :

lgtm, great work :-)

review: Approve
Colin Ian King (colin-king) wrote :

Thanks!

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'alarm/AlarmPage.qml'
2--- alarm/AlarmPage.qml 2014-02-13 20:46:28 +0000
3+++ alarm/AlarmPage.qml 2014-02-19 09:59:28 +0000
4@@ -26,6 +26,7 @@
5 id: alarmPage
6 objectName: "alarmPage"
7
8+ readonly property real alarmHeaderHeight: units.gu(9.5)
9 property string currentTime
10 property alias modelCount: listSavedAlarm.count
11 property int enabledAlarmCount: 0
12@@ -38,6 +39,7 @@
13 tempPosition = clockAnimationContainer.contentY
14 currentTime = Utils.convertTime(new Date().getHours(), new Date().getMinutes(), new Date().getUTCSeconds(), appSetting.contents.timeFormat)
15 }
16+ Component.onDestruction: Utils.log("AlarmPage unloaded")
17
18 onModelCountChanged: modelCount == 0 ? clockAnimationContainer.contentY = tempPosition : undefined
19
20@@ -173,7 +175,7 @@
21 Column {
22 id: listAlarm
23
24- property int dynamicTopSpacing: alarmPage.height - alarmPage.header.height - alarmFace.height - savedAlarmHeader.height - alarmFace.anchors.topMargin - divider.height;
25+ property int dynamicTopSpacing: alarmPage.height - alarmHeaderHeight - alarmFace.height - savedAlarmHeader.height - alarmFace.anchors.topMargin - divider.height;
26
27 height: childrenRect.height
28 visible: listSavedAlarm.count != 0 ? true : false
29
30=== modified file 'clock/ClockPage.qml'
31--- clock/ClockPage.qml 2014-02-11 11:58:51 +0000
32+++ clock/ClockPage.qml 2014-02-19 09:59:28 +0000
33@@ -30,6 +30,7 @@
34 id: clockPage
35
36 // Property to hold the formatted time string to show on the screen
37+ readonly property real clockHeaderHeight: units.gu(9.5)
38 property string currentTimeFormatted
39 property string currentDate
40 property real currentUTCTime
41@@ -76,6 +77,7 @@
42 Utils.log("Saved Current Location: " + currentLocation.contents.city);
43 Utils.log("Saved Current Location Coordinates: " + currentLocation.contents.lng + "," + currentLocation.contents.lat)
44 }
45+ Component.onDestruction: Utils.log("ClockPage unloaded")
46
47 actions: [
48 Action {
49@@ -178,17 +180,15 @@
50 horizontalCenter: parent.horizontalCenter
51 }
52
53+ showSecondHand: appSetting.contents.seconds === "true" ? true : false
54 innerLabel.text: currentTimeFormatted
55 innerLabel.font.pixelSize: appSetting.contents.timeFormat === "12-hour" ? units.dp(31): units.dp(41)
56
57- hours: new Date().getHours() * 5
58- minutes: new Date().getMinutes()
59- seconds: new Date().getUTCSeconds()
60-
61 function timeChanged(now) {
62 hours = now.getHours() * 5
63 minutes = now.getMinutes()
64- seconds = now.getUTCSeconds();
65+ if (appSetting.contents.seconds === "true")
66+ seconds = now.getUTCSeconds();
67 }
68
69 onClicked: {
70@@ -254,7 +254,7 @@
71 Column {
72 id: savedWorldClock
73
74- property int dynamicTopSpacing: clockPage.height - clockPage.header.height - clockFace.height - worldLocationHeader.height - clockFace.anchors.topMargin - divider.height;
75+ property int dynamicTopSpacing: clockPage.height - clockHeaderHeight - clockFace.height - worldLocationHeader.height - clockFace.anchors.topMargin - divider.height;
76
77 height: childrenRect.height;
78 anchors { left:parent.left; right:parent.right; top: clockFace.bottom; topMargin: savedWorldClock.dynamicTopSpacing }
79
80=== modified file 'clock/WorldClock.qml'
81--- clock/WorldClock.qml 2014-02-05 14:41:21 +0000
82+++ clock/WorldClock.qml 2014-02-19 09:59:28 +0000
83@@ -66,9 +66,9 @@
84 onStatusChanged: {
85 if(status == XmlListModel.Ready && worldClocks.city != "null") {
86 if (isWorldCity)
87- clockPage.addWorldLocation(worldClocks.city, getTimeDifference(cityDetailsModel.get(0).time), worldClocks.lng, worldClocks.lat)
88+ clockLoader.item.addWorldLocation(worldClocks.city, getTimeDifference(cityDetailsModel.get(0).time), worldClocks.lng, worldClocks.lat)
89 else
90- clockPage.updateCurrentLocation(worldClocks.city, worldClocks.lng, worldClocks.lat)
91+ clockLoader.item.updateCurrentLocation(worldClocks.city, worldClocks.lng, worldClocks.lat)
92 worldClocks.clearUserSearch();
93 pageStack.pop()
94 }
95
96=== modified file 'common/SettingsPage.qml'
97--- common/SettingsPage.qml 2014-02-01 15:30:26 +0000
98+++ common/SettingsPage.qml 2014-02-19 09:59:28 +0000
99@@ -18,7 +18,7 @@
100
101 import QtQuick 2.0
102 import Ubuntu.Components 0.1
103-import Ubuntu.Components.ListItems 0.1 as ListItem
104+import Ubuntu.Components.ListItems 0.1
105
106 Page {
107 id: settingsPage
108@@ -35,13 +35,34 @@
109 margins: units.gu(2)
110 }
111
112+ Standard {
113+ id: secondsOption
114+
115+ text: "Show Seconds"
116+ showDivider: false
117+ anchors {
118+ left: parent.left
119+ right: parent.right
120+ margins: units.gu(-2)
121+ }
122+
123+ control: Switch {
124+ checked: appSetting.contents.seconds === "true" ? true : false
125+ onClicked: {
126+ var settings = JSON.parse(JSON.stringify(appSetting.contents))
127+ settings.seconds = checked === true ? "true" : "false"
128+ appSetting.contents = settings
129+ }
130+ }
131+ }
132+
133 OptionSelector {
134 id: timeFormat
135 text: "Time Format"
136 model: ["12-hour", "24-hour"]
137 selectedIndex: appSetting.contents.timeFormat === "12-hour" ? 0 : 1
138 onSelectedIndexChanged: {
139- var settings = appSetting.contents
140+ var settings = JSON.parse(JSON.stringify(appSetting.contents))
141 settings.timeFormat = selectedIndex === 0 ? "12-hour" : "24-hour"
142 appSetting.contents = settings
143 }
144@@ -55,7 +76,7 @@
145 enabled: false
146 selectedIndex: appSetting.contents.style === "analogue" ? 0 : 1
147 onSelectedIndexChanged: {
148- var settings = appSetting.contents
149+ var settings = JSON.parse(JSON.stringify(appSetting.contents))
150 settings.style = selectedIndex === 0 ? "analogue" : "digital"
151 appSetting.contents = settings
152 }
153
154=== modified file 'stopwatch/StopwatchPage.qml'
155--- stopwatch/StopwatchPage.qml 2014-02-11 13:27:34 +0000
156+++ stopwatch/StopwatchPage.qml 2014-02-19 09:59:28 +0000
157@@ -28,9 +28,13 @@
158 Page {
159 id: stopwatchPage
160
161+ readonly property real stopwatchHeaderHeight: units.gu(9.5)
162 property alias lapStart: laps.lapStart
163+ property bool isRunning: analogStopwatch.timerStatus &&
164+ analogStopwatch.hours !== 0 || analogStopwatch.minutes !== 0 || analogStopwatch.seconds !== 0 || analogStopwatch.milliseconds !== 0
165
166 Component.onCompleted: Utils.log("StopwatchPage loaded");
167+ Component.onDestruction: Utils.log("Stopwatch unloaded");
168
169 // Function to create a lap
170 function create_lap() {
171@@ -166,7 +170,7 @@
172 id: listLap
173 lapModel: laps
174 anchors { left: parent.left; right: parent.right; top: analogStopwatch.bottom; topMargin: listLap.dynamicTopSpacing }
175- dynamicTopSpacing: stopwatchPage.height - stopwatchPage.header.height - analogStopwatch.height - headerHeight - analogStopwatch.anchors.topMargin - dividerHeight;
176+ dynamicTopSpacing: stopwatchPage.height - stopwatchHeaderHeight - analogStopwatch.height - headerHeight - analogStopwatch.anchors.topMargin - dividerHeight;
177 }
178 }
179 }
180
181=== modified file 'timer/TimerPage.qml'
182--- timer/TimerPage.qml 2014-02-11 09:48:53 +0000
183+++ timer/TimerPage.qml 2014-02-19 09:59:28 +0000
184@@ -28,12 +28,14 @@
185 Page {
186 id: timerPage
187
188+ readonly property real timerHeaderHeight: units.gu(9.5)
189 property alias minutes: analogTimer.minutes;
190 property alias seconds: analogTimer.seconds;
191 property alias totalTime: analogTimer.totalTime;
192 property alias timerOn: analogTimer.timerOn;
193 property real tempPosition
194 property bool setFocus: false
195+ property bool isRunning: analogTimer.state !== "" || timerPage.state !== "" || analogTimer.minutes !== 0 || analogTimer.seconds !== 0
196
197 // Default Timer Presets as defined by the design team
198 U1db.Document {
199@@ -166,6 +168,7 @@
200 Utils.log("TimerPage loaded");
201 tempPosition = timerAnimationContainer.contentY
202 }
203+ Component.onDestruction: Utils.log("TimerPage unloaded")
204
205 Flickable {
206 id: timerAnimationContainer
207@@ -209,6 +212,7 @@
208 onMinutesChanged: innerLabel.text = setTimerLabel(minutes, seconds);
209 onSecondsChanged: if (timerOn == true) seconds_timer.restart()
210 else innerLabel.text = setTimerLabel(minutes, seconds);
211+
212 states:[
213 State { name: "STOP" },
214 State { name: "PAUSE"},
215@@ -287,7 +291,7 @@
216 model: timers
217 visible: listCount !== 0
218 anchors { left: parent.left; right: parent.right; top: analogTimer.bottom; topMargin: listPreset.dynamicTopSpacing }
219- dynamicTopSpacing: timerPage.height - timerPage.header.height - analogTimer.height - analogTimer.anchors.topMargin - headerHeight - dividerHeight;
220+ dynamicTopSpacing: timerPage.height - timerHeaderHeight - analogTimer.height - analogTimer.anchors.topMargin - headerHeight - dividerHeight;
221 }
222 }
223
224
225=== modified file 'ubuntu-clock-app.qml'
226--- ubuntu-clock-app.qml 2014-02-11 13:54:38 +0000
227+++ ubuntu-clock-app.qml 2014-02-19 09:59:28 +0000
228@@ -47,11 +47,11 @@
229 footerColor: "#D75669"
230
231 focus: true
232- Keys.onReturnPressed: Keyboard.enterShortcut(event, rootTabs.selectedTabIndex, stopwatchPage)
233- Keys.onEnterPressed: Keyboard.enterShortcut(event, rootTabs.selectedTabIndex, stopwatchPage)
234- Keys.onSpacePressed: Keyboard.spaceShortcut(event, rootTabs.selectedTabIndex, stopwatchPage)
235- Keys.onEscapePressed: Keyboard.escapeShortcut(event, rootTabs.selectedTabIndex, pagestack, timerPage, stopwatchPage)
236- Keys.onPressed: rootTabs.selectedTabIndex = Keyboard.generalShortcuts(event, rootTabs.count, rootTabs.selectedTabIndex, pagestack, timerPage, stopwatchPage)
237+ Keys.onReturnPressed: Keyboard.enterShortcut(event, rootTabs.selectedTabIndex, stopwatchLoader.item)
238+ Keys.onEnterPressed: Keyboard.enterShortcut(event, rootTabs.selectedTabIndex, stopwatchLoader.item)
239+ Keys.onSpacePressed: Keyboard.spaceShortcut(event, rootTabs.selectedTabIndex, stopwatchLoader.item)
240+ Keys.onEscapePressed: Keyboard.escapeShortcut(event, rootTabs.selectedTabIndex, pagestack, timerLoader.item, stopwatchLoader.item)
241+ Keys.onPressed: rootTabs.selectedTabIndex = Keyboard.generalShortcuts(event, rootTabs.count, rootTabs.selectedTabIndex, pagestack, timerLoader.item, stopwatchLoader.item)
242
243 // Property to store the default application dimensions
244 readonly property real minimumWidth: units.gu(50)
245@@ -98,20 +98,12 @@
246
247 onTriggered: {
248 now = new Date();
249- // FIXME: only send callback to pages that need it
250- /* TODO: this timer should probably be changed to fire
251- every minute (max) when the app is in the background,
252- or just be activated when the app is visible in the
253- switcher
254- */
255- clockPage.onTimerUpdate(now);
256- alarmPage.onTimerUpdate(now);
257- timerPage.onTimerUpdate(now);
258-
259- /* stopwatchPage.onTimerUpdate(now) is not required since
260- there is an inbuilt stopwatch timer which runs at a
261- higher frequency.
262- */
263+ if(clockLoader.source != "")
264+ clockLoader.item.onTimerUpdate(now);
265+ if(alarmLoader.source != "")
266+ alarmLoader.item.onTimerUpdate(now);
267+ if(timerLoader.source != "")
268+ timerLoader.item.onTimerUpdate(now);
269 }
270 }
271
272@@ -127,7 +119,7 @@
273 database: db
274 docId: "appSettings"
275 create: true
276- defaults: { "timeFormat": "12-hour", "style": "analogue" }
277+ defaults: { "timeFormat": "12-hour", "style": "analogue", "seconds": "false" }
278 }
279
280 ////////////////////////////////////////////////////////////////////////////////
281@@ -143,51 +135,101 @@
282 objectName: "rootTabs"
283 anchors.fill: parent
284
285+ onSelectedTabChanged: {
286+ if(rootTabs.selectedTab === stopwatchTab)
287+ stopwatchLoader.source = Qt.resolvedUrl("stopwatch/StopwatchPage.qml")
288+ else if(stopwatchLoader.source != "" && !stopwatchLoader.item.isRunning)
289+ stopwatchLoader.source = ""
290+
291+ if(rootTabs.selectedTab === timerTab)
292+ timerLoader.source = Qt.resolvedUrl("timer/TimerPage.qml")
293+ else if(timerLoader.source != "" && !timerLoader.item.isRunning)
294+ timerLoader.source = ""
295+
296+ if(rootTabs.selectedTab === alarmTab)
297+ alarmLoader.source = Qt.resolvedUrl("alarm/AlarmPage.qml")
298+ else
299+ alarmLoader.source = ""
300+
301+ if(rootTabs.selectedTab === clockTab)
302+ clockLoader.source = Qt.resolvedUrl("clock/ClockPage.qml")
303+ else
304+ clockLoader.source = ""
305+ }
306+
307 Tab {
308+ id: clockTab
309 objectName: "ClockTab"
310
311 title: i18n.tr("Clock")
312
313 // Tab content begins here
314- page: ClockPage {
315- id: clockPage
316+ page: Loader {
317+ id: clockLoader
318+ parent: clockTab
319+ anchors {
320+ left: parent.left
321+ right: parent.right
322+ bottom: parent.bottom
323+ }
324 }
325 }
326
327 // Disabled Alarm Tab until the feature is ready for use.
328 Tab {
329+ id: alarmTab
330 objectName: "AlarmTab"
331
332 title: i18n.tr("Alarm")
333
334- page: AlarmPage {
335- id: alarmPage
336+ AlarmModel {
337+ id: alarmModel
338+ Component.onCompleted: Utils.log("Alarm Database loaded")
339+ onModelReset: if (alarmLoader.source != "") alarmLoader.item.get_next_active_alarm()
340+ }
341
342- AlarmModel {
343- id: alarmModel
344- Component.onCompleted: Utils.log("Alarm Database loaded")
345- onModelReset: alarmPage.get_next_active_alarm()
346+ page: Loader {
347+ id: alarmLoader
348+ parent: alarmTab
349+ anchors {
350+ left: parent.left
351+ right: parent.right
352+ bottom: parent.bottom
353 }
354 }
355 }
356
357 Tab {
358+ id: timerTab
359 objectName: "TimerTab"
360
361 title: i18n.tr("Timer")
362
363- page: TimerPage {
364- id: timerPage
365+ page: Loader {
366+ id: timerLoader
367+ parent: timerTab
368+ anchors {
369+ left: parent.left
370+ right: parent.right
371+ bottom: parent.bottom
372+ }
373 }
374 }
375
376 Tab {
377+ id: stopwatchTab
378 objectName: "StopwatchTab"
379
380 title: i18n.tr("Stopwatch")
381
382- page: StopwatchPage {
383- id: stopwatchPage
384+ page: Loader {
385+ id: stopwatchLoader
386+ parent: stopwatchTab
387+ anchors {
388+ left: parent.left
389+ right: parent.right
390+ bottom: parent.bottom
391+ }
392 }
393 }
394 }

Subscribers

People subscribed via source and target branches