Merge lp:~nik90/ubuntu-clock-app/world-clock-part1 into lp:ubuntu-clock-app/saucy
- world-clock-part1
- Merge into saucy
Proposed by
Nekhelesh Ramananthan
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Nekhelesh Ramananthan | ||||
Approved revision: | 108 | ||||
Merged at revision: | 103 | ||||
Proposed branch: | lp:~nik90/ubuntu-clock-app/world-clock-part1 | ||||
Merge into: | lp:ubuntu-clock-app/saucy | ||||
Prerequisite: | lp:~nik90/ubuntu-clock-app/initial-visual-design | ||||
Diff against target: |
607 lines (+506/-59) 4 files modified
clock/ClockPage.qml (+220/-58) clock/EasterEgg.qml (+1/-1) clock/WorldClock.qml (+107/-0) clock/WorldClockModel.qml (+178/-0) |
||||
To merge this branch: | bzr merge lp:~nik90/ubuntu-clock-app/world-clock-part1 | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Ubuntu Phone Apps Jenkins Bot | continuous-integration | Approve | |
Nekhelesh Ramananthan | Pending | ||
Review via email: mp+168537@code.launchpad.net |
Commit message
Adds the first phase of the world clock's feature. It currently implements the following,
- Necessary UI to show the world clocks
- Search world clocks online using geoname.org API
- World Time is updated every minute locally using existing timer
- Add world clock local storage. Stores world clocks selected by the user
- Clicking on world clock sets it as the current location.
- Add Clock toolbar action
Description of the change
This MP achieves the following,
- Necessary UI to show the world clocks
- Search world clocks online using geoname.org API
- World Time is updated every minute locally using existing timer
- Add world clock local storage. Stores world clocks selected by the user
- Clicking on world clock sets it as the current location.
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)
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-06-09 10:23:09 +0000 |
3 | +++ clock/ClockPage.qml 2013-06-14 19:10:32 +0000 |
4 | @@ -20,75 +20,237 @@ |
5 | |
6 | import QtQuick 2.0 |
7 | import Ubuntu.Components 0.1 |
8 | +import Ubuntu.Components.ListItems 0.1 as ListItem |
9 | +import QtQuick.XmlListModel 2.0 |
10 | import "../common/ClockUtils.js" as Utils |
11 | import "../common/Constants.js" as Constants |
12 | - |
13 | -Page { |
14 | +import "../common" |
15 | + |
16 | +Page { |
17 | + id: clockPage; |
18 | + |
19 | // Property to hold the formatted time string to show on the screen |
20 | property string currentTimeFormatted |
21 | + property real currentTimeStamp |
22 | + property real diff: new Date().getTimezoneOffset() |
23 | |
24 | Component.onCompleted: { |
25 | Utils.log("ClockPage loaded"); |
26 | - currentTimeFormatted = Qt.formatTime(new Date()); |
27 | + updateTime(); |
28 | } |
29 | |
30 | function onTimerUpdate(now) { |
31 | - currentTimeFormatted = Qt.formatTime(now); |
32 | + currentTimeFormatted = Qt.formatTime(new Date(currentTimeStamp + (diff * 60000)), "hh:mm") |
33 | + now.setMinutes(now.getMinutes() + diff) |
34 | clockFace.timeChanged(now) |
35 | - } |
36 | - |
37 | - // Label to show the current time |
38 | - Label { |
39 | - id: currentTimeLabel |
40 | - objectName: "currentTimeLabel" |
41 | - |
42 | - z: clockFace.z + 1; |
43 | - width: parent.width; height: parent.height / 4 |
44 | - anchors.centerIn: clockFace |
45 | - horizontalAlignment: Text.AlignHCenter |
46 | - verticalAlignment: Text.AlignVCenter |
47 | - fontSize: "x-large" |
48 | - color: Constants.brightWhite; |
49 | - |
50 | - text: currentTimeFormatted |
51 | - } |
52 | - |
53 | - // Qml Element to draw the analogue clock face along with its hour, minute and second hands. |
54 | - AnalogClockFace { |
55 | - id: clockFace |
56 | - |
57 | - anchors.centerIn: parent |
58 | - Component.onCompleted: easterEggCircle.reloadSunRiseModel() |
59 | - |
60 | - onClicked: { |
61 | - if (easterEggCircle.isReady == 1) { |
62 | - clockFace.state == "" ? clockFace.state = "easteregg" : clockFace.state = ""; |
63 | - } else { |
64 | - Utils.log("Sunrise/Sunset times not yet loaded.") |
65 | - } |
66 | - } |
67 | - |
68 | - EasterEgg { |
69 | - id: easterEggCircle |
70 | - anchors.centerIn: parent |
71 | + if (now.getUTCSeconds() == 0) { |
72 | + updateTime(); |
73 | + } |
74 | + } |
75 | + |
76 | + function updateTime() { |
77 | + var now = new Date(); |
78 | + currentTimeStamp = now.getTime(); |
79 | + } |
80 | + |
81 | + function getTimeDifference(data) { |
82 | + var worldTime = data.split(' ')[1].split(':'), |
83 | + hoursWT = parseInt(worldTime[0]), |
84 | + minutesWT = parseInt(worldTime[1]), |
85 | + now = new Date(); |
86 | + return ((hoursWT - now.getHours()) * 60 + (minutesWT - now.getMinutes())); |
87 | + } |
88 | + |
89 | + WorldClockModel { |
90 | + id: worldModel; |
91 | + |
92 | + Component.onCompleted: { |
93 | + _loadDB(); |
94 | + diff = worldModel.timeDiff; |
95 | + currentLocation.text = worldModel.city; |
96 | + currentTimeFormatted = Qt.formatTime(new Date(currentTimeStamp + (diff * 60000)), "hh:mm") |
97 | + } |
98 | + } |
99 | + |
100 | + AnimationContainer { |
101 | + id: clockAnimationContainer |
102 | + |
103 | + initYPos: units.gu(0); |
104 | + finalYPos: -listWorldClocks.height; |
105 | + |
106 | + anchors.fill: parent |
107 | + |
108 | + // Label to show the current time |
109 | + Rectangle { |
110 | + id: labelContainer; |
111 | + |
112 | + z: clockFace.z + 1; |
113 | width: clockFace.innerDimension; height: width; |
114 | - radius: width / 2; |
115 | - } |
116 | - |
117 | - states: [ |
118 | - State { |
119 | - name: "easteregg" |
120 | - PropertyChanges { target: easterEggCircle; opacity: 1; } |
121 | - PropertyChanges { target: currentTimeLabel; opacity: 0; } |
122 | - // TODO: Do some caching of data here. Store data locally to reduce API calls. |
123 | - PropertyChanges { target: easterEggCircle; sunriseLabel: easterEggCircle.getSunTime(easterEggCircle.model.get(0).sunrise); } |
124 | - PropertyChanges { target: easterEggCircle; sunsetLabel: easterEggCircle.getSunTime(easterEggCircle.model.get(0).sunset); } |
125 | - }, |
126 | - State { |
127 | - name: "" |
128 | - PropertyChanges { target: currentTimeLabel; opacity: 1; } |
129 | - PropertyChanges { target: easterEggCircle; opacity: 0; } |
130 | - } |
131 | - ] |
132 | + anchors.centerIn: clockFace; |
133 | + color: "transparent" |
134 | + |
135 | + Label { |
136 | + id: currentTimeLabel |
137 | + objectName: "currentTimeLabel" |
138 | + |
139 | + anchors.centerIn: parent |
140 | + horizontalAlignment: Text.AlignHCenter |
141 | + verticalAlignment: Text.AlignVCenter |
142 | + fontSize: "x-large" |
143 | + color: Constants.brightWhite; |
144 | + |
145 | + text: currentTimeFormatted |
146 | + } |
147 | + } |
148 | + |
149 | + // Qml Element to draw the analogue clock face along with its hour, minute and second hands. |
150 | + AnalogClockFace { |
151 | + id: clockFace |
152 | + |
153 | + anchors { top: parent.top; topMargin: units.gu(17); horizontalCenter: parent.horizontalCenter } |
154 | + Component.onCompleted: easterEggCircle.reloadSunRiseModel() |
155 | + |
156 | + onClicked: { |
157 | + if (easterEggCircle.isReady == XmlListModel.Ready) { |
158 | + clockFace.state == "" ? clockFace.state = "easteregg" : clockFace.state = ""; |
159 | + } else { |
160 | + Utils.log("Sunrise/Sunset times not yet loaded.") |
161 | + } |
162 | + } |
163 | + |
164 | + EasterEgg { |
165 | + id: easterEggCircle |
166 | + anchors.centerIn: parent |
167 | + width: clockFace.innerDimension; height: width; |
168 | + radius: width / 2; |
169 | + } |
170 | + |
171 | + states: [ |
172 | + State { |
173 | + name: "easteregg" |
174 | + PropertyChanges { target: easterEggCircle; opacity: 1; } |
175 | + PropertyChanges { target: currentTimeLabel; opacity: 0; } |
176 | + // TODO: Do some caching of data here. Store data locally to reduce API calls. |
177 | + PropertyChanges { target: easterEggCircle; sunriseLabel: easterEggCircle.getSunTime(easterEggCircle.model.get(0).sunrise); } |
178 | + PropertyChanges { target: easterEggCircle; sunsetLabel: easterEggCircle.getSunTime(easterEggCircle.model.get(0).sunset); } |
179 | + }, |
180 | + State { |
181 | + name: "" |
182 | + PropertyChanges { target: currentTimeLabel; opacity: 1; } |
183 | + PropertyChanges { target: easterEggCircle; opacity: 0; } |
184 | + } |
185 | + ] |
186 | + } |
187 | + |
188 | + Column { |
189 | + id: savedWorldClock |
190 | + |
191 | + height: childrenRect.height; |
192 | + anchors { left:parent.left; right:parent.right; top: clockFace.bottom; topMargin: units.gu(12)} |
193 | + |
194 | + ListItem.ThinDivider {} |
195 | + |
196 | + ListItem.Header { text: i18n.tr("Current Location") } |
197 | + |
198 | + ListItem.SingleValue { |
199 | + id: currentLocation |
200 | + text: "UTC" |
201 | + value: Qt.formatTime(new Date(currentTimeStamp + (diff * 60000)), "hh:mm A"); |
202 | + } |
203 | + |
204 | + ListItem.Header { text: i18n.tr("World") } |
205 | + |
206 | + ListView { |
207 | + id: listWorldClocks |
208 | + |
209 | + anchors { left: parent.left; right: parent.right } |
210 | + height: units.gu(30) |
211 | + model: worldModel |
212 | + currentIndex: -1 |
213 | + |
214 | + delegate: ListItem.Standard { |
215 | + text: cityName; |
216 | + |
217 | + Label { |
218 | + fontSize: "medium" |
219 | + text: Qt.formatTime(new Date(currentTimeStamp + (rawOffSet * 60000)), "hh:mm A"); |
220 | + anchors { verticalCenter: parent.verticalCenter; right: parent.right; rightMargin: units.gu(2) } |
221 | + } |
222 | + |
223 | + selected: listWorldClocks.currentIndex == index |
224 | + |
225 | + onClicked: { |
226 | + currentLocation.text = cityName; |
227 | + diff = rawOffSet; |
228 | + worldModel.appendCurrentLocation(cityName, diff); |
229 | + } |
230 | + } |
231 | + } |
232 | + } |
233 | + } |
234 | + |
235 | + WorldClock { |
236 | + id: worldClockList; |
237 | + |
238 | + anchors { left: parent.left; right: parent.right; top: parent.top; topMargin: units.gu(2) } |
239 | + |
240 | + // Xml model to retrieve timezone of searched city |
241 | + XmlListModel { |
242 | + id: cityDetailsModel; |
243 | + |
244 | + source: worldClockList.getCityTimezoneUrl(worldClockList.lat, worldClockList.lng) |
245 | + query: "/geonames/timezone" |
246 | + |
247 | + onStatusChanged: { |
248 | + if(status == XmlListModel.Ready && worldClockList.city != "null") { |
249 | + worldModel.appendPreset(worldClockList.city, getTimeDifference(cityDetailsModel.get(0).time)); |
250 | + } |
251 | + } |
252 | + |
253 | + XmlRole { name: "time"; query: "time/string()" } |
254 | + } |
255 | + |
256 | + onClicked: { |
257 | + lat = searchModel.get(index).lat; |
258 | + lng = searchModel.get(index).lng; |
259 | + city = searchModel.get(index).city; |
260 | + cityDetailsModel.reload() |
261 | + clockPage.state = "NORMAL" |
262 | + } |
263 | + } |
264 | + |
265 | + states: [ |
266 | + State { |
267 | + name: "ADDCITY" |
268 | + PropertyChanges { target: worldClockList; visible: true } |
269 | + PropertyChanges { target: clockAnimationContainer; visible: false } |
270 | + PropertyChanges { target: addCity; visible: false } |
271 | + }, |
272 | + |
273 | + State { |
274 | + name: "NORMAL" |
275 | + PropertyChanges { target: worldClockList; visible: false } |
276 | + PropertyChanges { target: clockAnimationContainer; visible: true } |
277 | + PropertyChanges { target: addCity; visible: true } |
278 | + } |
279 | + ] |
280 | + |
281 | + tools: ToolbarActions { |
282 | + id: toolbarClock |
283 | + |
284 | + Action { |
285 | + id: addCity |
286 | + |
287 | + iconSource: Qt.resolvedUrl("../images/add_icon.png") |
288 | + text: i18n.tr("Add City") |
289 | + visible: true; |
290 | + |
291 | + onTriggered: clockPage.state = "ADDCITY"; |
292 | + } |
293 | + |
294 | + back { |
295 | + visible: true; |
296 | + onTriggered: clockPage.state = "NORMAL"; |
297 | + } |
298 | } |
299 | } |
300 | |
301 | === modified file 'clock/EasterEgg.qml' |
302 | --- clock/EasterEgg.qml 2013-06-09 10:23:09 +0000 |
303 | +++ clock/EasterEgg.qml 2013-06-14 19:10:32 +0000 |
304 | @@ -52,7 +52,7 @@ |
305 | function getUrlString (latitude, longitude) { |
306 | var base_url,url; |
307 | base_url = "http://api.openweathermap.org/data/2.5/weather?"; |
308 | - url = base_url + "lat=" + latitude + "&lon=" + longitude + "&mode=xml"; |
309 | + url = base_url + "lat=" + latitude + "&lon=" + longitude + "&mode=xml"; |
310 | return url; |
311 | } |
312 | |
313 | |
314 | === added file 'clock/WorldClock.qml' |
315 | --- clock/WorldClock.qml 1970-01-01 00:00:00 +0000 |
316 | +++ clock/WorldClock.qml 2013-06-14 19:10:32 +0000 |
317 | @@ -0,0 +1,107 @@ |
318 | +import QtQuick 2.0 |
319 | +import Ubuntu.Components 0.1 |
320 | +import Ubuntu.Components.ListItems 0.1 as ListItem |
321 | +import QtQuick.XmlListModel 2.0 |
322 | +import "../common/ClockUtils.js" as Utils |
323 | +import "../common/Constants.js" as Constants |
324 | + |
325 | +Column { |
326 | + id: worldClocks |
327 | + |
328 | + // Properties to store the user searched city details |
329 | + property string city: "null"; |
330 | + property real lng: 0; |
331 | + property real lat: 0; |
332 | + property real rawOffSet: 0; |
333 | + |
334 | + // Property to store the city searched by the user |
335 | + property string search_string: "london"; |
336 | + |
337 | + // Properties to store the information related to api.geonames.org |
338 | + readonly property string username: "krnekhelesh"; |
339 | + readonly property string search_base_url: "http://api.geonames.org/search?q="; |
340 | + readonly property string timezone_base_url: "http://api.geonames.org/timezone?lat="; |
341 | + readonly property int no_of_results: 5; |
342 | + |
343 | + property alias searchModel: searchCityModel; |
344 | + property alias index: worldList.currentIndex; |
345 | + |
346 | + signal clicked() |
347 | + |
348 | + function searchCityUrl (city) { |
349 | + return (search_base_url + search_string + "&maxRows="+ no_of_results + "&username=" + username); |
350 | + } |
351 | + |
352 | + function getCityTimezoneUrl (lat, lng) { |
353 | + return (timezone_base_url + lat + "&lng=" + lng + "&username=" + username); |
354 | + } |
355 | + |
356 | + height: childrenRect.height; |
357 | + visible: false; |
358 | + |
359 | + // Xml model to search city online and retrieve latitude and longitude of searched city |
360 | + XmlListModel { |
361 | + id: searchCityModel; |
362 | + |
363 | + source: searchCityUrl(city) |
364 | + query: "/geonames/geoname" |
365 | + |
366 | + XmlRole { name: "city"; query: "toponymName/string()"; isKey: true } |
367 | + XmlRole { name: "lat"; query: "lat/string()"; isKey: true } |
368 | + XmlRole { name: "lng"; query: "lng/string()"; isKey: true } |
369 | + } |
370 | + |
371 | + Row { |
372 | + id: searchBox; |
373 | + |
374 | + spacing: units.gu(1) |
375 | + anchors.horizontalCenter: parent.horizontalCenter; |
376 | + height: childrenRect.height; |
377 | + |
378 | + TextField { |
379 | + id: searchLabel |
380 | + |
381 | + hasClearButton: true |
382 | + placeholderText: i18n.tr("Search"); |
383 | + } |
384 | + |
385 | + Button { |
386 | + id: searchButton; |
387 | + |
388 | + width: units.gu(12); height: searchLabel.height; |
389 | + color: Constants.green; |
390 | + text: i18n.tr("Search") |
391 | + |
392 | + onClicked: { |
393 | + if (searchLabel.text != "") { |
394 | + search_string = searchLabel.text; |
395 | + searchCityModel.reload(); |
396 | + } |
397 | + } |
398 | + } |
399 | + |
400 | + ActivityIndicator { |
401 | + running: searchCityModel.status === XmlListModel.Loading |
402 | + } |
403 | + } |
404 | + |
405 | + ListView { |
406 | + id: worldList |
407 | + |
408 | + anchors { left: parent.left; right: parent.right } |
409 | + height: units.gu(35) |
410 | + model: searchCityModel |
411 | + currentIndex: -1 |
412 | + |
413 | + delegate: ListItem.Standard { |
414 | + id: delegateTest; |
415 | + text: searchCityModel.status == XmlListModel.Ready ? searchCityModel.get(index).city : i18n.tr("Loading..."); |
416 | + selected: worldList.currentIndex == index; |
417 | + |
418 | + onClicked: { |
419 | + worldList.currentIndex = index; |
420 | + worldClocks.clicked() |
421 | + } |
422 | + } |
423 | + } |
424 | +} |
425 | |
426 | === added file 'clock/WorldClockModel.qml' |
427 | --- clock/WorldClockModel.qml 1970-01-01 00:00:00 +0000 |
428 | +++ clock/WorldClockModel.qml 2013-06-14 19:10:32 +0000 |
429 | @@ -0,0 +1,178 @@ |
430 | +/* |
431 | + * Copyright (C) 2013 Canonical Ltd |
432 | + * |
433 | + * This program is free software: you can redistribute it and/or modify |
434 | + * it under the terms of the GNU General Public License version 3 as |
435 | + * published by the Free Software Foundation. |
436 | + * |
437 | + * This program is distributed in the hope that it will be useful, |
438 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
439 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
440 | + * GNU General Public License for more details. |
441 | + * |
442 | + * You should have received a copy of the GNU General Public License |
443 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
444 | + * |
445 | + * Authored by: Nekhelesh Ramananthan <krnekhelesh@gmail.com> |
446 | + */ |
447 | + |
448 | +import QtQuick 2.0 |
449 | +import QtQuick.LocalStorage 2.0 |
450 | +import "../common/ClockUtils.js" as Utils |
451 | + |
452 | +ListModel { |
453 | + id: model |
454 | + |
455 | + readonly property string dbName: "ubuntu-clock-app" |
456 | + readonly property string dbVersion: "0.1" |
457 | + readonly property string dbDescription: "World Clock" |
458 | + |
459 | + property real timeDiff: new Date().getTimezoneOffset() |
460 | + property string city: "UTC"; |
461 | + |
462 | + property var _db: null |
463 | + |
464 | + function appendCurrentLocation(cityname, rawOffSet) |
465 | + { |
466 | + try { |
467 | + _db.transaction(function(tx){ |
468 | + var currentValue; |
469 | + var res = tx.executeSql('SELECT * FROM CurrentClock'); |
470 | + if (res.rows.length > 0) { |
471 | + currentValue = res.rows.item(0).rawOffSet; |
472 | + } |
473 | + |
474 | + if (currentValue !== rawOffSet) { |
475 | + // Update existing value or insert if none |
476 | + Utils.log("Outer loop"); |
477 | + if (currentValue !== undefined) { |
478 | + res = tx.executeSql('UPDATE CurrentClock SET rawOffSet = ?, cityName = ?', [rawOffSet, cityname]); |
479 | + Utils.log("Existing record found. Hence updating it!"); |
480 | + } else { |
481 | + res = tx.executeSql('INSERT INTO CurrentClock VALUES(?, ?)', [cityname, rawOffSet]); |
482 | + Utils.log("No City found. Creating a new entry."); |
483 | + } |
484 | + } |
485 | + }); |
486 | + } catch (err) { |
487 | + Utils.error("Error setting current location '" + "': " + err); |
488 | + return false; |
489 | + } |
490 | + } |
491 | + |
492 | + function appendPreset(cityName, rawOffSet) |
493 | + { |
494 | + if (_appendDB(cityName, rawOffSet)) { |
495 | + model.append({"cityName" : cityName, "rawOffSet" : rawOffSet}) |
496 | + } |
497 | + } |
498 | + |
499 | + function removePreset(index) |
500 | + { |
501 | + var cityName = get(index).cityName |
502 | + if (_removeDB(cityName)) { |
503 | + model.remove(index); |
504 | + } |
505 | + } |
506 | + |
507 | + function _createDB() { |
508 | + if (_db == null) return false; |
509 | + try { |
510 | + _db.transaction(function(tx){ |
511 | + tx.executeSql('CREATE TABLE IF NOT EXISTS WorldClock(cityName TEXT, rawOffSet REAL)'); |
512 | + }); |
513 | + } catch (err) { |
514 | + Utils.error("Error creating WorldClock table in db:" + err); |
515 | + return false; |
516 | + } |
517 | + try { |
518 | + _db.transaction(function(tx){ |
519 | + tx.executeSql('CREATE TABLE IF NOT EXISTS CurrentClock(cityName TEXT, rawOffSet REAL)'); |
520 | + }); |
521 | + } catch (err) { |
522 | + Utils.error("Error creating CurrentClock table in db:" + err); |
523 | + return false; |
524 | + } |
525 | + return true; |
526 | + } |
527 | + |
528 | + function _loadDB() { |
529 | + _db = LocalStorage.openDatabaseSync(model.dbName, model.dbVersion, model.dbDescription, 1000); |
530 | + if (_db == null) return false; |
531 | + if (!_createDB()) { |
532 | + _db = null; |
533 | + return false; |
534 | + } |
535 | + try { |
536 | + _db.readTransaction(function(tx){ |
537 | + var res = tx.executeSql('SELECT * FROM WorldClock'); |
538 | + if (res.rows.length > 0) { |
539 | + for (var i = 0; i < res.rows.length; i++) { |
540 | + model.append({"cityName" : res.rows.item(i).cityName, |
541 | + "rawOffSet" : res.rows.item(i).rawOffSet}); |
542 | + } |
543 | + } |
544 | + }); |
545 | + } catch (err) { |
546 | + Utils.error("Error opening database: " + err); |
547 | + _db = null |
548 | + return false; |
549 | + } |
550 | + try { |
551 | + _db.readTransaction(function(tx){ |
552 | + var currentstate = tx.executeSql('SELECT * FROM CurrentClock ORDER BY cityName'); |
553 | + if (currentstate.rows.length > 0) { |
554 | + city = currentstate.rows.item(0).cityName; |
555 | + timeDiff = currentstate.rows.item(0).rawOffSet |
556 | + Utils.log("Inside reading") |
557 | + } |
558 | + }); |
559 | + } catch (err) { |
560 | + Utils.error("Error opening database: " + err); |
561 | + _db = null |
562 | + return false; |
563 | + } |
564 | + return true; |
565 | + } |
566 | + |
567 | + function _appendDB(cityName, rawOffSet) { |
568 | + if (_db == null) return false; |
569 | + |
570 | + try { |
571 | + _db.transaction(function(tx){ |
572 | + var currentValue; |
573 | + var res = tx.executeSql('SELECT rawOffSet FROM WorldClock WHERE cityName=?', cityName); |
574 | + if (res.rows.length > 0) { |
575 | + currentValue = res.rows.item(0).rawOffSet; |
576 | + } |
577 | + |
578 | + if (currentValue !== rawOffSet) { |
579 | + // Update existing value or insert if none |
580 | + if (currentValue !== undefined) { |
581 | + res = tx.executeSql('UPDATE WorldClock SET rawOffSet = ? WHERE cityName = ?', [rawOffSet, cityName]); |
582 | + } else { |
583 | + res = tx.executeSql('INSERT INTO WorldClock VALUES(?, ?)', [cityName, rawOffSet]); |
584 | + } |
585 | + } |
586 | + }); |
587 | + } catch (err) { |
588 | + Utils.error("Error setting labeltxt '"+ label + "': " + err); |
589 | + return false; |
590 | + } |
591 | + return true; |
592 | + } |
593 | + |
594 | + function _removeDB(cityName) { |
595 | + if (_db == null) return false; |
596 | + |
597 | + try { |
598 | + _db.transaction(function(tx){ |
599 | + tx.executeSql('DELETE FROM WorldClock WHERE cityName = ?', [cityName]); |
600 | + }); |
601 | + } catch (err) { |
602 | + Utils.error("Error delete WorldClock'" + cityName + "': " + err); |
603 | + return false; |
604 | + } |
605 | + return true; |
606 | + } |
607 | +} |
PASSED: Continuous integration, rev:108 91.189. 93.125: 8080/job/ ubuntu- clock-app- ci/73/ 91.189. 93.125: 8080/job/ ubuntu- clock-app- quantal- amd64-ci/ 38 91.189. 93.125: 8080/job/ ubuntu- clock-app- raring- amd64-ci/ 73
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild: 91.189. 93.125: 8080/job/ ubuntu- clock-app- ci/73/rebuild
http://