Merge lp:~nik90/ubuntu-weather-app/finish-listitem-migration into lp:ubuntu-weather-app
- finish-listitem-migration
- Merge into reboot
Status: | Rejected |
---|---|
Rejected by: | Victor Thompson |
Proposed branch: | lp:~nik90/ubuntu-weather-app/finish-listitem-migration |
Merge into: | lp:ubuntu-weather-app |
Diff against target: |
1514 lines (+224/-973) 15 files modified
app/components/CMakeLists.txt (+0/-2) app/components/FakeHeader.qml (+39/-0) 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/PageWithBottomEdge.qml (+68/-18) app/components/WeatherListItem.qml (+0/-137) app/components/WeatherListView.qml (+1/-2) app/ui/LocationsPage.qml (+82/-53) po/com.ubuntu.weather.pot (+6/-22) ubuntu-weather-app.desktop.in.in (+1/-0) |
To merge this branch: | bzr merge lp:~nik90/ubuntu-weather-app/finish-listitem-migration |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Nekhelesh Ramananthan (community) | Disapprove | ||
Ubuntu Phone Apps Jenkins Bot | continuous-integration | Approve | |
Victor Thompson | Needs Fixing | ||
Review via email: mp+263136@code.launchpad.net |
Commit message
* 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)
Description of the change
This MP implements the following,
* 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)
- 64. By Nekhelesh Ramananthan
-
Fixed copyright header formatting in fakeheader.qml
- 65. By Nekhelesh Ramananthan
-
removed multiselect head state as it was no longer used
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
- 66. By Nekhelesh Ramananthan
-
Fixed locations names not eliding in locations page
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
PASSED: Continuous integration, rev:66
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 67. By Nekhelesh Ramananthan
-
Changed multi-delete to use the removeMultiLoca
tions() function
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
PASSED: Continuous integration, rev:67
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Nekhelesh Ramananthan (nik90) wrote : | # |
I consider this MP to be complete now. Please note the following,
- In trunk, there is a selectAll header button which is shown. Also pressing on the list item selects/deselects it.
This behaviour has not been implemented intentionally due to a bug [1] which I observed in a couple of apps now. I discussed this with Andrew Hayzen, and it turns out this bug is also present in his music-app MP [2]. So this issue is a SDK one and does not matter on the implementation which is a bit different between this MP and andrew's.
[1] https:/
[2] https:/
Victor Thompson (vthompson) wrote : | # |
Currently, there is no trailing divider in the LocationsPage.
The margins of the list items in the LocationsPage has been reduced in this MP--is that intentional?
Can we add a Select all/none toggle action to the multiselection on the LocationsPage?
The settings page always seems to have the list items offset/partially down the page. This was introduced in the previous mp. Can we fix this behaviour?
I see a lot of instances of the following error message, can we fix this?
file://
Nekhelesh Ramananthan (nik90) wrote : | # |
> Currently, there is no trailing divider in the LocationsPage.
>
Btw were you referring to the divider of the trailing swipe actions? Or for the listitem as a whole?
I believe the default behaviour of the new listitems and UbuntuListView is to *not* show a divider for the very last item of the listview. If you add more locations, you will notice the divider being shown.
> The margins of the list items in the LocationsPage has been reduced in this MP
> --is that intentional?
>
Nope, I will fix this.
> Can we add a Select all/none toggle action to the multiselection on the
> LocationsPage?
I'm afraid I can't. I have explained the reasoning at https:/
>
> The settings page always seems to have the list items offset/partially down
> the page. This was introduced in the previous mp. Can we fix this behaviour?
>
This is something I have noticed while testing on rc-proposed channel. And not with the my BQ E4.5 runnign the stable channel. I can check with t1mp tomorrow as to why this is the case. And yes same behavior observed with Podbird while testing on Nexus 4 and BQ.
> I see a lot of instances of the following error message, can we fix this?
>
> file://
> gnu/qt5/
> TypeError: Cannot read property of null
I believe this is a SDK error message that is seen in other apps as well. I haven't changed the PullToRefresh component.
Victor Thompson (vthompson) wrote : | # |
For that first comment, I was talking about the ListItem as a whole. While that may be the default, it is inconsistent with the listitems in the rest of the app. Also, and this is subjective, I think it looks kinda odd without a divider below the final item.
Victor Thompson (vthompson) wrote : | # |
Nik, I have a fix for the settings page ListItems being "offset" [1]. So you probably don't need to ping t1mp.
- 68. By Nekhelesh Ramananthan
-
merged lp:ubuntu-weather-app/reboot
- 69. By Nekhelesh Ramananthan
-
Added thindivider to the last listitem
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
PASSED: Continuous integration, rev:69
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Nekhelesh Ramananthan (nik90) wrote : | # |
@Victor, I added the thindivider to the last list item. Going over the stuff you wanted fixed,
- On looking closer, the margins of the listitems in the locations Page look the same to me. I also cross-checked with design and it looks the same. If you were referring to the margins during the multi-select mode, then yes that's changed and that's because the SDK draws the checkbox and the drag handler. I cannot change their margins I am afraid.
- After merging trunk, I am noticing the following error while deleting a location. I am unable to delete a location. On further testing, it seems commit 57 in trunk seems to be causing it. Can we get that reverted pls?
file://
All other issues have been addressed except for the newly cropped delete issue.
Victor Thompson (vthompson) wrote : | # |
I don't think that error is being caused by commit 57. Do you not have the API key and are using TWC perhaps?
Nekhelesh Ramananthan (nik90) wrote : | # |
> I don't think that error is being caused by commit 57. Do you not have the API
> key and are using TWC perhaps?
I cannot remember where I placed the API key, but I do all my testing with the OpenWeatherMap data provider. Also I can add locations and also see the weather data correctly. I am having trouble with only deleting locations. How can that be related to the API key or data provider?
Victor Thompson (vthompson) wrote : | # |
Andrew had seen the same error when he wasn't able to talk to the API (wifi and data were off) and had GPS/location detection turned off.
Maybe the issue is that you've tested with the migration done in commit 57, went back, and then tested with it in place again? Perhaps change addedCurrentLoc
Nekhelesh Ramananthan (nik90) wrote : | # |
What is your workflow? Where do you copy the key.js file to ensure that TheWeatherChannel API works? Either way don't you think it is an issue that with wifi/data/GPS off, deleting a location deletes some other random location? First of all I cannot wrap my head around how deleting a location is remotely connected to having wifi/data/GPS off. Its not like we report back to TheWeatherChannel when a user deletes a location. Somehow I am not happy with the way the storage is implemented.
Feel free to continue this branch. As far I can tell I simply migrated to the new listitems and used the same storage functions calls as before. I cannot resolve this bug.
Nekhelesh Ramananthan (nik90) wrote : | # |
And yes I tried starting with a clean setup by removing all existing databases and config files.
Unmerged revisions
- 69. By Nekhelesh Ramananthan
-
Added thindivider to the last listitem
- 68. By Nekhelesh Ramananthan
-
merged lp:ubuntu-weather-app/reboot
- 67. By Nekhelesh Ramananthan
-
Changed multi-delete to use the removeMultiLoca
tions() function - 66. By Nekhelesh Ramananthan
-
Fixed locations names not eliding in locations page
- 65. By Nekhelesh Ramananthan
-
removed multiselect head state as it was no longer used
- 64. By Nekhelesh Ramananthan
-
Fixed copyright header formatting in fakeheader.qml
- 63. By Nekhelesh Ramananthan
-
Lock orientation to portrait
- 62. By Nekhelesh Ramananthan
-
Removed more unnecessary components now that we have migrated to the new sdk listitems
- 61. By Nekhelesh Ramananthan
-
Implemented reorder support
- 60. By Nekhelesh Ramananthan
-
Removed unnecessary ListItemWithAct
ions.qml and WeatherListItem.qml
Preview Diff
1 | === modified file 'app/components/CMakeLists.txt' | |||
2 | --- app/components/CMakeLists.txt 2015-03-03 18:37:59 +0000 | |||
3 | +++ app/components/CMakeLists.txt 2015-06-29 10:16:30 +0000 | |||
4 | @@ -1,5 +1,3 @@ | |||
5 | 1 | add_subdirectory(ListItemActions) | ||
6 | 2 | |||
7 | 3 | file(GLOB COMPONENTS_QML_JS_FILES *.qml *.js) | 1 | file(GLOB COMPONENTS_QML_JS_FILES *.qml *.js) |
8 | 4 | 2 | ||
9 | 5 | add_custom_target(ubuntu-weather-app_components_QMlFiles ALL SOURCES ${COMPONENTS_QML_JS_FILES}) | 3 | add_custom_target(ubuntu-weather-app_components_QMlFiles ALL SOURCES ${COMPONENTS_QML_JS_FILES}) |
10 | 6 | 4 | ||
11 | === added file 'app/components/FakeHeader.qml' | |||
12 | --- app/components/FakeHeader.qml 1970-01-01 00:00:00 +0000 | |||
13 | +++ app/components/FakeHeader.qml 2015-06-29 10:16:30 +0000 | |||
14 | @@ -0,0 +1,39 @@ | |||
15 | 1 | /* | ||
16 | 2 | * Copyright (C) 2014 Canonical Ltd | ||
17 | 3 | * | ||
18 | 4 | * This file is part of Ubuntu Clock App | ||
19 | 5 | * | ||
20 | 6 | * Ubuntu Clock App is free software: you can redistribute it and/or modify | ||
21 | 7 | * it under the terms of the GNU General Public License version 3 as | ||
22 | 8 | * published by the Free Software Foundation. | ||
23 | 9 | * | ||
24 | 10 | * Ubuntu Clock App is distributed in the hope that it will be useful, | ||
25 | 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
26 | 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
27 | 13 | * GNU General Public License for more details. | ||
28 | 14 | * | ||
29 | 15 | * You should have received a copy of the GNU General Public License | ||
30 | 16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
31 | 17 | */ | ||
32 | 18 | |||
33 | 19 | import QtQuick 2.4 | ||
34 | 20 | import Ubuntu.Components 1.2 | ||
35 | 21 | |||
36 | 22 | Column { | ||
37 | 23 | id: fakeHeader | ||
38 | 24 | |||
39 | 25 | height: units.gu(9) | ||
40 | 26 | |||
41 | 27 | Rectangle { | ||
42 | 28 | height: units.gu(7) | ||
43 | 29 | width: parent.width | ||
44 | 30 | color: Theme.palette.normal.background | ||
45 | 31 | } | ||
46 | 32 | |||
47 | 33 | Rectangle { | ||
48 | 34 | color: "#C9C9C9" | ||
49 | 35 | height: units.gu(2) | ||
50 | 36 | anchors.left: parent.left | ||
51 | 37 | anchors.right: parent.right | ||
52 | 38 | } | ||
53 | 39 | } | ||
54 | 0 | 40 | ||
55 | === removed directory 'app/components/ListItemActions' | |||
56 | === removed file 'app/components/ListItemActions/CMakeLists.txt' | |||
57 | --- app/components/ListItemActions/CMakeLists.txt 2015-03-03 18:37:59 +0000 | |||
58 | +++ app/components/ListItemActions/CMakeLists.txt 1970-01-01 00:00:00 +0000 | |||
59 | @@ -1,5 +0,0 @@ | |||
60 | 1 | file(GLOB LISTITEMACTIONS_QML_JS_FILES *.qml *.js) | ||
61 | 2 | |||
62 | 3 | add_custom_target(ubuntu-weather-app_listitemactions_QMlFiles ALL SOURCES ${LISTITEMACTIONS_QML_JS_FILES}) | ||
63 | 4 | |||
64 | 5 | install(FILES ${LISTITEMACTIONS_QML_JS_FILES} DESTINATION ${UBUNTU-WEATHER_APP_DIR}/components/ListItemActions) | ||
65 | 6 | 0 | ||
66 | === removed file 'app/components/ListItemActions/CheckBox.qml' | |||
67 | --- app/components/ListItemActions/CheckBox.qml 2015-06-18 01:45:57 +0000 | |||
68 | +++ app/components/ListItemActions/CheckBox.qml 1970-01-01 00:00:00 +0000 | |||
69 | @@ -1,25 +0,0 @@ | |||
70 | 1 | /* | ||
71 | 2 | * Copyright (C) 2012-2014, 2015 Canonical, Ltd. | ||
72 | 3 | * | ||
73 | 4 | * This program is free software; you can redistribute it and/or modify | ||
74 | 5 | * it under the terms of the GNU General Public License as published by | ||
75 | 6 | * the Free Software Foundation; version 3. | ||
76 | 7 | * | ||
77 | 8 | * This program is distributed in the hope that it will be useful, | ||
78 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
79 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
80 | 11 | * GNU General Public License for more details. | ||
81 | 12 | * | ||
82 | 13 | * You should have received a copy of the GNU General Public License | ||
83 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
84 | 15 | */ | ||
85 | 16 | |||
86 | 17 | import QtQuick 2.4 | ||
87 | 18 | import Ubuntu.Components 1.2 | ||
88 | 19 | |||
89 | 20 | CheckBox { | ||
90 | 21 | checked: root.selected | ||
91 | 22 | width: implicitWidth | ||
92 | 23 | // disable item mouse area to avoid conflicts with parent mouse area | ||
93 | 24 | __mouseArea.enabled: false | ||
94 | 25 | } | ||
95 | 26 | 0 | ||
96 | === removed file 'app/components/ListItemActions/Remove.qml' | |||
97 | --- app/components/ListItemActions/Remove.qml 2015-06-18 01:42:03 +0000 | |||
98 | +++ app/components/ListItemActions/Remove.qml 1970-01-01 00:00:00 +0000 | |||
99 | @@ -1,27 +0,0 @@ | |||
100 | 1 | /* | ||
101 | 2 | * Copyright (C) 2014, 2015 Andrew Hayzen <ahayzen@gmail.com> | ||
102 | 3 | * Daniel Holm <d.holmen@gmail.com> | ||
103 | 4 | * Victor Thompson <victor.thompson@gmail.com> | ||
104 | 5 | * | ||
105 | 6 | * This program is free software; you can redistribute it and/or modify | ||
106 | 7 | * it under the terms of the GNU General Public License as published by | ||
107 | 8 | * the Free Software Foundation; version 3. | ||
108 | 9 | * | ||
109 | 10 | * This program is distributed in the hope that it will be useful, | ||
110 | 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
111 | 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
112 | 13 | * GNU General Public License for more details. | ||
113 | 14 | * | ||
114 | 15 | * You should have received a copy of the GNU General Public License | ||
115 | 16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
116 | 17 | */ | ||
117 | 18 | |||
118 | 19 | import QtQuick 2.4 | ||
119 | 20 | import Ubuntu.Components 1.2 | ||
120 | 21 | |||
121 | 22 | Action { | ||
122 | 23 | id: removeAction | ||
123 | 24 | iconName: "delete" | ||
124 | 25 | objectName: "swipeDeleteAction" | ||
125 | 26 | text: i18n.tr("Remove") | ||
126 | 27 | } | ||
127 | 28 | 0 | ||
128 | === removed file 'app/components/ListItemReorderComponent.qml' | |||
129 | --- app/components/ListItemReorderComponent.qml 2015-06-18 01:42:03 +0000 | |||
130 | +++ app/components/ListItemReorderComponent.qml 1970-01-01 00:00:00 +0000 | |||
131 | @@ -1,106 +0,0 @@ | |||
132 | 1 | /* | ||
133 | 2 | * Copyright (C) 2013, 2014, 2015 | ||
134 | 3 | * Andrew Hayzen <ahayzen@gmail.com> | ||
135 | 4 | * Nekhelesh Ramananthan <krnekhelesh@gmail.com> | ||
136 | 5 | * Victor Thompson <victor.thompson@gmail.com> | ||
137 | 6 | * | ||
138 | 7 | * This program is free software; you can redistribute it and/or modify | ||
139 | 8 | * it under the terms of the GNU General Public License as published by | ||
140 | 9 | * the Free Software Foundation; version 3. | ||
141 | 10 | * | ||
142 | 11 | * This program is distributed in the hope that it will be useful, | ||
143 | 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
144 | 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
145 | 14 | * GNU General Public License for more details. | ||
146 | 15 | * | ||
147 | 16 | * You should have received a copy of the GNU General Public License | ||
148 | 17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
149 | 18 | */ | ||
150 | 19 | |||
151 | 20 | import QtQuick 2.4 | ||
152 | 21 | import Ubuntu.Components 1.2 | ||
153 | 22 | |||
154 | 23 | |||
155 | 24 | Item { | ||
156 | 25 | id: actionReorder | ||
157 | 26 | width: units.gu(4) | ||
158 | 27 | |||
159 | 28 | Icon { | ||
160 | 29 | anchors { | ||
161 | 30 | horizontalCenter: parent.horizontalCenter | ||
162 | 31 | verticalCenter: parent.verticalCenter | ||
163 | 32 | } | ||
164 | 33 | name: "navigation-menu" // TODO: use proper image | ||
165 | 34 | height: width | ||
166 | 35 | width: units.gu(3) | ||
167 | 36 | } | ||
168 | 37 | |||
169 | 38 | MouseArea { | ||
170 | 39 | id: actionReorderMouseArea | ||
171 | 40 | anchors { | ||
172 | 41 | fill: parent | ||
173 | 42 | } | ||
174 | 43 | property int startY: 0 | ||
175 | 44 | property int startContentY: 0 | ||
176 | 45 | |||
177 | 46 | onPressed: { | ||
178 | 47 | root.parent.parent.interactive = false; // stop scrolling of listview | ||
179 | 48 | startY = root.y; | ||
180 | 49 | startContentY = root.parent.parent.contentY; | ||
181 | 50 | root.z += 10; // force ontop of other elements | ||
182 | 51 | |||
183 | 52 | console.debug("Reorder listitem pressed", root.y) | ||
184 | 53 | } | ||
185 | 54 | onMouseYChanged: root.y += mouse.y - (root.height / 2); | ||
186 | 55 | onReleased: { | ||
187 | 56 | console.debug("Reorder diff by position", getDiff()); | ||
188 | 57 | |||
189 | 58 | var diff = getDiff(); | ||
190 | 59 | |||
191 | 60 | // Remove the height of the actual item if moved down | ||
192 | 61 | if (diff > 0) { | ||
193 | 62 | diff -= 1; | ||
194 | 63 | } | ||
195 | 64 | |||
196 | 65 | root.parent.parent.interactive = true; // reenable scrolling | ||
197 | 66 | |||
198 | 67 | if (diff === 0) { | ||
199 | 68 | // Nothing has changed so reset the item | ||
200 | 69 | // z index is restored after animation | ||
201 | 70 | resetListItemYAnimation.start(); | ||
202 | 71 | } | ||
203 | 72 | else { | ||
204 | 73 | var newIndex = index + diff; | ||
205 | 74 | |||
206 | 75 | if (newIndex < 0) { | ||
207 | 76 | newIndex = 0; | ||
208 | 77 | } | ||
209 | 78 | else if (newIndex > root.parent.parent.count - 1) { | ||
210 | 79 | newIndex = root.parent.parent.count - 1; | ||
211 | 80 | } | ||
212 | 81 | |||
213 | 82 | root.z -= 10; // restore z index | ||
214 | 83 | reorder(index, newIndex) | ||
215 | 84 | } | ||
216 | 85 | } | ||
217 | 86 | |||
218 | 87 | function getDiff() { | ||
219 | 88 | // Get the amount of items that have been passed over (by centre) | ||
220 | 89 | return Math.round((((root.y - startY) + (root.parent.parent.contentY - startContentY)) / root.height) + 0.5); | ||
221 | 90 | } | ||
222 | 91 | } | ||
223 | 92 | |||
224 | 93 | SequentialAnimation { | ||
225 | 94 | id: resetListItemYAnimation | ||
226 | 95 | UbuntuNumberAnimation { | ||
227 | 96 | target: root; | ||
228 | 97 | property: "y"; | ||
229 | 98 | to: actionReorderMouseArea.startY | ||
230 | 99 | } | ||
231 | 100 | ScriptAction { | ||
232 | 101 | script: { | ||
233 | 102 | root.z -= 10; // restore z index | ||
234 | 103 | } | ||
235 | 104 | } | ||
236 | 105 | } | ||
237 | 106 | } | ||
238 | 107 | 0 | ||
239 | === removed file 'app/components/ListItemWithActions.qml' | |||
240 | --- app/components/ListItemWithActions.qml 2015-06-18 01:42:03 +0000 | |||
241 | +++ app/components/ListItemWithActions.qml 1970-01-01 00:00:00 +0000 | |||
242 | @@ -1,496 +0,0 @@ | |||
243 | 1 | /* | ||
244 | 2 | * Copyright (C) 2012-2015 Canonical, Ltd. | ||
245 | 3 | * | ||
246 | 4 | * This program is free software; you can redistribute it and/or modify | ||
247 | 5 | * it under the terms of the GNU General Public License as published by | ||
248 | 6 | * the Free Software Foundation; version 3. | ||
249 | 7 | * | ||
250 | 8 | * This program is distributed in the hope that it will be useful, | ||
251 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
252 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
253 | 11 | * GNU General Public License for more details. | ||
254 | 12 | * | ||
255 | 13 | * You should have received a copy of the GNU General Public License | ||
256 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
257 | 15 | */ | ||
258 | 16 | |||
259 | 17 | import QtQuick 2.4 | ||
260 | 18 | import Ubuntu.Components 1.2 | ||
261 | 19 | import Ubuntu.Components.ListItems 1.0 as ListItem | ||
262 | 20 | |||
263 | 21 | |||
264 | 22 | Item { | ||
265 | 23 | id: root | ||
266 | 24 | width: parent.width | ||
267 | 25 | |||
268 | 26 | property Action leftSideAction: null | ||
269 | 27 | property list<Action> rightSideActions | ||
270 | 28 | property double defaultHeight: units.gu(8) | ||
271 | 29 | property bool locked: false | ||
272 | 30 | property Action activeAction: null | ||
273 | 31 | property var activeItem: null | ||
274 | 32 | property bool triggerActionOnMouseRelease: false | ||
275 | 33 | property color color: Theme.palette.normal.background | ||
276 | 34 | property color selectedColor: "#E6E6E6" | ||
277 | 35 | property bool selected: false | ||
278 | 36 | property bool selectionMode: false | ||
279 | 37 | property alias internalAnchors: mainContents.anchors | ||
280 | 38 | default property alias contents: mainContents.children | ||
281 | 39 | |||
282 | 40 | readonly property double actionWidth: units.gu(4) | ||
283 | 41 | readonly property double leftActionWidth: units.gu(10) | ||
284 | 42 | readonly property double actionThreshold: actionWidth * 0.4 | ||
285 | 43 | readonly property double threshold: 0.4 | ||
286 | 44 | readonly property string swipeState: main.x == 0 ? "Normal" : main.x > 0 ? "LeftToRight" : "RightToLeft" | ||
287 | 45 | readonly property alias swipping: mainItemMoving.running | ||
288 | 46 | readonly property bool _showActions: mouseArea.pressed || swipeState != "Normal" || swipping | ||
289 | 47 | |||
290 | 48 | property alias _main: main // CUSTOM | ||
291 | 49 | property alias pressed: mouseArea.pressed // CUSTOM | ||
292 | 50 | |||
293 | 51 | /* internal */ | ||
294 | 52 | property var _visibleRightSideActions: filterVisibleActions(rightSideActions) | ||
295 | 53 | |||
296 | 54 | signal itemClicked(var mouse) | ||
297 | 55 | signal itemPressAndHold(var mouse) | ||
298 | 56 | |||
299 | 57 | function returnToBoundsRTL(direction) | ||
300 | 58 | { | ||
301 | 59 | var actionFullWidth = actionWidth + units.gu(2) | ||
302 | 60 | |||
303 | 61 | // go back to normal state if swipping reverse | ||
304 | 62 | if (direction === "LTR") { | ||
305 | 63 | updatePosition(0) | ||
306 | 64 | return | ||
307 | 65 | } else if (!triggerActionOnMouseRelease) { | ||
308 | 66 | updatePosition(-rightActionsView.width + units.gu(2)) | ||
309 | 67 | return | ||
310 | 68 | } | ||
311 | 69 | |||
312 | 70 | var xOffset = Math.abs(main.x) | ||
313 | 71 | var index = Math.min(Math.floor(xOffset / actionFullWidth), _visibleRightSideActions.length) | ||
314 | 72 | var newX = 0 | ||
315 | 73 | |||
316 | 74 | if (index === _visibleRightSideActions.length) { | ||
317 | 75 | newX = -(rightActionsView.width - units.gu(2)) | ||
318 | 76 | } else if (index >= 1) { | ||
319 | 77 | newX = -(actionFullWidth * index) | ||
320 | 78 | } | ||
321 | 79 | |||
322 | 80 | updatePosition(newX) | ||
323 | 81 | } | ||
324 | 82 | |||
325 | 83 | function returnToBoundsLTR(direction) | ||
326 | 84 | { | ||
327 | 85 | var finalX = leftActionWidth | ||
328 | 86 | if ((direction === "RTL") || (main.x <= (finalX * root.threshold))) | ||
329 | 87 | finalX = 0 | ||
330 | 88 | updatePosition(finalX) | ||
331 | 89 | } | ||
332 | 90 | |||
333 | 91 | function returnToBounds(direction) | ||
334 | 92 | { | ||
335 | 93 | if (main.x < 0) { | ||
336 | 94 | returnToBoundsRTL(direction) | ||
337 | 95 | } else if (main.x > 0) { | ||
338 | 96 | returnToBoundsLTR(direction) | ||
339 | 97 | } else { | ||
340 | 98 | updatePosition(0) | ||
341 | 99 | } | ||
342 | 100 | } | ||
343 | 101 | |||
344 | 102 | function contains(item, point, marginX) | ||
345 | 103 | { | ||
346 | 104 | var itemStartX = item.x - marginX | ||
347 | 105 | var itemEndX = item.x + item.width + marginX | ||
348 | 106 | return (point.x >= itemStartX) && (point.x <= itemEndX) && | ||
349 | 107 | (point.y >= item.y) && (point.y <= (item.y + item.height)); | ||
350 | 108 | } | ||
351 | 109 | |||
352 | 110 | function getActionAt(point) | ||
353 | 111 | { | ||
354 | 112 | if (leftSideAction && contains(leftActionViewLoader.item, point, 0)) { | ||
355 | 113 | return leftSideAction | ||
356 | 114 | } else if (contains(rightActionsView, point, 0)) { | ||
357 | 115 | var newPoint = root.mapToItem(rightActionsView, point.x, point.y) | ||
358 | 116 | for (var i = 0; i < rightActionsRepeater.count; i++) { | ||
359 | 117 | var child = rightActionsRepeater.itemAt(i) | ||
360 | 118 | if (contains(child, newPoint, units.gu(1))) { | ||
361 | 119 | return i | ||
362 | 120 | } | ||
363 | 121 | } | ||
364 | 122 | } | ||
365 | 123 | return -1 | ||
366 | 124 | } | ||
367 | 125 | |||
368 | 126 | function updateActiveAction() | ||
369 | 127 | { | ||
370 | 128 | if (triggerActionOnMouseRelease && | ||
371 | 129 | (main.x <= -(root.actionWidth + units.gu(2))) && | ||
372 | 130 | (main.x > -(rightActionsView.width - units.gu(2)))) { | ||
373 | 131 | var actionFullWidth = actionWidth + units.gu(2) | ||
374 | 132 | var xOffset = Math.abs(main.x) | ||
375 | 133 | var index = Math.min(Math.floor(xOffset / actionFullWidth), _visibleRightSideActions.length) | ||
376 | 134 | index = index - 1 | ||
377 | 135 | if (index > -1) { | ||
378 | 136 | root.activeItem = rightActionsRepeater.itemAt(index) | ||
379 | 137 | root.activeAction = root._visibleRightSideActions[index] | ||
380 | 138 | } | ||
381 | 139 | } else { | ||
382 | 140 | root.activeAction = null | ||
383 | 141 | } | ||
384 | 142 | } | ||
385 | 143 | |||
386 | 144 | function resetSwipe() | ||
387 | 145 | { | ||
388 | 146 | updatePosition(0) | ||
389 | 147 | } | ||
390 | 148 | |||
391 | 149 | function filterVisibleActions(actions) | ||
392 | 150 | { | ||
393 | 151 | var visibleActions = [] | ||
394 | 152 | for(var i = 0; i < actions.length; i++) { | ||
395 | 153 | var action = actions[i] | ||
396 | 154 | if (action.visible) { | ||
397 | 155 | visibleActions.push(action) | ||
398 | 156 | } | ||
399 | 157 | } | ||
400 | 158 | return visibleActions | ||
401 | 159 | } | ||
402 | 160 | |||
403 | 161 | function updatePosition(pos) | ||
404 | 162 | { | ||
405 | 163 | if (!root.triggerActionOnMouseRelease && (pos !== 0)) { | ||
406 | 164 | mouseArea.state = pos > 0 ? "RightToLeft" : "LeftToRight" | ||
407 | 165 | } else { | ||
408 | 166 | mouseArea.state = "" | ||
409 | 167 | } | ||
410 | 168 | main.x = pos | ||
411 | 169 | } | ||
412 | 170 | |||
413 | 171 | // CUSTOM remove animation | ||
414 | 172 | SequentialAnimation { | ||
415 | 173 | id: removeAnimation | ||
416 | 174 | |||
417 | 175 | property var action | ||
418 | 176 | |||
419 | 177 | UbuntuNumberAnimation { | ||
420 | 178 | target: root | ||
421 | 179 | duration: UbuntuAnimation.BriskDuration | ||
422 | 180 | property: "height"; | ||
423 | 181 | to: 0 | ||
424 | 182 | } | ||
425 | 183 | ScriptAction { | ||
426 | 184 | script: removeAnimation.action.trigger() | ||
427 | 185 | } | ||
428 | 186 | } | ||
429 | 187 | |||
430 | 188 | states: [ | ||
431 | 189 | State { | ||
432 | 190 | name: "select" | ||
433 | 191 | when: selectionMode || selected | ||
434 | 192 | PropertyChanges { | ||
435 | 193 | target: selectionIcon | ||
436 | 194 | source: Qt.resolvedUrl("ListItemActions/CheckBox.qml") | ||
437 | 195 | anchors.leftMargin: units.gu(2) | ||
438 | 196 | } | ||
439 | 197 | PropertyChanges { | ||
440 | 198 | target: root | ||
441 | 199 | locked: true | ||
442 | 200 | } | ||
443 | 201 | PropertyChanges { | ||
444 | 202 | target: main | ||
445 | 203 | x: 0 | ||
446 | 204 | } | ||
447 | 205 | } | ||
448 | 206 | ] | ||
449 | 207 | |||
450 | 208 | height: defaultHeight | ||
451 | 209 | //clip: height !== defaultHeight // CUSTOM | ||
452 | 210 | |||
453 | 211 | Loader { // CUSTOM | ||
454 | 212 | id: leftActionViewLoader | ||
455 | 213 | anchors { | ||
456 | 214 | top: parent.top | ||
457 | 215 | bottom: parent.bottom | ||
458 | 216 | right: main.left | ||
459 | 217 | } | ||
460 | 218 | asynchronous: true | ||
461 | 219 | sourceComponent: leftSideAction ? leftActionViewComponent : undefined | ||
462 | 220 | } | ||
463 | 221 | |||
464 | 222 | Component { // CUSTOM | ||
465 | 223 | id: leftActionViewComponent | ||
466 | 224 | |||
467 | 225 | Rectangle { | ||
468 | 226 | id: leftActionView | ||
469 | 227 | width: root.leftActionWidth + actionThreshold | ||
470 | 228 | color: UbuntuColors.red | ||
471 | 229 | |||
472 | 230 | Icon { | ||
473 | 231 | id: leftActionIcon | ||
474 | 232 | anchors { | ||
475 | 233 | centerIn: parent | ||
476 | 234 | horizontalCenterOffset: actionThreshold / 2 | ||
477 | 235 | } | ||
478 | 236 | objectName: "swipeDeleteAction" // CUSTOM | ||
479 | 237 | name: leftSideAction && _showActions ? leftSideAction.iconName : "" | ||
480 | 238 | color: Theme.palette.selected.field | ||
481 | 239 | height: units.gu(3) | ||
482 | 240 | width: units.gu(3) | ||
483 | 241 | } | ||
484 | 242 | } | ||
485 | 243 | } | ||
486 | 244 | |||
487 | 245 | //Rectangle { | ||
488 | 246 | Item { // CUSTOM | ||
489 | 247 | id: rightActionsView | ||
490 | 248 | |||
491 | 249 | anchors { | ||
492 | 250 | top: main.top | ||
493 | 251 | left: main.right | ||
494 | 252 | bottom: main.bottom | ||
495 | 253 | } | ||
496 | 254 | visible: _visibleRightSideActions.length > 0 | ||
497 | 255 | width: rightActionsRepeater.count > 0 ? rightActionsRepeater.count * (root.actionWidth + units.gu(2)) + root.actionThreshold + units.gu(2) : 0 | ||
498 | 256 | // color: "white" // CUSTOM | ||
499 | 257 | |||
500 | 258 | Row { | ||
501 | 259 | anchors{ | ||
502 | 260 | top: parent.top | ||
503 | 261 | left: parent.left | ||
504 | 262 | leftMargin: units.gu(2) | ||
505 | 263 | right: parent.right | ||
506 | 264 | rightMargin: units.gu(2) | ||
507 | 265 | bottom: parent.bottom | ||
508 | 266 | } | ||
509 | 267 | spacing: units.gu(2) | ||
510 | 268 | Repeater { | ||
511 | 269 | id: rightActionsRepeater | ||
512 | 270 | |||
513 | 271 | model: _showActions ? _visibleRightSideActions : [] | ||
514 | 272 | Item { | ||
515 | 273 | property alias image: img | ||
516 | 274 | |||
517 | 275 | height: rightActionsView.height | ||
518 | 276 | width: root.actionWidth | ||
519 | 277 | |||
520 | 278 | Icon { | ||
521 | 279 | id: img | ||
522 | 280 | |||
523 | 281 | anchors.centerIn: parent | ||
524 | 282 | objectName: rightSideActions[index].objectName // CUSTOM | ||
525 | 283 | width: units.gu(3) | ||
526 | 284 | height: units.gu(3) | ||
527 | 285 | name: modelData.iconName | ||
528 | 286 | color: root.activeAction === modelData ? UbuntuColors.orange : UbuntuColors.coolGrey // CUSTOM | ||
529 | 287 | } | ||
530 | 288 | } | ||
531 | 289 | } | ||
532 | 290 | } | ||
533 | 291 | } | ||
534 | 292 | |||
535 | 293 | Rectangle { | ||
536 | 294 | id: main | ||
537 | 295 | objectName: "mainItem" | ||
538 | 296 | |||
539 | 297 | anchors { | ||
540 | 298 | top: parent.top | ||
541 | 299 | bottom: parent.bottom | ||
542 | 300 | } | ||
543 | 301 | |||
544 | 302 | width: parent.width | ||
545 | 303 | color: root.selected ? root.selectedColor : root.color | ||
546 | 304 | |||
547 | 305 | Loader { | ||
548 | 306 | id: selectionIcon | ||
549 | 307 | |||
550 | 308 | anchors { | ||
551 | 309 | left: main.left | ||
552 | 310 | verticalCenter: main.verticalCenter | ||
553 | 311 | } | ||
554 | 312 | asynchronous: true // CUSTOM | ||
555 | 313 | width: (status === Loader.Ready) ? item.implicitWidth : 0 | ||
556 | 314 | visible: (status === Loader.Ready) && (item.width === item.implicitWidth) | ||
557 | 315 | |||
558 | 316 | Behavior on width { | ||
559 | 317 | NumberAnimation { | ||
560 | 318 | duration: UbuntuAnimation.SnapDuration | ||
561 | 319 | } | ||
562 | 320 | } | ||
563 | 321 | } | ||
564 | 322 | |||
565 | 323 | Item { | ||
566 | 324 | id: mainContents | ||
567 | 325 | |||
568 | 326 | anchors { | ||
569 | 327 | left: selectionIcon.right | ||
570 | 328 | //leftMargin: units.gu(2) // CUSTOM | ||
571 | 329 | top: parent.top | ||
572 | 330 | //topMargin: units.gu(1) // CUSTOM | ||
573 | 331 | right: parent.right | ||
574 | 332 | //rightMargin: units.gu(2) // CUSTOM | ||
575 | 333 | bottom: parent.bottom | ||
576 | 334 | //bottomMargin: units.gu(1) // CUSTOM | ||
577 | 335 | } | ||
578 | 336 | } | ||
579 | 337 | |||
580 | 338 | Behavior on x { | ||
581 | 339 | UbuntuNumberAnimation { | ||
582 | 340 | id: mainItemMoving | ||
583 | 341 | |||
584 | 342 | easing.type: Easing.OutElastic | ||
585 | 343 | duration: UbuntuAnimation.SlowDuration | ||
586 | 344 | } | ||
587 | 345 | } | ||
588 | 346 | } | ||
589 | 347 | |||
590 | 348 | SequentialAnimation { | ||
591 | 349 | id: triggerAction | ||
592 | 350 | |||
593 | 351 | property var currentItem: root.activeItem ? root.activeItem.image : null | ||
594 | 352 | |||
595 | 353 | running: false | ||
596 | 354 | ParallelAnimation { | ||
597 | 355 | UbuntuNumberAnimation { | ||
598 | 356 | target: triggerAction.currentItem | ||
599 | 357 | property: "opacity" | ||
600 | 358 | from: 1.0 | ||
601 | 359 | to: 0.0 | ||
602 | 360 | duration: UbuntuAnimation.SlowDuration | ||
603 | 361 | easing {type: Easing.InOutBack; } | ||
604 | 362 | } | ||
605 | 363 | UbuntuNumberAnimation { | ||
606 | 364 | target: triggerAction.currentItem | ||
607 | 365 | properties: "width, height" | ||
608 | 366 | from: units.gu(3) | ||
609 | 367 | to: root.actionWidth | ||
610 | 368 | duration: UbuntuAnimation.SlowDuration | ||
611 | 369 | easing {type: Easing.InOutBack; } | ||
612 | 370 | } | ||
613 | 371 | } | ||
614 | 372 | PropertyAction { | ||
615 | 373 | target: triggerAction.currentItem | ||
616 | 374 | properties: "width, height" | ||
617 | 375 | value: units.gu(3) | ||
618 | 376 | } | ||
619 | 377 | PropertyAction { | ||
620 | 378 | target: triggerAction.currentItem | ||
621 | 379 | properties: "opacity" | ||
622 | 380 | value: 1.0 | ||
623 | 381 | } | ||
624 | 382 | ScriptAction { | ||
625 | 383 | script: { | ||
626 | 384 | root.activeAction.triggered(root) | ||
627 | 385 | mouseArea.state = "" | ||
628 | 386 | } | ||
629 | 387 | } | ||
630 | 388 | PauseAnimation { | ||
631 | 389 | duration: 500 | ||
632 | 390 | } | ||
633 | 391 | UbuntuNumberAnimation { | ||
634 | 392 | target: main | ||
635 | 393 | property: "x" | ||
636 | 394 | to: 0 | ||
637 | 395 | } | ||
638 | 396 | } | ||
639 | 397 | |||
640 | 398 | MouseArea { | ||
641 | 399 | id: mouseArea | ||
642 | 400 | |||
643 | 401 | property bool locked: root.locked || ((root.leftSideAction === null) && (root._visibleRightSideActions.count === 0)) // CUSTOM | ||
644 | 402 | property bool manual: false | ||
645 | 403 | property string direction: "None" | ||
646 | 404 | property real lastX: -1 | ||
647 | 405 | |||
648 | 406 | anchors.fill: parent | ||
649 | 407 | drag { | ||
650 | 408 | target: locked ? null : main | ||
651 | 409 | axis: Drag.XAxis | ||
652 | 410 | minimumX: rightActionsView.visible ? -(rightActionsView.width) : 0 | ||
653 | 411 | maximumX: leftSideAction ? leftActionViewLoader.item.width : 0 | ||
654 | 412 | threshold: root.actionThreshold | ||
655 | 413 | } | ||
656 | 414 | |||
657 | 415 | states: [ | ||
658 | 416 | State { | ||
659 | 417 | name: "LeftToRight" | ||
660 | 418 | PropertyChanges { | ||
661 | 419 | target: mouseArea | ||
662 | 420 | drag.maximumX: 0 | ||
663 | 421 | } | ||
664 | 422 | }, | ||
665 | 423 | State { | ||
666 | 424 | name: "RightToLeft" | ||
667 | 425 | PropertyChanges { | ||
668 | 426 | target: mouseArea | ||
669 | 427 | drag.minimumX: 0 | ||
670 | 428 | } | ||
671 | 429 | } | ||
672 | 430 | ] | ||
673 | 431 | |||
674 | 432 | onMouseXChanged: { | ||
675 | 433 | var offset = (lastX - mouseX) | ||
676 | 434 | if (Math.abs(offset) <= root.actionThreshold) { | ||
677 | 435 | return | ||
678 | 436 | } | ||
679 | 437 | lastX = mouseX | ||
680 | 438 | direction = offset > 0 ? "RTL" : "LTR"; | ||
681 | 439 | } | ||
682 | 440 | |||
683 | 441 | onPressed: { | ||
684 | 442 | lastX = mouse.x | ||
685 | 443 | } | ||
686 | 444 | |||
687 | 445 | onReleased: { | ||
688 | 446 | if (root.triggerActionOnMouseRelease && root.activeAction) { | ||
689 | 447 | triggerAction.start() | ||
690 | 448 | } else { | ||
691 | 449 | root.returnToBounds() | ||
692 | 450 | root.activeAction = null | ||
693 | 451 | } | ||
694 | 452 | lastX = -1 | ||
695 | 453 | direction = "None" | ||
696 | 454 | } | ||
697 | 455 | onClicked: { | ||
698 | 456 | if (selectionMode) { // CUSTOM - selecting a listitem should toggle selection if in selectionMode | ||
699 | 457 | selected = !selected | ||
700 | 458 | return | ||
701 | 459 | } else if (main.x === 0) { | ||
702 | 460 | root.itemClicked(mouse) | ||
703 | 461 | } else if (main.x > 0) { | ||
704 | 462 | var action = getActionAt(Qt.point(mouse.x, mouse.y)) | ||
705 | 463 | if (action && action !== -1) { | ||
706 | 464 | //action.triggered(root) | ||
707 | 465 | removeAnimation.action = action // CUSTOM - use our animation instead | ||
708 | 466 | removeAnimation.start() // CUSTOM | ||
709 | 467 | } | ||
710 | 468 | } else { | ||
711 | 469 | var actionIndex = getActionAt(Qt.point(mouse.x, mouse.y)) | ||
712 | 470 | |||
713 | 471 | if (actionIndex !== -1 && actionIndex !== leftSideAction) { // CUSTOM - can be leftAction | ||
714 | 472 | root.activeItem = rightActionsRepeater.itemAt(actionIndex) | ||
715 | 473 | root.activeAction = root.rightSideActions[actionIndex] | ||
716 | 474 | triggerAction.start() | ||
717 | 475 | return | ||
718 | 476 | } | ||
719 | 477 | } | ||
720 | 478 | root.resetSwipe() | ||
721 | 479 | } | ||
722 | 480 | |||
723 | 481 | onPositionChanged: { | ||
724 | 482 | if (mouseArea.pressed) { | ||
725 | 483 | updateActiveAction() | ||
726 | 484 | |||
727 | 485 | listItemSwiping(index) // CUSTOM - tells other listitems to dismiss any swipe | ||
728 | 486 | } | ||
729 | 487 | } | ||
730 | 488 | onPressAndHold: { | ||
731 | 489 | if (main.x === 0) { | ||
732 | 490 | root.itemPressAndHold(mouse) | ||
733 | 491 | } | ||
734 | 492 | } | ||
735 | 493 | |||
736 | 494 | z: -1 | ||
737 | 495 | } | ||
738 | 496 | } | ||
739 | 497 | 0 | ||
740 | === removed file 'app/components/MultiSelectHeadState.qml' | |||
741 | --- app/components/MultiSelectHeadState.qml 2015-06-18 01:42:03 +0000 | |||
742 | +++ app/components/MultiSelectHeadState.qml 1970-01-01 00:00:00 +0000 | |||
743 | @@ -1,72 +0,0 @@ | |||
744 | 1 | /* | ||
745 | 2 | * Copyright (C) 2015 | ||
746 | 3 | * Andrew Hayzen <ahayzen@gmail.com> | ||
747 | 4 | * Victor Thompson <victor.thompson@gmail.com> | ||
748 | 5 | * | ||
749 | 6 | * This program is free software; you can redistribute it and/or modify | ||
750 | 7 | * it under the terms of the GNU General Public License as published by | ||
751 | 8 | * the Free Software Foundation; version 3. | ||
752 | 9 | * | ||
753 | 10 | * This program is distributed in the hope that it will be useful, | ||
754 | 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
755 | 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
756 | 13 | * GNU General Public License for more details. | ||
757 | 14 | * | ||
758 | 15 | * You should have received a copy of the GNU General Public License | ||
759 | 16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
760 | 17 | */ | ||
761 | 18 | |||
762 | 19 | import QtQuick 2.4 | ||
763 | 20 | import Ubuntu.Components 1.2 | ||
764 | 21 | |||
765 | 22 | PageHeadState { | ||
766 | 23 | id: selectionState | ||
767 | 24 | actions: [ | ||
768 | 25 | Action { | ||
769 | 26 | iconName: "select" | ||
770 | 27 | text: i18n.tr("Select All") | ||
771 | 28 | onTriggered: { | ||
772 | 29 | if (listview.selectedItems.length === listview.model.count) { | ||
773 | 30 | listview.clearSelection() | ||
774 | 31 | } else { | ||
775 | 32 | listview.selectAll() | ||
776 | 33 | } | ||
777 | 34 | } | ||
778 | 35 | }, | ||
779 | 36 | Action { | ||
780 | 37 | enabled: listview.selectedItems.length > 0 | ||
781 | 38 | iconName: "delete" | ||
782 | 39 | text: i18n.tr("Delete") | ||
783 | 40 | visible: removable | ||
784 | 41 | |||
785 | 42 | onTriggered: { | ||
786 | 43 | removed(listview.selectedItems) | ||
787 | 44 | |||
788 | 45 | listview.closeSelection() | ||
789 | 46 | } | ||
790 | 47 | } | ||
791 | 48 | |||
792 | 49 | ] | ||
793 | 50 | backAction: Action { | ||
794 | 51 | text: i18n.tr("Cancel selection") | ||
795 | 52 | iconName: "back" | ||
796 | 53 | onTriggered: { | ||
797 | 54 | listview.clearSelection() | ||
798 | 55 | listview.state = "normal" | ||
799 | 56 | } | ||
800 | 57 | } | ||
801 | 58 | head: thisPage.head | ||
802 | 59 | name: "selection" | ||
803 | 60 | |||
804 | 61 | PropertyChanges { | ||
805 | 62 | target: thisPage.head | ||
806 | 63 | backAction: selectionState.backAction | ||
807 | 64 | actions: selectionState.actions | ||
808 | 65 | } | ||
809 | 66 | |||
810 | 67 | property ListView listview | ||
811 | 68 | property bool removable: false | ||
812 | 69 | property Page thisPage | ||
813 | 70 | |||
814 | 71 | signal removed(var selectedItems) | ||
815 | 72 | } | ||
816 | 73 | 0 | ||
817 | === modified file 'app/components/MultiSelectListView.qml' | |||
818 | --- app/components/MultiSelectListView.qml 2015-06-18 01:42:03 +0000 | |||
819 | +++ app/components/MultiSelectListView.qml 2015-06-29 10:16:30 +0000 | |||
820 | @@ -20,21 +20,24 @@ | |||
821 | 20 | import QtQuick 2.4 | 20 | import QtQuick 2.4 |
822 | 21 | import Ubuntu.Components 1.2 | 21 | import Ubuntu.Components 1.2 |
823 | 22 | 22 | ||
824 | 23 | |||
825 | 24 | WeatherListView { | 23 | WeatherListView { |
826 | 25 | property var selectedItems: [] | ||
827 | 26 | |||
828 | 27 | signal clearSelection() | 24 | signal clearSelection() |
829 | 28 | signal closeSelection() | 25 | signal closeSelection() |
830 | 29 | signal selectAll() | 26 | signal selectAll() |
833 | 30 | 27 | signal reorder(int from, int to) | |
834 | 31 | onClearSelection: selectedItems = [] | 28 | |
835 | 29 | onClearSelection: { | ||
836 | 30 | ViewItems.selectedIndices = [] | ||
837 | 31 | } | ||
838 | 32 | |||
839 | 32 | onCloseSelection: { | 33 | onCloseSelection: { |
840 | 33 | clearSelection() | 34 | clearSelection() |
842 | 34 | state = "normal" | 35 | ViewItems.selectMode = false |
843 | 36 | ViewItems.dragMode = false | ||
844 | 35 | } | 37 | } |
845 | 38 | |||
846 | 36 | onSelectAll: { | 39 | onSelectAll: { |
848 | 37 | var tmp = selectedItems | 40 | var tmp = [] |
849 | 38 | 41 | ||
850 | 39 | for (var i=0; i < model.count; i++) { | 42 | for (var i=0; i < model.count; i++) { |
851 | 40 | if (tmp.indexOf(i) === -1) { | 43 | if (tmp.indexOf(i) === -1) { |
852 | @@ -42,11 +45,27 @@ | |||
853 | 42 | } | 45 | } |
854 | 43 | } | 46 | } |
855 | 44 | 47 | ||
857 | 45 | selectedItems = tmp | 48 | ViewItems.selectedIndices = tmp |
858 | 46 | } | 49 | } |
859 | 50 | |||
860 | 47 | onVisibleChanged: { | 51 | onVisibleChanged: { |
861 | 48 | if (!visible) { | 52 | if (!visible) { |
862 | 49 | closeSelection() | 53 | closeSelection() |
863 | 50 | } | 54 | } |
864 | 51 | } | 55 | } |
865 | 56 | |||
866 | 57 | moveDisplaced: Transition { | ||
867 | 58 | UbuntuNumberAnimation { | ||
868 | 59 | property: "y" | ||
869 | 60 | } | ||
870 | 61 | } | ||
871 | 62 | |||
872 | 63 | ViewItems.onDragUpdated: { | ||
873 | 64 | if (event.status === ListItemDrag.Moving) { | ||
874 | 65 | event.accept = false | ||
875 | 66 | } else if (event.status === ListItemDrag.Dropped) { | ||
876 | 67 | model.move(event.from, event.to, 1) | ||
877 | 68 | reorder(event.from, event.to) | ||
878 | 69 | } | ||
879 | 70 | } | ||
880 | 52 | } | 71 | } |
881 | 53 | 72 | ||
882 | === modified file 'app/components/PageWithBottomEdge.qml' | |||
883 | --- app/components/PageWithBottomEdge.qml 2015-06-18 01:45:57 +0000 | |||
884 | +++ app/components/PageWithBottomEdge.qml 2015-06-29 10:16:30 +0000 | |||
885 | @@ -77,7 +77,7 @@ | |||
886 | 77 | property bool reloadBottomEdgePage: true | 77 | property bool reloadBottomEdgePage: true |
887 | 78 | 78 | ||
888 | 79 | readonly property alias bottomEdgePage: edgeLoader.item | 79 | readonly property alias bottomEdgePage: edgeLoader.item |
890 | 80 | readonly property bool isReady: ((bottomEdge.y === 0) && bottomEdgePageLoaded && edgeLoader.item.active) | 80 | readonly property bool isReady: ((bottomEdge.y === fakeHeader.height) && bottomEdgePageLoaded && edgeLoader.item.active) |
891 | 81 | readonly property bool isCollapsed: (bottomEdge.y === page.height) | 81 | readonly property bool isCollapsed: (bottomEdge.y === page.height) |
892 | 82 | readonly property bool bottomEdgePageLoaded: (edgeLoader.status == Loader.Ready) | 82 | readonly property bool bottomEdgePageLoaded: (edgeLoader.status == Loader.Ready) |
893 | 83 | 83 | ||
894 | @@ -91,7 +91,6 @@ | |||
895 | 91 | signal bottomEdgeReleased() | 91 | signal bottomEdgeReleased() |
896 | 92 | signal bottomEdgeDismissed() | 92 | signal bottomEdgeDismissed() |
897 | 93 | 93 | ||
898 | 94 | |||
899 | 95 | function showBottomEdgePage(source, properties) | 94 | function showBottomEdgePage(source, properties) |
900 | 96 | { | 95 | { |
901 | 97 | edgeLoader.setSource(source, properties) | 96 | edgeLoader.setSource(source, properties) |
902 | @@ -152,6 +151,9 @@ | |||
903 | 152 | 151 | ||
904 | 153 | property bool hidden: (activeFocus === false) || ((bottomEdge.y - units.gu(1)) < tip.y) | 152 | property bool hidden: (activeFocus === false) || ((bottomEdge.y - units.gu(1)) < tip.y) |
905 | 154 | 153 | ||
906 | 154 | // CUSTOM | ||
907 | 155 | property bool isAnimating: true | ||
908 | 156 | |||
909 | 155 | enabled: mouseArea.enabled | 157 | enabled: mouseArea.enabled |
910 | 156 | visible: page.bottomEdgeEnabled | 158 | visible: page.bottomEdgeEnabled |
911 | 157 | anchors { | 159 | anchors { |
912 | @@ -167,6 +169,10 @@ | |||
913 | 167 | UbuntuNumberAnimation { | 169 | UbuntuNumberAnimation { |
914 | 168 | duration: UbuntuAnimation.SnapDuration | 170 | duration: UbuntuAnimation.SnapDuration |
915 | 169 | } | 171 | } |
916 | 172 | // CUSTOM | ||
917 | 173 | ScriptAction { | ||
918 | 174 | script: tip.isAnimating = false | ||
919 | 175 | } | ||
920 | 170 | } | 176 | } |
921 | 171 | } | 177 | } |
922 | 172 | } | 178 | } |
923 | @@ -232,7 +238,6 @@ | |||
924 | 232 | left: parent.left | 238 | left: parent.left |
925 | 233 | right: parent.right | 239 | right: parent.right |
926 | 234 | bottom: parent.bottom | 240 | bottom: parent.bottom |
927 | 235 | |||
928 | 236 | } | 241 | } |
929 | 237 | height: bottomEdge.tipHeight | 242 | height: bottomEdge.tipHeight |
930 | 238 | z: 1 | 243 | z: 1 |
931 | @@ -265,12 +270,31 @@ | |||
932 | 265 | } | 270 | } |
933 | 266 | } | 271 | } |
934 | 267 | 272 | ||
935 | 273 | // CUSTOM fake header to make the page with bottom edge transition smoother | ||
936 | 274 | FakeHeader { | ||
937 | 275 | id: fakeHeader | ||
938 | 276 | |||
939 | 277 | anchors { | ||
940 | 278 | left: parent.left | ||
941 | 279 | right: parent.right | ||
942 | 280 | } | ||
943 | 281 | y: -fakeHeader.height + (fakeHeader.height * (page.height - bottomEdge.y)) / (page.height - fakeHeader.height) | ||
944 | 282 | z: bgVisual.z + 1 | ||
945 | 283 | |||
946 | 284 | Behavior on y { | ||
947 | 285 | UbuntuNumberAnimation { | ||
948 | 286 | duration: UbuntuAnimation.SnapDuration | ||
949 | 287 | } | ||
950 | 288 | } | ||
951 | 289 | } | ||
952 | 290 | |||
953 | 268 | Rectangle { | 291 | Rectangle { |
954 | 269 | id: bottomEdge | 292 | id: bottomEdge |
955 | 270 | objectName: "bottomEdge" | 293 | objectName: "bottomEdge" |
956 | 271 | 294 | ||
957 | 272 | readonly property int tipHeight: units.gu(3) | 295 | readonly property int tipHeight: units.gu(3) |
959 | 273 | readonly property int pageStartY: 0 | 296 | // CUSTOM value |
960 | 297 | readonly property int pageStartY: fakeHeader.height | ||
961 | 274 | 298 | ||
962 | 275 | z: 1 | 299 | z: 1 |
963 | 276 | color: Theme.palette.normal.background | 300 | color: Theme.palette.normal.background |
964 | @@ -281,6 +305,7 @@ | |||
965 | 281 | } | 305 | } |
966 | 282 | height: page.height | 306 | height: page.height |
967 | 283 | y: height | 307 | y: height |
968 | 308 | |||
969 | 284 | visible: !page.isCollapsed | 309 | visible: !page.isCollapsed |
970 | 285 | state: "collapsed" | 310 | state: "collapsed" |
971 | 286 | states: [ | 311 | states: [ |
972 | @@ -290,6 +315,11 @@ | |||
973 | 290 | target: bottomEdge | 315 | target: bottomEdge |
974 | 291 | y: bottomEdge.height | 316 | y: bottomEdge.height |
975 | 292 | } | 317 | } |
976 | 318 | // CUSTOM | ||
977 | 319 | PropertyChanges { | ||
978 | 320 | target: fakeHeader | ||
979 | 321 | y: -fakeHeader.height | ||
980 | 322 | } | ||
981 | 293 | }, | 323 | }, |
982 | 294 | State { | 324 | State { |
983 | 295 | name: "expanded" | 325 | name: "expanded" |
984 | @@ -297,6 +327,11 @@ | |||
985 | 297 | target: bottomEdge | 327 | target: bottomEdge |
986 | 298 | y: bottomEdge.pageStartY | 328 | y: bottomEdge.pageStartY |
987 | 299 | } | 329 | } |
988 | 330 | // CUSTOM | ||
989 | 331 | PropertyChanges { | ||
990 | 332 | target: fakeHeader | ||
991 | 333 | y: 0 | ||
992 | 334 | } | ||
993 | 300 | }, | 335 | }, |
994 | 301 | State { | 336 | State { |
995 | 302 | name: "floating" | 337 | name: "floating" |
996 | @@ -313,12 +348,20 @@ | |||
997 | 313 | to: "expanded" | 348 | to: "expanded" |
998 | 314 | SequentialAnimation { | 349 | SequentialAnimation { |
999 | 315 | alwaysRunToEnd: true | 350 | alwaysRunToEnd: true |
1006 | 316 | 351 | ParallelAnimation { | |
1007 | 317 | SmoothedAnimation { | 352 | SmoothedAnimation { |
1008 | 318 | target: bottomEdge | 353 | target: bottomEdge |
1009 | 319 | property: "y" | 354 | property: "y" |
1010 | 320 | duration: UbuntuAnimation.FastDuration | 355 | duration: UbuntuAnimation.FastDuration |
1011 | 321 | easing.type: Easing.Linear | 356 | easing.type: Easing.Linear |
1012 | 357 | } | ||
1013 | 358 | // CUSTOM | ||
1014 | 359 | SmoothedAnimation { | ||
1015 | 360 | target: fakeHeader | ||
1016 | 361 | property: "y" | ||
1017 | 362 | duration: UbuntuAnimation.FastDuration | ||
1018 | 363 | easing.type: Easing.Linear | ||
1019 | 364 | } | ||
1020 | 322 | } | 365 | } |
1021 | 323 | SmoothedAnimation { | 366 | SmoothedAnimation { |
1022 | 324 | target: edgeLoader | 367 | target: edgeLoader |
1023 | @@ -353,17 +396,24 @@ | |||
1024 | 353 | edgeLoader.item.active = false | 396 | edgeLoader.item.active = false |
1025 | 354 | } | 397 | } |
1026 | 355 | } | 398 | } |
1031 | 356 | SmoothedAnimation { | 399 | ParallelAnimation { |
1032 | 357 | target: bottomEdge | 400 | SmoothedAnimation { |
1033 | 358 | property: "y" | 401 | target: bottomEdge |
1034 | 359 | duration: UbuntuAnimation.SlowDuration | 402 | property: "y" |
1035 | 403 | duration: UbuntuAnimation.SlowDuration | ||
1036 | 404 | } | ||
1037 | 405 | // CUSTOM | ||
1038 | 406 | SmoothedAnimation { | ||
1039 | 407 | target: fakeHeader | ||
1040 | 408 | property: "y" | ||
1041 | 409 | duration: UbuntuAnimation.SlowDuration | ||
1042 | 410 | } | ||
1043 | 360 | } | 411 | } |
1044 | 361 | ScriptAction { | 412 | ScriptAction { |
1045 | 362 | script: { | 413 | script: { |
1046 | 363 | // destroy current bottom page | 414 | // destroy current bottom page |
1047 | 364 | if (page.reloadBottomEdgePage) { | 415 | if (page.reloadBottomEdgePage) { |
1048 | 365 | edgeLoader.active = false | 416 | edgeLoader.active = false |
1049 | 366 | // tip will receive focus on page active true | ||
1050 | 367 | } else { | 417 | } else { |
1051 | 368 | tip.forceActiveFocus() | 418 | tip.forceActiveFocus() |
1052 | 369 | } | 419 | } |
1053 | @@ -379,10 +429,10 @@ | |||
1054 | 379 | Transition { | 429 | Transition { |
1055 | 380 | from: "floating" | 430 | from: "floating" |
1056 | 381 | to: "collapsed" | 431 | to: "collapsed" |
1058 | 382 | SmoothedAnimation { | 432 | // MODIFIED |
1059 | 433 | UbuntuNumberAnimation { | ||
1060 | 383 | target: bottomEdge | 434 | target: bottomEdge |
1063 | 384 | property: "y" | 435 | property: "opacity" |
1062 | 385 | duration: UbuntuAnimation.FastDuration | ||
1064 | 386 | } | 436 | } |
1065 | 387 | } | 437 | } |
1066 | 388 | ] | 438 | ] |
1067 | 389 | 439 | ||
1068 | === removed file 'app/components/WeatherListItem.qml' | |||
1069 | --- app/components/WeatherListItem.qml 2015-06-21 15:02:05 +0000 | |||
1070 | +++ app/components/WeatherListItem.qml 1970-01-01 00:00:00 +0000 | |||
1071 | @@ -1,137 +0,0 @@ | |||
1072 | 1 | /* | ||
1073 | 2 | * Copyright (C) 2013, 2014, 2015 | ||
1074 | 3 | * Andrew Hayzen <ahayzen@gmail.com> | ||
1075 | 4 | * Nekhelesh Ramananthan <krnekhelesh@gmail.com> | ||
1076 | 5 | * Victor Thompson <victor.thompson@gmail.com> | ||
1077 | 6 | * | ||
1078 | 7 | * This program is free software; you can redistribute it and/or modify | ||
1079 | 8 | * it under the terms of the GNU General Public License as published by | ||
1080 | 9 | * the Free Software Foundation; version 3. | ||
1081 | 10 | * | ||
1082 | 11 | * This program is distributed in the hope that it will be useful, | ||
1083 | 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
1084 | 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
1085 | 14 | * GNU General Public License for more details. | ||
1086 | 15 | * | ||
1087 | 16 | * You should have received a copy of the GNU General Public License | ||
1088 | 17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
1089 | 18 | */ | ||
1090 | 19 | |||
1091 | 20 | import QtQuick 2.4 | ||
1092 | 21 | import Ubuntu.Components 1.2 | ||
1093 | 22 | |||
1094 | 23 | ListItemWithActions { | ||
1095 | 24 | id: root | ||
1096 | 25 | |||
1097 | 26 | property int listItemIndex: index | ||
1098 | 27 | property bool multiselectable: false | ||
1099 | 28 | property int previousListItemIndex: -1 | ||
1100 | 29 | property bool reorderable: false | ||
1101 | 30 | |||
1102 | 31 | signal reorder(int from, int to) | ||
1103 | 32 | |||
1104 | 33 | onItemPressAndHold: { | ||
1105 | 34 | if (multiselectable) { | ||
1106 | 35 | selectionMode = true | ||
1107 | 36 | } | ||
1108 | 37 | } | ||
1109 | 38 | |||
1110 | 39 | onListItemIndexChanged: { | ||
1111 | 40 | var i = parent.parent.selectedItems.lastIndexOf(previousListItemIndex) | ||
1112 | 41 | |||
1113 | 42 | if (i !== -1) { | ||
1114 | 43 | parent.parent.selectedItems[i] = listItemIndex | ||
1115 | 44 | } | ||
1116 | 45 | |||
1117 | 46 | previousListItemIndex = listItemIndex | ||
1118 | 47 | } | ||
1119 | 48 | |||
1120 | 49 | onSelectedChanged: { | ||
1121 | 50 | if (selectionMode) { | ||
1122 | 51 | var tmp = parent.parent.selectedItems | ||
1123 | 52 | |||
1124 | 53 | if (selected) { | ||
1125 | 54 | if (parent.parent.selectedItems.indexOf(listItemIndex) === -1) { | ||
1126 | 55 | tmp.push(listItemIndex) | ||
1127 | 56 | parent.parent.selectedItems = tmp | ||
1128 | 57 | } | ||
1129 | 58 | } else { | ||
1130 | 59 | tmp.splice(parent.parent.selectedItems.indexOf(listItemIndex), 1) | ||
1131 | 60 | parent.parent.selectedItems = tmp | ||
1132 | 61 | } | ||
1133 | 62 | } | ||
1134 | 63 | } | ||
1135 | 64 | |||
1136 | 65 | onSelectionModeChanged: { | ||
1137 | 66 | if (reorderable && selectionMode) { | ||
1138 | 67 | resetSwipe() | ||
1139 | 68 | } | ||
1140 | 69 | |||
1141 | 70 | for (var j=0; j < _main.children.length; j++) { | ||
1142 | 71 | if (_main.children[j] !== actionReorderLoader) { | ||
1143 | 72 | _main.children[j].anchors.rightMargin = reorderable && selectionMode ? actionReorderLoader.width + units.gu(2) : 0 | ||
1144 | 73 | } | ||
1145 | 74 | } | ||
1146 | 75 | |||
1147 | 76 | parent.parent.state = selectionMode ? "multiselectable" : "normal" | ||
1148 | 77 | |||
1149 | 78 | if (!selectionMode) { | ||
1150 | 79 | selected = false | ||
1151 | 80 | } | ||
1152 | 81 | } | ||
1153 | 82 | |||
1154 | 83 | /* Highlight the listitem on press */ | ||
1155 | 84 | Rectangle { | ||
1156 | 85 | id: listItemBrighten | ||
1157 | 86 | color: root.pressed ? UbuntuColors.coolGrey : "transparent" | ||
1158 | 87 | opacity: 0.1 | ||
1159 | 88 | height: root.height | ||
1160 | 89 | x: root.x - parent.x // -parent.x due to selectionIcon in ListItemWithActions | ||
1161 | 90 | width: root.width | ||
1162 | 91 | } | ||
1163 | 92 | |||
1164 | 93 | /* Reorder Component */ | ||
1165 | 94 | Loader { | ||
1166 | 95 | id: actionReorderLoader | ||
1167 | 96 | active: reorderable && selectionMode && root.parent.parent.selectedItems.length === 0 | ||
1168 | 97 | anchors { | ||
1169 | 98 | bottom: parent.bottom | ||
1170 | 99 | right: parent.right | ||
1171 | 100 | rightMargin: units.gu(1) | ||
1172 | 101 | top: parent.top | ||
1173 | 102 | } | ||
1174 | 103 | asynchronous: true | ||
1175 | 104 | source: "ListItemReorderComponent.qml" | ||
1176 | 105 | } | ||
1177 | 106 | |||
1178 | 107 | Item { | ||
1179 | 108 | Connections { // Only allow one ListItem to be swiping at any time | ||
1180 | 109 | target: weatherApp | ||
1181 | 110 | onListItemSwiping: { | ||
1182 | 111 | if (i !== index) { | ||
1183 | 112 | root.resetSwipe(); | ||
1184 | 113 | } | ||
1185 | 114 | } | ||
1186 | 115 | } | ||
1187 | 116 | |||
1188 | 117 | Connections { // Connections from signals in the ListView | ||
1189 | 118 | target: root.parent.parent | ||
1190 | 119 | onClearSelection: selected = false | ||
1191 | 120 | onFlickingChanged: { | ||
1192 | 121 | if (root.parent.parent.flicking) { | ||
1193 | 122 | root.resetSwipe() | ||
1194 | 123 | } | ||
1195 | 124 | } | ||
1196 | 125 | onSelectAll: selected = true | ||
1197 | 126 | onStateChanged: selectionMode = root.parent.parent.state === "multiselectable" | ||
1198 | 127 | } | ||
1199 | 128 | } | ||
1200 | 129 | |||
1201 | 130 | Component.onCompleted: { // reload settings as delegates are destroyed | ||
1202 | 131 | if (parent.parent.selectedItems.indexOf(index) !== -1) { | ||
1203 | 132 | selected = true | ||
1204 | 133 | } | ||
1205 | 134 | |||
1206 | 135 | selectionMode = root.parent.parent.state === "multiselectable" | ||
1207 | 136 | } | ||
1208 | 137 | } | ||
1209 | 138 | 0 | ||
1210 | === modified file 'app/components/WeatherListView.qml' | |||
1211 | --- app/components/WeatherListView.qml 2015-06-18 01:42:03 +0000 | |||
1212 | +++ app/components/WeatherListView.qml 2015-06-29 10:16:30 +0000 | |||
1213 | @@ -20,8 +20,7 @@ | |||
1214 | 20 | import QtQuick 2.4 | 20 | import QtQuick 2.4 |
1215 | 21 | import Ubuntu.Components 1.2 | 21 | import Ubuntu.Components 1.2 |
1216 | 22 | 22 | ||
1219 | 23 | 23 | UbuntuListView { | |
1218 | 24 | ListView { | ||
1220 | 25 | Component.onCompleted: { | 24 | Component.onCompleted: { |
1221 | 26 | // FIXME: workaround for qtubuntu not returning values depending on the grid unit definition | 25 | // FIXME: workaround for qtubuntu not returning values depending on the grid unit definition |
1222 | 27 | // for Flickable.maximumFlickVelocity and Flickable.flickDeceleration | 26 | // for Flickable.maximumFlickVelocity and Flickable.flickDeceleration |
1223 | 28 | 27 | ||
1224 | === modified file 'app/ui/LocationsPage.qml' | |||
1225 | --- app/ui/LocationsPage.qml 2015-06-28 19:04:43 +0000 | |||
1226 | +++ app/ui/LocationsPage.qml 2015-06-29 10:16:30 +0000 | |||
1227 | @@ -18,39 +18,58 @@ | |||
1228 | 18 | 18 | ||
1229 | 19 | import QtQuick 2.4 | 19 | import QtQuick 2.4 |
1230 | 20 | import Ubuntu.Components 1.2 | 20 | import Ubuntu.Components 1.2 |
1232 | 21 | import Ubuntu.Components.ListItems 0.1 as ListItem | 21 | import Ubuntu.Components.ListItems 1.0 as ListItems |
1233 | 22 | import "../components" | 22 | import "../components" |
1234 | 23 | import "../components/ListItemActions" | ||
1235 | 24 | |||
1236 | 25 | 23 | ||
1237 | 26 | Page { | 24 | Page { |
1238 | 27 | id: locationsPage | 25 | id: locationsPage |
1239 | 26 | |||
1240 | 28 | // Set to null otherwise the first delegate appears +header.height down the page | 27 | // Set to null otherwise the first delegate appears +header.height down the page |
1241 | 29 | flickable: null | 28 | flickable: null |
1242 | 30 | title: i18n.tr("Locations") | 29 | title: i18n.tr("Locations") |
1243 | 31 | 30 | ||
1245 | 32 | state: locationsListView.state === "multiselectable" ? "selection" : "default" | 31 | state: "default" |
1246 | 33 | states: [ | 32 | states: [ |
1247 | 34 | PageHeadState { | 33 | PageHeadState { |
1248 | 35 | id: defaultState | ||
1249 | 36 | name: "default" | 34 | name: "default" |
1250 | 35 | head: locationsPage.head | ||
1251 | 37 | actions: [ | 36 | actions: [ |
1252 | 38 | Action { | 37 | Action { |
1253 | 39 | iconName: "add" | 38 | iconName: "add" |
1255 | 40 | onTriggered: mainPageStack.push(Qt.resolvedUrl("AddLocationPage.qml")) | 39 | onTriggered: { |
1256 | 40 | mainPageStack.push(Qt.resolvedUrl("AddLocationPage.qml")) | ||
1257 | 41 | } | ||
1258 | 41 | } | 42 | } |
1259 | 42 | ] | 43 | ] |
1263 | 43 | PropertyChanges { | 44 | backAction: Action { |
1264 | 44 | target: locationsPage.head | 45 | iconName: "down" |
1265 | 45 | actions: defaultState.actions | 46 | onTriggered: { |
1266 | 47 | pageStack.pop() | ||
1267 | 48 | } | ||
1268 | 46 | } | 49 | } |
1269 | 47 | }, | 50 | }, |
1270 | 48 | MultiSelectHeadState { | ||
1271 | 49 | listview: locationsListView | ||
1272 | 50 | removable: true | ||
1273 | 51 | thisPage: locationsPage | ||
1274 | 52 | 51 | ||
1276 | 53 | onRemoved: storage.removeMultiLocations(selectedItems.slice()) | 52 | PageHeadState { |
1277 | 53 | name: "selection" | ||
1278 | 54 | head: locationsPage.head | ||
1279 | 55 | when: locationsListView.ViewItems.selectMode | ||
1280 | 56 | backAction: Action { | ||
1281 | 57 | iconName: "back" | ||
1282 | 58 | onTriggered: { | ||
1283 | 59 | locationsListView.closeSelection() | ||
1284 | 60 | locationsPage.state = "default" | ||
1285 | 61 | } | ||
1286 | 62 | } | ||
1287 | 63 | actions: [ | ||
1288 | 64 | Action { | ||
1289 | 65 | iconName: "delete" | ||
1290 | 66 | enabled: locationsListView.ViewItems.selectedIndices.length !== 0 | ||
1291 | 67 | onTriggered: { | ||
1292 | 68 | storage.removeMultiLocations(locationsListView.ViewItems.selectedIndices) | ||
1293 | 69 | locationsListView.clearSelection() | ||
1294 | 70 | } | ||
1295 | 71 | } | ||
1296 | 72 | ] | ||
1297 | 54 | } | 73 | } |
1298 | 55 | ] | 74 | ] |
1299 | 56 | 75 | ||
1300 | @@ -58,27 +77,29 @@ | |||
1301 | 58 | id: currentLocationModel | 77 | id: currentLocationModel |
1302 | 59 | } | 78 | } |
1303 | 60 | 79 | ||
1304 | 80 | ListModel { | ||
1305 | 81 | id: locationsModel | ||
1306 | 82 | } | ||
1307 | 83 | |||
1308 | 61 | MultiSelectListView { | 84 | MultiSelectListView { |
1309 | 62 | id: locationsListView | 85 | id: locationsListView |
1316 | 63 | anchors { | 86 | |
1317 | 64 | fill: parent | 87 | clip: true |
1318 | 65 | } | 88 | anchors.fill: parent |
1319 | 66 | model: ListModel { | 89 | model: locationsModel |
1320 | 67 | id: locationsModel | 90 | |
1315 | 68 | } | ||
1321 | 69 | header: MultiSelectListView { | 91 | header: MultiSelectListView { |
1322 | 70 | id: currentLocationListView | 92 | id: currentLocationListView |
1327 | 71 | anchors { | 93 | |
1328 | 72 | left: parent.left | 94 | width: parent.width |
1325 | 73 | right: parent.right | ||
1326 | 74 | } | ||
1329 | 75 | height: settings.addedCurrentLocation ? units.gu(8) : units.gu(0) | 95 | height: settings.addedCurrentLocation ? units.gu(8) : units.gu(0) |
1330 | 76 | interactive: false | 96 | interactive: false |
1331 | 77 | model: currentLocationModel | 97 | model: currentLocationModel |
1333 | 78 | delegate: WeatherListItem { | 98 | |
1334 | 99 | delegate: ListItem { | ||
1335 | 79 | id: currentLocationListItem | 100 | id: currentLocationListItem |
1336 | 80 | 101 | ||
1338 | 81 | onItemClicked: { | 102 | onClicked: { |
1339 | 82 | settings.current = index; | 103 | settings.current = index; |
1340 | 83 | pageStack.pop() | 104 | pageStack.pop() |
1341 | 84 | } | 105 | } |
1342 | @@ -147,32 +168,44 @@ | |||
1343 | 147 | horizontalAlignment: Text.AlignRight | 168 | horizontalAlignment: Text.AlignRight |
1344 | 148 | text: temp + settings.tempScale | 169 | text: temp + settings.tempScale |
1345 | 149 | } | 170 | } |
1346 | 171 | |||
1347 | 172 | ListItems.ThinDivider { anchors.bottom: parent.bottom } | ||
1348 | 150 | } | 173 | } |
1349 | 151 | } | 174 | } |
1350 | 152 | 175 | ||
1352 | 153 | delegate: WeatherListItem { | 176 | // Added a thindivider to the listview since by default the last listitem does not show |
1353 | 177 | // a thindivider which does not follow design specs. | ||
1354 | 178 | footer: ListItems.ThinDivider { | ||
1355 | 179 | visible: locationsModel.count !== 0 | ||
1356 | 180 | } | ||
1357 | 181 | |||
1358 | 182 | onReorder: { | ||
1359 | 183 | console.debug("Move: ", from, to); | ||
1360 | 184 | storage.moveLocation(from, to); | ||
1361 | 185 | } | ||
1362 | 186 | |||
1363 | 187 | delegate: ListItem { | ||
1364 | 154 | id: locationsListItem | 188 | id: locationsListItem |
1384 | 155 | leftSideAction: Remove { | 189 | |
1385 | 156 | onTriggered: storage.removeLocation(index) | 190 | leadingActions: ListItemActions { |
1386 | 157 | } | 191 | actions: [ |
1387 | 158 | multiselectable: true | 192 | Action { |
1388 | 159 | reorderable: true | 193 | iconName: 'delete' |
1389 | 160 | 194 | onTriggered: storage.removeLocation(index) | |
1390 | 161 | onItemClicked: { | 195 | } |
1391 | 162 | settings.current = index + 1; | 196 | ] |
1392 | 163 | pageStack.pop() | 197 | } |
1393 | 164 | } | 198 | |
1394 | 165 | onReorder: { | 199 | onPressAndHold: { |
1395 | 166 | console.debug("Move: ", from, to); | 200 | ListView.view.ViewItems.selectMode = !ListView.view.ViewItems.selectMode |
1396 | 167 | 201 | ListView.view.ViewItems.dragMode = !ListView.view.ViewItems.dragMode | |
1397 | 168 | storage.moveLocation(from, to); | 202 | } |
1398 | 169 | } | 203 | |
1399 | 170 | 204 | onClicked: { | |
1400 | 171 | ListItem.ThinDivider { | 205 | if (!selectMode) { |
1401 | 172 | anchors { | 206 | settings.current = index + 1; |
1402 | 173 | top: parent.top | 207 | pageStack.pop() |
1403 | 174 | } | 208 | } |
1404 | 175 | visible: index == 0 | ||
1405 | 176 | } | 209 | } |
1406 | 177 | 210 | ||
1407 | 178 | Item { | 211 | Item { |
1408 | @@ -192,6 +225,7 @@ | |||
1409 | 192 | 225 | ||
1410 | 193 | Label { | 226 | Label { |
1411 | 194 | id: locationName | 227 | id: locationName |
1412 | 228 | width: parent.width | ||
1413 | 195 | elide: Text.ElideRight | 229 | elide: Text.ElideRight |
1414 | 196 | fontSize: "medium" | 230 | fontSize: "medium" |
1415 | 197 | text: name | 231 | text: name |
1416 | @@ -202,6 +236,7 @@ | |||
1417 | 202 | elide: Text.ElideRight | 236 | elide: Text.ElideRight |
1418 | 203 | fontSize: "small" | 237 | fontSize: "small" |
1419 | 204 | font.weight: Font.Light | 238 | font.weight: Font.Light |
1420 | 239 | width: parent.width | ||
1421 | 205 | text: adminName1 == name ? countryName : adminName1 | 240 | text: adminName1 == name ? countryName : adminName1 |
1422 | 206 | } | 241 | } |
1423 | 207 | } | 242 | } |
1424 | @@ -236,12 +271,6 @@ | |||
1425 | 236 | visible: locationsPage.state === "default" | 271 | visible: locationsPage.state === "default" |
1426 | 237 | } | 272 | } |
1427 | 238 | } | 273 | } |
1428 | 239 | |||
1429 | 240 | ListItem.ThinDivider { | ||
1430 | 241 | anchors { | ||
1431 | 242 | bottom: parent.bottom | ||
1432 | 243 | } | ||
1433 | 244 | } | ||
1434 | 245 | } | 274 | } |
1435 | 246 | } | 275 | } |
1436 | 247 | 276 | ||
1437 | 248 | 277 | ||
1438 | === modified file 'po/com.ubuntu.weather.pot' | |||
1439 | --- po/com.ubuntu.weather.pot 2015-06-29 00:20:51 +0000 | |||
1440 | +++ po/com.ubuntu.weather.pot 2015-06-29 10:16:30 +0000 | |||
1441 | @@ -8,7 +8,7 @@ | |||
1442 | 8 | msgstr "" | 8 | msgstr "" |
1443 | 9 | "Project-Id-Version: ubuntu-weather-app\n" | 9 | "Project-Id-Version: ubuntu-weather-app\n" |
1444 | 10 | "Report-Msgid-Bugs-To: \n" | 10 | "Report-Msgid-Bugs-To: \n" |
1446 | 11 | "POT-Creation-Date: 2015-06-28 19:17-0500\n" | 11 | "POT-Creation-Date: 2015-06-29 10:12+0000\n" |
1447 | 12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" | 12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" |
1448 | 13 | "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" | 13 | "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" |
1449 | 14 | "Language-Team: LANGUAGE <LL@li.org>\n" | 14 | "Language-Team: LANGUAGE <LL@li.org>\n" |
1450 | @@ -50,22 +50,6 @@ | |||
1451 | 50 | msgid "Today" | 50 | msgid "Today" |
1452 | 51 | msgstr "" | 51 | msgstr "" |
1453 | 52 | 52 | ||
1454 | 53 | #: ../app/components/ListItemActions/Remove.qml:26 | ||
1455 | 54 | msgid "Remove" | ||
1456 | 55 | msgstr "" | ||
1457 | 56 | |||
1458 | 57 | #: ../app/components/MultiSelectHeadState.qml:27 | ||
1459 | 58 | msgid "Select All" | ||
1460 | 59 | msgstr "" | ||
1461 | 60 | |||
1462 | 61 | #: ../app/components/MultiSelectHeadState.qml:39 | ||
1463 | 62 | msgid "Delete" | ||
1464 | 63 | msgstr "" | ||
1465 | 64 | |||
1466 | 65 | #: ../app/components/MultiSelectHeadState.qml:51 | ||
1467 | 66 | msgid "Cancel selection" | ||
1468 | 67 | msgstr "" | ||
1469 | 68 | |||
1470 | 69 | #: ../app/ubuntu-weather-app.qml:168 | 53 | #: ../app/ubuntu-weather-app.qml:168 |
1471 | 70 | msgid "Searching for current location..." | 54 | msgid "Searching for current location..." |
1472 | 71 | msgstr "" | 55 | msgstr "" |
1473 | @@ -106,11 +90,11 @@ | |||
1474 | 106 | msgid "OK" | 90 | msgid "OK" |
1475 | 107 | msgstr "" | 91 | msgstr "" |
1476 | 108 | 92 | ||
1478 | 109 | #: ../app/ui/HomePage.qml:31 ../app/ui/LocationsPage.qml:30 | 93 | #: ../app/ui/HomePage.qml:31 ../app/ui/LocationsPage.qml:29 |
1479 | 110 | msgid "Locations" | 94 | msgid "Locations" |
1480 | 111 | msgstr "" | 95 | msgstr "" |
1481 | 112 | 96 | ||
1483 | 113 | #: ../app/ui/LocationsPage.qml:104 | 97 | #: ../app/ui/LocationsPage.qml:125 |
1484 | 114 | msgid "Current Location" | 98 | msgid "Current Location" |
1485 | 115 | msgstr "" | 99 | msgstr "" |
1486 | 116 | 100 | ||
1487 | @@ -118,15 +102,15 @@ | |||
1488 | 118 | msgid "Settings" | 102 | msgid "Settings" |
1489 | 119 | msgstr "" | 103 | msgstr "" |
1490 | 120 | 104 | ||
1492 | 121 | #: ../app/ui/SettingsPage.qml:38 ../app/ui/settings/UnitsPage.qml:24 | 105 | #: ../app/ui/SettingsPage.qml:32 ../app/ui/settings/UnitsPage.qml:24 |
1493 | 122 | msgid "Units" | 106 | msgid "Units" |
1494 | 123 | msgstr "" | 107 | msgstr "" |
1495 | 124 | 108 | ||
1497 | 125 | #: ../app/ui/SettingsPage.qml:43 ../app/ui/settings/DataProviderPage.qml:24 | 109 | #: ../app/ui/SettingsPage.qml:37 ../app/ui/settings/DataProviderPage.qml:24 |
1498 | 126 | msgid "Data Provider" | 110 | msgid "Data Provider" |
1499 | 127 | msgstr "" | 111 | msgstr "" |
1500 | 128 | 112 | ||
1502 | 129 | #: ../app/ui/SettingsPage.qml:48 ../app/ui/settings/RefreshIntervalPage.qml:24 | 113 | #: ../app/ui/SettingsPage.qml:42 ../app/ui/settings/RefreshIntervalPage.qml:24 |
1503 | 130 | msgid "Refresh Interval" | 114 | msgid "Refresh Interval" |
1504 | 131 | msgstr "" | 115 | msgstr "" |
1505 | 132 | 116 | ||
1506 | 133 | 117 | ||
1507 | === modified file 'ubuntu-weather-app.desktop.in.in' | |||
1508 | --- ubuntu-weather-app.desktop.in.in 2015-01-23 23:15:52 +0000 | |||
1509 | +++ ubuntu-weather-app.desktop.in.in 2015-06-29 10:16:30 +0000 | |||
1510 | @@ -10,3 +10,4 @@ | |||
1511 | 10 | X-Ubuntu-Touch=true | 10 | X-Ubuntu-Touch=true |
1512 | 11 | X-Ubuntu-Default-Department-ID=accessories | 11 | X-Ubuntu-Default-Department-ID=accessories |
1513 | 12 | X-Ubuntu-Splash-Color=#F5F5F5 | 12 | X-Ubuntu-Splash-Color=#F5F5F5 |
1514 | 13 | X-Ubuntu-Supported-Orientations=portrait |
PASSED: Continuous integration, rev:65 91.189. 93.70:8080/ job/ubuntu- weather- app-reboot- ci/121/ 91.189. 93.70:8080/ job/ubuntu- weather- app-reboot- utopic- amd64-ci/ 91 91.189. 93.70:8080/ job/ubuntu- weather- app-reboot- vivid-amd64- ci/121
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild: 91.189. 93.70:8080/ job/ubuntu- weather- app-reboot- ci/121/ rebuild
http://