Merge lp:~unity-team/ubuntu-ui-toolkit/fix-1242647 into lp:ubuntu-ui-toolkit

Proposed by Michał Sawicz
Status: Work in progress
Proposed branch: lp:~unity-team/ubuntu-ui-toolkit/fix-1242647
Merge into: lp:ubuntu-ui-toolkit
Diff against target: 451 lines (+126/-72)
8 files modified
CHANGES (+2/-0)
components.api (+2/-0)
examples/ubuntu-ui-toolkit-gallery/OptionSelectors.qml (+7/-11)
modules/Ubuntu/Components/ListItems/ItemSelector.qml (+25/-5)
modules/Ubuntu/Components/OptionSelector.qml (+34/-17)
modules/Ubuntu/Components/OptionSelectorDelegate.qml (+20/-2)
tests/autopilot/ubuntuuitoolkit/tests/gallery/test_optionselector.py (+6/-5)
tests/unit_x11/tst_components/tst_optionselector.qml (+30/-32)
To merge this branch: bzr merge lp:~unity-team/ubuntu-ui-toolkit/fix-1242647
Reviewer Review Type Date Requested Status
PS Jenkins bot continuous-integration Needs Fixing
Tim Peeters Pending
Review via email: mp+203901@code.launchpad.net

This proposal supersedes a proposal from 2013-11-29.

Commit message

Added isSelected() and full support for multiple choice selection with or without a custom model.

Added multiple choice example with custom model to show the use of multi selection.

Cleaned up OptionSelector signal test.

Changed documentation to illustrate these changes.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
Nicolas d'Offay (nicolas-doffay) wrote : Posted in a previous version of this proposal

I've taken a different approach for this. Since there's no way to get a delegate's property, we're forced to use custom models to bind the 'selected' property to a role. I've illustrated how to use this to check/uncheck a delegate in a multiple choice selector. While I don't consider this the most ideal, QML doesn't currently support the alternative due to the aforementioned inability to get delegate properties which aren't roles.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
Tim Peeters (tpeeters) wrote : Posted in a previous version of this proposal

In OptionSelectors.qml, is it possible with the multiselection without custom model (objectName: "optionselector_multipleselection") to give the initial values of the options?

Revision history for this message
Tim Peeters (tpeeters) wrote : Posted in a previous version of this proposal

99 + if (typeof model.get === "function") {
100 + selected = model.get(i).selected;
101 + }

What happens if there is no "get" property (or function)? Will this give an error?
perhaps it should be:
if (model.hasOwnProperty("get") && (typeof model.get === "function")) {

Revision history for this message
Tim Peeters (tpeeters) wrote : Posted in a previous version of this proposal

(OptionSelectors.qml)

> onDelegateClicked: print("SELECTION ARRAY: " + isSelected(index));
> onDelegateClicked: print("SELECTED ROLE: " + isSelected(index));

The prints are a bit abstract, and it is not clear why you print two different things in onDelegateClicked.

I prefer something like this:
onDelegateClicked: print("Item "+index+" selected = "+isSelected(index))
in both cases.

review: Needs Fixing
Revision history for this message
Tim Peeters (tpeeters) wrote : Posted in a previous version of this proposal

200 + Is i of our model currently selected?

Is item i of our model currently selected?
(or option i)

Revision history for this message
Tim Peeters (tpeeters) wrote : Posted in a previous version of this proposal

Can you check the initialization of your variables in tst_optionselector.qml?

So, add a function initTestCase() to the TestCase which is executed before all the other test.

expanded: false can be removed in "selector" because it is the default.

then, initTestCase() add tests to check the initial state of currentlyExpanded:
compare(selector.currentlyExpanded, false, "Selector is not expanded initially");
compare(multiSelector.currentlyExpanded, true, "Multi selector is always expanded");

review: Needs Fixing
Revision history for this message
Tim Peeters (tpeeters) wrote : Posted in a previous version of this proposal

267 + if (typeof listView.model.setProperty === "function") {

Same comment as before when using typeof. Do we need to check listView.model.hasOwnProperty("setProperty")?

review: Needs Information
Revision history for this message
Tim Peeters (tpeeters) wrote : Posted in a previous version of this proposal

266 + //Only update our selected model property if 'model' inherits from QAbstractListModel
267 + if (typeof listView.model.setProperty === "function") {
268 + listView.model.setProperty(index, "selected", selected);
269 + } else {
270 + //Sync the selections array which we can access to check our current selection.
271 + listView.selections[index] = selected;
272 + }

Please document this behavior. You can add to the description of the model of the OptionSelector/ItemSelector that if the model inherits from QAbstractListModel, then the setProperty() function will be called to update the selected property. If not, the OptionSelector keeps its own list of selections.

review: Needs Fixing
Revision history for this message
Nicolas d'Offay (nicolas-doffay) wrote : Posted in a previous version of this proposal

"What happens if there is no "get" property (or function)? Will this give an error?
perhaps it should be:"

No, it falls back to the array of selection values. I'll update the documentation accordingly.

Revision history for this message
Tim Peeters (tpeeters) wrote : Posted in a previous version of this proposal

listview.selections is initialized as [], and then it is assigned values with selections[i] = value. It is never given a size, how can this work?

review: Needs Fixing
Revision history for this message
Tim Peeters (tpeeters) wrote : Posted in a previous version of this proposal

198 + /*!
199 + \preliminary
200 + Is i of our model currently selected?
201 + */
202 + function isSelected(i) {
203 + var selected = list.selections[i];
204 + if (typeof model.get === "function") {
205 + selected = model.get(i).selected;
206 + }
207 + return selected;
208 + }

I think it is cleaner if you put selected = list.selections[i] in an else { }, when the model does not have a get function.

review: Needs Fixing
Revision history for this message
Tim Peeters (tpeeters) wrote : Posted in a previous version of this proposal

Can you add a test that checks:

- An item in a multiselector is not selected
- Click the item
- the item is now selected (verify with isSelected(i)).

Revision history for this message
Tim Peeters (tpeeters) wrote : Posted in a previous version of this proposal

test_optionselector.py should not be removed, but fixed.

review: Needs Fixing
Revision history for this message
Nicolas d'Offay (nicolas-doffay) wrote : Posted in a previous version of this proposal

I'm going to be amending the current expanded test to include the multiple choice one. This already tests the functionality. I don't think we need to include an initTestCase().

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
Nicolas d'Offay (nicolas-doffay) wrote : Posted in a previous version of this proposal

"listview.selections is initialized as [], and then it is assigned values with selections[i] = value. It is never given a size, how can this work?"

Javascript can assign values to an empty array. This is evident when the values change and are printed out in the gallery example without the custom model.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
Tim Peeters (tpeeters) wrote : Posted in a previous version of this proposal

134 + property var selections: []

can you add a little comment here explaining where the property is is initialized and used?

Revision history for this message
Tim Peeters (tpeeters) wrote : Posted in a previous version of this proposal

388 + compare(multiSelector.expanded, false, "multi selector should be false on startup.")

you're checking the expanded property, but the text says "multi selector".

review: Needs Fixing
Revision history for this message
Tim Peeters (tpeeters) wrote : Posted in a previous version of this proposal

398 + function test_clicked_signal() {
399 + skip('FIXME: This test doesn\'t pass in CI')
400 + mouseClick(multiSelector, 100, 90, Qt.LeftButton);
401 + clickedSignal.wait();
402 + compare(multiSelector.isSelected(clickedSignal.signalArguments[0][0]), true);
403 +
404 + //Second option.
405 + mouseClick(multiSelector, 100, 90, Qt.LeftButton);
406 + clickedSignal.wait();
407 + //Did the second index get clicked?
408 + compare(multiSelector.isSelected(clickedSignal.signalArguments[1][0]), false);
409 + }
410 +

can you add a string saying what went wrong (if something went wrong) to the compare() calls?

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
Tim Peeters (tpeeters) wrote : Posted in a previous version of this proposal

Unit tests pass, but I get a bunch of warnings: http://pastebin.ubuntu.com/6749934/

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
Tim Peeters (tpeeters) wrote : Posted in a previous version of this proposal

112 + selected = list.selections[i]

add a ; in the end of the line

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
Tim Peeters (tpeeters) wrote : Posted in a previous version of this proposal

code looks good now, we only need to fix the tests (warnings locally, and one fail on jenkins)

Revision history for this message
Tim Peeters (tpeeters) wrote : Posted in a previous version of this proposal

The warnings are caused by this bug:
https://bugs.launchpad.net/ubuntu-ui-toolkit/+bug/1269019

Can be solved in a separate MR. Here it is sufficient to remove that extra delegate which is not necessary.

Revision history for this message
Tim Peeters (tpeeters) wrote : Posted in a previous version of this proposal

The skip() call in the test is my only complain left, but it is already there in our trunk, so this is good to go. Let's see what jenkins says.

review: Approve
Revision history for this message
Tim Peeters (tpeeters) wrote : Posted in a previous version of this proposal

apps work on device (including ubuntu-system-settings), but phablet-test-run ubuntu_system_settings fails, see http://pastebin.ubuntu.com/6751103/

investigating..

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
Tim Peeters (tpeeters) wrote : Posted in a previous version of this proposal

> apps work on device (including ubuntu-system-settings), but phablet-test-run
> ubuntu_system_settings fails, see http://pastebin.ubuntu.com/6751103/
>
> investigating..

I get the same AP failures for ubuntu-system-settings immediately after installing the latest ubuntu-system image on maguro without installing custom versions of UITK. So the fails above are not caused by this MR.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)

Unmerged revisions

899. By Nicolas d'Offay

Added additional skip to test.

898. By Nicolas d'Offay

Removed test and standalone selector delegate.

897. By Nicolas d'Offay

Readded skip for test which fails in CI. Removed prints.

896. By Nicolas d'Offay

Removed unused selectorDelegate.

895. By Nicolas d'Offay

Added semicolon.

894. By Nicolas d'Offay

Instantiated SelectorDelegate in class creation instead of externally as a component.

893. By Nicolas d'Offay

Removed skips in test.

892. By Nicolas d'Offay

Merged trunk.

891. By Nicolas d'Offay

Changed comment.

890. By Nicolas d'Offay

Fixed comment.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'CHANGES'
2--- CHANGES 2013-12-05 14:54:53 +0000
3+++ CHANGES 2014-01-30 09:34:41 +0000
4@@ -9,7 +9,9 @@
5
6 API Changes
7 ***********
8+* ADDED IN: OptionSelector: function isSelected(i)
9 * ADDED IN: PickerDelegate: readonly property Picker picker
10+* ADDED IN: ItemSelector: function isSelected(i)
11 * CHANGED IN: OptionSelector: readonly property bool currentlyExpanded TO property bool currentlyExpanded
12 * CHANGED IN: ItemSelector: readonly property bool currentlyExpanded TO property bool currentlyExpanded
13 * ADDED IN: Action: property string iconName
14
15=== modified file 'components.api'
16--- components.api 2013-12-17 14:05:43 +0000
17+++ components.api 2014-01-30 09:34:41 +0000
18@@ -122,6 +122,7 @@
19 readonly property real itemHeight
20 signal delegateClicked(int index)
21 signal expansionCompleted()
22+ function isSelected(i)
23 modules/Ubuntu/Components/ListItems/MultiValue.qml
24 Base
25 property variant values
26@@ -196,6 +197,7 @@
27 readonly property real itemHeight
28 signal delegateClicked(int index)
29 signal expansionCompleted()
30+ function isSelected(i)
31 modules/Ubuntu/Components/OptionSelectorDelegate.qml
32 ListItem.Standard
33 property string text
34
35=== modified file 'examples/ubuntu-ui-toolkit-gallery/OptionSelectors.qml'
36--- examples/ubuntu-ui-toolkit-gallery/OptionSelectors.qml 2013-12-02 14:03:16 +0000
37+++ examples/ubuntu-ui-toolkit-gallery/OptionSelectors.qml 2014-01-30 09:34:41 +0000
38@@ -59,24 +59,20 @@
39
40 OptionSelector {
41 objectName: "optionselector_custommodel"
42- text: i18n.tr("Custom Model")
43+ text: i18n.tr("Custom Model Multiple Selection")
44 model: customModel
45 expanded: true
46+ multiSelection: true
47 colourImage: true
48- delegate: selectorDelegate
49- }
50-
51- Component {
52- id: selectorDelegate
53- OptionSelectorDelegate { text: name; subText: description; iconSource: image }
54+ delegate: OptionSelectorDelegate { text: name; subText: description; iconSource: image; selected: selected }
55 }
56
57 ListModel {
58 id: customModel
59- ListElement { name: "Name 1"; description: "Description 1"; image: "images.png" }
60- ListElement { name: "Name 2"; description: "Description 2"; image: "images.png" }
61- ListElement { name: "Name 3"; description: "Description 3"; image: "images.png" }
62- ListElement { name: "Name 4"; description: "Description 4"; image: "images.png" }
63+ ListElement { name: "Name 1"; description: "Description 1"; image: "images.png"; selected: true}
64+ ListElement { name: "Name 2"; description: "Description 2"; image: "images.png"; selected: false }
65+ ListElement { name: "Name 3"; description: "Description 3"; image: "images.png"; selected: true }
66+ ListElement { name: "Name 4"; description: "Description 4"; image: "images.png"; selected: false }
67 }
68
69 OptionSelector {
70
71=== modified file 'modules/Ubuntu/Components/ListItems/ItemSelector.qml'
72--- modules/Ubuntu/Components/ListItems/ItemSelector.qml 2013-12-05 17:00:33 +0000
73+++ modules/Ubuntu/Components/ListItems/ItemSelector.qml 2014-01-30 09:34:41 +0000
74@@ -118,7 +118,8 @@
75
76 /*!
77 \preliminary
78- The list of values that will be shown under the label text. This is a model.
79+ The list of values that will be shown under the label text. This is a model. If the selector is a multiple selection and this model doesn't inherit from QAbstractListModel
80+ then we fall back to using an internal array of booleans to keep track of the selection.
81 */
82 property var model
83
84@@ -182,7 +183,7 @@
85 readonly property alias itemHeight: list.itemHeight
86
87 /*!
88- Called when delegate is clicked.
89+ Called when delegate is clicked. Parameters are the index clicked.
90 */
91 signal delegateClicked(int index)
92
93@@ -191,6 +192,21 @@
94 */
95 signal expansionCompleted()
96
97+ /*!
98+ \preliminary
99+ Is option i of our model currently selected?
100+ */
101+ function isSelected(i) {
102+ var selected;
103+ if (typeof model.get === "function") {
104+ selected = model.get(i).selected;
105+ } else {
106+ selected = list.selections[i]
107+ }
108+
109+ return selected;
110+ }
111+
112 __height: column.height
113 showDivider: false
114
115@@ -223,7 +239,7 @@
116 left: parent.left
117 right: parent.right
118 }
119- state: itemSelector.expanded ? "expanded" : "collapsed"
120+ state: itemSelector.expanded || itemSelector.multiSelection ? "expanded" : "collapsed"
121 style: Theme.createStyleComponent("ListItemOptionSelectorStyle.qml", listContainer)
122
123 states: [ State {
124@@ -266,17 +282,21 @@
125 id: list
126 objectName: "listView"
127
128+ property var selections: []
129+
130 property int previousIndex: list.currentIndex
131+ property real itemHeight
132+
133 readonly property alias expanded: itemSelector.expanded
134 readonly property alias multiSelection: itemSelector.multiSelection
135 readonly property alias container: listContainer
136- property real itemHeight
137+
138 signal delegateClicked(int index)
139
140 onDelegateClicked: itemSelector.delegateClicked(index);
141 interactive: listContainer.height !== list.contentHeight && listContainer.currentlyExpanded ? true : false
142 clip: true
143- currentIndex: 0
144+ currentIndex: multiSelection ? -1 : 0
145 model: itemSelector.model
146 anchors.fill: parent
147
148
149=== modified file 'modules/Ubuntu/Components/OptionSelector.qml'
150--- modules/Ubuntu/Components/OptionSelector.qml 2013-12-13 15:50:35 +0000
151+++ modules/Ubuntu/Components/OptionSelector.qml 2014-01-30 09:34:41 +0000
152@@ -51,7 +51,6 @@
153 }
154
155 OptionSelector {
156- objectName: "optionselector_multipleselection"
157 text: i18n.tr("Multiple Selection")
158 expanded: false
159 multiSelection: true
160@@ -62,24 +61,20 @@
161 }
162
163 OptionSelector {
164- text: i18n.tr("Label")
165+ text: i18n.tr("Multiple Choice Custom Model")
166 model: customModel
167 expanded: true
168 colourImage: true
169- delegate: selectorDelegate
170- }
171-
172- Component {
173- id: selectorDelegate
174- OptionSelectorDelegate { text: name; subText: description; iconSource: image }
175+ multiSelection: true
176+ delegate: OptionSelectorDelegate { text: name; subText: description; iconSource: image; selected: selected }
177 }
178
179 ListModel {
180 id: customModel
181- ListElement { name: "Name 1"; description: "Description 1"; image: "images.png" }
182- ListElement { name: "Name 2"; description: "Description 2"; image: "images.png" }
183- ListElement { name: "Name 3"; description: "Description 3"; image: "images.png" }
184- ListElement { name: "Name 4"; description: "Description 4"; image: "images.png" }
185+ ListElement { name: "Name 1"; description: "Description 1"; image: "images.png"; selected: true}
186+ ListElement { name: "Name 2"; description: "Description 2"; image: "images.png"; selected: false }
187+ ListElement { name: "Name 3"; description: "Description 3"; image: "images.png"; selected: true }
188+ ListElement { name: "Name 4"; description: "Description 4"; image: "images.png"; selected: false }
189 }
190
191 OptionSelector {
192@@ -117,7 +112,8 @@
193
194 /*!
195 \preliminary
196- The list of values that will be shown under the label text. This is a model.
197+ The list of values that will be shown under the label text. This is a model. If the selector is a multiple selection and this model doesn't inherit from QAbstractListModel
198+ then we fall back to using an internal array of booleans to keep track of the selection.
199 */
200 property var model
201
202@@ -181,7 +177,7 @@
203 readonly property alias itemHeight: list.itemHeight
204
205 /*!
206- Called when delegate is clicked.
207+ Called when delegate is clicked. Parameters are the index clicked.
208 */
209 signal delegateClicked(int index)
210
211@@ -190,6 +186,21 @@
212 */
213 signal expansionCompleted()
214
215+ /*!
216+ \preliminary
217+ Is option i of our model currently selected?
218+ */
219+ function isSelected(i) {
220+ var selected;
221+ if (typeof model.get === "function") {
222+ selected = model.get(i).selected;
223+ } else {
224+ selected = list.selections[i];
225+ }
226+
227+ return selected;
228+ }
229+
230 /*!
231 \internal
232 Trigger the action, passing the current index.
233@@ -231,7 +242,7 @@
234 left: parent.left
235 right: parent.right
236 }
237- state: optionSelector.expanded ? "expanded" : "collapsed"
238+ state: optionSelector.expanded || optionSelector.multiSelection ? "expanded" : "collapsed"
239 style: Theme.createStyleComponent("OptionSelectorStyle.qml", listContainer)
240 states: [ State {
241 name: "expanded"
242@@ -272,17 +283,23 @@
243 ListView {
244 id: list
245
246+ /*This array is initialised on an index by index basis in each OptionSelectorDelegate's onCompleted call.
247+ Values are reset everytime a multiple choice selection is clicked.*/
248+ property var selections: []
249+
250 property int previousIndex: -1
251+ property real itemHeight
252+
253 readonly property alias expanded: optionSelector.expanded
254 readonly property alias multiSelection: optionSelector.multiSelection
255 readonly property alias container: listContainer
256- property real itemHeight
257+
258 signal delegateClicked(int index)
259
260 onDelegateClicked: optionSelector.delegateClicked(index);
261 interactive: listContainer.height !== list.contentHeight && listContainer.currentlyExpanded ? true : false
262 clip: true
263- currentIndex: 0
264+ currentIndex: multiSelection ? -1 : 0
265 model: optionSelector.model
266 anchors.fill: parent
267
268
269=== modified file 'modules/Ubuntu/Components/OptionSelectorDelegate.qml'
270--- modules/Ubuntu/Components/OptionSelectorDelegate.qml 2013-12-04 15:51:58 +0000
271+++ modules/Ubuntu/Components/OptionSelectorDelegate.qml 2014-01-30 09:34:41 +0000
272@@ -147,16 +147,26 @@
273 left: parent.left
274 right: parent.right
275 }
276+
277+ /*! \internal */
278 onClicked: {
279 if (listView.container.currentlyExpanded) {
280- listView.delegateClicked(index);
281-
282 if (!listView.multiSelection) {
283+ //Set the current index which changes currentItem if multiple choice isn't active.
284 listView.previousIndex = listView.currentIndex;
285 listView.currentIndex = index;
286 } else {
287 selected = !selected;
288+ //Only update our selected model property if 'model' inherits from QAbstractListModel
289+ if (typeof listView.model.setProperty === "function") {
290+ listView.model.setProperty(index, "selected", selected);
291+ } else {
292+ //Sync the selections array which we can access to check our current selection.
293+ listView.selections[index] = selected;
294+ }
295 }
296+
297+ listView.delegateClicked(index);
298 }
299
300 if (!listView.expanded && !listView.multiSelection) {
301@@ -165,6 +175,14 @@
302 }
303
304 Component.onCompleted: {
305+ if (listView.multiSelection) {
306+ if (typeof listView.model.get === "function") {
307+ selected = listView.model.get(index).selected;
308+ } else {
309+ listView.selections[index] = selected;
310+ }
311+ }
312+
313 height = listView.itemHeight = childrenRect.height;
314 }
315
316
317=== modified file 'tests/autopilot/ubuntuuitoolkit/tests/gallery/test_optionselector.py'
318--- tests/autopilot/ubuntuuitoolkit/tests/gallery/test_optionselector.py 2013-11-08 09:19:02 +0000
319+++ tests/autopilot/ubuntuuitoolkit/tests/gallery/test_optionselector.py 2014-01-30 09:34:41 +0000
320@@ -81,16 +81,17 @@
321 self.reveal_item_by_flick(custommodel, flickable, FlickDirection.UP)
322 self.assertThat(flickable.flicking, Eventually(Equals(False)))
323
324- self.assertThat(custommodel.selectedIndex, Equals(0))
325- selectedValue = custommodel.select_single('Label', text='Name 4')
326+ selectedValue = custommodel.select_single('OptionSelectorDelegate',
327+ text='Name 4')
328 self.assertIsNotNone(selectedValue)
329 self.pointing_device.click_object(selectedValue)
330- self.assertThat(custommodel.selectedIndex, Eventually(Equals(3)))
331+ self.assertThat(selectedValue.selected, Eventually(Equals(True)))
332
333- selectedValue = custommodel.select_single('Label', text='Name 1')
334+ selectedValue = custommodel.select_single('OptionSelectorDelegate',
335+ text='Name 1')
336 self.assertIsNotNone(selectedValue)
337 self.pointing_device.click_object(selectedValue)
338- self.assertThat(custommodel.selectedIndex, Eventually(Equals(0)))
339+ self.assertThat(selectedValue.selected, Eventually(Equals(False)))
340
341 #scroll the page downward now.
342 collapsed = self.getObject("optionselector_collapsed")
343
344=== modified file 'tests/unit_x11/tst_components/tst_optionselector.qml'
345--- tests/unit_x11/tst_components/tst_optionselector.qml 2013-12-18 12:40:20 +0000
346+++ tests/unit_x11/tst_components/tst_optionselector.qml 2014-01-30 09:34:41 +0000
347@@ -33,9 +33,13 @@
348 id: selector
349
350 text: "TEST"
351- delegate: selectorDelegate
352+ delegate: OptionSelectorDelegate {
353+ text: name
354+ subText: description
355+ iconSource: image
356+ constrainImage: true
357+ }
358 model: customModel
359- expanded: true
360
361 action: {
362 enabled: true
363@@ -45,24 +49,12 @@
364 }
365 }
366
367- OptionSelectorDelegate {
368- id: testDelegate
369+ OptionSelector {
370+ id: multiSelector
371
372 text: "TEST"
373- subText: "test"
374- iconSource: "../../resources/optionselector/test.png"
375- constrainImage: true
376- }
377- }
378-
379- Component {
380- id: selectorDelegate
381-
382- OptionSelectorDelegate {
383- text: name
384- subText: description
385- iconSource: image
386- constrainImage: true
387+ model: [1, 2, 3, 4]
388+ multiSelection: true
389 }
390 }
391
392@@ -76,7 +68,7 @@
393
394 SignalSpy {
395 id: clickedSignal
396- target: selector
397+ target: multiSelector
398 signalName: "delegateClicked"
399 }
400
401@@ -99,7 +91,8 @@
402 function test_expanded() {
403 var listContainer = findChild(selector, "listContainer");
404
405- selector.expanded = false;
406+ compare(multiSelector.expanded, false, "expanded should be false on startup.")
407+
408 compare(listContainer.currentlyExpanded, false, "expanded should be true if list is an expanded one");
409 compare(listContainer.state, "collapsed", "state should be collapsed");
410
411@@ -127,23 +120,28 @@
412
413 function test_custom_model_delegate() {
414 compare(selector.model, customModel, "Model wasn't set correctly.");
415- compare(selector.delegate, selectorDelegate, "Delegate hasn't been set correctly");
416- }
417-
418- function test_image_constraint() {
419- var image = findChild(testDelegate, "icon");
420- compare(image.height, testDelegate.height);
421- }
422-
423- function test_signal() {
424- skip('FIXME: This test doesn\'t pass in CI')
425+ }
426+
427+ function test_clicked_signal() {
428+ skip('FIXME: This test doesn\'t pass in CI. Passes locally for anyone who tried.')
429+ mouseClick(multiSelector, 100, 100, Qt.LeftButton);
430+ clickedSignal.wait();
431+ compare(multiSelector.isSelected(clickedSignal.signalArguments[0][0]), true, "Clicked signal was not emitted and option was not selected.");
432+
433+ //Second option.
434+ mouseClick(multiSelector, 100, 100, Qt.LeftButton);
435+ clickedSignal.wait();
436+ //Did the second index get clicked?
437+ compare(multiSelector.isSelected(clickedSignal.signalArguments[1][0]), false, "Clicked signal was not emitted and option was not deselected.");
438+ }
439+
440+ function test_expansion_signal() {
441 mouseClick(selector, 100, 100, Qt.LeftButton);
442- clickedSignal.wait();
443 expansionSignal.wait();
444 }
445
446 function test_triggered() {
447- skip('FIXME: This test doesn\'t pass in CI')
448+ skip('FIXME: This test doesn\'t pass in CI. Passes locally for anyone who tried.')
449 mouseClick(selector, 100, 100, Qt.LeftButton);
450 triggeredSignal.wait();
451 }

Subscribers

People subscribed via source and target branches

to status/vote changes: