Merge lp:~ubuntu-weather-dev/ubuntu-weather-app/reboot-finish-listitem-migration into lp:ubuntu-weather-app

Proposed by Victor Thompson
Status: Needs review
Proposed branch: lp:~ubuntu-weather-dev/ubuntu-weather-app/reboot-finish-listitem-migration
Merge into: lp:ubuntu-weather-app
Prerequisite: lp:~ahayzen/ubuntu-weather-app/reboot-uc1.3-bump
Diff against target: 1236 lines (+98/-948)
13 files modified
app/components/CMakeLists.txt (+0/-2)
app/components/ListItemActions/CMakeLists.txt (+0/-5)
app/components/ListItemActions/CheckBox.qml (+0/-25)
app/components/ListItemActions/Remove.qml (+0/-27)
app/components/ListItemReorderComponent.qml (+0/-106)
app/components/ListItemWithActions.qml (+0/-496)
app/components/MultiSelectHeadState.qml (+0/-72)
app/components/MultiSelectListView.qml (+27/-8)
app/components/WeatherListItem.qml (+0/-138)
app/components/WeatherListView.qml (+1/-2)
app/ui/LocationsPage.qml (+63/-48)
debian/changelog (+4/-0)
po/com.ubuntu.weather.pot (+3/-19)
To merge this branch: bzr merge lp:~ubuntu-weather-dev/ubuntu-weather-app/reboot-finish-listitem-migration
Reviewer Review Type Date Requested Status
Jenkins Bot continuous-integration Approve
Andrew Hayzen Pending
Ubuntu Phone Apps Jenkins Bot continuous-integration Pending
Review via email: mp+278209@code.launchpad.net

This proposal supersedes a proposal from 2015-08-05.

Commit message

* Finish the migration to the new SDK list items
* Lock weather app in the Portrait orientation until we get some landscape designs
* Make the page with bottom edge animation less jarring when it reaches the top by adding a fake header (similar to what the clock app does)

Description of the change

* Finished the migration to the new SDK list items
* Locked weather app in the Portrait orientation until we get some landscape designs
* Made the page with bottom edge animation less jarring when it reaches the top by adding a fake header (similar to what the clock app does)
* Buy nik90 a beer for starting this effort

To post a comment you must log in.
Revision history for this message
Victor Thompson (vthompson) wrote : Posted in a previous version of this proposal
Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
Andrew Hayzen (ahayzen) wrote : Posted in a previous version of this proposal

A few inline comments, visually ...
1) there appears to be a space between the detected location and the first selected location
2) if you multiselect, select an item, then select delete you are still in multiselect mode, this is weird if you remove the last item in the list as you have to hit back what feels like twice. I suggest when delete is pressed in the header that the multiselect mode is cancelled.

review: Needs Fixing
Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
Victor Thompson (vthompson) wrote : Posted in a previous version of this proposal

> Should this have // CUSTOM as a note incase we do a pull of upstream and miss that we made changes?
Sure. I added a comment. I think eventually this will be folded into the SDK anyway. They already pulled in a hint component that we should make use of soonish.

> Why was this changed it looks the same just with { } around it?
No reason that I know of. I didn't like it either when I was resolving merge conflicts. Updated.

> Not A->Z
Fixed.

Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
Victor Thompson (vthompson) wrote : Posted in a previous version of this proposal

I've been testing this branch a bit. I think many of the list item blockers have been fixed. To aide in testing, could we get a comprehensive list of bugs that we should verify have been fixed?

Revision history for this message
Andrew Hayzen (ahayzen) wrote : Posted in a previous version of this proposal

Its the same set of bugs that are blocking the music one [0]

bug 1469471 (causes checkbox to not update in selectMode)
bug 1468100 (swiping can break selectMode)
bug 1486008 (swipe remove button is too small on mako)

IIRC it was only the last bug that was not fixed, which I think is now fixed in rc-proposed?

0 - https://code.launchpad.net/~ahayzen/music-app/refactor-use-sdk-listitems/+merge/261328

Revision history for this message
Victor Thompson (vthompson) wrote : Posted in a previous version of this proposal

Agreed, bug 1486008 appears to be fixed in rc-proposed.

Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
Andrew Hayzen (ahayzen) wrote : Posted in a previous version of this proposal

We will need to bump to uc1.3 for this as well, I'll make a branch that this can rebase onto.

Revision history for this message
Jenkins Bot (ubuntu-core-apps-jenkins-bot) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
Jenkins Bot (ubuntu-core-apps-jenkins-bot) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
Jenkins Bot (ubuntu-core-apps-jenkins-bot) wrote :
review: Approve (continuous-integration)
82. By Victor Thompson

Merge trunk, resolve conflicts, and add changelog entry

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

Unmerged revisions

82. By Victor Thompson

Merge trunk, resolve conflicts, and add changelog entry

81. By Victor Thompson

rebase on UC1.3 branch

80. By Victor Thompson

Merge of trunk

79. By Victor Thompson

Fix pot file

78. By Victor Thompson

Removed bad FakeHeader

77. By Victor Thompson

Merge of trunk and resolve conflicts.

76. By Victor Thompson

fix bad conflict resolution

75. By Victor Thompson

Merge and resolve conflicts.

74. By Victor Thompson

Merge of trunk

73. By Victor Thompson

Merge and resolve conflicts

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'app/components/CMakeLists.txt'
--- app/components/CMakeLists.txt 2015-03-03 18:37:59 +0000
+++ app/components/CMakeLists.txt 2015-12-10 01:16:13 +0000
@@ -1,5 +1,3 @@
1add_subdirectory(ListItemActions)
2
3file(GLOB COMPONENTS_QML_JS_FILES *.qml *.js)1file(GLOB COMPONENTS_QML_JS_FILES *.qml *.js)
42
5add_custom_target(ubuntu-weather-app_components_QMlFiles ALL SOURCES ${COMPONENTS_QML_JS_FILES})3add_custom_target(ubuntu-weather-app_components_QMlFiles ALL SOURCES ${COMPONENTS_QML_JS_FILES})
64
=== removed directory 'app/components/ListItemActions'
=== removed file 'app/components/ListItemActions/CMakeLists.txt'
--- app/components/ListItemActions/CMakeLists.txt 2015-03-03 18:37:59 +0000
+++ app/components/ListItemActions/CMakeLists.txt 1970-01-01 00:00:00 +0000
@@ -1,5 +0,0 @@
1file(GLOB LISTITEMACTIONS_QML_JS_FILES *.qml *.js)
2
3add_custom_target(ubuntu-weather-app_listitemactions_QMlFiles ALL SOURCES ${LISTITEMACTIONS_QML_JS_FILES})
4
5install(FILES ${LISTITEMACTIONS_QML_JS_FILES} DESTINATION ${UBUNTU-WEATHER_APP_DIR}/components/ListItemActions)
60
=== removed file 'app/components/ListItemActions/CheckBox.qml'
--- app/components/ListItemActions/CheckBox.qml 2015-11-02 21:28:34 +0000
+++ app/components/ListItemActions/CheckBox.qml 1970-01-01 00:00:00 +0000
@@ -1,25 +0,0 @@
1/*
2 * Copyright (C) 2012-2014, 2015 Canonical, Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 3.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17import QtQuick 2.4
18import Ubuntu.Components 1.3
19
20CheckBox {
21 checked: root.selected
22 width: implicitWidth
23 // disable item mouse area to avoid conflicts with parent mouse area
24 __mouseArea.enabled: false
25}
260
=== removed file 'app/components/ListItemActions/Remove.qml'
--- app/components/ListItemActions/Remove.qml 2015-11-02 21:28:34 +0000
+++ app/components/ListItemActions/Remove.qml 1970-01-01 00:00:00 +0000
@@ -1,27 +0,0 @@
1/*
2 * Copyright (C) 2014, 2015 Andrew Hayzen <ahayzen@gmail.com>
3 * Daniel Holm <d.holmen@gmail.com>
4 * Victor Thompson <victor.thompson@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 3.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19import QtQuick 2.4
20import Ubuntu.Components 1.3
21
22Action {
23 id: removeAction
24 iconName: "delete"
25 objectName: "swipeDeleteAction"
26 text: i18n.tr("Remove")
27}
280
=== removed file 'app/components/ListItemReorderComponent.qml'
--- app/components/ListItemReorderComponent.qml 2015-11-02 21:28:34 +0000
+++ app/components/ListItemReorderComponent.qml 1970-01-01 00:00:00 +0000
@@ -1,106 +0,0 @@
1/*
2 * Copyright (C) 2013, 2014, 2015
3 * Andrew Hayzen <ahayzen@gmail.com>
4 * Nekhelesh Ramananthan <krnekhelesh@gmail.com>
5 * Victor Thompson <victor.thompson@gmail.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 3.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20import QtQuick 2.4
21import Ubuntu.Components 1.3
22
23
24Item {
25 id: actionReorder
26 width: units.gu(4)
27
28 Icon {
29 anchors {
30 horizontalCenter: parent.horizontalCenter
31 verticalCenter: parent.verticalCenter
32 }
33 name: "navigation-menu" // TODO: use proper image
34 height: width
35 width: units.gu(3)
36 }
37
38 MouseArea {
39 id: actionReorderMouseArea
40 anchors {
41 fill: parent
42 }
43 property int startY: 0
44 property int startContentY: 0
45
46 onPressed: {
47 root.parent.parent.interactive = false; // stop scrolling of listview
48 startY = root.y;
49 startContentY = root.parent.parent.contentY;
50 root.z += 10; // force ontop of other elements
51
52 console.debug("Reorder listitem pressed", root.y)
53 }
54 onMouseYChanged: root.y += mouse.y - (root.height / 2);
55 onReleased: {
56 console.debug("Reorder diff by position", getDiff());
57
58 var diff = getDiff();
59
60 // Remove the height of the actual item if moved down
61 if (diff > 0) {
62 diff -= 1;
63 }
64
65 root.parent.parent.interactive = true; // reenable scrolling
66
67 if (diff === 0) {
68 // Nothing has changed so reset the item
69 // z index is restored after animation
70 resetListItemYAnimation.start();
71 }
72 else {
73 var newIndex = index + diff;
74
75 if (newIndex < 0) {
76 newIndex = 0;
77 }
78 else if (newIndex > root.parent.parent.count - 1) {
79 newIndex = root.parent.parent.count - 1;
80 }
81
82 root.z -= 10; // restore z index
83 reorder(index, newIndex)
84 }
85 }
86
87 function getDiff() {
88 // Get the amount of items that have been passed over (by centre)
89 return Math.round((((root.y - startY) + (root.parent.parent.contentY - startContentY)) / root.height) + 0.5);
90 }
91 }
92
93 SequentialAnimation {
94 id: resetListItemYAnimation
95 UbuntuNumberAnimation {
96 target: root;
97 property: "y";
98 to: actionReorderMouseArea.startY
99 }
100 ScriptAction {
101 script: {
102 root.z -= 10; // restore z index
103 }
104 }
105 }
106}
1070
=== removed file 'app/components/ListItemWithActions.qml'
--- app/components/ListItemWithActions.qml 2015-11-02 21:28:34 +0000
+++ app/components/ListItemWithActions.qml 1970-01-01 00:00:00 +0000
@@ -1,496 +0,0 @@
1/*
2 * Copyright (C) 2012-2015 Canonical, Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 3.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17import QtQuick 2.4
18import Ubuntu.Components 1.3
19import Ubuntu.Components.ListItems 1.0 as ListItem
20
21
22Item {
23 id: root
24 width: parent.width
25
26 property Action leftSideAction: null
27 property list<Action> rightSideActions
28 property double defaultHeight: units.gu(8)
29 property bool locked: false
30 property Action activeAction: null
31 property var activeItem: null
32 property bool triggerActionOnMouseRelease: false
33 property color color: Theme.palette.normal.background
34 property color selectedColor: "#E6E6E6"
35 property bool selected: false
36 property bool selectionMode: false
37 property alias internalAnchors: mainContents.anchors
38 default property alias contents: mainContents.children
39
40 readonly property double actionWidth: units.gu(4)
41 readonly property double leftActionWidth: units.gu(10)
42 readonly property double actionThreshold: actionWidth * 0.4
43 readonly property double threshold: 0.4
44 readonly property string swipeState: main.x == 0 ? "Normal" : main.x > 0 ? "LeftToRight" : "RightToLeft"
45 readonly property alias swipping: mainItemMoving.running
46 readonly property bool _showActions: mouseArea.pressed || swipeState != "Normal" || swipping
47
48 property alias _main: main // CUSTOM
49 property alias pressed: mouseArea.pressed // CUSTOM
50
51 /* internal */
52 property var _visibleRightSideActions: filterVisibleActions(rightSideActions)
53
54 signal itemClicked(var mouse)
55 signal itemPressAndHold(var mouse)
56
57 function returnToBoundsRTL(direction)
58 {
59 var actionFullWidth = actionWidth + units.gu(2)
60
61 // go back to normal state if swipping reverse
62 if (direction === "LTR") {
63 updatePosition(0)
64 return
65 } else if (!triggerActionOnMouseRelease) {
66 updatePosition(-rightActionsView.width + units.gu(2))
67 return
68 }
69
70 var xOffset = Math.abs(main.x)
71 var index = Math.min(Math.floor(xOffset / actionFullWidth), _visibleRightSideActions.length)
72 var newX = 0
73
74 if (index === _visibleRightSideActions.length) {
75 newX = -(rightActionsView.width - units.gu(2))
76 } else if (index >= 1) {
77 newX = -(actionFullWidth * index)
78 }
79
80 updatePosition(newX)
81 }
82
83 function returnToBoundsLTR(direction)
84 {
85 var finalX = leftActionWidth
86 if ((direction === "RTL") || (main.x <= (finalX * root.threshold)))
87 finalX = 0
88 updatePosition(finalX)
89 }
90
91 function returnToBounds(direction)
92 {
93 if (main.x < 0) {
94 returnToBoundsRTL(direction)
95 } else if (main.x > 0) {
96 returnToBoundsLTR(direction)
97 } else {
98 updatePosition(0)
99 }
100 }
101
102 function contains(item, point, marginX)
103 {
104 var itemStartX = item.x - marginX
105 var itemEndX = item.x + item.width + marginX
106 return (point.x >= itemStartX) && (point.x <= itemEndX) &&
107 (point.y >= item.y) && (point.y <= (item.y + item.height));
108 }
109
110 function getActionAt(point)
111 {
112 if (leftSideAction && contains(leftActionViewLoader.item, point, 0)) {
113 return leftSideAction
114 } else if (contains(rightActionsView, point, 0)) {
115 var newPoint = root.mapToItem(rightActionsView, point.x, point.y)
116 for (var i = 0; i < rightActionsRepeater.count; i++) {
117 var child = rightActionsRepeater.itemAt(i)
118 if (contains(child, newPoint, units.gu(1))) {
119 return i
120 }
121 }
122 }
123 return -1
124 }
125
126 function updateActiveAction()
127 {
128 if (triggerActionOnMouseRelease &&
129 (main.x <= -(root.actionWidth + units.gu(2))) &&
130 (main.x > -(rightActionsView.width - units.gu(2)))) {
131 var actionFullWidth = actionWidth + units.gu(2)
132 var xOffset = Math.abs(main.x)
133 var index = Math.min(Math.floor(xOffset / actionFullWidth), _visibleRightSideActions.length)
134 index = index - 1
135 if (index > -1) {
136 root.activeItem = rightActionsRepeater.itemAt(index)
137 root.activeAction = root._visibleRightSideActions[index]
138 }
139 } else {
140 root.activeAction = null
141 }
142 }
143
144 function resetSwipe()
145 {
146 updatePosition(0)
147 }
148
149 function filterVisibleActions(actions)
150 {
151 var visibleActions = []
152 for(var i = 0; i < actions.length; i++) {
153 var action = actions[i]
154 if (action.visible) {
155 visibleActions.push(action)
156 }
157 }
158 return visibleActions
159 }
160
161 function updatePosition(pos)
162 {
163 if (!root.triggerActionOnMouseRelease && (pos !== 0)) {
164 mouseArea.state = pos > 0 ? "RightToLeft" : "LeftToRight"
165 } else {
166 mouseArea.state = ""
167 }
168 main.x = pos
169 }
170
171 // CUSTOM remove animation
172 SequentialAnimation {
173 id: removeAnimation
174
175 property var action
176
177 UbuntuNumberAnimation {
178 target: root
179 duration: UbuntuAnimation.BriskDuration
180 property: "height";
181 to: 0
182 }
183 ScriptAction {
184 script: removeAnimation.action.trigger()
185 }
186 }
187
188 states: [
189 State {
190 name: "select"
191 when: selectionMode || selected
192 PropertyChanges {
193 target: selectionIcon
194 source: Qt.resolvedUrl("ListItemActions/CheckBox.qml")
195 anchors.leftMargin: units.gu(2)
196 }
197 PropertyChanges {
198 target: root
199 locked: true
200 }
201 PropertyChanges {
202 target: main
203 x: 0
204 }
205 }
206 ]
207
208 height: defaultHeight
209 //clip: height !== defaultHeight // CUSTOM
210
211 Loader { // CUSTOM
212 id: leftActionViewLoader
213 anchors {
214 top: parent.top
215 bottom: parent.bottom
216 right: main.left
217 }
218 asynchronous: true
219 sourceComponent: leftSideAction ? leftActionViewComponent : undefined
220 }
221
222 Component { // CUSTOM
223 id: leftActionViewComponent
224
225 Rectangle {
226 id: leftActionView
227 width: root.leftActionWidth + actionThreshold
228 color: UbuntuColors.red
229
230 Icon {
231 id: leftActionIcon
232 anchors {
233 centerIn: parent
234 horizontalCenterOffset: actionThreshold / 2
235 }
236 objectName: "swipeDeleteAction" // CUSTOM
237 name: leftSideAction && _showActions ? leftSideAction.iconName : ""
238 color: Theme.palette.selected.field
239 height: units.gu(3)
240 width: units.gu(3)
241 }
242 }
243 }
244
245 //Rectangle {
246 Item { // CUSTOM
247 id: rightActionsView
248
249 anchors {
250 top: main.top
251 left: main.right
252 bottom: main.bottom
253 }
254 visible: _visibleRightSideActions.length > 0
255 width: rightActionsRepeater.count > 0 ? rightActionsRepeater.count * (root.actionWidth + units.gu(2)) + root.actionThreshold + units.gu(2) : 0
256 // color: "white" // CUSTOM
257
258 Row {
259 anchors{
260 top: parent.top
261 left: parent.left
262 leftMargin: units.gu(2)
263 right: parent.right
264 rightMargin: units.gu(2)
265 bottom: parent.bottom
266 }
267 spacing: units.gu(2)
268 Repeater {
269 id: rightActionsRepeater
270
271 model: _showActions ? _visibleRightSideActions : []
272 Item {
273 property alias image: img
274
275 height: rightActionsView.height
276 width: root.actionWidth
277
278 Icon {
279 id: img
280
281 anchors.centerIn: parent
282 objectName: rightSideActions[index].objectName // CUSTOM
283 width: units.gu(3)
284 height: units.gu(3)
285 name: modelData.iconName
286 color: root.activeAction === modelData ? UbuntuColors.orange : UbuntuColors.coolGrey // CUSTOM
287 }
288 }
289 }
290 }
291 }
292
293 Rectangle {
294 id: main
295 objectName: "mainItem"
296
297 anchors {
298 top: parent.top
299 bottom: parent.bottom
300 }
301
302 width: parent.width
303 color: root.selected ? root.selectedColor : root.color
304
305 Loader {
306 id: selectionIcon
307
308 anchors {
309 left: main.left
310 verticalCenter: main.verticalCenter
311 }
312 asynchronous: true // CUSTOM
313 width: (status === Loader.Ready) ? item.implicitWidth : 0
314 visible: (status === Loader.Ready) && (item.width === item.implicitWidth)
315
316 Behavior on width {
317 NumberAnimation {
318 duration: UbuntuAnimation.SnapDuration
319 }
320 }
321 }
322
323 Item {
324 id: mainContents
325
326 anchors {
327 left: selectionIcon.right
328 //leftMargin: units.gu(2) // CUSTOM
329 top: parent.top
330 //topMargin: units.gu(1) // CUSTOM
331 right: parent.right
332 //rightMargin: units.gu(2) // CUSTOM
333 bottom: parent.bottom
334 //bottomMargin: units.gu(1) // CUSTOM
335 }
336 }
337
338 Behavior on x {
339 UbuntuNumberAnimation {
340 id: mainItemMoving
341
342 easing.type: Easing.OutElastic
343 duration: UbuntuAnimation.SlowDuration
344 }
345 }
346 }
347
348 SequentialAnimation {
349 id: triggerAction
350
351 property var currentItem: root.activeItem ? root.activeItem.image : null
352
353 running: false
354 ParallelAnimation {
355 UbuntuNumberAnimation {
356 target: triggerAction.currentItem
357 property: "opacity"
358 from: 1.0
359 to: 0.0
360 duration: UbuntuAnimation.SlowDuration
361 easing {type: Easing.InOutBack; }
362 }
363 UbuntuNumberAnimation {
364 target: triggerAction.currentItem
365 properties: "width, height"
366 from: units.gu(3)
367 to: root.actionWidth
368 duration: UbuntuAnimation.SlowDuration
369 easing {type: Easing.InOutBack; }
370 }
371 }
372 PropertyAction {
373 target: triggerAction.currentItem
374 properties: "width, height"
375 value: units.gu(3)
376 }
377 PropertyAction {
378 target: triggerAction.currentItem
379 properties: "opacity"
380 value: 1.0
381 }
382 ScriptAction {
383 script: {
384 root.activeAction.triggered(root)
385 mouseArea.state = ""
386 }
387 }
388 PauseAnimation {
389 duration: 500
390 }
391 UbuntuNumberAnimation {
392 target: main
393 property: "x"
394 to: 0
395 }
396 }
397
398 MouseArea {
399 id: mouseArea
400
401 property bool locked: root.locked || ((root.leftSideAction === null) && (root._visibleRightSideActions.count === 0)) // CUSTOM
402 property bool manual: false
403 property string direction: "None"
404 property real lastX: -1
405
406 anchors.fill: parent
407 drag {
408 target: locked ? null : main
409 axis: Drag.XAxis
410 minimumX: rightActionsView.visible ? -(rightActionsView.width) : 0
411 maximumX: leftSideAction ? leftActionViewLoader.item.width : 0
412 threshold: root.actionThreshold
413 }
414
415 states: [
416 State {
417 name: "LeftToRight"
418 PropertyChanges {
419 target: mouseArea
420 drag.maximumX: 0
421 }
422 },
423 State {
424 name: "RightToLeft"
425 PropertyChanges {
426 target: mouseArea
427 drag.minimumX: 0
428 }
429 }
430 ]
431
432 onMouseXChanged: {
433 var offset = (lastX - mouseX)
434 if (Math.abs(offset) <= root.actionThreshold) {
435 return
436 }
437 lastX = mouseX
438 direction = offset > 0 ? "RTL" : "LTR";
439 }
440
441 onPressed: {
442 lastX = mouse.x
443 }
444
445 onReleased: {
446 if (root.triggerActionOnMouseRelease && root.activeAction) {
447 triggerAction.start()
448 } else {
449 root.returnToBounds()
450 root.activeAction = null
451 }
452 lastX = -1
453 direction = "None"
454 }
455 onClicked: {
456 if (selectionMode) { // CUSTOM - selecting a listitem should toggle selection if in selectionMode
457 selected = !selected
458 return
459 } else if (main.x === 0) {
460 root.itemClicked(mouse)
461 } else if (main.x > 0) {
462 var action = getActionAt(Qt.point(mouse.x, mouse.y))
463 if (action && action !== -1) {
464 //action.triggered(root)
465 removeAnimation.action = action // CUSTOM - use our animation instead
466 removeAnimation.start() // CUSTOM
467 }
468 } else {
469 var actionIndex = getActionAt(Qt.point(mouse.x, mouse.y))
470
471 if (actionIndex !== -1 && actionIndex !== leftSideAction) { // CUSTOM - can be leftAction
472 root.activeItem = rightActionsRepeater.itemAt(actionIndex)
473 root.activeAction = root.rightSideActions[actionIndex]
474 triggerAction.start()
475 return
476 }
477 }
478 root.resetSwipe()
479 }
480
481 onPositionChanged: {
482 if (mouseArea.pressed) {
483 updateActiveAction()
484
485 listItemSwiping(index) // CUSTOM - tells other listitems to dismiss any swipe
486 }
487 }
488 onPressAndHold: {
489 if (main.x === 0) {
490 root.itemPressAndHold(mouse)
491 }
492 }
493
494 z: -1
495 }
496}
4970
=== removed file 'app/components/MultiSelectHeadState.qml'
--- app/components/MultiSelectHeadState.qml 2015-11-02 21:28:34 +0000
+++ app/components/MultiSelectHeadState.qml 1970-01-01 00:00:00 +0000
@@ -1,72 +0,0 @@
1/*
2 * Copyright (C) 2015
3 * Andrew Hayzen <ahayzen@gmail.com>
4 * Victor Thompson <victor.thompson@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 3.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19import QtQuick 2.4
20import Ubuntu.Components 1.3
21
22PageHeadState {
23 id: selectionState
24 actions: [
25 Action {
26 iconName: "select"
27 text: i18n.tr("Select All")
28 onTriggered: {
29 if (listview.selectedItems.length === listview.model.count) {
30 listview.clearSelection()
31 } else {
32 listview.selectAll()
33 }
34 }
35 },
36 Action {
37 enabled: listview.selectedItems.length > 0
38 iconName: "delete"
39 text: i18n.tr("Delete")
40 visible: removable
41
42 onTriggered: {
43 removed(listview.selectedItems)
44
45 listview.closeSelection()
46 }
47 }
48
49 ]
50 backAction: Action {
51 text: i18n.tr("Cancel selection")
52 iconName: "back"
53 onTriggered: {
54 listview.clearSelection()
55 listview.state = "normal"
56 }
57 }
58 head: thisPage.head
59 name: "selection"
60
61 PropertyChanges {
62 target: thisPage.head
63 backAction: selectionState.backAction
64 actions: selectionState.actions
65 }
66
67 property ListView listview
68 property bool removable: false
69 property Page thisPage
70
71 signal removed(var selectedItems)
72}
730
=== modified file 'app/components/MultiSelectListView.qml'
--- app/components/MultiSelectListView.qml 2015-11-02 21:28:34 +0000
+++ app/components/MultiSelectListView.qml 2015-12-10 01:16:13 +0000
@@ -20,21 +20,24 @@
20import QtQuick 2.420import QtQuick 2.4
21import Ubuntu.Components 1.321import Ubuntu.Components 1.3
2222
23
24WeatherListView {23WeatherListView {
25 property var selectedItems: []
26
27 signal clearSelection()24 signal clearSelection()
28 signal closeSelection()25 signal closeSelection()
29 signal selectAll()26 signal selectAll()
3027 signal reorder(int from, int to)
31 onClearSelection: selectedItems = []28
29 onClearSelection: {
30 ViewItems.selectedIndices = []
31 }
32
32 onCloseSelection: {33 onCloseSelection: {
33 clearSelection()34 clearSelection()
34 state = "normal"35 ViewItems.selectMode = false
36 ViewItems.dragMode = false
35 }37 }
38
36 onSelectAll: {39 onSelectAll: {
37 var tmp = selectedItems40 var tmp = []
3841
39 for (var i=0; i < model.count; i++) {42 for (var i=0; i < model.count; i++) {
40 if (tmp.indexOf(i) === -1) {43 if (tmp.indexOf(i) === -1) {
@@ -42,11 +45,27 @@
42 }45 }
43 }46 }
4447
45 selectedItems = tmp48 ViewItems.selectedIndices = tmp
46 }49 }
50
47 onVisibleChanged: {51 onVisibleChanged: {
48 if (!visible) {52 if (!visible) {
49 closeSelection()53 closeSelection()
50 }54 }
51 }55 }
56
57 moveDisplaced: Transition {
58 UbuntuNumberAnimation {
59 property: "y"
60 }
61 }
62
63 ViewItems.onDragUpdated: {
64 if (event.status === ListItemDrag.Moving) {
65 event.accept = false
66 } else if (event.status === ListItemDrag.Dropped) {
67 model.move(event.from, event.to, 1)
68 reorder(event.from, event.to)
69 }
70 }
52}71}
5372
=== removed file 'app/components/WeatherListItem.qml'
--- app/components/WeatherListItem.qml 2015-11-02 21:28:34 +0000
+++ app/components/WeatherListItem.qml 1970-01-01 00:00:00 +0000
@@ -1,138 +0,0 @@
1/*
2 * Copyright (C) 2013, 2014, 2015
3 * Andrew Hayzen <ahayzen@gmail.com>
4 * Nekhelesh Ramananthan <krnekhelesh@gmail.com>
5 * Victor Thompson <victor.thompson@gmail.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 3.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20import QtQuick 2.4
21import Ubuntu.Components 1.3
22
23ListItemWithActions {
24 id: root
25 color: "transparent"
26
27 property int listItemIndex: index
28 property bool multiselectable: false
29 property int previousListItemIndex: -1
30 property bool reorderable: false
31
32 signal reorder(int from, int to)
33
34 onItemPressAndHold: {
35 if (multiselectable) {
36 selectionMode = true
37 }
38 }
39
40 onListItemIndexChanged: {
41 var i = parent.parent.selectedItems.lastIndexOf(previousListItemIndex)
42
43 if (i !== -1) {
44 parent.parent.selectedItems[i] = listItemIndex
45 }
46
47 previousListItemIndex = listItemIndex
48 }
49
50 onSelectedChanged: {
51 if (selectionMode) {
52 var tmp = parent.parent.selectedItems
53
54 if (selected) {
55 if (parent.parent.selectedItems.indexOf(listItemIndex) === -1) {
56 tmp.push(listItemIndex)
57 parent.parent.selectedItems = tmp
58 }
59 } else {
60 tmp.splice(parent.parent.selectedItems.indexOf(listItemIndex), 1)
61 parent.parent.selectedItems = tmp
62 }
63 }
64 }
65
66 onSelectionModeChanged: {
67 if (reorderable && selectionMode) {
68 resetSwipe()
69 }
70
71 for (var j=0; j < _main.children.length; j++) {
72 if (_main.children[j] !== actionReorderLoader) {
73 _main.children[j].anchors.rightMargin = reorderable && selectionMode ? actionReorderLoader.width + units.gu(2) : 0
74 }
75 }
76
77 parent.parent.state = selectionMode ? "multiselectable" : "normal"
78
79 if (!selectionMode) {
80 selected = false
81 }
82 }
83
84 /* Highlight the listitem on press */
85 Rectangle {
86 id: listItemBrighten
87 color: root.pressed ? UbuntuColors.coolGrey : "transparent"
88 opacity: 0.1
89 height: root.height
90 x: root.x - parent.x // -parent.x due to selectionIcon in ListItemWithActions
91 width: root.width
92 }
93
94 /* Reorder Component */
95 Loader {
96 id: actionReorderLoader
97 active: reorderable && selectionMode && root.parent.parent.selectedItems.length === 0
98 anchors {
99 bottom: parent.bottom
100 right: parent.right
101 rightMargin: units.gu(1)
102 top: parent.top
103 }
104 asynchronous: true
105 source: "ListItemReorderComponent.qml"
106 }
107
108 Item {
109 Connections { // Only allow one ListItem to be swiping at any time
110 target: weatherApp
111 onListItemSwiping: {
112 if (i !== index) {
113 root.resetSwipe();
114 }
115 }
116 }
117
118 Connections { // Connections from signals in the ListView
119 target: root.parent.parent
120 onClearSelection: selected = false
121 onFlickingChanged: {
122 if (root.parent.parent.flicking) {
123 root.resetSwipe()
124 }
125 }
126 onSelectAll: selected = true
127 onStateChanged: selectionMode = root.parent.parent.state === "multiselectable"
128 }
129 }
130
131 Component.onCompleted: { // reload settings as delegates are destroyed
132 if (parent.parent.selectedItems.indexOf(index) !== -1) {
133 selected = true
134 }
135
136 selectionMode = root.parent.parent.state === "multiselectable"
137 }
138}
1390
=== modified file 'app/components/WeatherListView.qml'
--- app/components/WeatherListView.qml 2015-11-02 21:28:34 +0000
+++ app/components/WeatherListView.qml 2015-12-10 01:16:13 +0000
@@ -20,8 +20,7 @@
20import QtQuick 2.420import QtQuick 2.4
21import Ubuntu.Components 1.321import Ubuntu.Components 1.3
2222
2323UbuntuListView {
24ListView {
25 Component.onCompleted: {24 Component.onCompleted: {
26 // FIXME: workaround for qtubuntu not returning values depending on the grid unit definition25 // FIXME: workaround for qtubuntu not returning values depending on the grid unit definition
27 // for Flickable.maximumFlickVelocity and Flickable.flickDeceleration26 // for Flickable.maximumFlickVelocity and Flickable.flickDeceleration
2827
=== modified file 'app/ui/LocationsPage.qml'
--- app/ui/LocationsPage.qml 2015-11-02 21:28:34 +0000
+++ app/ui/LocationsPage.qml 2015-12-10 01:16:13 +0000
@@ -18,22 +18,19 @@
1818
19import QtQuick 2.419import QtQuick 2.4
20import Ubuntu.Components 1.320import Ubuntu.Components 1.3
21import Ubuntu.Components.ListItems 0.1 as ListItem21import Ubuntu.Components.ListItems 1.0 as ListItems
22import "../components"22import "../components"
23import "../components/ListItemActions"
24
2523
26Page {24Page {
27 id: locationsPage25 id: locationsPage
28 objectName: "locationsPage"26 objectName: "locationsPage"
29 title: i18n.tr("Locations")27 title: i18n.tr("Locations")
3028
31 state: locationsListView.state === "multiselectable" ? "selection" : "default"29 state: "default"
32 states: [30 states: [
33 PageHeadState {31 PageHeadState {
34 id: defaultState
35 head: locationsPage.head
36 name: "default"32 name: "default"
33 head: locationsPage.head
37 actions: [34 actions: [
38 Action {35 Action {
39 iconName: "add"36 iconName: "add"
@@ -48,12 +45,28 @@
48 }45 }
49 }46 }
50 },47 },
51 MultiSelectHeadState {48 PageHeadState {
52 listview: locationsListView49 name: "selection"
53 removable: true50 head: locationsPage.head
54 thisPage: locationsPage51 when: locationsListView.ViewItems.selectMode
5552 backAction: Action {
56 onRemoved: storage.removeMultiLocations(selectedItems.slice());53 iconName: "back"
54 onTriggered: {
55 locationsListView.closeSelection()
56 locationsPage.state = "default"
57 }
58 }
59 actions: [
60 Action {
61 iconName: "delete"
62 enabled: locationsListView.ViewItems.selectedIndices.length !== 0
63 onTriggered: {
64 storage.removeMultiLocations(locationsListView.ViewItems.selectedIndices)
65 locationsListView.closeSelection()
66 locationsPage.state = "default"
67 }
68 }
69 ]
57 }70 }
58 ]71 ]
5972
@@ -73,17 +86,16 @@
73 }86 }
74 header: MultiSelectListView {87 header: MultiSelectListView {
75 id: currentLocationListView88 id: currentLocationListView
76 anchors {89
77 left: parent.left90 height: settings.addedCurrentLocation && settings.detectCurrentLocation ? units.gu(7) : units.gu(0)
78 right: parent.right
79 }
80 height: settings.addedCurrentLocation && settings.detectCurrentLocation ? units.gu(8) : units.gu(0)
81 interactive: false91 interactive: false
82 model: currentLocationModel92 model: currentLocationModel
83 delegate: WeatherListItem {93 width: parent.width
94
95 delegate: ListItem {
84 id: currentLocationListItem96 id: currentLocationListItem
8597
86 onItemClicked: {98 onClicked: {
87 settings.current = index;99 settings.current = index;
88 pageStack.pop()100 pageStack.pop()
89 }101 }
@@ -154,39 +166,48 @@
154 horizontalAlignment: Text.AlignRight166 horizontalAlignment: Text.AlignRight
155 text: temp + settings.tempScale167 text: temp + settings.tempScale
156 }168 }
169
170 ListItems.ThinDivider { anchors.bottom: parent.bottom }
157 }171 }
158 }172 }
159173
160 delegate: WeatherListItem {174 // Added a thindivider to the listview since by default the last listitem does not show
175 // a thindivider which does not follow design specs.
176 footer: ListItems.ThinDivider {
177 visible: locationsModel.count !== 0
178 }
179
180 onReorder: {
181 console.debug("Move: ", from, to);
182 storage.moveLocation(from, to);
183 }
184
185 delegate: ListItem {
161 id: locationsListItem186 id: locationsListItem
162 objectName: "location" + index187 objectName: "location" + index
163 leftSideAction: Remove {188
164 onTriggered: storage.removeLocation(index)189 leadingActions: ListItemActions {
165 }190 actions: [
166 multiselectable: true191 Action {
167 reorderable: true192 iconName: 'delete'
168193 onTriggered: storage.removeLocation(index)
169 onItemClicked: {194 }
170 if (settings.addedCurrentLocation && settings.detectCurrentLocation) {195 ]
196 }
197
198 onPressAndHold: {
199 ListView.view.ViewItems.selectMode = !ListView.view.ViewItems.selectMode
200 ListView.view.ViewItems.dragMode = !ListView.view.ViewItems.dragMode
201 }
202
203 onClicked: {
204 if (!selectMode) {
171 settings.current = index + 1;205 settings.current = index + 1;
172 } else {206 pageStack.pop()
173 settings.current = index;
174 }207 }
175208
176 pageStack.pop()209 pageStack.pop()
177 }210 }
178 onReorder: {
179 console.debug("Move: ", from, to);
180
181 storage.moveLocation(from, to);
182 }
183
184 ListItem.ThinDivider {
185 anchors {
186 top: parent.top
187 }
188 visible: index == 0
189 }
190211
191 Item {212 Item {
192 anchors {213 anchors {
@@ -252,12 +273,6 @@
252 visible: locationsPage.state === "default"273 visible: locationsPage.state === "default"
253 }274 }
254 }275 }
255
256 ListItem.ThinDivider {
257 anchors {
258 bottom: parent.bottom
259 }
260 }
261 }276 }
262 }277 }
263278
264279
=== modified file 'debian/changelog'
--- debian/changelog 2015-12-03 15:22:45 +0000
+++ debian/changelog 2015-12-10 01:16:13 +0000
@@ -1,7 +1,11 @@
1ubuntu-weather-app (3.2) UNRELEASED; urgency=medium1ubuntu-weather-app (3.2) UNRELEASED; urgency=medium
22
3 [ Andrew Hayzen ]
3 * Release 3.1 and bump version to 3.24 * Release 3.1 and bump version to 3.2
45
6 [ Victor Thompson ]
7 * Use the new ListItems from Ubuntu Components 1.3
8
5 -- Andrew Hayzen <ahayzen@gmail.com> Thu, 03 Dec 2015 15:20:49 +00009 -- Andrew Hayzen <ahayzen@gmail.com> Thu, 03 Dec 2015 15:20:49 +0000
610
7ubuntu-weather-app (3.1ubuntu1) vivid; urgency=medium11ubuntu-weather-app (3.1ubuntu1) vivid; urgency=medium
812
=== modified file 'po/com.ubuntu.weather.pot'
--- po/com.ubuntu.weather.pot 2015-11-26 02:05:13 +0000
+++ po/com.ubuntu.weather.pot 2015-12-10 01:16:13 +0000
@@ -8,7 +8,7 @@
8msgstr ""8msgstr ""
9"Project-Id-Version: ubuntu-weather-app\n"9"Project-Id-Version: ubuntu-weather-app\n"
10"Report-Msgid-Bugs-To: \n"10"Report-Msgid-Bugs-To: \n"
11"POT-Creation-Date: 2015-11-26 02:04+0000\n"11"POT-Creation-Date: 2015-12-09 19:09-0600\n"
12"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"12"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
13"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"13"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
14"Language-Team: LANGUAGE <LL@li.org>\n"14"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -62,26 +62,10 @@
62msgid "Today"62msgid "Today"
63msgstr ""63msgstr ""
6464
65#: ../app/components/ListItemActions/Remove.qml:26
66msgid "Remove"
67msgstr ""
68
69#: ../app/components/LocationsPageEmptyStateComponent.qml:3665#: ../app/components/LocationsPageEmptyStateComponent.qml:36
70msgid "No locations found. Tap the plus icon to search for one."66msgid "No locations found. Tap the plus icon to search for one."
71msgstr ""67msgstr ""
7268
73#: ../app/components/MultiSelectHeadState.qml:27
74msgid "Select All"
75msgstr ""
76
77#: ../app/components/MultiSelectHeadState.qml:39
78msgid "Delete"
79msgstr ""
80
81#: ../app/components/MultiSelectHeadState.qml:51
82msgid "Cancel selection"
83msgstr ""
84
85#: ../app/components/NetworkErrorStateComponent.qml:4869#: ../app/components/NetworkErrorStateComponent.qml:48
86msgid "Network Error"70msgid "Network Error"
87msgstr ""71msgstr ""
@@ -136,11 +120,11 @@
136msgid "OK"120msgid "OK"
137msgstr ""121msgstr ""
138122
139#: ../app/ui/HomePage.qml:32 ../app/ui/LocationsPage.qml:29123#: ../app/ui/HomePage.qml:32 ../app/ui/LocationsPage.qml:27
140msgid "Locations"124msgid "Locations"
141msgstr ""125msgstr ""
142126
143#: ../app/ui/LocationsPage.qml:109127#: ../app/ui/LocationsPage.qml:121
144msgid "Current Location"128msgid "Current Location"
145msgstr ""129msgstr ""
146130

Subscribers

People subscribed via source and target branches