Merge lp:~martin-borho/ubuntu-weather-app/reboot-nav-and-snap-scrolling into lp:ubuntu-weather-app

Proposed by Martin Borho
Status: Merged
Approved by: Victor Thompson
Approved revision: 19
Merged at revision: 11
Proposed branch: lp:~martin-borho/ubuntu-weather-app/reboot-nav-and-snap-scrolling
Merge into: lp:ubuntu-weather-app
Diff against target: 429 lines (+217/-110)
5 files modified
app/ubuntu-weather-app.qml (+10/-12)
app/ui/HomePage.qml (+53/-93)
app/ui/LocationPane.qml (+145/-0)
app/ui/LocationsPage.qml (+7/-3)
po/com.ubuntu.weather.pot (+2/-2)
To merge this branch: bzr merge lp:~martin-borho/ubuntu-weather-app/reboot-nav-and-snap-scrolling
Reviewer Review Type Date Requested Status
Victor Thompson Approve
Ubuntu Phone Apps Jenkins Bot continuous-integration Approve
Andrew Hayzen Approve
Review via email: mp+249772@code.launchpad.net

Commit message

Implemented horizontal scrolling through loctions and a functional bottom edge.

Description of the change

Implemented horizontal scrolling through locations and a functional bottom edge.

But there are some caveats:

- newly added ListView for horizontal scrolling cannot be used with "snapMode: ListView.SnapOneItem", because the "currentIndex" property is getting ignored when doing so (Bug!?) I have implemented a non-snap-mode solution the, until problem with snapMode gets sorted out.

- jumping through the bottom edge to a location does't work reliable all the time. Some things are broken somehow (Qt/SDK?). Log output:

qml: WARNING! Do not put Page/Tabs/PageStack inside another Page because that causes confusion which is the active page that sets the title and actions.
file:///usr/lib/x86_64-linux-gnu/qt5/qml/Ubuntu/Components/PageWrapperUtils.js:30: TypeError: Cannot read property 'createObject' of null
qml: WARNING! Do not put Page/Tabs/PageStack inside another Page because that causes confusion which is the active page that sets the title and actions.
qml: WARNING! Do not put Page/Tabs/PageStack inside another Page because that causes confusion which is the active page that sets the title and actions.

I think it's good to go for the moment, shortcomings above shouldn't stop us from moving forward.

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
Andrew Hayzen (ahayzen) wrote :

- newly added ListView for horizontal scrolling cannot be used with "snapMode: ListView.SnapOneItem", because the "currentIndex" property is getting ignored when doing so (Bug!?) I have implemented a non-snap-mode solution the, until problem with snapMode gets sorted out.

This sounds strange I'll investigate to see if i can figure out what is going on.

- app won't start on device, claiming "LocationPane is no type". But works on desktop!

The component is probably missing in the cmake and not being included in the .click? or an import is failing somewhere.

- jumping through the bottom edge to a location does't work reliable all the time. Some things are broken somehow (Qt/SDK?). Log output:

Most of those warnings you can safely ignore, but it should be able to work all of the time, i'll double check if there isn't something causing it to break.

1 inline comment:
- I wonder if we can change this to mainPageStack.push("ui/HomePage.qml") instead of using the component?
- I have some massive OCD over formatting, could you ensure that all of the properties have a space between the : and the value?

review: Needs Fixing
14. By Martin Borho

added current property to settings

Revision history for this message
Andrew Hayzen (ahayzen) wrote :

Thanks for adding the settings as discussed :)

One further thing, the Rectangle in LocationsPane L24 could probably be a Item as there is no colour set? This will help with performance.

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
Andrew Hayzen (ahayzen) wrote :

I've also found that the currentIndex can get out of sync

1) Start the app with two locations
2) Use the bottom edge to switch to the second location
3) Restart the app, notice that it starts at the first index and not the second
4) Now try and use the bottom edge to switch to the second location, note nothing happens

It appears from the app log that as the location list is reset and loaded the currentIndex is lost.

15. By Martin Borho

removed highlightMoveDuration

16. By Martin Borho

currentIndex gets set from settings.current

17. By Martin Borho

formatting

18. By Martin Borho

pushing HomePage.qml directly to pagestack

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
Andrew Hayzen (ahayzen) wrote :

LGTM, thanks for the extra changes :)

@Victor can you double check there isn't anything else :)

review: Approve
Revision history for this message
Victor Thompson (vthompson) wrote :

The code looks good, maybe we can do something like the following to workaround the snapMode issue?

=== modified file 'app/ui/HomePage.qml'
--- app/ui/HomePage.qml 2015-02-15 15:44:33 +0000
+++ app/ui/HomePage.qml 2015-02-15 18:22:31 +0000
@@ -88,6 +88,13 @@

             property bool loaded: false

+ // TODO: workaround for not being able to use snapMode property
+ Component.onCompleted: {
+ var scaleFactor = units.gridUnit * 10;
+ maximumFlickVelocity = maximumFlickVelocity * scaleFactor;
+ flickDeceleration = flickDeceleration * scaleFactor;
+ }
+

19. By Martin Borho

added workaround by victor for snapMode bug

Revision history for this message
Martin Borho (martin-borho) wrote :

@vthompson workaround added!

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
Victor Thompson (vthompson) wrote :

Thanks! lgtm, thanks Martin!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'app/ubuntu-weather-app.qml'
2--- app/ubuntu-weather-app.qml 2015-02-10 14:09:17 +0000
3+++ app/ubuntu-weather-app.qml 2015-02-15 19:22:09 +0000
4@@ -45,7 +45,7 @@
5 /*
6 List of locations and their data, accessible through index
7 */
8- property var locationsList: []
9+ property var locationsList: []
10
11 /*
12 Index of Location before a refresh, to go back after
13@@ -81,9 +81,8 @@
14
15 /* Fill the location pages with their data. */
16 function fillPages(locations) {
17+ locationsList = []
18 locationsList = locations;
19- // refactor this when Location are in a ListView!
20- homePage.renderData();
21 }
22
23 /*
24@@ -98,9 +97,9 @@
25 WeatherApi.sendRequest({
26 action: "updateData",
27 params: {
28- locations:locations,
29- force:force_refresh,
30- service:settings.service,
31+ locations: locations,
32+ force: force_refresh,
33+ service: settings.service,
34 api_key: Key.twcKey,
35 interval: settings.refreshInterval
36 }
37@@ -112,6 +111,10 @@
38 Settings {
39 id: settings
40 category: "weatherSettings"
41+ /*
42+ Index of the current locationList of locations and their data, accessible through index
43+ */
44+ property int current: 0
45
46 property int refreshInterval: 1800
47 property string precipUnits
48@@ -142,11 +145,6 @@
49
50 PageStack {
51 id: mainPageStack
52-
53- HomePage {
54- id: homePage
55- }
56-
57- Component.onCompleted: mainPageStack.push(homePage)
58+ Component.onCompleted: mainPageStack.push(Qt.resolvedUrl("ui/HomePage.qml"))
59 }
60 }
61
62=== modified file 'app/ui/HomePage.qml'
63--- app/ui/HomePage.qml 2015-02-11 04:14:16 +0000
64+++ app/ui/HomePage.qml 2015-02-15 19:22:09 +0000
65@@ -18,7 +18,6 @@
66
67 import QtQuick 2.3
68 import Ubuntu.Components 1.1
69-import Ubuntu.Components.ListItems 0.1 as ListItem
70 import "../components"
71
72
73@@ -32,16 +31,6 @@
74 tipColor: UbuntuColors.orange
75 tipLabelColor: "#FFF"
76
77- /*
78- Data properties
79- */
80- property string name
81- property string conditionText
82- property string currentTemp
83- property string todayMaxTemp
84- property string todayMinTemp
85- property string iconName
86-
87 // TODO map iconnames to source image names
88 property var iconMap: {
89 "moon": "moon.svg"
90@@ -57,89 +46,60 @@
91 }
92
93 /*
94- Extracts values from the location weather data and puts them into the appropriate components
95- to display them.
96-
97- Attention: Data access happens through "weatherApp.locationList[]" by index, since complex
98- data in models will lead to type problems.
99+ Flickable to scroll the location vertically.
100+ The respective contentHeight gets calculated after the Location is filled with data.
101 */
102- function renderData() {
103- var index = Math.floor(Math.random()*weatherApp.locationsList.length), // TODO get this value from ListView.currentIndex later!
104- data = weatherApp.locationsList[index],
105- current = data.data[0].current,
106- forecasts = data.data,
107- forecastsLength = forecasts.length,
108- today = forecasts[0];
109-
110- var tempUnits = settings.tempScale === "°C" ? "metric" : "imperial"
111-
112- // set general location data
113- name = data.location.name;
114-
115- // set current temps and condition
116- iconName = (current.icon) ? current.icon : ""
117- conditionText = (current.condition.main) ? current.condition.main : current.condition; // difference TWC/OWM
118- todayMaxTemp = (today[tempUnits].tempMax !== undefined) ? Math.round(today[tempUnits].tempMax).toString() + settings.tempScale: "";
119- todayMinTemp = Math.round(today[tempUnits].tempMin).toString() + settings.tempScale;
120- currentTemp = Math.round(current[tempUnits].temp).toString() + String("°");
121-
122- // reset days list
123- mainPageWeekdayListView.model.clear()
124-
125- // set daily forecasts
126- if(forecastsLength > 0) {
127- for(var x=1;x<forecastsLength;x++) {
128- // print(JSON.stringify(forecasts[x][units]))
129- var dayData = {
130- day: formatTimestamp(forecasts[x].date, 'dddd'),
131- low: Math.round(forecasts[x][tempUnits].tempMin).toString() + settings.tempScale,
132- high: (forecasts[x][tempUnits].tempMax !== undefined) ? Math.round(forecasts[x][tempUnits].tempMax).toString() + settings.tempScale : "",
133- image: (forecasts[x].icon !== undefined && iconMap[forecasts[x].icon] !== undefined) ? iconMap[forecasts[x].icon] + settings.tempScale : ""
134- }
135- mainPageWeekdayListView.model.append(dayData);
136- }
137- }
138- }
139-
140- ListView {
141- id: mainPageWeekdayListView
142- anchors {
143- fill: parent
144- margins: units.gu(2)
145- }
146-
147- header: Column {
148- anchors {
149- left: parent.left
150- right: parent.right
151- }
152- spacing: units.gu(1)
153-
154- HeaderRow {
155- locationName: locationPage.name
156- }
157-
158- HomeGraphic {
159- icon: locationPage.iconName
160- }
161-
162- HomeTempInfo {
163- description: locationPage.conditionText
164- high: locationPage.todayMaxTemp
165- low: locationPage.todayMinTemp
166- now: locationPage.currentTemp
167- }
168-
169- ListItem.ThinDivider {
170-
171- }
172- }
173- model: ListModel {}
174-
175- delegate: DayDelegate {
176- day: model.day
177- high: model.high
178- low: model.low
179+ Flickable {
180+ id: locationFlickable
181+ width: parent.width
182+ height: parent.height
183+ contentWidth: parent.width
184+
185+ /*
186+ ListView for locations with snap-scrolling horizontally.
187+ */
188+ ListView {
189+ id: locationPages
190+ anchors.fill: parent
191+ width: parent.width
192+ height: childrenRect.height
193+ contentWidth: parent.width
194+ contentHeight: childrenRect.height
195+ model: weatherApp.locationsList.length
196+ // TODO with snapMode, currentIndex is not properly set and setting currentIndex fails
197+ //snapMode: ListView.SnapOneItem
198+ orientation: ListView.Horizontal
199+ currentIndex: settings.current
200+ highlightRangeMode: ListView.StrictlyEnforceRange
201+ onCurrentIndexChanged: {
202+ print("CI: "+currentIndex)
203+ if (loaded) {
204+ settings.current = currentIndex
205+ }
206+ }
207+ onModelChanged: {
208+ currentIndex = settings.current
209+
210+ if (model > 0) {
211+ loaded = true
212+ }
213+ }
214+ delegate: LocationPane {}
215+
216+ property bool loaded: false
217+ // TODO: workaround for not being able to use snapMode property
218+ Component.onCompleted: {
219+ var scaleFactor = units.gridUnit * 10;
220+ maximumFlickVelocity = maximumFlickVelocity * scaleFactor;
221+ flickDeceleration = flickDeceleration * scaleFactor;
222+ }
223+
224+ Connections {
225+ target: settings
226+ onCurrentChanged: {
227+ locationPages.currentIndex = settings.current
228+ }
229+ }
230 }
231 }
232 }
233
234=== added file 'app/ui/LocationPane.qml'
235--- app/ui/LocationPane.qml 1970-01-01 00:00:00 +0000
236+++ app/ui/LocationPane.qml 2015-02-15 19:22:09 +0000
237@@ -0,0 +1,145 @@
238+/*
239+ * Copyright (C) 2015 Canonical Ltd
240+ *
241+ * This file is part of Ubuntu Weather App
242+ *
243+ * Ubuntu Weather App is free software: you can redistribute it and/or modify
244+ * it under the terms of the GNU General Public License version 3 as
245+ * published by the Free Software Foundation.
246+ *
247+ * Ubuntu Weather App is distributed in the hope that it will be useful,
248+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
249+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
250+ * GNU General Public License for more details.
251+ *
252+ * You should have received a copy of the GNU General Public License
253+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
254+ */
255+
256+import QtQuick 2.3
257+import Ubuntu.Components 1.1
258+import Ubuntu.Components.ListItems 0.1 as ListItem
259+import "../components"
260+
261+Rectangle {
262+ id: locationItem
263+ /*
264+ Data properties
265+ */
266+ property string name
267+ property string conditionText
268+ property string currentTemp
269+ property string todayMaxTemp
270+ property string todayMinTemp
271+ property string iconName
272+
273+ Component.onCompleted: renderData(index)
274+
275+ width: locationPage.width
276+ height: childrenRect.height
277+ anchors.fill: parent.fill
278+
279+ /*
280+ Calculates the height of all location data components, to set the Flickable.contentHeight right.
281+ */
282+ function setFlickableContentHeight() {
283+ var contentHeightGu = (homeTempInfo.height+homeGraphic.height
284+ +(weekdayColumn.height*mainPageWeekdayListView.model.count))/units.gridUnit;
285+ locationFlickable.contentHeight = units.gu(contentHeightGu+25);
286+ }
287+
288+ /*
289+ Extracts values from the location weather data and puts them into the appropriate components
290+ to display them.
291+
292+ Attention: Data access happens through "weatherApp.locationList[]" by index, since complex
293+ data in models will lead to type problems.
294+ */
295+ function renderData(index) {
296+ var data = weatherApp.locationsList[index],
297+ current = data.data[0].current,
298+ forecasts = data.data,
299+ forecastsLength = forecasts.length,
300+ today = forecasts[0];
301+
302+ var tempUnits = settings.tempScale === "°C" ? "metric" : "imperial"
303+
304+ // set general location data
305+ name = data.location.name;
306+
307+ // set current temps and condition
308+ iconName = (current.icon) ? current.icon : ""
309+ conditionText = (current.condition.main) ? current.condition.main : current.condition; // difference TWC/OWM
310+ todayMaxTemp = (today[tempUnits].tempMax !== undefined) ? Math.round(today[tempUnits].tempMax).toString() + settings.tempScale: "";
311+ todayMinTemp = Math.round(today[tempUnits].tempMin).toString() + settings.tempScale;
312+ currentTemp = Math.round(current[tempUnits].temp).toString() + String("°");
313+
314+ // reset days list
315+ mainPageWeekdayListView.model.clear()
316+
317+ // set daily forecasts
318+ if(forecastsLength > 0) {
319+ for(var x=1;x<forecastsLength;x++) {
320+ // print(JSON.stringify(forecasts[x][units]))
321+ var dayData = {
322+ day: formatTimestamp(forecasts[x].date, 'dddd'),
323+ low: Math.round(forecasts[x][tempUnits].tempMin).toString() + settings.tempScale,
324+ high: (forecasts[x][tempUnits].tempMax !== undefined) ? Math.round(forecasts[x][tempUnits].tempMax).toString() + settings.tempScale : "",
325+ image: (forecasts[x].icon !== undefined && iconMap[forecasts[x].icon] !== undefined) ? iconMap[forecasts[x].icon] + settings.tempScale : ""
326+ }
327+ mainPageWeekdayListView.model.append(dayData);
328+ }
329+ }
330+ setFlickableContentHeight();
331+ }
332+
333+ Column {
334+ id: locationTop
335+ anchors {
336+ left: parent.left
337+ right: parent.right
338+ margins: units.gu(2)
339+ }
340+ spacing: units.gu(1)
341+
342+ HeaderRow {
343+ id: headerRow
344+ locationName: locationItem.name
345+ }
346+
347+ HomeGraphic {
348+ id: homeGraphic
349+ icon: locationItem.iconName
350+ }
351+
352+ HomeTempInfo {
353+ id: homeTempInfo
354+ description: conditionText
355+ high: locationItem.todayMaxTemp
356+ low: locationItem.todayMinTemp
357+ now: locationItem.currentTemp
358+ }
359+
360+ ListItem.ThinDivider {}
361+ }
362+ Column {
363+ id: weekdayColumn
364+ width: parent.width
365+ height: childrenRect.height
366+ anchors {
367+ top: locationTop.bottom
368+ left: parent.left
369+ right: parent.right
370+ margins: units.gu(2)
371+ }
372+ Repeater {
373+ id: mainPageWeekdayListView
374+ model: ListModel{}
375+ DayDelegate {
376+ day: model.day
377+ high: model.high
378+ low: model.low
379+ }
380+ }
381+ }
382+}
383
384=== modified file 'app/ui/LocationsPage.qml'
385--- app/ui/LocationsPage.qml 2015-02-08 19:09:07 +0000
386+++ app/ui/LocationsPage.qml 2015-02-15 19:22:09 +0000
387@@ -36,14 +36,18 @@
388 }
389 delegate: ListItem.Standard {
390 text: model.location.name
391+ onClicked: {
392+ settings.current = index;
393+ pageStack.pop()
394+ }
395 }
396 }
397
398 function populateLocationsModel(locations) {
399- for (var i=0; i < locations.length; i++) {
400- locationsModel.append(locations[i])
401+ for (var i=0; i < weatherApp.locationsList.length; i++) {
402+ locationsModel.append(weatherApp.locationsList[i])
403 }
404 }
405
406- Component.onCompleted: storage.getLocations(populateLocationsModel)
407+ Component.onCompleted: populateLocationsModel()
408 }
409
410=== modified file 'po/com.ubuntu.weather.pot'
411--- po/com.ubuntu.weather.pot 2015-02-11 04:29:28 +0000
412+++ po/com.ubuntu.weather.pot 2015-02-15 19:22:09 +0000
413@@ -8,7 +8,7 @@
414 msgstr ""
415 "Project-Id-Version: ubuntu-weather-app\n"
416 "Report-Msgid-Bugs-To: \n"
417-"POT-Creation-Date: 2015-02-11 04:15+0000\n"
418+"POT-Creation-Date: 2015-02-15 14:57+0100\n"
419 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
420 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
421 "Language-Team: LANGUAGE <LL@li.org>\n"
422@@ -21,7 +21,7 @@
423 msgid "Today"
424 msgstr ""
425
426-#: ../app/ui/HomePage.qml:31 ../app/ui/LocationsPage.qml:28
427+#: ../app/ui/HomePage.qml:30 ../app/ui/LocationsPage.qml:28
428 msgid "Locations"
429 msgstr ""
430

Subscribers

People subscribed via source and target branches

to all changes: