Merge lp:~nik90/ubuntu-clock-app/sync-clock-backend into lp:ubuntu-clock-app/saucy

Proposed by Nekhelesh Ramananthan
Status: Merged
Approved by: Alan Pope 🍺🐧🐱 πŸ¦„
Approved revision: 223
Merged at revision: 205
Proposed branch: lp:~nik90/ubuntu-clock-app/sync-clock-backend
Merge into: lp:ubuntu-clock-app/saucy
Diff against target: 370 lines (+124/-59)
5 files modified
clock/ClockPage.qml (+57/-31)
clock/EasterEgg.qml (+3/-3)
clock/GeoIPModel.qml (+31/-0)
clock/WorldClockModel.qml (+21/-22)
clock/WorldPage.qml (+12/-3)
To merge this branch: bzr merge lp:~nik90/ubuntu-clock-app/sync-clock-backend
Reviewer Review Type Date Requested Status
Ubuntu Phone Apps Jenkins Bot continuous-integration Approve
David Planella Needs Information
Review via email: mp+186923@code.launchpad.net

Commit message

This commits implements the following,

- Remove the ability to see world clock as current location (since on changing system time, this will not be reflected in the clock app causing a discrepancy)
- Always show current system time to maintain uniformity between clock app, indicator time and welcome screen time
- Change world clock time diff calculation to be based on utc time instead of local time (more reliable)
- Add the ability for the user to edit/set the current location name
- Retrieve current location *automatically* using geoIP from http://geoip.ubuntu.com/lookup

Description of the change

This MP implements the following,

- Remove the ability to see world clock as current location (since on changing system time, this will not be reflected in the clock app causing a discrepancy)
- Always show current system time to maintain uniformity between clock app, indicator time and welcome screen time
- Change world clock time diff calculation to be based on utc time instead of local time (more reliable)
- Add the ability for the user to edit/set the current location name
- Retrieve current location *automatically* using geoIP from http://geoip.ubuntu.com/lookup

GPS Location backend (using qtlocation) will be added in a future MP. This MP is more focused on fixing issues with the clock app not following system time. As a result, dont want these bug fixes waiting on GPS.

To post a comment you must log in.
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
David Planella (dpm) wrote :

Nice work as usual, Nekhelesh. A couple of questions:

121 + text: i18n.tr("Retrieving current location...")

- What's the behaviour if you're offline?

- Is GeoIP a backend that could be accessed via Qt Location instead of querying http://geoip.ubuntu.com directly?

review: Needs Information
Revision history for this message
Nekhelesh Ramananthan (nik90) wrote :

> Nice work as usual, Nekhelesh. A couple of questions:
>
> 121 + text: i18n.tr("Retrieving current location...")
>
> - What's the behaviour if you're offline?
>

Nice question. This is something I specifically tested to ensure that when offline, it notifies the user. So when offline, it will set the string to "Set current location name". The user can click the current location list item to set it manually via the same database used to add a world city. You can test this behaviour on your desktop by clearing the clock database and then going offline.

> - Is GeoIP a backend that could be accessed via Qt Location instead of
> querying http://geoip.ubuntu.com directly?

I will look into this. Popey contact bzoltan for sample code to get location via GPS. You can find his branch at https://code.launchpad.net/~bzoltan/+junk/SystemInfo. However bzoltan while testing it came to the conclusion that it takes a long time to find a gps satellite and retrieve the location coordinates. He said that a bug report needs to be reported on this. I was told all this by Popey, so please contact him regarding gps support. As for using qtlocation for geoIP, the same code used by bzoltan can be used as well for geoIP. However on testing it on my desktop and phone, I found it unreliable to get coordinates via geoIP using qtlocation. Sometime it worked and sometime it didnt.

Revision history for this message
Nekhelesh Ramananthan (nik90) wrote :

After a discussion with dpm and bzoltan this morning, it was concluded that qtlocation is not able to retrieve location reliably and quickly. And hence until that is worked out, the direct lookup method is acceptable. We will return to the qtlocation method in the near future.

Revision history for this message
David Planella (dpm) wrote :

Note that the the initial (long) delay in getting the GPS location is
probably to be expected and it is not a bug in Qt Location.

I'm not an expert on GPS, but I'm told it can take around 12 mins to get a
fix (your position from GPS measurements), as we currently don't have any
AGPS support to speed it. Take this statement with a pinch of salt, but
also bear it in mind when testing GPS support.

Thanks!

On Wed, Sep 25, 2013 at 1:44 PM, Nekhelesh Ramananthan <
<email address hidden>> wrote:

> The proposal to merge lp:~nik90/ubuntu-clock-app/sync-clock-backend into
> lp:ubuntu-clock-app has been updated.
>
> Status: Needs review => Work in progress
>
> For more details, see:
>
> https://code.launchpad.net/~nik90/ubuntu-clock-app/sync-clock-backend/+merge/186923
> --
>
> https://code.launchpad.net/~nik90/ubuntu-clock-app/sync-clock-backend/+merge/186923
> You are reviewing the proposed merge of
> lp:~nik90/ubuntu-clock-app/sync-clock-backend into lp:ubuntu-clock-app.
>

Revision history for this message
Nekhelesh Ramananthan (nik90) wrote :

@dpm, thnx for the info. I will be testing the qtlocation this weekend. While using qtlocation, i had a few crashes on the desktop which is not good. Anyways this branch is more focussed on fixing the default time shown by the clock app and ensure it is the same as the system time. As a bonus, I added the geoIP feature for automatic location retrieval. So from the perspective I consider this MP complete and ready for trunk merge.

As said above, I will test qtlocation in the weekend and propose that in a new branch by itself to spot any regression due to qtlocation quicker. Please approve if you agree.

222. By Nekhelesh Ramananthan

merge from trunk

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

merged trunk

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

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'clock/ClockPage.qml'
2--- clock/ClockPage.qml 2013-09-26 06:14:47 +0000
3+++ clock/ClockPage.qml 2013-09-27 08:38:25 +0000
4@@ -30,18 +30,23 @@
5
6 // Property to hold the formatted time string to show on the screen
7 property string currentTimeFormatted
8- property real currentTimeStamp
9+ property real currentUTCTime
10 property real diff: new Date().getTimezoneOffset()
11+ property alias currentCity: currentLocationCity.text
12+ property alias currentLat: easterEggCircle.latitude
13+ property alias currentLng: easterEggCircle.longitude
14
15 Component.onCompleted: {
16- Utils.log("ClockPage loaded");
17- diff = worldModel.timeDiff;
18- currentLocationCity.text = worldModel.city;
19- easterEggCircle.longitude = worldModel.longitude;
20- easterEggCircle.latitude = worldModel.latitude;
21+ // TODO: Query GPS for location data
22+ Utils.log("ClockPage loaded");
23+ if (worldModel.city !== "undefined") {
24+ currentCity = worldModel.city;
25+ currentLng = worldModel.longitude;
26+ currentLat = worldModel.latitude;
27+ }
28 Utils.log("Saved Current Location: " + worldModel.city);
29- Utils.log("Saved Current Location Coordinates: " + easterEggCircle.longitude + "," + easterEggCircle.latitude)
30- currentTimeFormatted = Qt.formatTime(new Date(currentTimeStamp + (diff * 60000)), "hh:mm")
31+ Utils.log("Saved Current Location Coordinates: " + currentLng + "," + currentLat)
32+ currentTimeFormatted = Qt.formatTime(new Date(), "hh:mm")
33 updateTime();
34 }
35
36@@ -53,13 +58,12 @@
37 keywords: i18n.tr("Add;Timezone;Timezones;World;City;Cities;Town;Towns;Place;Places;Location;Locations;Time;Locale;Local;Current")
38 description: "Add a world city"
39 iconSource: Qt.resolvedUrl("../images/add_icon.png")
40- onTriggered: pagestack.push(Qt.resolvedUrl("WorldPage.qml"))
41+ onTriggered: pagestack.push(Qt.resolvedUrl("WorldPage.qml"), {"isWorldCity": true})
42 }
43 ]
44
45 function onTimerUpdate(now) {
46- currentTimeFormatted = Qt.formatTime(new Date(currentTimeStamp + (diff * 60000)), "hh:mm")
47- now.setMinutes(now.getMinutes() + diff)
48+ currentTimeFormatted = Qt.formatTime(new Date(), "hh:mm")
49 clockFace.timeChanged(now)
50 if (now.getUTCSeconds() == 0) {
51 updateTime();
52@@ -68,15 +72,42 @@
53
54 function updateTime() {
55 var now = new Date();
56- currentTimeStamp = now.getTime();
57- }
58+ now.setMinutes(now.getMinutes() + diff)
59+ currentUTCTime = now.getTime();
60+ }
61+
62+ GeoIPModel {
63+ id: geoIP
64+ onStatusChanged: {
65+ if (status == XmlListModel.Ready && geoIP.get(0).city != worldModel.city && geoIP.get(0).city != "None") {
66+ Utils.log("Retrieved current location using GeoIP. Writing into database and setting it as current location")
67+ currentCity = geoIP.get(0).city
68+ currentLng = geoIP.get(0).lng
69+ currentLat = geoIP.get(0).lat
70+ worldModel.appendCurrentLocation(currentCity, currentLng, currentLat);
71+ }
72+ else if (status == XmlListModel.Ready && geoIP.get(0).city == "None") {
73+ if (worldModel.city == "undefined") {
74+ currentCity = i18n.tr("Set current location name")
75+ currentLocation.progression = true
76+ }
77+ }
78+ else if(status == XmlListModel.Error) {
79+ Utils.error("Unable to retrieve GeoIP Data -> " + geoIP.errorString())
80+ if (worldModel.city == "undefined") {
81+ currentCity = i18n.tr("Set current location name")
82+ currentLocation.progression = true
83+ }
84+ }
85+ }
86+ }
87
88 Flickable {
89 id: clockAnimationContainer
90
91 clip: true;
92 anchors.fill: parent
93- contentWidth: parent.width
94+ contentWidth: parent.width
95 contentHeight: clockFace.height + clockFace.anchors.topMargin + savedWorldClock.height + savedWorldClock.anchors.topMargin + units.gu(3)
96
97 // Label to show the current time
98@@ -108,10 +139,10 @@
99 anchors { top: parent.top; topMargin: units.gu(10); horizontalCenter: parent.horizontalCenter }
100
101 onClicked: {
102- if (easterEggCircle.isReady == XmlListModel.Ready) {
103+ if (easterEggCircle.isReady == XmlListModel.Ready && worldModel.city !== "undefined") {
104 clockFace.state == "" ? clockFace.state = "easteregg" : clockFace.state = "";
105 } else {
106- Utils.log("Sunrise/Sunset times not yet loaded.")
107+ Utils.error("Sunrise/Sunset times cannot be loaded without setting the current location or without a internet connection.")
108 }
109 }
110
111@@ -127,7 +158,6 @@
112 name: "easteregg"
113 PropertyChanges { target: easterEggCircle; opacity: 1; }
114 PropertyChanges { target: currentTimeLabel; opacity: 0; }
115- // TODO: Do some caching of data here. Store data locally to reduce API calls.
116 PropertyChanges { target: easterEggCircle; sunriseLabel: easterEggCircle.getSunTime(easterEggCircle.model.get(0).sunriseTime); }
117 PropertyChanges { target: easterEggCircle; sunsetLabel: easterEggCircle.getSunTime(easterEggCircle.model.get(0).sunsetTime); }
118 },
119@@ -161,20 +191,24 @@
120
121 ListItem.Standard {
122 id: currentLocation
123+
124 Label {
125 id: currentLocationCity
126- // TRANSLATORS: this refers to Coordinated Universal Time
127- text: i18n.tr("UTC")
128+ text: i18n.tr("Retrieving current location...")
129 anchors { verticalCenter: parent.verticalCenter; left: parent.left; leftMargin: units.gu(3) }
130 color: Theme.palette.normal.baseText
131 fontSize: "large"
132 }
133 Label {
134- text: Qt.formatTime(new Date(currentTimeStamp + (diff * 60000)), "hh:mm A")
135- anchors { verticalCenter: parent.verticalCenter; right: parent.right; rightMargin: units.gu(2) }
136+ id: currentLocationTime
137+ visible: worldModel.city !== "undefined" ? true : false
138+ text: currentTimeFormatted
139+ anchors { verticalCenter: parent.verticalCenter; right: parent.right; rightMargin: currentLocation.progression == true ? units.gu(6) : units.gu(2) }
140 color: Theme.palette.normal.baseText
141 fontSize: "large"
142 }
143+
144+ onClicked: pagestack.push(Qt.resolvedUrl("WorldPage.qml"), {"isWorldCity": false})
145 }
146
147 ListItem.Header {
148@@ -190,7 +224,7 @@
149 id: listWorldClocks
150
151 clip: true
152- anchors { left: parent.left; right: parent.right }
153+ anchors { left: parent.left; right: parent.right }
154 height: 3 * units.gu(6) + units.gu(1) // height is defined to show 3 items by default with a small margin
155 model: worldModel
156 currentIndex: -1
157@@ -204,7 +238,7 @@
158 }
159
160 Label {
161- text: Qt.formatTime(new Date(currentTimeStamp + (rawOffSet * 60000)), "hh:mm A")
162+ text: Qt.formatTime(new Date(currentUTCTime + (rawOffSet * 60000)), "hh:mm")
163 anchors { verticalCenter: parent.verticalCenter; right: parent.right; rightMargin: units.gu(2) }
164 color: Theme.palette.normal.baseText
165 fontSize: "large"
166@@ -221,14 +255,6 @@
167 onItemRemoved: {
168 worldModel.removePreset(index);
169 }
170-
171- onClicked: {
172- currentLocationCity.text = cityName;
173- diff = rawOffSet;
174- easterEggCircle.longitude = longitude;
175- easterEggCircle.latitude = latitude;
176- worldModel.appendCurrentLocation(cityName, diff, longitude, latitude);
177- }
178 }
179 }
180 }
181
182=== modified file 'clock/EasterEgg.qml'
183--- clock/EasterEgg.qml 2013-09-03 18:55:04 +0000
184+++ clock/EasterEgg.qml 2013-09-27 08:38:25 +0000
185@@ -86,8 +86,8 @@
186 }
187
188 // FIXME: Replace these constant values with user's location coordinates when automatic location detection is implemented.
189- property real latitude: 52.01;
190- property real longitude: 4.35;
191+ property real latitude: 200;
192+ property real longitude: 200;
193
194 // properties to set/retrieve the sunrise and sunset times
195 property alias sunriseLabel: sunriseTimeLabel.text;
196@@ -134,7 +134,7 @@
197 var savedData = getSavedData();
198 var checkedDate = savedData[0][1].split('T')[0]
199 var date = new Date().toISOString();
200- if (status == XmlListModel.Ready && checkedDate != date.split('T')[0]){
201+ if (status == XmlListModel.Ready && checkedDate != date.split('T')[0] && longitude != 200 && latitude != 200){
202 sunriseTimeLabel.text = getSunTime(sunRiseModel.get(0).sunriseTime);
203 sunsetTimeLabel.text = getSunTime(sunRiseModel.get(0).sunsetTime);
204 saveSunTimes(date, sunriseTimeLabel.text, sunsetTimeLabel.text);
205
206=== added file 'clock/GeoIPModel.qml'
207--- clock/GeoIPModel.qml 1970-01-01 00:00:00 +0000
208+++ clock/GeoIPModel.qml 2013-09-27 08:38:25 +0000
209@@ -0,0 +1,31 @@
210+/*
211+ * Copyright (C) 2013 Canonical Ltd
212+ *
213+ * This program is free software: you can redistribute it and/or modify
214+ * it under the terms of the GNU General Public License version 3 as
215+ * published by the Free Software Foundation.
216+ *
217+ * This program is distributed in the hope that it will be useful,
218+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
219+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
220+ * GNU General Public License for more details.
221+ *
222+ * You should have received a copy of the GNU General Public License
223+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
224+ *
225+ * Authored by: Nekhelesh Ramananthan <krnekhelesh@gmail.com>
226+ */
227+
228+import QtQuick 2.0
229+import QtQuick.XmlListModel 2.0
230+
231+// Xml model to retrieve user's current location based on geoIP
232+XmlListModel {
233+ id: geoIPModel;
234+
235+ source: "http://geoip.ubuntu.com/lookup"
236+ query: "/Response"
237+ XmlRole { name: "city"; query: "City/string()"; isKey: true }
238+ XmlRole { name: "lat"; query: "Latitude/string()"; isKey: true }
239+ XmlRole { name: "lng"; query: "Longitude/string()"; isKey: true }
240+}
241
242=== modified file 'clock/WorldClockModel.qml'
243--- clock/WorldClockModel.qml 2013-07-01 14:40:35 +0000
244+++ clock/WorldClockModel.qml 2013-09-27 08:38:25 +0000
245@@ -27,31 +27,31 @@
246 readonly property string dbVersion: "0.1"
247 readonly property string dbDescription: "World Clock"
248
249- property real timeDiff: new Date().getTimezoneOffset()
250- property string city: "UTC";
251- property real longitude: 4.35;
252- property real latitude: 52.01;
253+ property string city: "undefined";
254+ property real longitude: 200;
255+ property real latitude: 200;
256
257 property var _db: null
258
259- function appendCurrentLocation(cityname, rawOffSet, longitude, latitude)
260+ function appendCurrentLocation(cityname, longitude, latitude)
261 {
262 try {
263 _db.transaction(function(tx){
264 var currentValue;
265 var res = tx.executeSql('SELECT * FROM CurrentClock');
266- if (res.rows.length > 0) {
267- currentValue = res.rows.item(0).rawOffSet;
268- }
269-
270- if (currentValue !== rawOffSet) {
271- // Update existing value or insert if none
272- if (currentValue !== undefined) {
273- res = tx.executeSql('UPDATE CurrentClock SET rawOffSet = ?, cityName = ?, longitude = ?, latitude = ?', [rawOffSet, cityname, longitude, latitude]);
274- } else {
275- res = tx.executeSql('INSERT INTO CurrentClock VALUES(?, ?, ?, ?)', [cityname, rawOffSet, longitude, latitude]);
276- }
277- }
278+
279+ if (res.rows.length > 0)
280+ currentValue = res.rows.item(0).cityName;
281+
282+ if (currentValue !== undefined) // Update existing value or insert if none
283+ res = tx.executeSql('UPDATE CurrentClock SET cityName = ?, longitude = ?, latitude = ?', [cityname, longitude, latitude]);
284+ else
285+ res = tx.executeSql('INSERT INTO CurrentClock VALUES(?, ?, ?)', [cityname, longitude, latitude]);
286+
287+ clockPage.currentCity = model.city = cityname
288+ clockPage.currentLng = model.longitude = longitude
289+ clockPage.currentLat = model.latitude = latitude
290+ Utils.log("Updating current location (manually)")
291 });
292 } catch (err) {
293 Utils.error("Error setting current location '" + "': " + err);
294@@ -86,7 +86,7 @@
295 }
296 try {
297 _db.transaction(function(tx){
298- tx.executeSql('CREATE TABLE IF NOT EXISTS CurrentClock(cityName TEXT, rawOffSet REAL, longitude REAL, latitude REAL)');
299+ tx.executeSql('CREATE TABLE IF NOT EXISTS CurrentClock(cityName TEXT, longitude REAL, latitude REAL)');
300 });
301 } catch (err) {
302 Utils.error("Error creating CurrentClock table in db:" + err);
303@@ -108,9 +108,9 @@
304 if (res.rows.length > 0) {
305 for (var i = 0; i < res.rows.length; i++) {
306 model.append({"cityName" : res.rows.item(i).cityName,
307- "rawOffSet": res.rows.item(i).rawOffSet,
308- "longitude": res.rows.item(i).longitude,
309- "latitude" : res.rows.item(i).latitude
310+ "rawOffSet": res.rows.item(i).rawOffSet,
311+ "longitude": res.rows.item(i).longitude,
312+ "latitude" : res.rows.item(i).latitude
313 });
314 }
315 }
316@@ -125,7 +125,6 @@
317 var currentstate = tx.executeSql('SELECT * FROM CurrentClock ORDER BY cityName');
318 if (currentstate.rows.length > 0) {
319 city = currentstate.rows.item(0).cityName;
320- timeDiff = currentstate.rows.item(0).rawOffSet;
321 longitude = currentstate.rows.item(0).longitude;
322 latitude = currentstate.rows.item(0).latitude;
323 }
324
325=== modified file 'clock/WorldPage.qml'
326--- clock/WorldPage.qml 2013-09-04 11:28:52 +0000
327+++ clock/WorldPage.qml 2013-09-27 08:38:25 +0000
328@@ -23,14 +23,20 @@
329 Page {
330 id: worldPage
331
332+ property bool isWorldCity;
333+
334 visible: false;
335- title: i18n.tr("Add City")
336+ title: isWorldCity ? i18n.tr("Add City") : i18n.tr("Edit Current Location")
337
338 function getTimeDifference(data) {
339 var worldTime = data.split(' ')[1].split(':');
340 var hoursWT = parseInt(worldTime[0]);
341 var minutesWT = parseInt(worldTime[1]);
342 var now = new Date();
343+ var UTCdiff = new Date().getTimezoneOffset()
344+ now.setMinutes(now.getMinutes() + UTCdiff)
345+
346+ // Calculating world city time diff w.r.t UTC
347 return ((hoursWT - now.getHours()) * 60 + (minutesWT - now.getMinutes()));
348 }
349
350@@ -48,7 +54,10 @@
351
352 onStatusChanged: {
353 if(status == XmlListModel.Ready && worldClockList.city != "null") {
354- worldModel.appendPreset(worldClockList.city, getTimeDifference(cityDetailsModel.get(0).time), worldClockList.lng, worldClockList.lat);
355+ if (isWorldCity)
356+ worldModel.appendPreset(worldClockList.city, getTimeDifference(cityDetailsModel.get(0).time), worldClockList.lng, worldClockList.lat);
357+ else
358+ worldModel.appendCurrentLocation(worldClockList.city, worldClockList.lng, worldClockList.lat);
359 worldClockList.clearUserSearch();
360 pageStack.pop()
361 }
362@@ -61,7 +70,7 @@
363 lat = searchModel.get(index).lat;
364 lng = searchModel.get(index).lng;
365 city = searchModel.get(index).city;
366- cityDetailsModel.reload()
367+ cityDetailsModel.reload()
368 }
369 }
370 }

Subscribers

People subscribed via source and target branches