Merge lp:~nik90/ubuntu-clock-app/add-multiselection-mode into lp:ubuntu-clock-app
- add-multiselection-mode
- Merge into trunk
Status: | Merged | ||||
---|---|---|---|---|---|
Merged at revision: | 48 | ||||
Proposed branch: | lp:~nik90/ubuntu-clock-app/add-multiselection-mode | ||||
Merge into: | lp:ubuntu-clock-app | ||||
Diff against target: |
800 lines (+479/-215) 8 files modified
app/alarm/AlarmDelegate.qml (+57/-66) app/alarm/AlarmList.qml (+111/-134) app/alarm/AlarmPage.qml (+71/-12) app/upstreamcomponents/ListItemWithActions.qml (+1/-0) app/upstreamcomponents/MultipleSelectionListView.qml (+199/-0) app/upstreamcomponents/MultipleSelectionVisualModel.qml (+31/-0) app/upstreamcomponents/README.components (+7/-0) tests/autopilot/ubuntu_clock_app/emulators.py (+2/-3) |
||||
To merge this branch: | bzr merge lp:~nik90/ubuntu-clock-app/add-multiselection-mode | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Ubuntu Phone Apps Jenkins Bot | continuous-integration | Needs Fixing | |
Alan Pope πΊπ§π± π¦ (community) | Approve | ||
Review via email: mp+230140@code.launchpad.net |
Commit message
This MP adds multiselection mode for the alarm list.
Description of the change
This MP adds multiselection mode for the alarm list.
To Test:
1. Proceed to alarm page
2. Add a couple of alarms
3. Long press on an alarm to activate selection mode. See if you can delete a group of alarm in one go.
4. That's about it :)
Note: MultipleSelecti
Renato Araujo Oliveira Filho (renatofilho) wrote : | # |
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:48
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:49
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:51
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:52
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:53
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
Alan Pope πΊπ§π± π¦ (popey) wrote : | # |
Works great on device, thanks!
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:54
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Autolanding.
More details in the following jenkins job:
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Preview Diff
1 | === modified file 'app/alarm/AlarmDelegate.qml' |
2 | --- app/alarm/AlarmDelegate.qml 2014-08-07 13:17:02 +0000 |
3 | +++ app/alarm/AlarmDelegate.qml 2014-08-11 15:43:15 +0000 |
4 | @@ -23,82 +23,73 @@ |
5 | ListItemWithActions { |
6 | id: root |
7 | |
8 | + width: parent ? parent.width : 0 |
9 | height: units.gu(6) |
10 | - width: parent ? parent.width : 0 |
11 | color: "Transparent" |
12 | - |
13 | - Item { |
14 | - id: delegate |
15 | - |
16 | - anchors.fill: parent |
17 | + selectedColor: "Transparent" |
18 | + |
19 | + Label { |
20 | + id: alarmTime |
21 | + objectName: "listAlarmTime" + index |
22 | + |
23 | + anchors { |
24 | + top: alarmDetailsColumn.top |
25 | + left: parent.left |
26 | + } |
27 | + |
28 | + fontSize: "medium" |
29 | + text: Qt.formatTime(date) |
30 | + } |
31 | + |
32 | + Column { |
33 | + id: alarmDetailsColumn |
34 | + |
35 | + anchors { |
36 | + left: alarmTime.right |
37 | + right: alarmStatus.left |
38 | + verticalCenter: parent.verticalCenter |
39 | + margins: units.gu(1) |
40 | + } |
41 | |
42 | Label { |
43 | - id: alarmTime |
44 | - objectName: "listAlarmTime" + index |
45 | - |
46 | - anchors { |
47 | - top: alarmDetailsColumn.top |
48 | - left: parent.left |
49 | - } |
50 | - |
51 | + id: alarmLabel |
52 | + objectName: "listAlarmLabel" + index |
53 | + |
54 | + text: message |
55 | fontSize: "medium" |
56 | - text: Qt.formatTime(date) |
57 | - } |
58 | - |
59 | - Column { |
60 | - id: alarmDetailsColumn |
61 | - |
62 | - anchors { |
63 | - left: alarmTime.right |
64 | - right: alarmStatus.left |
65 | - verticalCenter: parent.verticalCenter |
66 | - margins: units.gu(1) |
67 | - } |
68 | - |
69 | - Label { |
70 | - id: alarmLabel |
71 | - objectName: "listAlarmLabel" + index |
72 | - |
73 | - text: message |
74 | - fontSize: "medium" |
75 | - elide: Text.ElideRight |
76 | - color: UbuntuColors.midAubergine |
77 | - } |
78 | - |
79 | - Label { |
80 | - id: alarmSubtitle |
81 | - objectName: "listAlarmSubtitle" + index |
82 | - |
83 | - fontSize: "xx-small" |
84 | - width: parent.width |
85 | - wrapMode: Text.WrapAtWordBoundaryOrAnywhere |
86 | - text: alarmUtils.format_day_string(daysOfWeek) |
87 | - } |
88 | - } |
89 | - |
90 | - Switch { |
91 | - id: alarmStatus |
92 | - objectName: "listAlarmStatus" + index |
93 | - |
94 | - anchors { |
95 | - right: parent.right |
96 | - verticalCenter: parent.verticalCenter |
97 | - } |
98 | - |
99 | - checked: enabled |
100 | - |
101 | - /* |
102 | + width: parent.width |
103 | + elide: Text.ElideRight |
104 | + color: UbuntuColors.midAubergine |
105 | + } |
106 | + |
107 | + Label { |
108 | + id: alarmSubtitle |
109 | + objectName: "listAlarmSubtitle" + index |
110 | + |
111 | + fontSize: "xx-small" |
112 | + width: parent.width |
113 | + wrapMode: Text.WrapAtWordBoundaryOrAnywhere |
114 | + text: alarmUtils.format_day_string(daysOfWeek) |
115 | + } |
116 | + } |
117 | + |
118 | + Switch { |
119 | + id: alarmStatus |
120 | + objectName: "listAlarmStatus" + index |
121 | + |
122 | + anchors { |
123 | + right: parent.right |
124 | + verticalCenter: parent.verticalCenter |
125 | + } |
126 | + |
127 | + checked: enabled |
128 | + |
129 | + /* |
130 | #TODO: Add the ability to enable/disable alarms using the |
131 | switch. At the moment it only shows the alarm status. |
132 | This was postponed since a similar implementation in the |
133 | old clock app caused it to loop. So if user clicks on the |
134 | switch, it disables and then re-enables the alarm again. |
135 | */ |
136 | - } |
137 | - } |
138 | - |
139 | - onItemClicked: { |
140 | - mainStack.push(Qt.resolvedUrl("EditAlarmPage.qml"), |
141 | - {"isNewAlarm": false, "alarmIndex": index}) |
142 | } |
143 | } |
144 | |
145 | === modified file 'app/alarm/AlarmList.qml' |
146 | --- app/alarm/AlarmList.qml 2014-08-09 14:38:15 +0000 |
147 | +++ app/alarm/AlarmList.qml 2014-08-11 15:43:15 +0000 |
148 | @@ -20,150 +20,127 @@ |
149 | import Ubuntu.Components 1.1 |
150 | import Ubuntu.Components.ListItems 1.0 as ListItem |
151 | import "../components" |
152 | +import "../upstreamcomponents" |
153 | import "../components/Utils.js" as Utils |
154 | |
155 | -Flickable { |
156 | - id: alarmListFlickable |
157 | - objectName: "alarmListFlickable" |
158 | - |
159 | - // Property to set the model of the saved alarm list |
160 | - property var model |
161 | - |
162 | - /* |
163 | - Property to set the minimum drag distance before activating the add |
164 | - alarm signal |
165 | - */ |
166 | - property int _minThreshold: addAlarmButton.maxThreshold + units.gu(2) |
167 | +MultipleSelectionListView { |
168 | + id: alarmListView |
169 | + objectName: "alarmListView" |
170 | + |
171 | + property var _currentSwipedItem: null |
172 | + |
173 | + function _updateSwipeState(item) |
174 | + { |
175 | + if (item.swipping) { |
176 | + return |
177 | + } |
178 | + |
179 | + if (item.swipeState !== "Normal") { |
180 | + if (alarmListView._currentSwipedItem !== item) { |
181 | + if (alarmListView._currentSwipedItem) { |
182 | + alarmListView._currentSwipedItem.resetSwipe() |
183 | + } |
184 | + alarmListView._currentSwipedItem = item |
185 | + } |
186 | + } else if (item.swipeState !== "Normal" |
187 | + && alarmListView._currentSwipedItem === item) { |
188 | + alarmListView._currentSwipedItem = null |
189 | + } |
190 | + } |
191 | |
192 | clip: true |
193 | anchors.fill: parent |
194 | - contentHeight: alarmList.height |
195 | |
196 | AlarmUtils { |
197 | id: alarmUtils |
198 | } |
199 | |
200 | - PullToAdd { |
201 | - id: addAlarmButton |
202 | - objectName: "addAlarmButton" |
203 | - |
204 | - anchors { |
205 | - top: parent.top |
206 | - topMargin: -labelHeight - units.gu(3) |
207 | - horizontalCenter: parent.horizontalCenter |
208 | - } |
209 | - |
210 | - leftLabel: i18n.tr("Add") |
211 | - rightLabel: i18n.tr("Alarm") |
212 | - } |
213 | - |
214 | - Column { |
215 | - id: alarmList |
216 | - objectName: 'alarmList' |
217 | - anchors.fill: parent |
218 | - |
219 | - Repeater { |
220 | - id: alarmRepeater |
221 | - objectName: "alarmListRepeater" |
222 | - |
223 | - property var _currentSwipedItem: null |
224 | - |
225 | - function _updateSwipeState(item) |
226 | - { |
227 | - if (item.swipping) { |
228 | - return |
229 | - } |
230 | - |
231 | - if (item.swipeState !== "Normal") { |
232 | - if (alarmRepeater._currentSwipedItem !== item) { |
233 | - if (alarmRepeater._currentSwipedItem) { |
234 | - alarmRepeater._currentSwipedItem.resetSwipe() |
235 | - } |
236 | - alarmRepeater._currentSwipedItem = item |
237 | - } |
238 | - } else if (item.swipeState !== "Normal" |
239 | - && alarmRepeater._currentSwipedItem === item) { |
240 | - alarmRepeater._currentSwipedItem = null |
241 | - } |
242 | - } |
243 | - |
244 | - model: alarmListFlickable.model |
245 | - |
246 | - delegate: AlarmDelegate { |
247 | - id: alarmDelegate |
248 | - objectName: "alarm" + index |
249 | - |
250 | - property var removalAnimation |
251 | - |
252 | - function remove() { |
253 | - removalAnimation.start() |
254 | - } |
255 | - |
256 | - onSwippingChanged: { |
257 | - alarmRepeater._updateSwipeState(alarmDelegate) |
258 | - } |
259 | - |
260 | - onSwipeStateChanged: { |
261 | - alarmRepeater._updateSwipeState(alarmDelegate) |
262 | - } |
263 | - |
264 | - leftSideAction: Action { |
265 | - iconName: "delete" |
266 | - text: i18n.tr("Delete") |
267 | - onTriggered: { |
268 | - alarmDelegate.remove() |
269 | - } |
270 | - } |
271 | - |
272 | - ListView.onRemove: ScriptAction { |
273 | - script: { |
274 | - if (alarmRepeater._currentSwipedItem |
275 | - === alarmDelegate) { |
276 | - alarmRepeater._currentSwipedItem = null |
277 | - } |
278 | - } |
279 | - } |
280 | - |
281 | - removalAnimation: SequentialAnimation { |
282 | - alwaysRunToEnd: true |
283 | - |
284 | - PropertyAction { |
285 | - target: alarmDelegate |
286 | - property: "ListView.delayRemove" |
287 | - value: true |
288 | - } |
289 | - |
290 | - UbuntuNumberAnimation { |
291 | - target: alarmDelegate |
292 | - property: "height" |
293 | - to: 0 |
294 | - } |
295 | - |
296 | - PropertyAction { |
297 | - target: alarmDelegate |
298 | - property: "ListView.delayRemove" |
299 | - value: false |
300 | - } |
301 | - |
302 | - ScriptAction { |
303 | - script: { |
304 | - var alarm = alarmModel.get(index) |
305 | - alarm.cancel() |
306 | - } |
307 | - } |
308 | - } |
309 | - } |
310 | - } |
311 | - } |
312 | - |
313 | - onDragEnded: { |
314 | - if(contentY < _minThreshold) |
315 | - mainStack.push(Qt.resolvedUrl("EditAlarmPage.qml")) |
316 | - } |
317 | - |
318 | - onContentYChanged: { |
319 | - if(contentY < 0 && atYBeginning) { |
320 | - addAlarmButton.dragPosition = contentY.toFixed(0) |
321 | + listDelegate: AlarmDelegate { |
322 | + id: alarmDelegate |
323 | + objectName: "alarm" + index |
324 | + |
325 | + property var removalAnimation |
326 | + |
327 | + function remove() { |
328 | + removalAnimation.start() |
329 | + } |
330 | + |
331 | + selectionMode: alarmListView.isInSelectionMode |
332 | + selected: alarmListView.isSelected(alarmDelegate) |
333 | + |
334 | + onSwippingChanged: { |
335 | + _updateSwipeState(alarmDelegate) |
336 | + } |
337 | + |
338 | + onSwipeStateChanged: { |
339 | + _updateSwipeState(alarmDelegate) |
340 | + } |
341 | + |
342 | + leftSideAction: Action { |
343 | + iconName: "delete" |
344 | + text: i18n.tr("Delete") |
345 | + onTriggered: { |
346 | + alarmDelegate.remove() |
347 | + } |
348 | + } |
349 | + |
350 | + ListView.onRemove: ScriptAction { |
351 | + script: { |
352 | + if (_currentSwipedItem |
353 | + === alarmDelegate) { |
354 | + _currentSwipedItem = null |
355 | + } |
356 | + } |
357 | + } |
358 | + |
359 | + removalAnimation: SequentialAnimation { |
360 | + alwaysRunToEnd: true |
361 | + |
362 | + PropertyAction { |
363 | + target: alarmDelegate |
364 | + property: "ListView.delayRemove" |
365 | + value: true |
366 | + } |
367 | + |
368 | + UbuntuNumberAnimation { |
369 | + target: alarmDelegate |
370 | + property: "height" |
371 | + to: 0 |
372 | + } |
373 | + |
374 | + PropertyAction { |
375 | + target: alarmDelegate |
376 | + property: "ListView.delayRemove" |
377 | + value: false |
378 | + } |
379 | + |
380 | + ScriptAction { |
381 | + script: { |
382 | + var alarm = alarmModel.get(index) |
383 | + alarm.cancel() |
384 | + } |
385 | + } |
386 | + } |
387 | + |
388 | + onItemClicked: { |
389 | + if(alarmListView.isInSelectionMode) { |
390 | + if(!alarmListView.selectItem(alarmDelegate)) { |
391 | + alarmListView.deselectItem(alarmDelegate) |
392 | + } |
393 | + return |
394 | + } |
395 | + |
396 | + else { |
397 | + mainStack.push(Qt.resolvedUrl("EditAlarmPage.qml"), |
398 | + {"isNewAlarm": false, "alarmIndex": index}) |
399 | + } |
400 | + } |
401 | + |
402 | + onItemPressAndHold: { |
403 | + if (!alarmListView.isInSelectionMode) { |
404 | + alarmListView.startSelection() |
405 | + alarmListView.selectItem(alarmDelegate) |
406 | + } |
407 | } |
408 | } |
409 | } |
410 | |
411 | === modified file 'app/alarm/AlarmPage.qml' |
412 | --- app/alarm/AlarmPage.qml 2014-08-01 19:31:37 +0000 |
413 | +++ app/alarm/AlarmPage.qml 2014-08-11 15:43:15 +0000 |
414 | @@ -21,25 +21,84 @@ |
415 | import "../components/Utils.js" as Utils |
416 | |
417 | Page { |
418 | - title: "Alarms" |
419 | + id: alarmPage |
420 | + |
421 | + title: i18n.tr("Alarms") |
422 | objectName: 'AlarmPage' |
423 | |
424 | + Component.onCompleted: Utils.log(debugMode, "Alarm Page loaded") |
425 | + |
426 | flickable: null |
427 | |
428 | - head.actions: Action { |
429 | - objectName: "addAlarmAction" |
430 | - iconName: "add" |
431 | - text: i18n.tr("Alarm") |
432 | - onTriggered: { |
433 | - mainStack.push(Qt.resolvedUrl("EditAlarmPage.qml")) |
434 | + states: [ |
435 | + PageHeadState { |
436 | + name: "default" |
437 | + head: alarmPage.head |
438 | + when: !alarmListView.isInSelectionMode |
439 | + actions: [ |
440 | + Action { |
441 | + objectName: "addAlarmAction" |
442 | + iconName: "add" |
443 | + text: i18n.tr("Alarm") |
444 | + onTriggered: { |
445 | + mainStack.push(Qt.resolvedUrl("EditAlarmPage.qml")) |
446 | + } |
447 | + } |
448 | + ] |
449 | + }, |
450 | + |
451 | + PageHeadState { |
452 | + name: "selection" |
453 | + head: alarmPage.head |
454 | + when: alarmListView.isInSelectionMode |
455 | + backAction: Action { |
456 | + text: i18n.tr("Cancel selection") |
457 | + iconName: "close" |
458 | + onTriggered: { |
459 | + alarmListView.cancelSelection() |
460 | + } |
461 | + } |
462 | + |
463 | + actions: [ |
464 | + Action { |
465 | + text: i18n.tr("Select All") |
466 | + iconName: "select" |
467 | + onTriggered: { |
468 | + if(alarmListView.selectedItems.count |
469 | + === alarmListView.count) { |
470 | + alarmListView.clearSelection() |
471 | + } |
472 | + else { |
473 | + alarmListView.selectAll() |
474 | + } |
475 | + } |
476 | + }, |
477 | + |
478 | + Action { |
479 | + text: i18n.tr("Delete") |
480 | + iconName: "delete" |
481 | + onTriggered: { |
482 | + var items = alarmListView.selectedItems |
483 | + |
484 | + for(var i=0; i < items.count; i++) { |
485 | + var alarm = alarmModel.get(items.get(i).itemsIndex) |
486 | + alarm.cancel() |
487 | + } |
488 | + |
489 | + alarmListView.endSelection() |
490 | + } |
491 | + } |
492 | + ] |
493 | + |
494 | + contents: Label { |
495 | + text: "" |
496 | + } |
497 | } |
498 | - } |
499 | - |
500 | - Component.onCompleted: Utils.log(debugMode, "Alarm Page loaded") |
501 | + ] |
502 | |
503 | AlarmList{ |
504 | - id: listAlarm |
505 | - model: alarmModel |
506 | + id: alarmListView |
507 | + listModel: alarmModel |
508 | anchors.fill: parent |
509 | } |
510 | } |
511 | |
512 | === modified file 'app/upstreamcomponents/ListItemWithActions.qml' |
513 | --- app/upstreamcomponents/ListItemWithActions.qml 2014-08-06 21:07:37 +0000 |
514 | +++ app/upstreamcomponents/ListItemWithActions.qml 2014-08-11 15:43:15 +0000 |
515 | @@ -262,6 +262,7 @@ |
516 | } |
517 | } |
518 | Behavior on color { |
519 | + enabled: (root.color != root.selectedColor) |
520 | ColorAnimation {} |
521 | } |
522 | } |
523 | |
524 | === added file 'app/upstreamcomponents/MultipleSelectionListView.qml' |
525 | --- app/upstreamcomponents/MultipleSelectionListView.qml 1970-01-01 00:00:00 +0000 |
526 | +++ app/upstreamcomponents/MultipleSelectionListView.qml 2014-08-11 15:43:15 +0000 |
527 | @@ -0,0 +1,199 @@ |
528 | +/* |
529 | + * Copyright (C) 2013 Canonical, Ltd. |
530 | + * |
531 | + * This program is free software; you can redistribute it and/or modify |
532 | + * it under the terms of the GNU General Public License as published by |
533 | + * the Free Software Foundation; version 3. |
534 | + * |
535 | + * This program is distributed in the hope that it will be useful, |
536 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
537 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
538 | + * GNU General Public License for more details. |
539 | + * |
540 | + * You should have received a copy of the GNU General Public License |
541 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
542 | + */ |
543 | + |
544 | +import QtQuick 2.2 |
545 | +import Ubuntu.Components 1.1 |
546 | +import Ubuntu.Components.Popups 1.0 as Popups |
547 | + |
548 | +/*! |
549 | + \qmltype ContactSimpleListView |
550 | + \inqmlmodule Ubuntu.Contacts 0.1 |
551 | + \ingroup ubuntu |
552 | + \brief The MultipleSelectionListView provides a ListView with support to multiple selection |
553 | + |
554 | + The MultipleSelectionListViewprovides a ListView with support to multiple selection which can be used by any |
555 | + application. |
556 | + |
557 | + Example: |
558 | + \qml |
559 | + import Ubuntu.Contacts 0.1 |
560 | + |
561 | + MultipleSelectionListView { |
562 | + id: view |
563 | + anchors.fill: paret |
564 | + model: 100 |
565 | + delegate: Rectangle { |
566 | + width: parent.width |
567 | + height: 100 |
568 | + color: view.selectedItems.indexOf(index) == -1 ? "white" : "blue" |
569 | + |
570 | + MouseArea { |
571 | + anchors.fill: parent |
572 | + onClicked: { |
573 | + if (view.isInSelectionModel) { |
574 | + view.selectItem(index) |
575 | + } |
576 | + } |
577 | + onPressAndHold: view.startSelection() |
578 | + } |
579 | + } |
580 | + onSelectionDone: console.debug("Selected items:" + view.selectedItems) |
581 | + } |
582 | + \endqml |
583 | +*/ |
584 | + |
585 | +ListView { |
586 | + id: listView |
587 | + |
588 | + /*! |
589 | + \qmlproperty model selectedItems |
590 | + |
591 | + This property holds the list of selected items |
592 | + */ |
593 | + readonly property alias selectedItems: visualModel.selectedItems |
594 | + /*! |
595 | + \qmlproperty bool multipleSelection |
596 | + |
597 | + This property holds if the selection will accept multiple items or single items |
598 | + */ |
599 | + property bool multipleSelection: true |
600 | + |
601 | + /*! |
602 | + \qmlproperty model listModel |
603 | + |
604 | + This property holds the model providing data for the list. |
605 | + */ |
606 | + property alias listModel: visualModel.model |
607 | + /*! |
608 | + \qmlproperty Component listDelegate |
609 | + |
610 | + The delegate provides a template defining each item instantiated by the view. |
611 | + */ |
612 | + property alias listDelegate: visualModel.delegate |
613 | + |
614 | + /*! |
615 | + \qmlproperty bool isInSelectionMode |
616 | + |
617 | + This property holds a list with the index of selected items |
618 | + */ |
619 | + readonly property bool isInSelectionMode: state === "selection" |
620 | + /*! |
621 | + This handler is called when the selection mode is finished without be canceled |
622 | + */ |
623 | + signal selectionDone(var items) |
624 | + /*! |
625 | + This handler is called when the selection mode is canceled |
626 | + */ |
627 | + signal selectionCanceled() |
628 | + |
629 | + /*! |
630 | + Start the selection mode on the list view. |
631 | + */ |
632 | + function startSelection() |
633 | + { |
634 | + state = "selection" |
635 | + } |
636 | + /*! |
637 | + Check if the item is selected |
638 | + Returns true if the item was marked as selected or false if the item is unselected |
639 | + */ |
640 | + function isSelected(item) |
641 | + { |
642 | + if (item && item.VisualDataModel) { |
643 | + return (item.VisualDataModel.inSelected === true) |
644 | + } else { |
645 | + return false |
646 | + } |
647 | + } |
648 | + /*! |
649 | + Mark the item as selected |
650 | + Returns true if the item was marked as selected or false if the item is already selected |
651 | + */ |
652 | + function selectItem(item) |
653 | + { |
654 | + if (item.VisualDataModel.inSelected) { |
655 | + return false |
656 | + } else { |
657 | + if (!multipleSelection) { |
658 | + clearSelection() |
659 | + } |
660 | + item.VisualDataModel.inSelected = true |
661 | + return true |
662 | + } |
663 | + } |
664 | + /*! |
665 | + Remove the index from the selected list |
666 | + */ |
667 | + function deselectItem(item) |
668 | + { |
669 | + var result = false |
670 | + if (item.VisualDataModel.inSelected) { |
671 | + item.VisualDataModel.inSelected = false |
672 | + result = true |
673 | + } |
674 | + return result |
675 | + } |
676 | + /*! |
677 | + Finish the selection mode with sucess |
678 | + */ |
679 | + function endSelection() |
680 | + { |
681 | + selectionDone(listView.selectedItems) |
682 | + clearSelection() |
683 | + state = "" |
684 | + } |
685 | + /*! |
686 | + Cancel the selection |
687 | + */ |
688 | + function cancelSelection() |
689 | + { |
690 | + selectionCanceled() |
691 | + clearSelection() |
692 | + state = "" |
693 | + } |
694 | + /*! |
695 | + Remove any selected item from the selection list |
696 | + */ |
697 | + function clearSelection() |
698 | + { |
699 | + if (selectedItems.count > 0) { |
700 | + selectedItems.remove(0, selectedItems.count) |
701 | + } |
702 | + } |
703 | + /*! |
704 | + Select all items in the list |
705 | + */ |
706 | + function selectAll() |
707 | + { |
708 | + if (multipleSelection) { |
709 | + visualModel.items.addGroups(0, visualModel.items.count, ["selected"] ) |
710 | + } |
711 | + } |
712 | + |
713 | + model: visualModel |
714 | + |
715 | + MultipleSelectionVisualModel { |
716 | + id: visualModel |
717 | + } |
718 | + |
719 | + Component.onCompleted: { |
720 | + // FIXME: workaround for qtubuntu not returning values depending on the grid unit definition |
721 | + // for Flickable.maximumFlickVelocity and Flickable.flickDeceleration |
722 | + var scaleFactor = units.gridUnit / 8; |
723 | + maximumFlickVelocity = maximumFlickVelocity * scaleFactor; |
724 | + flickDeceleration = flickDeceleration * scaleFactor; |
725 | + } |
726 | +} |
727 | |
728 | === added file 'app/upstreamcomponents/MultipleSelectionVisualModel.qml' |
729 | --- app/upstreamcomponents/MultipleSelectionVisualModel.qml 1970-01-01 00:00:00 +0000 |
730 | +++ app/upstreamcomponents/MultipleSelectionVisualModel.qml 2014-08-11 15:43:15 +0000 |
731 | @@ -0,0 +1,31 @@ |
732 | +/* |
733 | + * Copyright (C) 2012-2013 Canonical, Ltd. |
734 | + * |
735 | + * This program is free software; you can redistribute it and/or modify |
736 | + * it under the terms of the GNU General Public License as published by |
737 | + * the Free Software Foundation; version 3. |
738 | + * |
739 | + * This program is distributed in the hope that it will be useful, |
740 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
741 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
742 | + * GNU General Public License for more details. |
743 | + * |
744 | + * You should have received a copy of the GNU General Public License |
745 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
746 | + */ |
747 | + |
748 | +import QtQuick 2.2 |
749 | + |
750 | +VisualDataModel { |
751 | + id: contactVisualModel |
752 | + |
753 | + property alias selectedItems: selectedGroup |
754 | + |
755 | + groups: [ |
756 | + VisualDataGroup { |
757 | + id: selectedGroup |
758 | + |
759 | + name: "selected" |
760 | + } |
761 | + ] |
762 | +} |
763 | |
764 | === modified file 'app/upstreamcomponents/README.components' |
765 | --- app/upstreamcomponents/README.components 2014-08-07 01:01:36 +0000 |
766 | +++ app/upstreamcomponents/README.components 2014-08-11 15:43:15 +0000 |
767 | @@ -24,3 +24,10 @@ |
768 | |
769 | https://bazaar.launchpad.net/~phablet-team/address-book-app/trunk/view/head:/src/imports/Ubuntu/Contacts/ListItemWithActionsCheckBox.qml |
770 | |
771 | +MultipleSelectionListView.qml |
772 | + |
773 | +https://bazaar.launchpad.net/~phablet-team/address-book-app/trunk/view/head:/src/imports/Ubuntu/Contacts/MultipleSelectionListView.qml |
774 | + |
775 | +MultipleSelectionVisualModel.qml |
776 | + |
777 | +https://bazaar.launchpad.net/~phablet-team/address-book-app/trunk/view/head:/src/imports/Ubuntu/Contacts/MultipleSelectionVisualModel.qml |
778 | |
779 | === modified file 'tests/autopilot/ubuntu_clock_app/emulators.py' |
780 | --- tests/autopilot/ubuntu_clock_app/emulators.py 2014-08-08 09:11:06 +0000 |
781 | +++ tests/autopilot/ubuntu_clock_app/emulators.py 2014-08-11 15:43:15 +0000 |
782 | @@ -347,7 +347,7 @@ |
783 | @classmethod |
784 | def select(cls, main_view): |
785 | proxy_object = main_view.wait_select_single( |
786 | - objectName='alarmListFlickable') |
787 | + 'AlarmList', objectName='alarmListView') |
788 | proxy_object.visible.wait_for(True) |
789 | return cls(proxy_object) |
790 | |
791 | @@ -357,8 +357,7 @@ |
792 | |
793 | def _get_saved_alarms_list(self): |
794 | """Return the saved alarm list""" |
795 | - return self.proxy_object.wait_select_single( |
796 | - 'QQuickRepeater', objectName='alarmListRepeater') |
797 | + return self.proxy_object |
798 | |
799 | def get_saved_alarms(self): |
800 | """Return a list with the information of the saved alarms. |
You should use listModel and listDelegate property, this is necessary due the VisualModel used by multipleSelection model.
this is the patch: http:// paste.ubuntu. com/7993101/
I fixed other small problems.