Merge lp:~gang65/ubuntu-clock-app/ubuntu-clock-mainclock-runtime-timezone-fix into lp:ubuntu-clock-app

Proposed by Bartosz Kosiorek
Status: Merged
Approved by: Nekhelesh Ramananthan
Approved revision: 417
Merged at revision: 396
Proposed branch: lp:~gang65/ubuntu-clock-app/ubuntu-clock-mainclock-runtime-timezone-fix
Merge into: lp:ubuntu-clock-app
Diff against target: 820 lines (+227/-158)
23 files modified
README.unittest (+3/-3)
app/MainPage.qml (+12/-4)
app/alarm/AlarmPage.qml (+12/-1)
app/alarm/AlarmSettingsPage.qml (+1/-20)
app/alarm/AlarmUtils.qml (+11/-1)
app/alarm/EditAlarmPage.qml (+6/-6)
app/clock/ClockPage.qml (+35/-11)
app/components/AnalogMode.qml (+17/-3)
app/components/Clock.qml (+8/-5)
app/components/DigitalMode.qml (+7/-7)
app/ubuntu-clock-app.qml (+9/-16)
app/worldclock/UserWorldCityDelegate.qml (+2/-16)
app/worldclock/WorldCityList.qml (+1/-1)
backend/modules/WorldClock/datetime.cpp (+25/-15)
backend/modules/WorldClock/datetime.h (+26/-15)
backend/modules/WorldClock/timezonemodel.cpp (+9/-6)
backend/modules/WorldClock/timezonemodel.h (+3/-2)
debian/changelog (+3/-0)
tests/manual/2014.com.ubuntu.clock:clock-tests/jobs/worldcity.pxu (+27/-0)
tests/unit/CMakeLists.txt (+2/-2)
tests/unit/MockClockApp.qml (+3/-10)
tests/unit/tst_alarm.qml (+0/-11)
tests/unit/tst_alarmUtils.qml (+5/-3)
To merge this branch: bzr merge lp:~gang65/ubuntu-clock-app/ubuntu-clock-mainclock-runtime-timezone-fix
Reviewer Review Type Date Requested Status
Nekhelesh Ramananthan Approve
Ubuntu Phone Apps Jenkins Bot continuous-integration Approve
Review via email: mp+271033@code.launchpad.net

Commit message

* Fix wrong date and time after changing timezone while clock running (LP: #1447441)

Description of the change

* Fix wrong date and time after changing timezone while clock running (LP: #1447441)

TODO:
Test manually Daylight saving time changing.
List of all switches from/to DST is available at:
https://en.wikipedia.org/wiki/Daylight_saving_time_by_country

To post a comment you must log in.
Revision history for this message
Nekhelesh Ramananthan (nik90) wrote :
Download full text (3.9 KiB)

Preliminary Code Review
-----------------------

1. This MP changes some core stuff of the clock app and has potential to introduce regressions. And so we need to make sure that the changes in this MP are the ones which are absolutely necessary and only fixes one issue. With that in mind, please revert changes made to Stopwatch_placeholder.svg, worldclock_placeholder.svg. This way if we have to revert this MP after it lands in trunk, we don't potentially lose out other improvements that were bundled along.

2. I see two variables clockTimeInMain and clockAnalogTimeInMain. It would be better if you could rename it as analogClockTime and digitalClockTime and drop the "Main" postfix.

3. Why is there a need for 2 variable names clockAnalogTimeInMain and clockAnalogTimeinClockPage? We're essentially passing clockAnalogTimeInMain as an argument to the clock page. Perhaps the variable in the clock page can be named as analogTime and digitalTime. The "InMain" and "InClockPage" seems a bit messy in my opinion.

4. As mentioned during our chat, I would like to see a comment above rotation: (parseInt(analogTime.split(":")[1]) * 6) + (parseInt(analogTime.split(":")[2]) / 10) explaining the input string and how it is split up into mulitple strings for better understandability.

5. I am bit afraid that we're losing out on important code below,

- text: {
- if (time.search(Qt.locale().amText) !== -1) {
- // 12 hour format detected with the localised AM text
- return time.replace(Qt.locale().amText, "").trim()
- }
- else if (time.search(Qt.locale().pmText) !== -1) {
- // 12 hour format detected with the localised PM text
- return time.replace(Qt.locale().pmText, "").trim()
- }
- else {
- // 24-hour format detected, return full time string
- return time
- }
- }
+ text: localizedTimeString.split(" ")[0]

The replace() function was used to fix bugs like https://bugs.launchpad.net/ubuntu-clock-app/+bug/1458808. Please again provide a comment above + text: localizedTimeString.split(" ")[0] with the input string format and what is being split. And please test this in the chineese locale to see if it works correctly.

6. In the following code below,

- subText: {
- /*
- FIXME: When the upstream QT bug at
- https://bugreports.qt-project.org/browse/QTBUG-40275 is fixed
- it will be possible to receive a datetime object directly
- instead of using this hack.
- */
- var localTime = new Date
- (
- localTimeSource.localDateString.split(":")[0],
- localTimeSource.localDateString.split(":")[1]-1,
- localTimeSource.localDateString.split(":")[2],
- localTimeSource.localTimeString.split(":")[0],
- localTimeSource.localTimeString.split(":")[1],
- localTimeSource.loca...

Read more...

review: Needs Fixing (preliminary code review)
Revision history for this message
Nekhelesh Ramananthan (nik90) wrote :

Also requires manual tests as we are fixing multiple critical bugs. Please write manual tests for *each* critical bug fixed. Ideally you should start with writing tests before fixing the bug as we follow Test Driven Development (TDD) ;)

review: Needs Fixing (preliminary code review)
Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
Nekhelesh Ramananthan (nik90) wrote :
Download full text (5.8 KiB)

A couples of fixed needed,

1. In the Settings Page, the time & date are shown as undefined.

2. The alarm function breaks (like in trunk) when editing alarms. But I guess we can tackle this in more detail in the next MP. So that's fine for now.

3. I would like a dedicated localized datetime property to be used here instead of localTimeString + localDateString analogy. Can you introduce a property in the c++ class called localizedDateTimeString and use that instead.

- subText: {
- /*
- FIXME: When the upstream QT bug at
- https://bugreports.qt-project.org/browse/QTBUG-40275 is fixed
- it will be possible to receive a datetime object directly
- instead of using this hack.
- */
- var localTime = new Date
- (
- localTimeSource.localDateString.split(":")[0],
- localTimeSource.localDateString.split(":")[1]-1,
- localTimeSource.localDateString.split(":")[2],
- localTimeSource.localTimeString.split(":")[0],
- localTimeSource.localTimeString.split(":")[1],
- localTimeSource.localTimeString.split(":")[2],
- localTimeSource.localTimeString.split(":")[3]
- )
- return localTime.toLocaleString()
- }
-
+ subText: localTimeSource.localTimeString + " " + localTimeSource.localDateString

4. This code has a logical flaw. For instance let's say the local user date time (in Poland) is 17th September 2015, 00:30. If I change to London, the local date time should be 16th September 2015, 23:30. Notice that the date has changed from 17th to 16th september. However in the code below, the date is obtained using the javascript date object which doesn't work well with timezones and may not be aware of this change leading to bugs in the date.

- localTime: clockTime
+ localTime: {
+ var date = new Date();
+ return new Date
+ (
+ date.getFullYear(),
+ date.getMonth(),
+ date.getDate(),
+ notLocalizedTimeString.split(":")[0],
+ notLocalizedTimeString.split(":")[1],
+ notLocalizedTimeString.split(":")[2],
+ 0
+ )
+ }

5. Same issue as issue #4.

+ var date = new Date();
+ var clockTime = new Date
+ (
+ date.getFullYear(),
+ date.getMonth(),
+ date.getDate(),
+ clockTimeString.split(":")[0],
+ clockTimeString.split(":")[1],
+ clockTimeString.split(":")[2],
+ 0
+ )

6. Same issue as issue #4

+ var date = new Date();
                     return new Date
                             (
- currentTime.localDateString.split(":")[0],
- ...

Read more...

review: Needs Fixing (manual testing + preliminary code review)
Revision history for this message
Nekhelesh Ramananthan (nik90) wrote :

The following code changes are not necessary. Let me explain the reasoning why,

These code changes would add additional roles to *every* world city delegate in the c++ side and cost us performance. Instead, let's stick with the original code that returns the correct timezone info (hh:mm) as expected and just pass the current local time of the user as a property to the worldcitydelegate.qml. So we save one additional role in the QAbsractModel.

Also do note that you added the extra role in the TimeZone Model class which is the base class. This role will be inherited unnecessarily by StaticTimeZoneModel and JsonTimeZoneModel class where this role is useless as we just show the time at that city.

If you want, instead of the hard code "hh:mm" format, you could return the time in Qt::DefaultLocaleShortDate format.

+ RoleTimezoneId,
+ RoleNotLocalizedTimeString,
+ RoleLocalizedTimeString,

- case RoleTimeString:
+ case RoleNotLocalizedTimeString:
         /*
          FIXME: Until https://bugreports.qt-project.org/browse/QTBUG-40275
          is fixed, we will have to return a string.
         */
- return worldCityTime.toString("hh:mm");
+ return worldCityTime.toString("hh:mm:ss");
+ case RoleLocalizedTimeString:
+ return worldCityTime.time().toString(Qt::DefaultLocaleShortDate);

review: Needs Fixing (performance regression)
Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote :
review: Needs Fixing (continuous-integration)
416. By Bartosz Kosiorek

Fix unit tests

Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
Bartosz Kosiorek (gang65) wrote :

I checked geolocation and after 40 minutes it was autorefreshed automatically:

qml: [LOG]: Starting geolocation update service at UTC time: Mon Nov 16 22:25:17 2015 GMT+0100
UbuntuClipboard - Got invalid serialized mime data. Ignoring it.
qml: [LOG]: Searching online for user location at http://api.geonames.org/findNearbyPlaceNameJSON?lat=51.746&lng=19.5053&username=krnekhelesh&style=full
qml: [LOG]: Stopping geolocation update service

417. By Bartosz Kosiorek

Remove not used variables

Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
Nekhelesh Ramananthan (nik90) wrote :

lgtm! Nice Work!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'README.unittest'
2--- README.unittest 2015-09-12 11:54:16 +0000
3+++ README.unittest 2015-10-08 21:50:22 +0000
4@@ -21,11 +21,11 @@
5
6 If you want to run all tests, then run the following command from the builddir,
7
8- $ make test
9+ $ ctest --output-on-failure
10
11 If you want more verbose output, then run,
12
13- $ ctest -V
14+ $ ctest -VV
15
16 Running individual test cases,
17 ==============================
18@@ -34,7 +34,7 @@
19 unit tests folder by,
20
21 * Navigate to the tests/unit directory
22- $ cd reboot/tests/unit
23+ $ cd tests/unit
24
25 * Run the test by providing their filenames
26 $ qmltestrunner -input tst_alarmLabel.qml
27
28=== modified file 'app/MainPage.qml'
29--- app/MainPage.qml 2015-09-11 13:29:07 +0000
30+++ app/MainPage.qml 2015-10-08 21:50:22 +0000
31@@ -30,8 +30,14 @@
32 id: _mainPage
33 objectName: "mainPage"
34
35- // Property to keep track of the clock time
36- property var clockTime: new Date()
37+ // String with not localized date and time in format "yyyy:MM:dd:hh:mm:ss", eg.: "2015:10:05:16:10:15"
38+ property string notLocalizedDateTimeString
39+
40+ // String with localized time, eg.: "4:10 PM"
41+ property string localizedTimeString
42+
43+ // String with localized date, eg.: "Thursday, 17 September 2015"
44+ property string localizedDateString
45
46 // Property to keep track of an app cold start status
47 property alias isColdStart: clockPage.isColdStart
48@@ -43,7 +49,7 @@
49 property var alarmModel
50
51 flickable: null
52- bottomEdgeTitle: _mainPage.visible ? alarmUtils.set_bottom_edge_title(alarmModel, clockTime)
53+ bottomEdgeTitle: _mainPage.visible ? alarmUtils.set_bottom_edge_title(alarmModel, notLocalizedDateTimeString)
54 : i18n.tr("No active alarms")
55
56 Component.onCompleted: {
57@@ -64,7 +70,9 @@
58 id: navigationModel
59 ClockPage {
60 id: clockPage
61- clockTime: _mainPage.clockTime
62+ notLocalizedClockTimeString: _mainPage.notLocalizedDateTimeString
63+ localizedClockTimeString: _mainPage.localizedTimeString
64+ localizedClockDateString: _mainPage.localizedDateString
65 width: clockApp.width
66 height: listview.height
67 }
68
69=== modified file 'app/alarm/AlarmPage.qml'
70--- app/alarm/AlarmPage.qml 2015-08-23 00:53:57 +0000
71+++ app/alarm/AlarmPage.qml 2015-10-08 21:50:22 +0000
72@@ -120,7 +120,18 @@
73 id: alarmListView
74 model: alarmModel
75 anchors.fill: parent
76- localTime: clockTime
77+ localTime: {
78+ return new Date
79+ (
80+ notLocalizedDateTimeString.split(":")[0],
81+ notLocalizedDateTimeString.split(":")[1] - 1,
82+ notLocalizedDateTimeString.split(":")[2],
83+ notLocalizedDateTimeString.split(":")[3],
84+ notLocalizedDateTimeString.split(":")[4],
85+ notLocalizedDateTimeString.split(":")[5],
86+ 0
87+ )
88+ }
89 }
90
91 Loader {
92
93=== modified file 'app/alarm/AlarmSettingsPage.qml'
94--- app/alarm/AlarmSettingsPage.qml 2015-08-26 23:35:50 +0000
95+++ app/alarm/AlarmSettingsPage.qml 2015-10-08 21:50:22 +0000
96@@ -231,26 +231,7 @@
97
98 SubtitledListItem {
99 text: i18n.tr("Change time and date")
100- subText: {
101- /*
102- FIXME: When the upstream QT bug at
103- https://bugreports.qt-project.org/browse/QTBUG-40275 is fixed
104- it will be possible to receive a datetime object directly
105- instead of using this hack.
106- */
107- var localTime = new Date
108- (
109- localTimeSource.localDateString.split(":")[0],
110- localTimeSource.localDateString.split(":")[1]-1,
111- localTimeSource.localDateString.split(":")[2],
112- localTimeSource.localTimeString.split(":")[0],
113- localTimeSource.localTimeString.split(":")[1],
114- localTimeSource.localTimeString.split(":")[2],
115- localTimeSource.localTimeString.split(":")[3]
116- )
117- return localTime.toLocaleString()
118- }
119-
120+ subText: localTimeSource.localizedCurrentDateString + " " + localTimeSource.localizedCurrentTimeString
121 onClicked: {
122 Qt.openUrlExternally("settings:///system/time-date")
123 }
124
125=== modified file 'app/alarm/AlarmUtils.qml'
126--- app/alarm/AlarmUtils.qml 2015-08-14 05:34:49 +0000
127+++ app/alarm/AlarmUtils.qml 2015-10-08 21:50:22 +0000
128@@ -51,9 +51,19 @@
129 }
130
131 // Function to set the bottom edge title with "Next Active in..."
132- function set_bottom_edge_title(alarmModel, clockTime) {
133+ function set_bottom_edge_title(alarmModel, clockTimeString) {
134 var bottom_edge_title = i18n.tr("No active alarms")
135
136+ var clockTime = new Date
137+ (
138+ clockTimeString.split(":")[0],
139+ clockTimeString.split(":")[1] - 1,
140+ clockTimeString.split(":")[2],
141+ clockTimeString.split(":")[3],
142+ clockTimeString.split(":")[4],
143+ clockTimeString.split(":")[5],
144+ 0
145+ )
146 /*
147 Check if alarm model received is valid and has saved alarms and only
148 then proceed to find the next active alarm.
149
150=== modified file 'app/alarm/EditAlarmPage.qml'
151--- app/alarm/EditAlarmPage.qml 2015-08-28 20:06:32 +0000
152+++ app/alarm/EditAlarmPage.qml 2015-10-08 21:50:22 +0000
153@@ -248,12 +248,12 @@
154 if(isNewAlarm) {
155 return new Date
156 (
157- currentTime.localDateString.split(":")[0],
158- currentTime.localDateString.split(":")[1] - 1,
159- currentTime.localDateString.split(":")[2],
160- currentTime.localTimeString.split(":")[0],
161- Math.ceil((parseInt(currentTime.localTimeString
162- .split(":")[1]) + 1) / 5) * 5,
163+ currentTime.notLocalizedCurrentDateTimeString.split(":")[0],
164+ currentTime.notLocalizedCurrentDateTimeString.split(":")[1] - 1,
165+ currentTime.notLocalizedCurrentDateTimeString.split(":")[2],
166+ currentTime.notLocalizedCurrentDateTimeString.split(":")[3],
167+ Math.ceil((parseInt(currentTime.notLocalizedCurrentDateTimeString
168+ .split(":")[4]) + 1) / 5) * 5,
169 0,
170 0
171 )
172
173=== modified file 'app/clock/ClockPage.qml'
174--- app/clock/ClockPage.qml 2015-08-26 23:30:10 +0000
175+++ app/clock/ClockPage.qml 2015-10-08 21:50:22 +0000
176@@ -31,12 +31,31 @@
177 // Property to keep track of the clock mode
178 property alias isDigital: clock.isDigital
179
180- // Property to keep track of the clock time
181- property var clockTime: new Date()
182+ // String with not localized date and time in format "yyyy:MM:dd:hh:mm:ss", eg.: "2015:10:05:16:10:15"
183+ property string notLocalizedClockTimeString
184+
185+ // String with localized time, eg.: "4:10 PM"
186+ property string localizedClockTimeString
187+
188+ // String with localized date, eg.: "Thursday, 17 September 2015"
189+ property string localizedClockDateString
190
191 // Property to keep track of app cold start status
192 property alias isColdStart: clock.isColdStart
193
194+ function get_current_utc_time() {
195+ var localDate = new Date()
196+ // FIXME Date() is not working correctly in runtime, when timezone is changed.
197+ // To avoid issues with Date(), clock app needs to be restarted every timezone is changed
198+ return new Date(localDate.getUTCFullYear(),
199+ localDate.getUTCMonth(),
200+ localDate.getUTCDate(),
201+ localDate.getUTCHours(),
202+ localDate.getUTCMinutes(),
203+ localDate.getUTCSeconds(),
204+ localDate.getUTCMilliseconds())
205+ }
206+
207 Component.onCompleted: {
208 console.log("[LOG]: Clock Page loaded")
209 otherElementsStartUpAnimation.start()
210@@ -106,14 +125,17 @@
211 If Clock App is brought from background after more than 30 mins,
212 query the user location to ensure it is up to date.
213 */
214+ // FIXME Date() is not working correctly in runtime, when timezone is changed.
215+ // To avoid issues with Date(), clock app needs to be restarted every timezone is changed
216+ var currentUTCTime = get_current_utc_time()
217 if(applicationState
218- && Math.abs(clock.analogTime - geoposition.lastUpdate) > 1800000) {
219- if(!geoposition.active)
220+ && Math.abs(currentUTCTime - geoposition.lastUpdate) > 1800000) {
221+ if(!geoposition.active) {
222+ console.log("[LOG]: Starting geolocation update service at UTC time: " + currentUTCTime)
223 geoposition.start()
224- }
225-
226- else if (!applicationState) {
227- geoposition.lastUpdate = clock.analogTime
228+ }
229+ } else if (!applicationState) {
230+ geoposition.lastUpdate = currentUTCTime
231 }
232 }
233 }
234@@ -161,10 +183,12 @@
235 objectName: "clock"
236
237 Component.onCompleted: {
238- geoposition.lastUpdate = analogTime
239+ geoposition.lastUpdate = get_current_utc_time()
240 }
241
242- analogTime: clockTime
243+ notLocalizedDateTimeString: notLocalizedClockTimeString
244+ localizedTimeString: localizedClockTimeString
245+ localizedDateString: localizedClockDateString
246
247 anchors {
248 verticalCenter: parent.top
249@@ -182,7 +206,7 @@
250 horizontalCenter: parent.horizontalCenter
251 }
252
253- text: clock.analogTime.toLocaleDateString()
254+ text: clock.localizedDateString
255
256 opacity: 0
257 color: locationRow.visible ? Theme.palette.normal.baseText : UbuntuColors.midAubergine
258
259=== modified file 'app/components/AnalogMode.qml'
260--- app/components/AnalogMode.qml 2015-08-14 05:34:49 +0000
261+++ app/components/AnalogMode.qml 2015-10-08 21:50:22 +0000
262@@ -53,7 +53,12 @@
263 smooth: true
264 source: "../graphics/Hour_Hand.png"
265 fillMode: Image.PreserveAspectFit
266- rotation: (analogTime.getHours() * 30) + (analogTime.getMinutes() / 2)
267+ // notLocalizedDateTimeString.split(":")[3] is hours
268+ // notLocalizedDateTimeString.split(":")[4] is minutes
269+ // We need to calculate degree number for rotation (0 degrees means no rotation).
270+ // Full rotate has 360 degrees and we have 12 hours in clock face,
271+ // For hours: 360deg/12h=30 deg/h, for minutes 30deg/60min= 0.5 deg/min
272+ rotation: (parseInt(notLocalizedDateTimeString.split(":")[3]) * 30) + (parseInt(notLocalizedDateTimeString.split(":")[4]) * 0.5)
273 }
274
275 Image {
276@@ -65,7 +70,12 @@
277 smooth: true
278 source: "../graphics/Minute_Hand.png"
279 fillMode: Image.PreserveAspectFit
280- rotation: (analogTime.getMinutes() * 6) + (analogTime.getSeconds() / 10)
281+ // notLocalizedDateTimeString.split(":")[4] is minutes
282+ // notLocalizedDateTimeString.split(":")[5] is seconds
283+ // We need to calculate degree number for rotation (0 degrees means no rotation).
284+ // Full rotate has 360 degrees and we have 60 miutes in clock face,
285+ // For minutes: 360deg/60min=6 deg/min, for seconds 6deg/60sec= 0.1 deg/sec
286+ rotation: (parseInt(notLocalizedDateTimeString.split(":")[4]) * 6) + (parseInt(notLocalizedDateTimeString.split(":")[5]) * 0.1)
287 }
288
289 Image {
290@@ -78,7 +88,11 @@
291 visible: showSeconds
292 source: "../graphics/Second_Hand.png"
293 fillMode: Image.PreserveAspectFit
294- rotation: visible ? analogTime.getSeconds() * 6 : 0
295+ // notLocalizedDateTimeString.split(":")[5] is seconds
296+ // We need to calculate degree number for rotation (0 degrees means no rotation).
297+ // Full rotate has 360 degrees and we have 60 seconds in clock face,
298+ // For seconds 360deg/60sec= 6 deg/sec
299+ rotation: visible ? parseInt(notLocalizedDateTimeString.split(":")[5]) * 6 : 0
300 }
301
302 Image {
303
304=== modified file 'app/components/Clock.qml'
305--- app/components/Clock.qml 2015-08-14 05:34:49 +0000
306+++ app/components/Clock.qml 2015-10-08 21:50:22 +0000
307@@ -41,11 +41,14 @@
308 ClockCircle {
309 id: _outerCircle
310
311- // Property to set the analog time
312- property var analogTime
313-
314- // Property to set the digital time label
315- property string time: Qt.formatTime(analogTime)
316+ // String with not localized date and time in format "yyyy:MM:dd:hh:mm:ss", eg.: "2015:10:05:16:10:15"
317+ property string notLocalizedDateTimeString
318+
319+ // String with localized time, eg.: "4:10 PM"
320+ property string localizedTimeString
321+
322+ // String with localized date, eg.: "Thursday, 17 September 2015"
323+ property string localizedDateString
324
325 // Property to keep track of the clock mode
326 property alias isDigital: clockModeFlipable.isDigital
327
328=== modified file 'app/components/DigitalMode.qml'
329--- app/components/DigitalMode.qml 2015-08-14 05:34:49 +0000
330+++ app/components/DigitalMode.qml 2015-10-08 21:50:22 +0000
331@@ -56,17 +56,17 @@
332 color: UbuntuColors.midAubergine
333 font.pixelSize: units.dp(1)
334 text: {
335- if (time.search(Qt.locale().amText) !== -1) {
336+ if (localizedTimeString.search(Qt.locale().amText) !== -1) {
337 // 12 hour format detected with the localised AM text
338- return time.replace(Qt.locale().amText, "").trim()
339+ return localizedTimeString.replace(Qt.locale().amText, "").trim()
340 }
341- else if (time.search(Qt.locale().pmText) !== -1) {
342+ else if (localizedTimeString.search(Qt.locale().pmText) !== -1) {
343 // 12 hour format detected with the localised PM text
344- return time.replace(Qt.locale().pmText, "").trim()
345+ return localizedTimeString.replace(Qt.locale().pmText, "").trim()
346 }
347 else {
348 // 24-hour format detected, return full time string
349- return time
350+ return localizedTimeString
351 }
352 }
353 }
354@@ -81,11 +81,11 @@
355 font.pixelSize: units.dp(1)
356 visible: text !== ""
357 text: {
358- if (time.search(Qt.locale().amText) !== -1) {
359+ if (localizedTimeString.search(Qt.locale().amText) !== -1) {
360 // 12 hour format detected with the localised AM text
361 return Qt.locale().amText
362 }
363- else if (time.search(Qt.locale().pmText) !== -1) {
364+ else if (localizedTimeString.search(Qt.locale().pmText) !== -1) {
365 // 12 hour format detected with the localised PM text
366 return Qt.locale().pmText
367 }
368
369=== modified file 'app/ubuntu-clock-app.qml'
370--- app/ubuntu-clock-app.qml 2015-09-09 20:26:42 +0000
371+++ app/ubuntu-clock-app.qml 2015-10-08 21:50:22 +0000
372@@ -135,24 +135,17 @@
373 is required.
374 */
375
376- /*
377- #FIXME: When the upstream QT bug at
378- https://bugreports.qt-project.org/browse/QTBUG-40275 is fixed it will be
379- possible to receive a datetime object directly instead of using this hack.
380- */
381-
382 alarmModel: alarmModelLoader.item
383 bottomEdgeEnabled: alarmModelLoader.status === Loader.Ready && alarmModelLoader.item.isReady && isClockPage
384- clockTime: new Date
385- (
386- localTimeSource.localDateString.split(":")[0],
387- localTimeSource.localDateString.split(":")[1]-1,
388- localTimeSource.localDateString.split(":")[2],
389- localTimeSource.localTimeString.split(":")[0],
390- localTimeSource.localTimeString.split(":")[1],
391- localTimeSource.localTimeString.split(":")[2],
392- localTimeSource.localTimeString.split(":")[3]
393- )
394+
395+ /*
396+ FIXME: When the upstream QT bug at
397+ https://bugreports.qt-project.org/browse/QTBUG-40275 is fixed
398+ it will be possible to receive a datetime object directly for notLocalizedDateTimeString variable.
399+ */
400+ notLocalizedDateTimeString: localTimeSource.notLocalizedCurrentDateTimeString
401+ localizedTimeString: localTimeSource.localizedCurrentTimeString
402+ localizedDateString: localTimeSource.localizedCurrentDateString
403 }
404 }
405 }
406
407=== modified file 'app/worldclock/UserWorldCityDelegate.qml'
408--- app/worldclock/UserWorldCityDelegate.qml 2015-08-29 01:45:19 +0000
409+++ app/worldclock/UserWorldCityDelegate.qml 2015-10-08 21:50:22 +0000
410@@ -73,27 +73,13 @@
411 id: localTimeVisual
412 objectName: "localTimeVisual" + index
413
414- /*
415- This function would not be required once the upstream QT bug at
416- https://bugreports.qt-project.org/browse/QTBUG-40275 is fixed.
417- Due to this bug we are returning a time string instead of a
418- time object which forces us to parse the string and convert it
419- into a time object here.
420- */
421- function getTime(timeString) {
422- var properTime = new Date()
423- properTime.setHours(timeString.split(":")[0])
424- properTime.setMinutes(timeString.split(":")[1])
425- properTime.setSeconds(0)
426- return properTime
427- }
428-
429 fontSize: units.dp(14)
430 periodFontSize: units.dp(7)
431 innerCircleWidth: units.gu(5)
432 width: units.gu(7)
433
434- analogTime: getTime(model.localTime)
435+ notLocalizedDateTimeString: model.notLocalizedZoneTime
436+ localizedTimeString: model.localizedZoneTime
437
438 anchors.centerIn: parent
439
440
441=== modified file 'app/worldclock/WorldCityList.qml'
442--- app/worldclock/WorldCityList.qml 2015-09-03 21:07:54 +0000
443+++ app/worldclock/WorldCityList.qml 2015-10-08 21:50:22 +0000
444@@ -355,7 +355,7 @@
445
446 Label {
447 id: _localTime
448- text: localTime
449+ text: localizedZoneTime
450 anchors {
451 right: parent.right
452 rightMargin: units.gu(2)
453
454=== modified file 'backend/modules/WorldClock/datetime.cpp'
455--- backend/modules/WorldClock/datetime.cpp 2015-08-25 16:04:13 +0000
456+++ backend/modules/WorldClock/datetime.cpp 2015-10-08 21:50:22 +0000
457@@ -24,8 +24,10 @@
458 QObject(parent)
459 {
460 // Initialise the date and time at start rather than wait for a sec to do so.
461- m_localtime = QDateTime::currentDateTime().toString("hh:mm:ss:z");
462- m_localdate = QDateTime::currentDateTime().toString("yyyy:M:d");
463+
464+ m_notLocalizedCurrentDateTime = QDateTime::currentDateTime().toString("yyyy:MM:dd:hh:mm:ss");
465+ m_localizedCurrentTime = QTime::currentTime().toString(Qt::DefaultLocaleShortDate);
466+ m_localizedCurrentDate = QDate::currentDate().toString(Qt::DefaultLocaleLongDate);
467
468 m_updateTimer.setInterval(1000);
469 connect(&m_updateTimer, &QTimer::timeout, this, &DateTime::update);
470@@ -33,23 +35,31 @@
471 m_updateTimer.start();
472 }
473
474-QString DateTime::localTimeString() const
475-{
476- return m_localtime;
477-}
478-
479-QString DateTime::localDateString() const
480-{
481- return m_localdate;
482+QString DateTime::notLocalizedCurrentDateTimeString() const
483+{
484+ return m_notLocalizedCurrentDateTime;
485+}
486+
487+QString DateTime::localizedCurrentTimeString() const
488+{
489+ return m_localizedCurrentTime;
490+}
491+
492+QString DateTime::localizedCurrentDateString() const
493+{
494+ return m_localizedCurrentDate;
495 }
496
497 void DateTime::update()
498 {
499- m_localtime = QDateTime::currentDateTime().toString("hh:mm:ss:z");
500- emit localTimeStringChanged();
501-
502- m_localdate = QDateTime::currentDateTime().toString("yyyy:M:d");
503- emit localDateStringChanged();
504+ m_notLocalizedCurrentDateTime = QDateTime::currentDateTime().toString("yyyy:MM:dd:hh:mm:ss");
505+ emit notLocalizedCurrentDateTimeStringChanged();
506+
507+ m_localizedCurrentTime = QTime::currentTime().toString(Qt::DefaultLocaleShortDate);
508+ emit localizedCurrentTimeStringChanged();
509+
510+ m_localizedCurrentDate = QDate::currentDate().toString(Qt::DefaultLocaleLongDate);
511+ emit localizedCurrentDateStringChanged();
512 }
513
514 int DateTime::updateInterval() const
515
516=== modified file 'backend/modules/WorldClock/datetime.h'
517--- backend/modules/WorldClock/datetime.h 2015-08-25 16:04:13 +0000
518+++ backend/modules/WorldClock/datetime.h 2015-10-08 21:50:22 +0000
519@@ -41,15 +41,20 @@
520 in the correct user locale.
521 */
522
523- // Property to determine the local time string (format hh:mm:ss)
524- Q_PROPERTY(QString localTimeString
525- READ localTimeString
526- NOTIFY localTimeStringChanged)
527-
528- // Property to determine the local date string (format yyyy:M:d)
529- Q_PROPERTY(QString localDateString
530- READ localDateString
531- NOTIFY localDateStringChanged)
532+ // Property to determine not localized string of local time (format yyyy:MM:dd:hh:mm:ss)
533+ Q_PROPERTY(QString notLocalizedCurrentDateTimeString
534+ READ notLocalizedCurrentDateTimeString
535+ NOTIFY notLocalizedCurrentDateTimeStringChanged)
536+
537+ // Property to determine the localized string of local time (format Qt::DefaultLocaleShortDate)
538+ Q_PROPERTY(QString localizedCurrentTimeString
539+ READ localizedCurrentTimeString
540+ NOTIFY localizedCurrentTimeStringChanged)
541+
542+ // Property to determine the localized string of local date (format Qt::DefaultLocaleLongDate)
543+ Q_PROPERTY(QString localizedCurrentDateString
544+ READ localizedCurrentDateString
545+ NOTIFY localizedCurrentDateStringChanged)
546 public:
547 DateTime(QObject *parent = 0);
548
549@@ -59,18 +64,23 @@
550 // Function to set the update interval
551 void setUpdateInterval(int updateInterval);
552
553+ QString notLocalizedCurrentDateTimeString() const;
554+
555 // Function to read the local time string
556- QString localTimeString() const;
557+ QString localizedCurrentTimeString() const;
558
559 // Function to read the local date string
560- QString localDateString() const;
561+ QString localizedCurrentDateString() const;
562
563 signals:
564+
565+ void notLocalizedCurrentDateTimeStringChanged();
566+
567 // Signal to notify the local time string change to QML
568- void localTimeStringChanged();
569+ void localizedCurrentTimeStringChanged();
570
571 // Signal to notify the local date string change in QML
572- void localDateStringChanged();
573+ void localizedCurrentDateStringChanged();
574
575 // Signal to notify the updateInterval change to QML
576 void updateIntervalChanged();
577@@ -84,8 +94,9 @@
578
579 private:
580 // Private copies of the local time and date
581- QString m_localtime;
582- QString m_localdate;
583+ QString m_notLocalizedCurrentDateTime;
584+ QString m_localizedCurrentTime;
585+ QString m_localizedCurrentDate;
586
587 // Private internal timer to update the values at a specified interval
588 QTimer m_updateTimer;
589
590=== modified file 'backend/modules/WorldClock/timezonemodel.cpp'
591--- backend/modules/WorldClock/timezonemodel.cpp 2015-08-25 16:11:38 +0000
592+++ backend/modules/WorldClock/timezonemodel.cpp 2015-10-08 21:50:22 +0000
593@@ -74,7 +74,7 @@
594 return m_citiesData.at(row).cityName;
595 case RoleCountryName:
596 return m_citiesData.at(row).countryName;
597- case RoleTimeZoneId:
598+ case RoleTimezoneId:
599 return m_citiesData.at(row).timeZone.id();
600 }
601
602@@ -82,12 +82,14 @@
603 QDateTime worldCityTime(currentDateTime.toTimeZone(m_citiesData.at(row).timeZone));
604
605 switch (role) {
606- case RoleTimeString:
607+ case RoleNotLocalizedTimeString:
608 /*
609 FIXME: Until https://bugreports.qt-project.org/browse/QTBUG-40275
610 is fixed, we will have to return a string.
611 */
612- return worldCityTime.toString("hh:mm");
613+ return worldCityTime.toString("yyyy:MM:dd:hh:mm:ss");
614+ case RoleLocalizedTimeString:
615+ return worldCityTime.time().toString(Qt::DefaultLocaleShortDate);
616 case RoleTimeTo:
617 /*
618 FIXME: Workaround for currentDateTime.secsTo(worldCityTime) which returns
619@@ -109,8 +111,9 @@
620 roles.insert(RoleCityId, "cityId");
621 roles.insert(RoleCityName, "cityName");
622 roles.insert(RoleCountryName, "countryName");
623- roles.insert(RoleTimeZoneId, "timezoneID");
624- roles.insert(RoleTimeString, "localTime");
625+ roles.insert(RoleTimezoneId, "timezoneID");
626+ roles.insert(RoleNotLocalizedTimeString, "notLocalizedZoneTime");
627+ roles.insert(RoleLocalizedTimeString, "localizedZoneTime");
628 roles.insert(RoleTimeTo, "timeTo");
629 return roles;
630 }
631@@ -150,7 +153,7 @@
632 QModelIndex startIndex = index(0);
633 QModelIndex endIndex = index(m_citiesData.count() - 1);
634 QVector<int> roles;
635- roles << RoleTimeString << RoleTimeTo;
636+ roles << RoleLocalizedTimeString << RoleNotLocalizedTimeString << RoleTimeTo;
637 emit dataChanged(startIndex, endIndex, roles);
638 }
639
640
641=== modified file 'backend/modules/WorldClock/timezonemodel.h'
642--- backend/modules/WorldClock/timezonemodel.h 2015-08-25 16:11:38 +0000
643+++ backend/modules/WorldClock/timezonemodel.h 2015-10-08 21:50:22 +0000
644@@ -52,8 +52,9 @@
645 RoleCityId,
646 RoleCityName,
647 RoleCountryName,
648- RoleTimeZoneId,
649- RoleTimeString,
650+ RoleTimezoneId,
651+ RoleNotLocalizedTimeString,
652+ RoleLocalizedTimeString,
653 RoleTimeTo,
654 };
655
656
657=== modified file 'debian/changelog'
658--- debian/changelog 2015-09-12 11:29:50 +0000
659+++ debian/changelog 2015-10-08 21:50:22 +0000
660@@ -12,7 +12,10 @@
661 * Fix wrong time after changing timezone, when stopwatch is running (LP: #1491024)
662 * Reduce size of images (with tinypng.com) to decrease click image size (LP: #1492057)
663 * Fix Czech Republic country name (LP: #1494004)
664+ * Fix wrong date and time after changing timezone while clock running (LP: #1480546)
665 * Fix stopwatch issue appering during changing timezone during runtime (LP: #1493358)
666+ * Fix Daylight Saving Time issues (LP: #1437805)
667+ * Fix time for second location wrong after daylight saving started (LP: #1457523)
668
669 -- Bartosz Kosiorek <gang65@poczta.onet.pl> Wed, 02 Sep 2015 15:16:29 +0200
670
671
672=== modified file 'tests/manual/2014.com.ubuntu.clock:clock-tests/jobs/worldcity.pxu'
673--- tests/manual/2014.com.ubuntu.clock:clock-tests/jobs/worldcity.pxu 2015-08-23 09:35:44 +0000
674+++ tests/manual/2014.com.ubuntu.clock:clock-tests/jobs/worldcity.pxu 2015-10-08 21:50:22 +0000
675@@ -23,3 +23,30 @@
676 7. Press the add city button.
677 The add world city page is shown with a list of cities in Espanol
678
679+id: worldcity/timezone-change
680+plugin: manual
681+_summary: Test to check if clock time and world city times are correct after changing timezone during runtime
682+estimated_duration: 600
683+_description:
684+ Test to check if clock time and world city times are correct after changing timezone during runtime
685+ 1. Launch the clock app.
686+ Clock app opens showing the current local time.
687+ 2. Press on clock face and switch to Digital mode.
688+ Main clock is showing current time in digital mode.
689+ 3. Press the add city button.
690+ The add world city page is shown with a list of cities.
691+ 4. Select a city from different timezone.
692+ The main clock page will be shown with the city you selected.
693+ 5. Press the add city button.
694+ The add world city page is shown with a list of cities.
695+ 6. Select a city from current timezone.
696+ The main clock page will be shown with the city you selected.
697+ 7. Remeber time of World Cities and Main Clock
698+ 8. Switch to the system settings app. Navigate to Date & Time.
699+ The field with current timezone should be visible. Remember current timezone setting.
700+ 9. Press the current timezone field and change system timezone to something different.
701+ The timezone field now shows the newly selected timezone.
702+ 10. Switch to clock app.
703+ The Main Clock hours have not been changed.
704+ The Main Clock shows the same time as on top bar (system time).
705+ The World Clocks hours should remains unchanged.
706
707=== modified file 'tests/unit/CMakeLists.txt'
708--- tests/unit/CMakeLists.txt 2015-08-09 21:50:06 +0000
709+++ tests/unit/CMakeLists.txt 2015-10-08 21:50:22 +0000
710@@ -9,7 +9,7 @@
711 )
712
713 macro(DECLARE_QML_TEST TST_NAME TST_QML_FILE)
714- if(USE_XVFB)
715+ if(USE_XVFB AND XVFB_RUN_BIN)
716 set(COMMAND_PREFIX ${XVFB_RUN_BIN} -a -s "-screen 0 400x600x24")
717 else()
718 set(COMMAND_PREFIX "")
719@@ -20,7 +20,7 @@
720 )
721 endmacro()
722
723-if(QMLTESTRUNNER_BIN AND XVFB_RUN_BIN)
724+if(QMLTESTRUNNER_BIN)
725 declare_qml_test("AlarmLabel" tst_alarmLabel.qml)
726 declare_qml_test("AlarmRepeat" tst_alarmRepeat.qml)
727 declare_qml_test("Alarm" tst_alarm.qml)
728
729=== modified file 'tests/unit/MockClockApp.qml'
730--- tests/unit/MockClockApp.qml 2015-08-26 23:30:10 +0000
731+++ tests/unit/MockClockApp.qml 2015-10-08 21:50:22 +0000
732@@ -82,16 +82,9 @@
733
734 alarmModel: alarmModelLoader.item
735 bottomEdgeEnabled: alarmModelLoader.status === Loader.Ready && alarmModelLoader.item.isReady && isClockPage
736- clockTime: new Date
737- (
738- localTimeSource.localDateString.split(":")[0],
739- localTimeSource.localDateString.split(":")[1]-1,
740- localTimeSource.localDateString.split(":")[2],
741- localTimeSource.localTimeString.split(":")[0],
742- localTimeSource.localTimeString.split(":")[1],
743- localTimeSource.localTimeString.split(":")[2],
744- localTimeSource.localTimeString.split(":")[3]
745- )
746+ notLocalizedDateTimeString: localTimeSource.notLocalizedCurrentDateTimeString
747+ localizedTimeString: localTimeSource.localizedCurrentTimeString
748+ localizedDateString: localTimeSource.localizedCurrentDateString
749 }
750 }
751 }
752
753=== modified file 'tests/unit/tst_alarm.qml'
754--- tests/unit/tst_alarm.qml 2015-08-26 23:30:10 +0000
755+++ tests/unit/tst_alarm.qml 2015-10-08 21:50:22 +0000
756@@ -27,17 +27,6 @@
757 width: units.gu(40)
758 height: units.gu(70)
759
760- property var clockTime: new Date
761- (
762- localTimeSource.localDateString.split(":")[0],
763- localTimeSource.localDateString.split(":")[1]-1,
764- localTimeSource.localDateString.split(":")[2],
765- localTimeSource.localTimeString.split(":")[0],
766- localTimeSource.localTimeString.split(":")[1],
767- localTimeSource.localTimeString.split(":")[2],
768- localTimeSource.localTimeString.split(":")[3]
769- )
770-
771 AlarmModel {
772 id: alarmModel
773 }
774
775=== modified file 'tests/unit/tst_alarmUtils.qml'
776--- tests/unit/tst_alarmUtils.qml 2015-08-12 16:57:29 +0000
777+++ tests/unit/tst_alarmUtils.qml 2015-10-08 21:50:22 +0000
778@@ -27,6 +27,7 @@
779
780 property var futureTime: new Date()
781 property var currentTime: new Date()
782+ property var mock_notLocalizedDateTimeString: ""
783
784 AlarmUtils {
785 id: alarmUtils
786@@ -48,6 +49,7 @@
787 mockAlarmDatabase.append({"name": "Alarm1", "date": futureTime, "enabled": false})
788 futureTime.setHours((futureTime.getHours() + 5))
789 mockAlarmDatabase.append({"name": "Alarm2", "date": futureTime, "enabled": true})
790+ mock_notLocalizedDateTimeString = currentTime.getFullYear().toString() + ":" + (currentTime.getMonth() + 1).toString() + ":" + currentTime.getDate().toString() + ":" + currentTime.getHours().toString() + ":" + currentTime.getMinutes().toString() + ":" +currentTime.getSeconds().toString()
791 }
792
793 /*
794@@ -55,7 +57,7 @@
795 to the active alarms amongst other disabled alarms.
796 */
797 function test_bottomEdgeTitleMustDisplayActiveAlarm() {
798- var result = alarmUtils.set_bottom_edge_title(mockAlarmDatabase, currentTime)
799+ var result = alarmUtils.set_bottom_edge_title(mockAlarmDatabase, mock_notLocalizedDateTimeString)
800 compare(result, "Next Alarm in 7h 1m", "Bottom edge title is incorrect")
801 }
802
803@@ -65,7 +67,7 @@
804 */
805 function test_bottomEdgeTitleMustDisplayNoActiveAlarm() {
806 mockAlarmDatabase.set(1, {"enabled": false})
807- var result = alarmUtils.set_bottom_edge_title(mockAlarmDatabase, currentTime)
808+ var result = alarmUtils.set_bottom_edge_title(mockAlarmDatabase, mock_notLocalizedDateTimeString)
809 compare(result, "No active alarms", "Bottom edge title is not correctly set when there are no enabled alarms")
810 mockAlarmDatabase.set(1, {"enabled": true})
811 }
812@@ -76,7 +78,7 @@
813 */
814 function test_bottomEdgeTitleMustDisplayNextActiveAlarm() {
815 mockAlarmDatabase.set(0, {"enabled": true})
816- var result = alarmUtils.set_bottom_edge_title(mockAlarmDatabase, currentTime)
817+ var result = alarmUtils.set_bottom_edge_title(mockAlarmDatabase, mock_notLocalizedDateTimeString)
818 compare(result, "Next Alarm in 2h 1m", "Bottom edge title is not correctly set to the next immediate active alarm where there are multiple active alarms.")
819 mockAlarmDatabase.set(0, {"enabled": false})
820 }

Subscribers

People subscribed via source and target branches