Merge lp:~nik90/ubuntu-clock-app/implement-location-finding into lp:ubuntu-clock-app

Proposed by Nekhelesh Ramananthan
Status: Merged
Approved by: Nekhelesh Ramananthan
Approved revision: 88
Merged at revision: 165
Proposed branch: lp:~nik90/ubuntu-clock-app/implement-location-finding
Merge into: lp:ubuntu-clock-app
Diff against target: 770 lines (+451/-32)
14 files modified
CMakeLists.txt (+2/-2)
app/clock/ClockPage.qml (+126/-4)
app/ubuntu-clock-app.qml (+8/-0)
backend/CMakeLists.txt (+23/-0)
backend/modules/GeoLocation/backend.cpp (+34/-0)
backend/modules/GeoLocation/backend.h (+35/-0)
backend/modules/GeoLocation/geolocation.cpp (+100/-0)
backend/modules/GeoLocation/geolocation.h (+78/-0)
backend/modules/GeoLocation/qmldir (+2/-0)
debian/changelog (+1/-0)
debian/control (+2/-0)
po/com.ubuntu.clock.pot (+29/-25)
tests/unit/MockClockApp.qml (+9/-0)
ubuntu-clock-app.json (+2/-1)
To merge this branch: bzr merge lp:~nik90/ubuntu-clock-app/implement-location-finding
Reviewer Review Type Date Requested Status
Riccardo Padovani Approve
Ubuntu Phone Apps Jenkins Bot continuous-integration Approve
Nekhelesh Ramananthan Needs Fixing
Review via email: mp+231793@code.launchpad.net

Commit message

Adds user location finding to the clock app.

Description of the change

Adds user location finding to the clock app.

==== Testing ====

This MP requires extensive testing for different scenarios that I have listed below. Please comment below if any of the scenarios don't work as expected. I will be adding these scenarios to the manual test suite to ensure we don't regress with a new clock release.

### Prerequisites

I tested this on Mako RTM Stable Image #5. I expect it to work reliably with #5 and higher. Please execute the following commands before *each* case for a fresh clean testing environment.

- Clean up the ubuntu location service and clock app files (for a fresh start) by,
"stop ubuntu-location-service-trust-stored"
"rm -r .local/share/UbuntuLocationService"
"rm -r .local/share/com.ubuntu.clock"
"start ubuntu-location-service-trust-stored"

### Case 1: User opens clock app for the first time (previous location unknown and location service enabled)

- Once you open the clock app, you should be prompted the first time for allowing clock app to access GPS. Press "Allow" here. That's the sign it is working.

- The clock app should show "Retrieving Location". After GPS coordinates are obtained (should take few seconds at most), it should show your city or country.

- Restart the clock app. It should show you the last saved city immediately and not "Retrieving location" again.

### Case 2: User opens clock app for the first time (previous location unknown and location services denied)

- Once you open the clock app, in the location service trust store prompt, press "Deny"!.

- The clock app should now show "Location Service Error" to indicate that it cannot access the location service.

- Restart the clock app and it should still read "Location Service Error".

### Case 3: User opens clock app as usual (not first-time)

- Open the clock app and it should prompt as usual for access to GPS. Press "Allow". The user location should then be shown within a few seconds.

- Close clock app

- Run "sudo stop ubuntu-location-service"

- Reopen clock app. It should show previous saved location and *not* "Location Service Error!".

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: Needs Fixing (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
Alan Pope 🍺🐧🐱 πŸ¦„ (popey) wrote :

#blocked on bug 1359866

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: Needs Fixing (continuous-integration)
Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote :
review: Approve (continuous-integration)
81. By Nekhelesh Ramananthan

Added some comments

82. By Nekhelesh Ramananthan

Added more comments and cleaned lat and long calculation

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
Alan Pope 🍺🐧🐱 πŸ¦„ (popey) wrote :

As bug 1359866 is now fixed, is this unblocked?

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

#unblocked This was part of the 3 MPs that I requested you to test since they are ready code wise.

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

#blocked I believe this MP requires silo-001 [1] (ubuntu-rtm) to land in rtm stable otherwise I wouldn't be able to release a new clock app. Unfortunately the person (thomas voss) who requested silo-001 is on vacation.

I did request QA to go ahead and test the silo considering that it is already in utopic, however I was told that due to a regression in the past, QA doesn't test silos which haven't been tested by the lander first.

I will keep updating this MP as I get more details.

 dbus-cpp 4.0.0+14.10.20140917~rtm-0ubuntu1
 location-service 2.1+14.10.20140917.1~rtm-0ubuntu1

[1] https://launchpad.net/~ci-train-ppa-service/+archive/ubuntu-rtm/landing-001

review: Needs Fixing
Revision history for this message
Alan Pope 🍺🐧🐱 πŸ¦„ (popey) wrote :

I gather this is still un-testable due to the location stuff not being complete and landed?

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

> I gather this is still un-testable due to the location stuff not being
> complete and landed?

Yes, from what I know, the HERE location service is not reliably started on phone reboots, and also the HERE location fixes differ between RTM and Utopic images leading to different testing results. As such, I first would like the HERE service to be available on the different channels reliably before proceeding to fix this MP.

I say wait 1-2 weeks for HERE service to be reliable, after which I am going to postpone this to post-rtm since I am not comfortable landing a big MP this late in the development cycle.

83. By Nekhelesh Ramananthan

Merged trunk

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

I tested this on RTM Stable #5 Mako and it worked for all the use cases mentioned above in the MP description. I am a bit nervous about pushing this feature this late in the cycle. I would like some additional people like popey, davmor, and any others that come to mind to test this before we merge to trunk.

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

#unblocked

84. By Nekhelesh Ramananthan

Fixed qml tests

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

Added missing dependency which caused qml test to fail

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

Added comments

87. By Nekhelesh Ramananthan

Updated pot file

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
Mihir Soni (mihirsoni) wrote :

I have tested this and it works fine on the first glance,
I'll test more and will update here.

88. By Nekhelesh Ramananthan

Renamed backend location plugin to geolocation

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
Riccardo Padovani (rpadovani) wrote :

On rtm #6 the app doesn't start, it is stucked on the splash screen, both with gps activated or deasctivated.

Also, it doesn't create a log, so unfortunately I cannot understand what's wrong. I created the click package twice, so I don't think is my failure.

Anyway, I left a inline comment about a doubt on the code.

review: Needs Information
Revision history for this message
Riccardo Padovani (rpadovani) wrote :

If I launch it from QTC (instead of creating a clic package) works.

Tests work as expected, but if I launch the app with position deactivate from the indicator it says "Location Service Error" as expected, but when I turn on position service from indicator the app doesn't try to update location, but stays stucked on "Location Service Error"

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

> If I launch it from QTC (instead of creating a click package) works.
>
> Tests work as expected, but if I launch the app with position deactivate from
> the indicator it says "Location Service Error" as expected, but when I turn on
> position service from indicator the app doesn't try to update location, but
> stays stucked on "Location Service Error"

Yeah that's because the clock app you will need to restart the app to update the location. Currently the location is updated only on 2 conditions,

1. On application startup
2. If the clock app is brought to the foreground 30 mins later

It does not continuously keep searching for the user location since that would be bad for the battery. So in your situation where you disabled the position service and then renabled it, the clock app does not get a signal that you turned it on. So you will need to restart the clock app.

A better way of fixing your situation would be to add a refresh button which the user can press to search for the location, but we are way past UI freezes to get this done.

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

63 + Stop querying for the user location if it is found to be
64 + the same as the one stored in the app setting database
65 + */
66 + if (userLongitude === userLocationDocument.contents.long ||
67 + userLatitude === userLocationDocument.contents.lat) {

>Riccardo Padovani (rpadovani) wrote 1 hour ago:
>I don't understand that if. Why you use OR and not an AND? If a user takes a plane in Rome, and >lands in Barcellona, the lat is the same, so the position isn'update?

No no that's not what this if loop is for. It is basically there to ensure that no invalid long or lat is supplied the clock app. Normally when the application is started up, the lat and long returned is usually garbage values. So this if loop checks the validity of the coordinates.

So if *either* lat or long is invalid, then it returns. Only if both of them are valid, does it continue to search for the user's location.

Hope this answers your question.

Revision history for this message
Riccardo Padovani (rpadovani) wrote :

Yap, thanks Nik, now is definitely better :-)

Great work!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'CMakeLists.txt'
2--- CMakeLists.txt 2014-09-27 10:36:56 +0000
3+++ CMakeLists.txt 2014-11-04 15:58:17 +0000
4@@ -111,9 +111,9 @@
5
6 add_custom_target("autopilot" chmod +x ${CMAKE_SOURCE_DIR}/tests/autopilot/run
7 COMMAND ${CMAKE_SOURCE_DIR}/tests/autopilot/run
8- DEPENDS timezone timezone-qmldir alarmsettings alarmsettings-qmldir datetime datetime-qmldir
9+ DEPENDS timezone timezone-qmldir alarmsettings alarmsettings-qmldir datetime datetime-qmldir geolocation geolocation-qmldir
10 WORKING_DIRECTORY ./app)
11
12 add_custom_target("run" /usr/bin/qmlscene -I ${CMAKE_BINARY_DIR}/backend ${CMAKE_SOURCE_DIR}/app/ubuntu-clock-app.qml
13- DEPENDS timezone timezone-qmldir alarmsettings alarmsettings-qmldir datetime datetime-qmldir
14+ DEPENDS timezone timezone-qmldir alarmsettings alarmsettings-qmldir datetime datetime-qmldir geolocation geolocation-qmldir
15 WORKING_DIRECTORY ./app)
16
17=== modified file 'app/clock/ClockPage.qml'
18--- app/clock/ClockPage.qml 2014-10-10 19:58:49 +0000
19+++ app/clock/ClockPage.qml 2014-11-04 15:58:17 +0000
20@@ -17,7 +17,10 @@
21 */
22
23 import QtQuick 2.3
24+import U1db 1.0 as U1db
25+import QtPositioning 5.2
26 import Ubuntu.Components 1.1
27+import GeoLocation 1.0
28 import "../alarm"
29 import "../components"
30 import "../upstreamcomponents"
31@@ -47,6 +50,110 @@
32 id: alarmUtils
33 }
34
35+ PositionSource {
36+ id: geoposition
37+
38+ // Property to store the time of the last GPS location update
39+ property var lastUpdate
40+
41+ readonly property real userLongitude: position.coordinate.longitude
42+
43+ readonly property real userLatitude: position.coordinate.latitude
44+
45+ active: true
46+ updateInterval: 1000
47+
48+ onSourceErrorChanged: {
49+ // Stop querying user location if location service is not available
50+ if (sourceError !== PositionSource.NoError) {
51+ console.log("[Source Error]: Location Service Error")
52+ geoposition.stop()
53+ }
54+ }
55+
56+ onPositionChanged: {
57+ // Do not accept an invalid user location
58+ if(!position.longitudeValid || !position.latitudeValid) {
59+ return
60+ }
61+
62+ /*
63+ Stop querying for the user location if it is found to be
64+ the same as the one stored in the app setting database
65+ */
66+ if (userLongitude === userLocationDocument.contents.long ||
67+ userLatitude === userLocationDocument.contents.lat) {
68+ if (geoposition.active) {
69+ console.log("[LOG]: Stopping geolocation update service")
70+ geoposition.stop()
71+ }
72+ return
73+ }
74+
75+ else {
76+ // Retrieve user location online after receiving the user's lat and lng.
77+ userLocation.setSource(position.coordinate.latitude, position.coordinate.longitude)
78+ }
79+ }
80+ }
81+
82+ Connections {
83+ target: clockApp
84+ onApplicationStateChanged: {
85+ /*
86+ If Clock App is brought from background after more than 30 mins,
87+ query the user location to ensure it is up to date.
88+ */
89+ if(applicationState
90+ && Math.abs(clock.analogTime - geoposition.lastUpdate) > 1800000) {
91+ if(!geoposition.active)
92+ geoposition.start()
93+ }
94+
95+ else if (!applicationState) {
96+ geoposition.lastUpdate = clock.analogTime
97+ }
98+ }
99+ }
100+
101+ GeoLocation {
102+ id: userLocation
103+
104+ function setSource(lat, lng) {
105+ var url = String("%1%2%3%4%5")
106+ .arg("http://api.geonames.org/findNearbyPlaceNameJSON?lat=")
107+ .arg(lat)
108+ .arg("&lng=")
109+ .arg(lng)
110+ .arg("&username=krnekhelesh&style=full")
111+
112+ console.log("[LOG]: Searching online for user location at " + url)
113+
114+ userLocation.source = url;
115+ }
116+
117+ onLocationChanged: {
118+ var locationData = JSON.parse
119+ (JSON.stringify(userLocationDocument.contents))
120+
121+ locationData.lat = geoposition.userLatitude
122+ locationData.long = geoposition.userLongitude
123+ locationData.location = userLocation.location
124+
125+ userLocationDocument.contents = locationData
126+
127+ /*
128+ Stop querying the user coordinates once the user location has been
129+ determined and saved to disk
130+ */
131+ if(geoposition.active) {
132+ console.log("[LOG]: Stopping geolocation update service")
133+ geoposition.stop()
134+ }
135+
136+ }
137+ }
138+
139 Flickable {
140 id: _flickable
141
142@@ -100,6 +207,10 @@
143 id: clock
144 objectName: "clock"
145
146+ Component.onCompleted: {
147+ geoposition.lastUpdate = analogTime
148+ }
149+
150 analogTime: clockTime
151
152 anchors {
153@@ -130,9 +241,6 @@
154 opacity: settingsIcon.opacity
155 spacing: units.gu(1)
156
157- // TODO: Remove this once user location finding is implemented
158- visible: false
159-
160 anchors {
161 top: date.bottom
162 topMargin: units.gu(1)
163@@ -149,10 +257,24 @@
164 Label {
165 id: location
166 objectName: "location"
167- text: i18n.tr("Location")
168+
169 fontSize: "medium"
170 anchors.verticalCenter: locationIcon.verticalCenter
171 color: UbuntuColors.midAubergine
172+
173+ text: {
174+ if (userLocationDocument.contents.location === "Null") {
175+ if(geoposition.sourceError !== PositionSource.NoError) {
176+ return i18n.tr("Location Service Error!")
177+ } else {
178+ return i18n.tr("Retrieving location...")
179+ }
180+ }
181+
182+ else {
183+ return userLocationDocument.contents.location
184+ }
185+ }
186 }
187 }
188
189
190=== modified file 'app/ubuntu-clock-app.qml'
191--- app/ubuntu-clock-app.qml 2014-10-11 17:53:39 +0000
192+++ app/ubuntu-clock-app.qml 2014-11-04 15:58:17 +0000
193@@ -71,6 +71,14 @@
194 defaults: { "digitalMode": false }
195 }
196
197+ U1db.Document {
198+ id: userLocationDocument
199+ create: true
200+ database: clockDB
201+ docId: "userLocationDocument"
202+ defaults: { "lat": "NaN", "long": "Nan", "location": "Null" }
203+ }
204+
205 DateTime {
206 id: localTimeSource
207 updateInterval: 1000
208
209=== modified file 'backend/CMakeLists.txt'
210--- backend/CMakeLists.txt 2014-09-12 05:05:03 +0000
211+++ backend/CMakeLists.txt 2014-11-04 15:58:17 +0000
212@@ -25,6 +25,12 @@
213 modules/Alarm/Settings/alarmsettings.cpp
214 )
215
216+set(
217+ geolocation_SRCS
218+ modules/GeoLocation/backend.cpp
219+ modules/GeoLocation/geolocation.cpp
220+)
221+
222 add_library(timezone MODULE
223 ${timezone_SRCS}
224 )
225@@ -37,6 +43,10 @@
226 ${alarmsettings_SRCS}
227 )
228
229+add_library(geolocation MODULE
230+ ${geolocation_SRCS}
231+)
232+
233 set_target_properties(timezone PROPERTIES
234 LIBRARY_OUTPUT_DIRECTORY Timezone
235 )
236@@ -49,9 +59,14 @@
237 LIBRARY_OUTPUT_DIRECTORY Alarm/Settings
238 )
239
240+set_target_properties(geolocation PROPERTIES
241+ LIBRARY_OUTPUT_DIRECTORY GeoLocation
242+)
243+
244 qt5_use_modules(datetime Gui Qml Quick)
245 qt5_use_modules(timezone Gui Qml Quick)
246 qt5_use_modules(alarmsettings Gui Qml Quick DBus)
247+qt5_use_modules(geolocation Gui Qml Quick)
248
249 # Copy qmldir file to build dir for running in QtCreator
250 add_custom_target(timezone-qmldir ALL
251@@ -69,6 +84,11 @@
252 DEPENDS ${QMLFILES}
253 )
254
255+add_custom_target(geolocation-qmldir ALL
256+ COMMAND cp ${CMAKE_CURRENT_SOURCE_DIR}/modules/GeoLocation/qmldir ${CMAKE_CURRENT_BINARY_DIR}/GeoLocation
257+ DEPENDS ${QMLFILES}
258+)
259+
260 # Install plugin file
261 install(TARGETS timezone DESTINATION ${MODULE_PATH}/Timezone/)
262 install(FILES modules/Timezone/qmldir DESTINATION ${MODULE_PATH}/Timezone/)
263@@ -78,3 +98,6 @@
264
265 install(TARGETS alarmsettings DESTINATION ${MODULE_PATH}/Alarm/Settings/)
266 install(FILES modules/Alarm/Settings/qmldir DESTINATION ${MODULE_PATH}/Alarm/Settings/)
267+
268+install(TARGETS geolocation DESTINATION ${MODULE_PATH}/GeoLocation/)
269+install(FILES modules/GeoLocation/qmldir DESTINATION ${MODULE_PATH}/GeoLocation/)
270
271=== added directory 'backend/modules/GeoLocation'
272=== added file 'backend/modules/GeoLocation/backend.cpp'
273--- backend/modules/GeoLocation/backend.cpp 1970-01-01 00:00:00 +0000
274+++ backend/modules/GeoLocation/backend.cpp 2014-11-04 15:58:17 +0000
275@@ -0,0 +1,34 @@
276+/*
277+ * Copyright (C) 2014 Canonical Ltd
278+ *
279+ * This file is part of Ubuntu Clock App
280+ *
281+ * Ubuntu Clock App is free software: you can redistribute it and/or modify
282+ * it under the terms of the GNU General Public License version 3 as
283+ * published by the Free Software Foundation.
284+ *
285+ * Ubuntu Clock App is distributed in the hope that it will be useful,
286+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
287+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
288+ * GNU General Public License for more details.
289+ *
290+ * You should have received a copy of the GNU General Public License
291+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
292+ */
293+
294+#include <QtQml>
295+#include <QtQml/QQmlContext>
296+#include "backend.h"
297+#include "geolocation.h"
298+
299+void BackendPlugin::registerTypes(const char *uri)
300+{
301+ Q_ASSERT(uri == QLatin1String("GeoLocation"));
302+
303+ qmlRegisterType<GeoLocation>(uri, 1, 0, "GeoLocation");
304+}
305+
306+void BackendPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
307+{
308+ QQmlExtensionPlugin::initializeEngine(engine, uri);
309+}
310
311=== added file 'backend/modules/GeoLocation/backend.h'
312--- backend/modules/GeoLocation/backend.h 1970-01-01 00:00:00 +0000
313+++ backend/modules/GeoLocation/backend.h 2014-11-04 15:58:17 +0000
314@@ -0,0 +1,35 @@
315+/*
316+ * Copyright (C) 2014 Canonical Ltd
317+ *
318+ * This file is part of Ubuntu Clock App
319+ *
320+ * Ubuntu Clock App is free software: you can redistribute it and/or modify
321+ * it under the terms of the GNU General Public License version 3 as
322+ * published by the Free Software Foundation.
323+ *
324+ * Ubuntu Clock App is distributed in the hope that it will be useful,
325+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
326+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
327+ * GNU General Public License for more details.
328+ *
329+ * You should have received a copy of the GNU General Public License
330+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
331+ */
332+
333+#ifndef BACKEND_PLUGIN_H
334+#define BACKEND_PLUGIN_H
335+
336+#include <QtQml/QQmlEngine>
337+#include <QtQml/QQmlExtensionPlugin>
338+
339+class BackendPlugin : public QQmlExtensionPlugin
340+{
341+ Q_OBJECT
342+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
343+
344+public:
345+ void registerTypes(const char *uri);
346+ void initializeEngine(QQmlEngine *engine, const char *uri);
347+};
348+#endif // BACKEND_PLUGIN_H
349+
350
351=== added file 'backend/modules/GeoLocation/geolocation.cpp'
352--- backend/modules/GeoLocation/geolocation.cpp 1970-01-01 00:00:00 +0000
353+++ backend/modules/GeoLocation/geolocation.cpp 2014-11-04 15:58:17 +0000
354@@ -0,0 +1,100 @@
355+/*
356+ * Copyright (C) 2014 Canonical Ltd
357+ *
358+ * This file is part of Ubuntu Clock App
359+ *
360+ * Ubuntu Clock App is free software: you can redistribute it and/or modify
361+ * it under the terms of the GNU General Public License version 3 as
362+ * published by the Free Software Foundation.
363+ *
364+ * Ubuntu Clock App is distributed in the hope that it will be useful,
365+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
366+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
367+ * GNU General Public License for more details.
368+ *
369+ * You should have received a copy of the GNU General Public License
370+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
371+ */
372+
373+#include <QDebug>
374+#include <QNetworkReply>
375+#include <QNetworkRequest>
376+#include <QJsonDocument>
377+
378+#include "geolocation.h"
379+
380+GeoLocation::GeoLocation(QObject *parent):
381+ QObject(parent)
382+{
383+ m_nam = new QNetworkAccessManager(this);
384+ connect(m_nam,
385+ SIGNAL(finished(QNetworkReply*)),
386+ this,
387+ SLOT(networkReplyFinished(QNetworkReply*)));
388+}
389+
390+QUrl GeoLocation::source() const
391+{
392+ return m_source;
393+}
394+
395+QString GeoLocation::location() const
396+{
397+ return m_location;
398+}
399+
400+void GeoLocation::setSource(const QUrl &source)
401+{
402+ if (m_source == source) {
403+ // Don't set the source again if it is the same source being set again
404+ return;
405+ }
406+
407+ // Update the source and emit the changed signal to let QML know
408+ m_source = source;
409+ emit sourceChanged();
410+
411+ retrieveLocationFromJson();
412+}
413+
414+void GeoLocation::retrieveLocationFromJson()
415+{
416+ // Define the request
417+ QNetworkRequest request(m_source);
418+
419+ // Make the request to retrieve the data
420+ m_nam->get(request);
421+}
422+
423+void GeoLocation::networkReplyFinished(QNetworkReply *reply)
424+{
425+ if(reply->error() != QNetworkReply::NoError) {
426+ qDebug() << "[LOG] Network error: " << reply->errorString();
427+ return;
428+ }
429+
430+ QByteArray data = reply->readAll();
431+
432+ QJsonDocument jsonDoc = QJsonDocument::fromJson(data);
433+
434+ QVariant cityData = jsonDoc.toVariant();
435+
436+ foreach (const QVariant &entry, cityData.toMap().value("geonames").toList())
437+ {
438+ auto data = entry.toMap();
439+ auto adminName2 = data.value("adminName2").toString();
440+ auto adminName1 = data.value("adminName1").toString();
441+
442+ if (!adminName2.isEmpty()) {
443+ m_location = adminName2;
444+ emit locationChanged();
445+ }
446+
447+ else if (!adminName1.isEmpty()) {
448+ m_location = adminName1;
449+ emit locationChanged();
450+ }
451+ }
452+
453+ reply->deleteLater();
454+}
455
456=== added file 'backend/modules/GeoLocation/geolocation.h'
457--- backend/modules/GeoLocation/geolocation.h 1970-01-01 00:00:00 +0000
458+++ backend/modules/GeoLocation/geolocation.h 2014-11-04 15:58:17 +0000
459@@ -0,0 +1,78 @@
460+/*
461+ * Copyright (C) 2014 Canonical Ltd
462+ *
463+ * This file is part of Ubuntu Clock App
464+ *
465+ * Ubuntu Clock App is free software: you can redistribute it and/or modify
466+ * it under the terms of the GNU General Public License version 3 as
467+ * published by the Free Software Foundation.
468+ *
469+ * Ubuntu Clock App is distributed in the hope that it will be useful,
470+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
471+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
472+ * GNU General Public License for more details.
473+ *
474+ * You should have received a copy of the GNU General Public License
475+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
476+ */
477+
478+#ifndef LOCATION_H
479+#define LOCATION_H
480+
481+#include <QObject>
482+#include <QUrl>
483+#include <QNetworkAccessManager>
484+
485+class GeoLocation : public QObject
486+{
487+ Q_OBJECT
488+
489+ // Property to set the user's longitude and latitude
490+ Q_PROPERTY(QUrl source
491+ READ source
492+ WRITE setSource
493+ NOTIFY sourceChanged)
494+
495+ // Property to return the user's location (cityname or countryname)
496+ Q_PROPERTY(QString location
497+ READ location
498+ NOTIFY locationChanged)
499+
500+public:
501+ GeoLocation(QObject *parent = 0);
502+
503+ // Function to read the json document source
504+ QUrl source() const;
505+
506+ // Function to set the source
507+ void setSource(const QUrl &source);
508+
509+ // Function to read the user's location
510+ QString location() const;
511+
512+signals:
513+ // Signal to notify the source has been changed
514+ void sourceChanged();
515+
516+ // Signal to notify the location has been changed
517+ void locationChanged();
518+
519+private slots:
520+ // Function to process the json document when a reply is received
521+ void networkReplyFinished(QNetworkReply *reply);
522+
523+private:
524+ // Private copy of the source received from QML
525+ QUrl m_source;
526+
527+ // Network access manager to request data from the online source
528+ QNetworkAccessManager *m_nam;
529+
530+ // Private copy of the user location
531+ QString m_location;
532+
533+ // Function to initiate the location retrieval process
534+ void retrieveLocationFromJson();
535+};
536+
537+#endif // LOCATION_H
538
539=== added file 'backend/modules/GeoLocation/qmldir'
540--- backend/modules/GeoLocation/qmldir 1970-01-01 00:00:00 +0000
541+++ backend/modules/GeoLocation/qmldir 2014-11-04 15:58:17 +0000
542@@ -0,0 +1,2 @@
543+module GeoLocation
544+plugin geolocation
545
546=== modified file 'debian/changelog'
547--- debian/changelog 2014-10-25 13:32:07 +0000
548+++ debian/changelog 2014-11-04 15:58:17 +0000
549@@ -55,6 +55,7 @@
550 * Updated QtQuick library imports to v2.3
551 * Switched bzr branch to lp:ubuntu-clock-app
552 * Updated pot file name
553+ * Added support for user location retrieval using GPS (LP: #1323198)
554 * Added header shortcut to select/deselect all alarm repeat options (LP: #1362089)
555 * Added visual tweaks (80% opacity for disabled alarms) and show time to
556 next alarm when enabling an alarm.
557
558=== modified file 'debian/control'
559--- debian/control 2014-09-26 10:56:42 +0000
560+++ debian/control 2014-11-04 15:58:17 +0000
561@@ -12,6 +12,7 @@
562 qml-module-qttest,
563 qtdeclarative5-u1db1.0,
564 qtdeclarative5-qtmultimedia-plugin,
565+ qtdeclarative5-qtpositioning-plugin,
566 qt5-default,
567 qtbase5-dev,
568 qtdeclarative5-dev,
569@@ -32,6 +33,7 @@
570 qtdeclarative5-ubuntu-ui-toolkit-plugin | qt-components-ubuntu,
571 qtdeclarative5-xmllistmodel-plugin,
572 qtdeclarative5-qtmultimedia-plugin,
573+ qtdeclarative5-qtpositioning-plugin,
574 ubuntu-touch-sounds,
575 suru-icon-theme | ubuntu-mobile-icons,
576 ${misc:Depends},
577
578=== modified file 'po/com.ubuntu.clock.pot'
579--- po/com.ubuntu.clock.pot 2014-10-15 09:53:08 +0000
580+++ po/com.ubuntu.clock.pot 2014-11-04 15:58:17 +0000
581@@ -8,7 +8,7 @@
582 msgstr ""
583 "Project-Id-Version: \n"
584 "Report-Msgid-Bugs-To: \n"
585-"POT-Creation-Date: 2014-10-15 11:52+0200\n"
586+"POT-Creation-Date: 2014-11-04 16:55+0100\n"
587 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
588 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
589 "Language-Team: LANGUAGE <LL@li.org>\n"
590@@ -18,11 +18,11 @@
591 "Content-Transfer-Encoding: 8bit\n"
592
593 #: ../app/alarm/AlarmLabel.qml:30 ../app/alarm/AlarmLabel.qml:56
594-#: ../app/alarm/EditAlarmPage.qml:303
595+#: ../app/alarm/EditAlarmPage.qml:302
596 msgid "Label"
597 msgstr ""
598
599-#: ../app/alarm/AlarmList.qml:78 ../app/alarm/AlarmPage.qml:108
600+#: ../app/alarm/AlarmList.qml:78 ../app/alarm/AlarmPage.qml:117
601 #: ../app/worldclock/UserWorldCityList.qml:101
602 msgid "Delete"
603 msgstr ""
604@@ -36,27 +36,27 @@
605 msgid "Alarm"
606 msgstr ""
607
608-#: ../app/alarm/AlarmPage.qml:58 ../app/worldclock/WorldCityList.qml:79
609+#: ../app/alarm/AlarmPage.qml:58 ../app/worldclock/WorldCityList.qml:80
610 msgid "Back"
611 msgstr ""
612
613-#: ../app/alarm/AlarmPage.qml:78
614+#: ../app/alarm/AlarmPage.qml:87
615 msgid "Select None"
616 msgstr ""
617
618-#: ../app/alarm/AlarmPage.qml:80 ../app/alarm/AlarmRepeat.qml:35
619+#: ../app/alarm/AlarmPage.qml:89 ../app/alarm/AlarmRepeat.qml:35
620 msgid "Select All"
621 msgstr ""
622
623-#: ../app/alarm/AlarmPage.qml:138
624+#: ../app/alarm/AlarmPage.qml:149
625 msgid "No saved alarms"
626 msgstr ""
627
628-#: ../app/alarm/AlarmPage.qml:139
629+#: ../app/alarm/AlarmPage.qml:150
630 msgid "Tap the + icon to add an alarm"
631 msgstr ""
632
633-#: ../app/alarm/AlarmRepeat.qml:31 ../app/alarm/EditAlarmPage.qml:293
634+#: ../app/alarm/AlarmRepeat.qml:31 ../app/alarm/EditAlarmPage.qml:292
635 msgid "Repeat"
636 msgstr ""
637
638@@ -68,33 +68,33 @@
639 #: ../app/alarm/AlarmSettingsPage.qml:55 ../app/alarm/AlarmSettingsPage.qml:56
640 #: ../app/alarm/AlarmSettingsPage.qml:65 ../app/alarm/AlarmSettingsPage.qml:66
641 #: ../app/alarm/AlarmSettingsPage.qml:67 ../app/alarm/AlarmSettingsPage.qml:68
642-#: ../app/alarm/AlarmSettingsPage.qml:139
643-#: ../app/alarm/AlarmSettingsPage.qml:206
644+#: ../app/alarm/AlarmSettingsPage.qml:146
645+#: ../app/alarm/AlarmSettingsPage.qml:215
646 #, qt-format
647 msgid "%1 minutes"
648 msgstr ""
649
650-#: ../app/alarm/AlarmSettingsPage.qml:93
651+#: ../app/alarm/AlarmSettingsPage.qml:92
652 msgid "Alarm volume"
653 msgstr ""
654
655-#: ../app/alarm/AlarmSettingsPage.qml:138
656+#: ../app/alarm/AlarmSettingsPage.qml:145
657 msgid "Silence after"
658 msgstr ""
659
660-#: ../app/alarm/AlarmSettingsPage.qml:205
661+#: ../app/alarm/AlarmSettingsPage.qml:214
662 msgid "Snooze for"
663 msgstr ""
664
665-#: ../app/alarm/AlarmSettingsPage.qml:249
666+#: ../app/alarm/AlarmSettingsPage.qml:259
667 msgid "Vibration"
668 msgstr ""
669
670-#: ../app/alarm/AlarmSettingsPage.qml:278
671+#: ../app/alarm/AlarmSettingsPage.qml:293
672 msgid "Change time and date"
673 msgstr ""
674
675-#: ../app/alarm/AlarmSound.qml:28 ../app/alarm/EditAlarmPage.qml:316
676+#: ../app/alarm/AlarmSound.qml:28 ../app/alarm/EditAlarmPage.qml:315
677 msgid "Sound"
678 msgstr ""
679
680@@ -150,12 +150,16 @@
681 msgid "Edit alarm"
682 msgstr ""
683
684-#: ../app/alarm/EditAlarmPage.qml:337
685+#: ../app/alarm/EditAlarmPage.qml:336
686 msgid "Delete alarm"
687 msgstr ""
688
689-#: ../app/clock/ClockPage.qml:152
690-msgid "Location"
691+#: ../app/clock/ClockPage.qml:268
692+msgid "Location Service Error!"
693+msgstr ""
694+
695+#: ../app/clock/ClockPage.qml:270
696+msgid "Retrieving location..."
697 msgstr ""
698
699 #: ../app/worldclock/AddWorldCityButton.qml:30
700@@ -207,23 +211,23 @@
701 msgid "Select a city"
702 msgstr ""
703
704-#: ../app/worldclock/WorldCityList.qml:94
705+#: ../app/worldclock/WorldCityList.qml:109
706 msgid "Search..."
707 msgstr ""
708
709-#: ../app/worldclock/WorldCityList.qml:205
710+#: ../app/worldclock/WorldCityList.qml:214
711 msgid "Searching for a city"
712 msgstr ""
713
714-#: ../app/worldclock/WorldCityList.qml:210
715+#: ../app/worldclock/WorldCityList.qml:219
716 msgid "No City Found"
717 msgstr ""
718
719-#: ../app/worldclock/WorldCityList.qml:216
720+#: ../app/worldclock/WorldCityList.qml:225
721 msgid "Unable to connect."
722 msgstr ""
723
724-#: ../app/worldclock/WorldCityList.qml:217
725+#: ../app/worldclock/WorldCityList.qml:226
726 msgid "Please check your network connection and try again"
727 msgstr ""
728
729
730=== modified file 'tests/unit/MockClockApp.qml'
731--- tests/unit/MockClockApp.qml 2014-10-13 19:57:35 +0000
732+++ tests/unit/MockClockApp.qml 2014-11-04 15:58:17 +0000
733@@ -21,6 +21,7 @@
734 import U1db 1.0 as U1db
735 import Ubuntu.Components 1.1
736 import "../../app/clock"
737+import "../../app/components"
738
739 /*
740 This file is meant to create a fake but fully fleshed clock app with its
741@@ -52,6 +53,14 @@
742 defaults: { "digitalMode": false }
743 }
744
745+ U1db.Document {
746+ id: userLocationDocument
747+ create: true
748+ database: clockDB
749+ docId: "userLocationDocument"
750+ defaults: { "lat": "NaN", "long": "Nan", "location": "Null" }
751+ }
752+
753 DateTime {
754 id: localTimeSource
755 updateInterval: 1000
756
757=== modified file 'ubuntu-clock-app.json'
758--- ubuntu-clock-app.json 2014-08-18 21:37:23 +0000
759+++ ubuntu-clock-app.json 2014-11-04 15:58:17 +0000
760@@ -2,7 +2,8 @@
761 "policy_groups": [
762 "audio",
763 "calendar",
764- "networking"
765+ "networking",
766+ "location"
767 ],
768 "policy_version": 1.2
769 }
770\ No newline at end of file

Subscribers

People subscribed via source and target branches