Merge lp:~nik90/ubuntu-weather-app/1-improve-add-location-page into lp:ubuntu-weather-app

Proposed by Nekhelesh Ramananthan
Status: Merged
Approved by: Martin Borho
Approved revision: 20
Merged at revision: 17
Proposed branch: lp:~nik90/ubuntu-weather-app/1-improve-add-location-page
Merge into: lp:ubuntu-weather-app
Prerequisite: lp:~nik90/ubuntu-weather-app/0-fix-broken-settings-links
Diff against target: 777 lines (+600/-55)
5 files modified
app/components/FastScroll.js (+130/-0)
app/components/FastScroll.qml (+321/-0)
app/ui/AddLocationPage.qml (+126/-40)
app/ui/LocationsPage.qml (+1/-1)
po/com.ubuntu.weather.pot (+22/-14)
To merge this branch: bzr merge lp:~nik90/ubuntu-weather-app/1-improve-add-location-page
Reviewer Review Type Date Requested Status
Martin Borho Approve
Ubuntu Phone Apps Jenkins Bot continuous-integration Approve
Review via email: mp+252115@code.launchpad.net

This proposal supersedes a proposal from 2015-03-06.

Commit message

This MP brings the Add Location Page more in line with Clock app's own add city page to maintain consistency. Also there was no design specified for the add location page in weather app's design spec.

- Added fast scroll to add location page
- Renamed AddPage.qml to AddLocationPage.qml to be more specific
- Added section headers to listview
- Removed focus on search textfield immediately after opening the add location page. The reasoning here being that we show a list of cities that the user can choose from. Only if doesnt find his city there should he resort to searching online.
- Moved the search textfield to a component to allow for dynamic loading

Description of the change

This MP brings the Add Location Page more in line with Clock app's own add city page to maintain consistency. Also there was no design specified for the add location page in weather app's design spec.

- Added fast scroll to add location page
- Renamed AddPage.qml to AddLocationPage.qml to be more specific
- Added section headers to listview
- Removed focus on search textfield immediately after opening the add location page. The reasoning here being that we show a list of cities that the user can choose from. Only if doesnt find his city there should he resort to searching online.
- Moved the search textfield to a component to allow for dynamic loading

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
Martin Borho (martin-borho) wrote :

Very good, thanks!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file 'app/components/FastScroll.js'
2--- app/components/FastScroll.js 1970-01-01 00:00:00 +0000
3+++ app/components/FastScroll.js 2015-03-06 14:21:02 +0000
4@@ -0,0 +1,130 @@
5+/****************************************************************************
6+**
7+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
8+** Copyright (C) 2014 Canonical Ltda
9+** All rights reserved.
10+** Contact: Nokia Corporation (qt-info@nokia.com)
11+**
12+** This file is part of the Qt Components project.
13+**
14+** $QT_BEGIN_LICENSE:BSD$
15+** You may use this file under the terms of the BSD license as follows:
16+**
17+** "Redistribution and use in source and binary forms, with or without
18+** modification, are permitted provided that the following conditions are
19+** met:
20+** * Redistributions of source code must retain the above copyright
21+** notice, this list of conditions and the following disclaimer.
22+** * Redistributions in binary form must reproduce the above copyright
23+** notice, this list of conditions and the following disclaimer in
24+** the documentation and/or other materials provided with the
25+** distribution.
26+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
27+** the names of its contributors may be used to endorse or promote
28+** products derived from this software without specific prior written
29+** permission.
30+**
31+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
34+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
36+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
37+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
38+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
39+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
40+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
41+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
42+** $QT_END_LICENSE$
43+**
44+****************************************************************************/
45+
46+// FastScroll.js - this is just SectionScroller.js with a fix for
47+// section.criteria == ViewSection.FirstCharacter
48+var sectionData = [];
49+var _sections = [];
50+
51+function initialize(list) {
52+ initSectionData(list);
53+}
54+
55+function contains(name) {
56+ return (_sections.indexOf(name) > -1)
57+}
58+
59+function initSectionData(list) {
60+ if (!list || !list.model) return;
61+ sectionData = [];
62+ _sections = [];
63+ var current = "",
64+ prop = list.section.property,
65+ sectionText;
66+
67+ if (list.section.criteria === ViewSection.FullString) {
68+ for (var i = 0, count = list.model.count; i < count; i++) {
69+ sectionText = list.getSectionText(i)
70+ if (sectionText !== current) {
71+ current = sectionText;
72+ _sections.push(current);
73+ sectionData.push({ index: i, header: current });
74+ }
75+ }
76+ } else if (list.section.criteria === ViewSection.FirstCharacter) {
77+ for (var i = 0, count = list.model.count; i < count; i++) {
78+ sectionText = list.getSectionText(i).substring(0, 1)
79+ if (sectionText !== current) {
80+ current = sectionText
81+ _sections.push(sectionText);
82+ sectionData.push({ index: i, header: current });
83+ }
84+ }
85+ }
86+}
87+
88+function getSectionPositionString(name) {
89+ var val = _sections.indexOf(name);
90+ return val === 0 ? "first" :
91+ val === _sections.length - 1 ? "last" : false;
92+}
93+
94+function getAt(pos) {
95+ return _sections[pos] ? _sections[pos] : "";
96+}
97+
98+function getRelativeSections(current) {
99+ var val = _sections.indexOf(current),
100+ sect = [],
101+ sl = _sections.length;
102+
103+ val = val < 1 ? 1 : val >= sl-1 ? sl-2 : val;
104+ sect = [getAt(val - 1), getAt(val), getAt(val + 1)];
105+
106+ return sect;
107+}
108+
109+function getClosestSection(pos, down) {
110+ var tmp = (_sections.length) * pos;
111+ var val = Math.ceil(tmp) // TODO: better algorithm
112+ val = val < 2 ? 1 : val;
113+ return _sections[val-1];
114+}
115+
116+function getNextSection(current) {
117+ var val = _sections.indexOf(current);
118+ return (val > -1 ? _sections[(val < _sections.length - 1 ? val + 1 : val)] : _sections[0]) || "";
119+}
120+
121+function getPreviousSection(current) {
122+ var val = _sections.indexOf(current);
123+ return (val > -1 ? _sections[(val > 0 ? val - 1 : val)] : _sections[0]) || "";
124+}
125+
126+function getIndexFor(sectionName) {
127+ var data = sectionData[_sections.indexOf(sectionName)]
128+ if (data) {
129+ var val = data.index;
130+ return val === 0 || val > 0 ? val : -1;
131+ } else {
132+ return -1
133+ }
134+}
135
136=== added file 'app/components/FastScroll.qml'
137--- app/components/FastScroll.qml 1970-01-01 00:00:00 +0000
138+++ app/components/FastScroll.qml 2015-03-06 14:21:02 +0000
139@@ -0,0 +1,321 @@
140+/****************************************************************************
141+**
142+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
143+** Copyright (C) 2014 Canonical Ltda
144+** All rights reserved.
145+** Contact: Nokia Corporation (qt-info@nokia.com)
146+**
147+** This file is part of the Qt Components project.
148+**
149+** $QT_BEGIN_LICENSE:BSD$
150+** You may use this file under the terms of the BSD license as follows:
151+**
152+** "Redistribution and use in source and binary forms, with or without
153+** modification, are permitted provided that the following conditions are
154+** met:
155+** * Redistributions of source code must retain the above copyright
156+** notice, this list of conditions and the following disclaimer.
157+** * Redistributions in binary form must reproduce the above copyright
158+** notice, this list of conditions and the following disclaimer in
159+** the documentation and/or other materials provided with the
160+** distribution.
161+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
162+** the names of its contributors may be used to endorse or promote
163+** products derived from this software without specific prior written
164+** permission.
165+**
166+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
167+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
168+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
169+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
170+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
171+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
172+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
173+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
174+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
175+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
176+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
177+** $QT_END_LICENSE$
178+**
179+****************************************************************************/
180+
181+// FastScroll.qml
182+import QtQuick 2.3
183+import Ubuntu.Components 1.1
184+import "FastScroll.js" as Sections
185+
186+Item {
187+ id: root
188+
189+ property ListView listView
190+ property int pinSize: units.gu(2)
191+
192+ readonly property var letters: ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"]
193+ readonly property alias fastScrolling: internal.fastScrolling
194+ readonly property bool showing: (rail.opacity !== 0.0)
195+ readonly property double minimumHeight: rail.height
196+
197+ width: units.gu(7)
198+ height: rail.height
199+
200+ onListViewChanged: {
201+ if (listView && listView.model) {
202+ internal.initDirtyObserver();
203+ } else if (listView) {
204+ listView.modelChanged.connect(function() {
205+ if (listView.model) {
206+ internal.initDirtyObserver();
207+ }
208+ });
209+ }
210+ }
211+
212+ Connections {
213+ target: listView
214+ onCurrentIndexChanged: {
215+ if (currentIndex != -1) {
216+ rail.opacity = 0.0
217+ }
218+ }
219+ }
220+
221+ Rectangle {
222+ id: magnified
223+
224+ color: Theme.palette.normal.overlay
225+ radius: height * 0.3
226+ height: pinSize * 2
227+ width: height
228+ opacity: internal.fastScrolling && root.enabled ? 1.0 : 0.0
229+ x: -cursor.width - units.gu(3)
230+ y: {
231+ if (internal.currentItem) {
232+ var itemCenterY = rail.y + internal.currentItem.y + (internal.currentItem.height / 2)
233+ return (itemCenterY - (magnified.height / 2))
234+ } else {
235+ return 0
236+ }
237+ }
238+
239+ Label {
240+ anchors.fill: parent
241+ horizontalAlignment: Text.AlignHCenter
242+ verticalAlignment: Text.AlignVCenter
243+ text: internal.desireSection
244+ fontSize: "small"
245+ }
246+
247+ Behavior on opacity {
248+ UbuntuNumberAnimation {}
249+ }
250+ }
251+
252+ Rectangle {
253+ id: cursor
254+
255+ property bool showLabel: false
256+ property string currentSectionName: ""
257+
258+ radius: pinSize * 0.3
259+ height: pinSize
260+ width: height
261+ color: Theme.palette.normal.foreground
262+ opacity: rail.opacity
263+ x: rail.x
264+ y: {
265+ if (internal.currentItem) {
266+ var itemCenterY = rail.y + internal.currentItem.y + (internal.currentItem.height / 2)
267+ return (itemCenterY - (cursor.height / 2))
268+ } else {
269+ return 0
270+ }
271+ }
272+ Behavior on y {
273+ enabled: !internal.fastScrolling
274+ UbuntuNumberAnimation { }
275+ }
276+ }
277+
278+ Column {
279+ id: rail
280+
281+ property bool isVisible: root.enabled &&
282+ (listView.flicking || dragArea.pressed) &&
283+ (listView.currentIndex == -1)
284+ anchors {
285+ right: parent.right
286+ rightMargin: units.gu(2)
287+ left: parent.left
288+ leftMargin: units.gu(2)
289+ top: parent.top
290+ }
291+ height: childrenRect.height
292+ opacity: 0.0
293+ onIsVisibleChanged: {
294+ if (isVisible) {
295+ rail.opacity = 1.0
296+ hideTimer.stop()
297+ } else if (!root.enabled) {
298+ rail.opacity = 0.0
299+ } else {
300+ hideTimer.restart()
301+ }
302+ }
303+
304+ Behavior on opacity {
305+ UbuntuNumberAnimation { }
306+ }
307+
308+ Repeater {
309+ id: sectionsRepeater
310+
311+ model: root.letters
312+ Label {
313+ id: lbl
314+
315+ anchors.left: parent.left
316+ height: pinSize
317+ width: pinSize
318+ verticalAlignment: Text.AlignVCenter
319+ horizontalAlignment: Text.AlignHCenter
320+ text: modelData
321+ fontSize: "x-small"
322+ color: cursor.y === y ? "white" : Theme.palette.selected.backgroundText
323+ opacity: !internal.modelDirty && Sections.contains(text) ? 1.0 : 0.5
324+ }
325+ }
326+
327+ Timer {
328+ id: hideTimer
329+
330+ running: false
331+ interval: 2000
332+ onTriggered: rail.opacity = 0.0
333+ }
334+ }
335+
336+ MouseArea {
337+ id: dragArea
338+
339+ anchors {
340+ left: parent.left
341+ right: parent.right
342+ }
343+ y: rail.y
344+ height: rail.height
345+ visible: rail.opacity == 1.0
346+
347+ preventStealing: true
348+ onPressed: {
349+ internal.adjustContentPosition(mouseY)
350+ dragginTimer.start()
351+ }
352+
353+ onReleased: {
354+ dragginTimer.stop()
355+ internal.desireSection = ""
356+ internal.fastScrolling = false
357+ }
358+
359+ onPositionChanged: internal.adjustContentPosition(mouseY)
360+
361+ Timer {
362+ id: dragginTimer
363+
364+ running: false
365+ interval: 150
366+ onTriggered: {
367+ internal.fastScrolling = true
368+ }
369+ }
370+ }
371+
372+ Timer {
373+ id: dirtyTimer
374+ interval: 500
375+ running: false
376+ onTriggered: {
377+ Sections.initSectionData(listView);
378+ internal.modelDirty = false;
379+ }
380+ }
381+
382+ Timer {
383+ id: timerScroll
384+
385+ running: false
386+ interval: 10
387+ onTriggered: {
388+ if (internal.desireSection != internal.currentSection) {
389+ var idx = Sections.getIndexFor(internal.desireSection)
390+ if (idx !== -1) {
391+ listView.cancelFlick()
392+ listView.positionViewAtIndex(idx, ListView.Beginning)
393+ }
394+ }
395+ }
396+ }
397+
398+ QtObject {
399+ id: internal
400+
401+ property string currentSection: listView.currentSection
402+ property string desireSection: ""
403+ property string targetSection: fastScrolling ? desireSection : currentSection
404+ property int oldY: 0
405+ property bool modelDirty: false
406+ property bool down: true
407+ property bool fastScrolling: false
408+ property var currentItem: null
409+
410+ onTargetSectionChanged: moveIndicator(targetSection)
411+
412+ function initDirtyObserver() {
413+ Sections.initialize(listView);
414+ function dirtyObserver() {
415+ if (!internal.modelDirty) {
416+ internal.modelDirty = true;
417+ dirtyTimer.running = true;
418+ }
419+ }
420+
421+ if (listView.model.countChanged)
422+ listView.model.countChanged.connect(dirtyObserver);
423+
424+ if (listView.model.itemsChanged)
425+ listView.model.itemsChanged.connect(dirtyObserver);
426+
427+ if (listView.model.itemsInserted)
428+ listView.model.itemsInserted.connect(dirtyObserver);
429+
430+ if (listView.model.itemsMoved)
431+ listView.model.itemsMoved.connect(dirtyObserver);
432+
433+ if (listView.model.itemsRemoved)
434+ listView.model.itemsRemoved.connect(dirtyObserver);
435+ }
436+
437+ function adjustContentPosition(mouseY) {
438+ var child = rail.childAt(rail.width / 2, mouseY)
439+ if (!child || child.text === "") {
440+ return
441+ }
442+ var section = child.text
443+ if (internal.desireSection !== section) {
444+ internal.desireSection = section
445+ moveIndicator(section)
446+ if (dragArea.pressed) {
447+ timerScroll.restart()
448+ }
449+ }
450+ }
451+
452+ function moveIndicator(section)
453+ {
454+ var index = root.letters.indexOf(section)
455+ if (index != -1) {
456+ currentItem = sectionsRepeater.itemAt(index)
457+ }
458+ }
459+ }
460+}
461
462=== renamed file 'app/ui/AddPage.qml' => 'app/ui/AddLocationPage.qml'
463--- app/ui/AddPage.qml 2015-03-03 13:52:31 +0000
464+++ app/ui/AddLocationPage.qml 2015-03-06 14:21:02 +0000
465@@ -25,32 +25,77 @@
466 import "../data/WeatherApi.js" as WeatherApi
467
468 Page {
469- id: addPage
470- title: i18n.tr("Add city")
471-
472- head.contents: TextField {
473- id: searchField
474- anchors {
475- left: parent ? parent.left : undefined
476- right: parent ? parent.right : undefined
477- rightMargin: units.gu(2)
478- }
479- hasClearButton: true
480- inputMethodHints: Qt.ImhNoPredictiveText
481- placeholderText: i18n.tr("Search city")
482-
483- onTextChanged: {
484- if (text.trim() === "") {
485- loadEmpty()
486- } else {
487- loadFromProvider(text)
488- }
489- }
490-
491- onVisibleChanged: {
492- if (visible) {
493- forceActiveFocus()
494- }
495+ id: addLocationPage
496+
497+ title: i18n.tr("Select a city")
498+ visible: false
499+
500+ /*
501+ Flickable is set to null to stop page header from hiding since the fast
502+ scroll component hides top anchor margin is incorrect.
503+ */
504+ flickable: null
505+
506+ state: "default"
507+ states: [
508+ PageHeadState {
509+ name: "default"
510+ head: addLocationPage.head
511+ actions: [
512+ Action {
513+ iconName: "search"
514+ text: i18n.tr("City")
515+ onTriggered: {
516+ addLocationPage.state = "search"
517+ searchComponentLoader.sourceComponent = searchComponent
518+ searchComponentLoader.item.forceActiveFocus()
519+ }
520+ }
521+ ]
522+ },
523+
524+ PageHeadState {
525+ name: "search"
526+ head: addLocationPage.head
527+ backAction: Action {
528+ iconName: "back"
529+ text: i18n.tr("Back")
530+ onTriggered: {
531+ locationList.forceActiveFocus()
532+ searchComponentLoader.item.text = ""
533+ addLocationPage.state = "default"
534+ searchComponentLoader.sourceComponent = undefined
535+ }
536+ }
537+
538+ contents: Loader {
539+ id: searchComponentLoader
540+ anchors {
541+ left: parent ? parent.left : undefined
542+ right: parent ? parent.right : undefined
543+ rightMargin: units.gu(2)
544+ }
545+ }
546+ }
547+ ]
548+
549+ Component {
550+ id: searchComponent
551+ TextField {
552+ id: searchField
553+ objectName: "searchField"
554+
555+ inputMethodHints: Qt.ImhNoPredictiveText
556+ placeholderText: i18n.tr("Search city")
557+ hasClearButton: true
558+
559+ onTextChanged: {
560+ if (text.trim() === "") {
561+ loadEmpty()
562+ } else {
563+ loadFromProvider(text)
564+ }
565+ }
566 }
567 }
568
569@@ -78,12 +123,12 @@
570 clearModelForLoading()
571
572 WeatherApi.sendRequest({
573- action: "searchByName",
574- params: {
575- name: search,
576- units: "metric"
577- }
578- }, searchResponseHandler)
579+ action: "searchByName",
580+ params: {
581+ name: search,
582+ units: "metric"
583+ }
584+ }, searchResponseHandler)
585 }
586
587 function searchResponseHandler(msgObject) {
588@@ -97,10 +142,30 @@
589 }
590
591 ListView {
592- id: addLocationView
593- anchors {
594- fill: parent
595- }
596+ id: locationList
597+
598+ clip: true
599+ currentIndex: -1
600+ anchors.fill: parent
601+ anchors.rightMargin: fastScroll.showing ? fastScroll.width - units.gu(1)
602+ : 0
603+
604+ function getSectionText(index) {
605+ return citiesModel.get(index).name.substring(0,1)
606+ }
607+
608+ onFlickStarted: {
609+ forceActiveFocus()
610+ }
611+
612+ section.property: "name"
613+ section.criteria: ViewSection.FirstCharacter
614+ section.labelPositioning: ViewSection.InlineLabels
615+
616+ section.delegate: ListItem.Header {
617+ text: section
618+ }
619+
620 model: ListModel {
621 id: citiesModel
622
623@@ -109,7 +174,9 @@
624
625 onRowsAboutToBeInserted: loading = false
626 }
627+
628 delegate: ListItem.Empty {
629+ showDivider: false
630 Column {
631 anchors {
632 left: parent.left
633@@ -118,20 +185,19 @@
634 rightMargin: units.gu(2)
635 verticalCenter: parent.verticalCenter
636 }
637- spacing: units.gu(0.5)
638
639 Label {
640 color: UbuntuColors.darkGrey
641 elide: Text.ElideRight
642 fontSize: "medium"
643- text: model.name
644+ text: name
645 }
646
647 Label {
648 color: UbuntuColors.lightGrey
649 elide: Text.ElideRight
650- fontSize: "small"
651- text: model.countryName
652+ fontSize: "xx-small"
653+ text: countryName
654 }
655 }
656
657@@ -145,6 +211,26 @@
658 }
659
660 Component.onCompleted: loadEmpty()
661+
662+ Behavior on anchors.rightMargin {
663+ UbuntuNumberAnimation {}
664+ }
665+ }
666+
667+ FastScroll {
668+ id: fastScroll
669+
670+ listView: locationList
671+
672+ enabled: (locationList.contentHeight > (locationList.height * 2)) &&
673+ (locationList.height >= minimumHeight)
674+
675+ anchors {
676+ top: locationList.top
677+ topMargin: units.gu(1.5)
678+ bottom: locationList.bottom
679+ right: parent.right
680+ }
681 }
682
683 ActivityIndicator {
684
685=== modified file 'app/ui/LocationsPage.qml'
686--- app/ui/LocationsPage.qml 2015-03-03 18:37:59 +0000
687+++ app/ui/LocationsPage.qml 2015-03-06 14:21:02 +0000
688@@ -37,7 +37,7 @@
689 actions: [
690 Action {
691 iconName: "add"
692- onTriggered: mainPageStack.push(Qt.resolvedUrl("AddPage.qml"))
693+ onTriggered: mainPageStack.push(Qt.resolvedUrl("AddLocationPage.qml"))
694 }
695 ]
696 PropertyChanges {
697
698=== modified file 'po/com.ubuntu.weather.pot'
699--- po/com.ubuntu.weather.pot 2015-03-06 14:21:02 +0000
700+++ po/com.ubuntu.weather.pot 2015-03-06 14:21:02 +0000
701@@ -8,7 +8,7 @@
702 msgstr ""
703 "Project-Id-Version: ubuntu-weather-app\n"
704 "Report-Msgid-Bugs-To: \n"
705-"POT-Creation-Date: 2015-03-06 14:23+0100\n"
706+"POT-Creation-Date: 2015-03-06 15:08+0100\n"
707 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
708 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
709 "Language-Team: LANGUAGE <LL@li.org>\n"
710@@ -37,27 +37,35 @@
711 msgid "Cancel selection"
712 msgstr ""
713
714-#: ../app/ui/AddPage.qml:29
715-msgid "Add city"
716-msgstr ""
717-
718-#: ../app/ui/AddPage.qml:40
719+#: ../app/ui/AddLocationPage.qml:30
720+msgid "Select a city"
721+msgstr ""
722+
723+#: ../app/ui/AddLocationPage.qml:47
724+msgid "City"
725+msgstr ""
726+
727+#: ../app/ui/AddLocationPage.qml:62
728+msgid "Back"
729+msgstr ""
730+
731+#: ../app/ui/AddLocationPage.qml:89
732 msgid "Search city"
733 msgstr ""
734
735-#: ../app/ui/AddPage.qml:163
736+#: ../app/ui/AddLocationPage.qml:249
737 msgid "No city found"
738 msgstr ""
739
740-#: ../app/ui/AddPage.qml:176
741+#: ../app/ui/AddLocationPage.qml:262
742 msgid "Couldn't load weather data, please try later again!"
743 msgstr ""
744
745-#: ../app/ui/AddPage.qml:186
746+#: ../app/ui/AddLocationPage.qml:272
747 msgid "Location already added."
748 msgstr ""
749
750-#: ../app/ui/AddPage.qml:189
751+#: ../app/ui/AddLocationPage.qml:275
752 msgid "OK"
753 msgstr ""
754
755@@ -65,19 +73,19 @@
756 msgid "Locations"
757 msgstr ""
758
759-#: ../app/ui/SettingsPage.qml:25
760+#: ../app/ui/SettingsPage.qml:24
761 msgid "Settings"
762 msgstr ""
763
764-#: ../app/ui/SettingsPage.qml:42 ../app/ui/settings/UnitsPage.qml:25
765+#: ../app/ui/SettingsPage.qml:41 ../app/ui/settings/UnitsPage.qml:25
766 msgid "Units"
767 msgstr ""
768
769-#: ../app/ui/SettingsPage.qml:49 ../app/ui/settings/DataProviderPage.qml:25
770+#: ../app/ui/SettingsPage.qml:48 ../app/ui/settings/DataProviderPage.qml:25
771 msgid "Data Provider"
772 msgstr ""
773
774-#: ../app/ui/SettingsPage.qml:56 ../app/ui/settings/RefreshIntervalPage.qml:25
775+#: ../app/ui/SettingsPage.qml:55 ../app/ui/settings/RefreshIntervalPage.qml:25
776 msgid "Refresh Interval"
777 msgstr ""
778

Subscribers

People subscribed via source and target branches