6a9c7872c81e65d960494248d7523f5d676b2e65
[profile/ivi/qtdeclarative.git] / tests / auto / declarative / qdeclarativelistcompositor / tst_qdeclarativelistcompositor.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: http://www.qt-project.org/
6 **
7 ** This file is part of the test suite of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 **
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 **
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
29 **
30 ** Other Usage
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 #include <qtest.h>
42 #include <private/qdeclarativelistcompositor_p.h>
43
44 template<typename T, int N> int lengthOf(const T (&)[N]) { return N; }
45
46 typedef QDeclarativeListCompositor C;
47
48 struct Range
49 {
50     Range() {}
51     Range(void *list, int index, int count, int flags)
52         : list(list), index(index), count(count), flags(flags) {}
53     void *list;
54     int index;
55     int count;
56     int flags;
57 };
58
59 template <typename T>  struct Array
60 {
61     Array() : array(0), count(0) {}
62     template<int N> Array(const T (&array)[N]) : array(array), count(N) {}
63
64     T operator [](int index) const { return array[index]; }
65
66     const T *array;
67     int count;
68 };
69
70 typedef Array<int> IndexArray;
71 typedef Array<const void *> ListArray;
72
73 typedef QVector<QDeclarativeListCompositor::Remove> RemoveList;
74 typedef QVector<QDeclarativeListCompositor::Insert> InsertList;
75 typedef QVector<QDeclarativeListCompositor::Change> ChangeList;
76
77 typedef QVector<Range> RangeList;
78
79 Q_DECLARE_METATYPE(RangeList)
80 Q_DECLARE_METATYPE(RemoveList)
81 Q_DECLARE_METATYPE(InsertList)
82 Q_DECLARE_METATYPE(ChangeList)
83 Q_DECLARE_METATYPE(void *)
84 Q_DECLARE_METATYPE(IndexArray)
85 Q_DECLARE_METATYPE(ListArray)
86 Q_DECLARE_METATYPE(C::Group)
87
88 QT_BEGIN_NAMESPACE
89 bool operator ==(const C::Change &left, const C::Change &right)
90 {
91     return left.index[3] == right.index[3]
92             && left.index[2] == right.index[2]
93             && left.index[1] == right.index[1]
94             && left.index[0] == right.index[0]
95             && left.count == right.count
96             && left.groups() == right.groups()
97             && left.inCache() == right.inCache()
98             && (left.moveId == -1) == (right.moveId == -1);
99 }
100 QT_END_NAMESPACE
101
102 static const C::Group Visible = C::Group(2);
103 static const C::Group Selection = C::Group(3);
104
105 class tst_qdeclarativelistcompositor : public QObject
106 {
107     Q_OBJECT
108
109     enum {
110         VisibleFlag   = 0x04,
111         SelectionFlag = 0x08
112     };
113
114     void populateChange(
115             C::Change &change, int sIndex, int vIndex, int dIndex, int cIndex, int count, int flags, int moveId)
116     {
117         change.index[Selection] = sIndex;
118         change.index[Visible] = vIndex;
119         change.index[C::Default] = dIndex;
120         change.index[C::Cache] = cIndex;
121         change.count = count;
122         change.flags = flags;
123         change.moveId = moveId;
124     }
125
126     C::Remove Remove(
127             int sIndex, int vIndex, int dIndex, int cIndex, int count, int flags, int moveId = -1)
128     {
129         C::Remove remove;
130         populateChange(remove, sIndex, vIndex, dIndex, cIndex, count, flags, moveId);
131         return remove;
132     }
133
134     C::Insert Insert(
135             int sIndex, int vIndex, int dIndex, int cIndex, int count, int flags, int moveId = -1)
136     {
137         C::Insert insert;
138         populateChange(insert, sIndex, vIndex, dIndex, cIndex, count, flags, moveId);
139         return insert;
140     }
141
142     C::Change Change(
143         int sIndex, int vIndex, int dIndex, int cIndex, int count, int flags, int moveId = -1)
144     {
145         C::Change change;
146         populateChange(change, sIndex, vIndex, dIndex, cIndex, count, flags, moveId);
147         return change;
148     }
149
150 private slots:
151     void find_data();
152     void find();
153     void findInsertPosition_data();
154     void findInsertPosition();
155     void insert();
156     void clearFlags_data();
157     void clearFlags();
158     void setFlags_data();
159     void setFlags();
160     void move_data();
161     void move();
162     void moveFromEnd();
163     void clear();
164     void listItemsInserted_data();
165     void listItemsInserted();
166     void listItemsRemoved_data();
167     void listItemsRemoved();
168     void listItemsMoved_data();
169     void listItemsMoved();
170     void listItemsChanged_data();
171     void listItemsChanged();
172 };
173
174 void tst_qdeclarativelistcompositor::find_data()
175 {
176     QTest::addColumn<RangeList>("ranges");
177     QTest::addColumn<C::Group>("startGroup");
178     QTest::addColumn<int>("startIndex");
179     QTest::addColumn<C::Group>("group");
180     QTest::addColumn<int>("index");
181     QTest::addColumn<int>("selectionIndex");
182     QTest::addColumn<int>("visibleIndex");
183     QTest::addColumn<int>("defaultIndex");
184     QTest::addColumn<int>("cacheIndex");
185     QTest::addColumn<uint>("rangeFlags");
186     QTest::addColumn<int>("rangeIndex");
187
188     int listA; void *a = &listA;
189
190     QTest::newRow("Start")
191             << (RangeList()
192                 << Range(a, 0, 1, int(C::PrependFlag |  SelectionFlag | C::DefaultFlag | C::CacheFlag))
193                 << Range(a, 1, 1, int(C::AppendFlag | C::PrependFlag | C::CacheFlag))
194                 << Range(0, 0, 1, int(VisibleFlag| C::CacheFlag)))
195             << C::Cache << 2
196             << Selection << 0
197             << 0 << 0 << 0 << 0
198             << uint(C::PrependFlag |  SelectionFlag | C::DefaultFlag | C::CacheFlag) << 0;
199 }
200
201 void tst_qdeclarativelistcompositor::find()
202 {
203     QFETCH(RangeList, ranges);
204     QFETCH(C::Group, startGroup);
205     QFETCH(int, startIndex);
206     QFETCH(C::Group, group);
207     QFETCH(int, index);
208     QFETCH(int, cacheIndex);
209     QFETCH(int, defaultIndex);
210     QFETCH(int, visibleIndex);
211     QFETCH(int, selectionIndex);
212     QFETCH(uint, rangeFlags);
213     QFETCH(int, rangeIndex);
214
215     QDeclarativeListCompositor compositor;
216     compositor.setGroupCount(4);
217     compositor.setDefaultGroups(VisibleFlag | C::DefaultFlag);
218
219     foreach (const Range &range, ranges)
220         compositor.append(range.list, range.index, range.count, range.flags);
221
222     compositor.find(startGroup, startIndex);
223
224     QDeclarativeListCompositor::iterator it = compositor.find(group, index);
225     QCOMPARE(it.index[C::Cache], cacheIndex);
226     QCOMPARE(it.index[C::Default], defaultIndex);
227     QCOMPARE(it.index[Visible], visibleIndex);
228     QCOMPARE(it.index[Selection], selectionIndex);
229     QCOMPARE(it->flags, rangeFlags);
230     QCOMPARE(it->index, rangeIndex);
231 }
232
233 void tst_qdeclarativelistcompositor::findInsertPosition_data()
234 {
235     QTest::addColumn<RangeList>("ranges");
236     QTest::addColumn<C::Group>("group");
237     QTest::addColumn<int>("index");
238     QTest::addColumn<int>("selectionIndex");
239     QTest::addColumn<int>("visibleIndex");
240     QTest::addColumn<int>("defaultIndex");
241     QTest::addColumn<int>("cacheIndex");
242     QTest::addColumn<uint>("rangeFlags");
243     QTest::addColumn<int>("rangeIndex");
244
245     int listA; void *a = &listA;
246
247     QTest::newRow("Start")
248             << (RangeList()
249                 << Range(a, 0, 1, int(C::PrependFlag |  SelectionFlag | C::DefaultFlag | C::CacheFlag))
250                 << Range(a, 1, 1, int(C::AppendFlag | C::PrependFlag | C::CacheFlag))
251                 << Range(0, 0, 1, int(VisibleFlag| C::CacheFlag)))
252             << Selection << 0
253             << 0 << 0 << 0 << 0
254             << uint(C::PrependFlag |  SelectionFlag | C::DefaultFlag | C::CacheFlag) << 0;
255     QTest::newRow("1")
256             << (RangeList()
257                 << Range(a, 0, 1, int(C::PrependFlag |  SelectionFlag | C::DefaultFlag | C::CacheFlag))
258                 << Range(a, 1, 1, int(C::AppendFlag | C::PrependFlag | C::CacheFlag))
259                 << Range(0, 0, 1, int(VisibleFlag| C::CacheFlag)))
260             << Selection << 1
261             << 1 << 0 << 1 << 1
262             << uint(C::AppendFlag | C::PrependFlag | C::CacheFlag) << 1;
263 }
264
265 void tst_qdeclarativelistcompositor::findInsertPosition()
266 {
267     QFETCH(RangeList, ranges);
268     QFETCH(C::Group, group);
269     QFETCH(int, index);
270     QFETCH(int, cacheIndex);
271     QFETCH(int, defaultIndex);
272     QFETCH(int, visibleIndex);
273     QFETCH(int, selectionIndex);
274     QFETCH(uint, rangeFlags);
275     QFETCH(int, rangeIndex);
276
277     QDeclarativeListCompositor compositor;
278     compositor.setGroupCount(4);
279     compositor.setDefaultGroups(VisibleFlag | C::DefaultFlag);
280
281     foreach (const Range &range, ranges)
282         compositor.append(range.list, range.index, range.count, range.flags);
283
284     QDeclarativeListCompositor::insert_iterator it = compositor.findInsertPosition(group, index);
285     QCOMPARE(it.index[C::Cache], cacheIndex);
286     QCOMPARE(it.index[C::Default], defaultIndex);
287     QCOMPARE(it.index[Visible], visibleIndex);
288     QCOMPARE(it.index[Selection], selectionIndex);
289     QCOMPARE(it->flags, rangeFlags);
290     QCOMPARE(it->index, rangeIndex);
291 }
292
293 void tst_qdeclarativelistcompositor::insert()
294 {
295     QDeclarativeListCompositor compositor;
296     compositor.setGroupCount(4);
297     compositor.setDefaultGroups(VisibleFlag | C::DefaultFlag);
298
299     C::iterator it;
300
301     int listA; int *a = &listA;
302     int listB; int *b = &listB;
303     int listC; int *c = &listC;
304
305     {
306         compositor.append(a, 0, 12, C::AppendFlag | C::PrependFlag | C::DefaultFlag);
307         const int indexes[] = {0,1,2,3,4,5,6,7,8,9,10,11};
308         const int *lists[]  = {a,a,a,a,a,a,a,a,a,a, a, a};
309         QCOMPARE(compositor.count(C::Default), lengthOf(indexes));
310         for (int i = 0; i < lengthOf(indexes); ++i) {
311             it = compositor.find(C::Default, i);
312             QCOMPARE(it.list<int>(), lists[i]);
313             if (lists[i]) QCOMPARE(it.modelIndex(), indexes[i]);
314         }
315     } {
316         compositor.append(b, 4, 4, C::DefaultFlag);
317         const int indexes[] = {0,1,2,3,4,5,6,7,8,9,10,11,4,5,6,7};
318         const int *lists[]  = {a,a,a,a,a,a,a,a,a,a, a, a,b,b,b,b};
319         QCOMPARE(compositor.count(C::Default), lengthOf(indexes));
320         for (int i = 0; i < lengthOf(indexes); ++i) {
321             it = compositor.find(C::Default, i);
322             QCOMPARE(it.list<int>(), lists[i]);
323             if (lists[i]) QCOMPARE(it.modelIndex(), indexes[i]);
324         }
325     } { // Insert at end.
326         compositor.insert(
327                 C::Default, 16, c, 2, 2, C::DefaultFlag);
328         const int indexes[] = {0,1,2,3,4,5,6,7,8,9,10,11,4,5,6,7,2,3};
329         const int *lists[]  = {a,a,a,a,a,a,a,a,a,a, a, a,b,b,b,b,c,c};
330         QCOMPARE(compositor.count(C::Default), lengthOf(indexes));
331         for (int i = 0; i < lengthOf(indexes); ++i) {
332             it = compositor.find(C::Default, i);
333             QCOMPARE(it.list<int>(), lists[i]);
334             if (lists[i]) QCOMPARE(it.modelIndex(), indexes[i]);
335         }
336     } { // Insert at start
337         compositor.insert(
338                 C::Default, 0, c, 6, 4, C::DefaultFlag);
339         const int indexes[] = {6,7,8,9,0,1,2,3,4,5,6,7,8,9,10,11,4,5,6,7,2,3};
340         const int *lists[]  = {c,c,c,c,a,a,a,a,a,a,a,a,a,a, a, a,b,b,b,b,c,c};
341         QCOMPARE(compositor.count(C::Default), lengthOf(indexes));
342         for (int i = 0; i < lengthOf(indexes); ++i) {
343             it = compositor.find(C::Default, i);
344             QCOMPARE(it.list<int>(), lists[i]);
345             if (lists[i]) QCOMPARE(it.modelIndex(), indexes[i]);
346         }
347     } { // Insert after static range.
348         compositor.insert(
349                 C::Default, 4, b, 0, 8, C::AppendFlag | C::PrependFlag | C::DefaultFlag);
350         const int indexes[] = {6,7,8,9,0,1,2,3,4,5,6,7,0,1,2,3,4,5,6,7,8,9,10,11,4,5,6,7,2,3};
351         const int *lists[]  = {c,c,c,c,b,b,b,b,b,b,b,b,a,a,a,a,a,a,a,a,a,a, a, a,b,b,b,b,c,c};
352         QCOMPARE(compositor.count(C::Default), lengthOf(indexes));
353         for (int i = 0; i < lengthOf(indexes); ++i) {
354             it = compositor.find(C::Default, i);
355             QCOMPARE(it.list<int>(), lists[i]);
356             if (lists[i]) QCOMPARE(it.modelIndex(), indexes[i]);
357         }
358     } { // Insert at end of dynamic range.
359         compositor.insert(
360                 C::Default, 12, c, 0, 4, C::AppendFlag | C::PrependFlag | C::DefaultFlag);
361         const int indexes[] = {6,7,8,9,0,1,2,3,4,5,6,7,0,1,2,3,0,1,2,3,4,5,6,7,8,9,10,11,4,5,6,7,2,3};
362         const int *lists[]  = {c,c,c,c,b,b,b,b,b,b,b,b,c,c,c,c,a,a,a,a,a,a,a,a,a,a, a, a,b,b,b,b,c,c};
363         QCOMPARE(compositor.count(C::Default), lengthOf(indexes));
364         for (int i = 0; i < lengthOf(indexes); ++i) {
365             it = compositor.find(C::Default, i);
366             QCOMPARE(it.list<int>(), lists[i]);
367             if (lists[i]) QCOMPARE(it.modelIndex(), indexes[i]);
368         }
369     } { // Insert into range.
370         compositor.insert(
371                 C::Default, 8, c, 0, 4, C::AppendFlag | C::PrependFlag | C::DefaultFlag);
372         const int indexes[] = {6,7,8,9,0,1,2,3,0,1,2,3,4,5,6,7,0,1,2,3,0,1,2,3,4,5,6,7,8,9,10,11,4,5,6,7,2,3};
373         const int *lists[]  = {c,c,c,c,b,b,b,b,c,c,c,c,b,b,b,b,c,c,c,c,a,a,a,a,a,a,a,a,a,a, a, a,b,b,b,b,c,c};
374         QCOMPARE(compositor.count(C::Default), lengthOf(indexes));
375         for (int i = 0; i < lengthOf(indexes); ++i) {
376             it = compositor.find(C::Default, i);
377             QCOMPARE(it.list<int>(), lists[i]);
378             if (lists[i]) QCOMPARE(it.modelIndex(), indexes[i]);
379         }
380     }
381 }
382
383 void tst_qdeclarativelistcompositor::clearFlags_data()
384 {
385     QTest::addColumn<RangeList>("ranges");
386     QTest::addColumn<C::Group>("group");
387     QTest::addColumn<int>("index");
388     QTest::addColumn<int>("count");
389     QTest::addColumn<int>("flags");
390     QTest::addColumn<RemoveList>("expectedRemoves");
391     QTest::addColumn<IndexArray>("cacheIndexes");
392     QTest::addColumn<ListArray>("cacheLists");
393     QTest::addColumn<IndexArray>("defaultIndexes");
394     QTest::addColumn<ListArray>("defaultLists");
395     QTest::addColumn<IndexArray>("visibleIndexes");
396     QTest::addColumn<ListArray>("visibleLists");
397     QTest::addColumn<IndexArray>("selectionIndexes");
398     QTest::addColumn<ListArray>("selectionLists");
399
400     int listA; void *a = &listA;
401
402     {   static const int cacheIndexes[] = {0,1,2,3,4,5,6,7,8,9,10,11,0,0,0,0};
403         static const void *cacheLists[] = {a,a,a,a,a,a,a,a,a,a, a, a,0,0,0,0};
404         static const int defaultIndexes[] = {0,1,2,3,4,5,6,7,8,9,10,11,0,0,0,0};
405         static const void *defaultLists[] = {a,a,a,a,a,a,a,a,a,a, a, a,0,0,0,0};
406         static const int visibleIndexes[] = {0,1,2,3,4,5,6,7,8,9,10,11,0,0,0,0};
407         static const void *visibleLists[] = {a,a,a,a,a,a,a,a,a,a, a, a,0,0,0,0};
408         static const int selectionIndexes[] = {0,1,4,5,6,7,8,9,10,11,0,0,0,0};
409         static const void *selectionLists[] = {a,a,a,a,a,a,a,a, a, a,0,0,0,0};
410         QTest::newRow("Default, 2, 2, Selection")
411                 << (RangeList()
412                     << Range(a, 0, 12, int(C::AppendFlag | C::PrependFlag |  SelectionFlag | VisibleFlag | C::DefaultFlag | C::CacheFlag))
413                     << Range(0, 0, 4, int(SelectionFlag | VisibleFlag | C::DefaultFlag | C::CacheFlag)))
414                 << C::Default << 2 << 2 << int(SelectionFlag)
415                 << (RemoveList()
416                     << Remove(2, 2, 2, 2, 2, SelectionFlag | C::CacheFlag))
417                 << IndexArray(cacheIndexes) << ListArray(cacheLists)
418                 << IndexArray(defaultIndexes) << ListArray(defaultLists)
419                 << IndexArray(visibleIndexes) << ListArray(visibleLists)
420                 << IndexArray(selectionIndexes) << ListArray(selectionLists);
421     } { static const int cacheIndexes[] = {0,1,2,3,4,5,6,7,8,9,10,11,0,0,0,0};
422         static const void *cacheLists[] = {a,a,a,a,a,a,a,a,a,a, a, a,0,0,0,0};
423         static const int defaultIndexes[] = {0,1,2,3,4,5,6,7,8,9,10,11,0,0,0,0};
424         static const void *defaultLists[] = {a,a,a,a,a,a,a,a,a,a, a, a,0,0,0,0};
425         static const int visibleIndexes[] = {0,2,3,5,6,7,8,9,10,11,0,0,0,0};
426         static const void *visibleLists[] = {a,a,a,a,a,a,a,a, a, a,0,0,0,0};
427         static const int selectionIndexes[] = {0,1,4,5,6,7,8,9,10,11,0,0,0,0};
428         static const void *selectionLists[] = {a,a,a,a,a,a,a,a, a, a,0,0,0,0};
429         QTest::newRow("Selection, 1, 2, Visible")
430                 << (RangeList()
431                     << Range(a, 0, 2, int(C::PrependFlag | SelectionFlag | VisibleFlag | C::DefaultFlag  | C::CacheFlag))
432                     << Range(a, 2, 2, int(C::PrependFlag | VisibleFlag | C::DefaultFlag  | C::CacheFlag))
433                     << Range(a, 4, 8, int(C::AppendFlag | C::PrependFlag | SelectionFlag | VisibleFlag | C::DefaultFlag  | C::CacheFlag))
434                     << Range(0, 0, 4, int(SelectionFlag | VisibleFlag | C::DefaultFlag | C::CacheFlag)))
435                 << Selection << 1 << 2 << int(VisibleFlag)
436                 << (RemoveList()
437                     << Remove(1, 1, 1, 1, 1, VisibleFlag | C::CacheFlag)
438                     << Remove(2, 3, 4, 4, 1, VisibleFlag | C::CacheFlag))
439                 << IndexArray(cacheIndexes) << ListArray(cacheLists)
440                 << IndexArray(defaultIndexes) << ListArray(defaultLists)
441                 << IndexArray(visibleIndexes) << ListArray(visibleLists)
442                 << IndexArray(selectionIndexes) << ListArray(selectionLists);
443     } { static const int cacheIndexes[] = {0,1,2,3,4,5,6,7,8,9,10,11,0,0,0,0};
444         static const void *cacheLists[] = {a,a,a,a,a,a,a,a,a,a, a, a,0,0,0,0};
445         static const int defaultIndexes[] = {0,1,2,3,4,5,6,7,8,9,10,11,0,0,0};
446         static const void *defaultLists[] = {a,a,a,a,a,a,a,a,a,a, a, a,0,0,0};
447         static const int visibleIndexes[] = {0,2,3,5,6,7,8,9,10,11,0,0,0};
448         static const void *visibleLists[] = {a,a,a,a,a,a,a,a, a, a,0,0,0};
449         static const int selectionIndexes[] = {0,1,4,5,6,7,8,9,10,11,0,0,0};
450         static const void *selectionLists[] = {a,a,a,a,a,a,a,a, a, a,0,0,0};
451         QTest::newRow("Default, 13, 1, Prepend | Selection | Visible | Default")
452                 << (RangeList()
453                     << Range(a, 0, 1, int(C::PrependFlag | SelectionFlag | VisibleFlag | C::DefaultFlag  | C::CacheFlag))
454                     << Range(a, 1, 1, int(C::PrependFlag | SelectionFlag | C::DefaultFlag  | C::CacheFlag))
455                     << Range(a, 2, 2, int(C::PrependFlag | VisibleFlag | C::DefaultFlag  | C::CacheFlag))
456                     << Range(a, 4, 1, int(C::PrependFlag | SelectionFlag | C::DefaultFlag  | C::CacheFlag))
457                     << Range(a, 5, 7, int(C::AppendFlag | C::PrependFlag | SelectionFlag | VisibleFlag | C::DefaultFlag  | C::CacheFlag))
458                     << Range(0, 0, 4, int(SelectionFlag | VisibleFlag | C::DefaultFlag | C::CacheFlag)))
459                 << C::Default << 13 << 1 << int(C::PrependFlag | SelectionFlag | VisibleFlag | C::DefaultFlag)
460                 << (RemoveList()
461                     << Remove(11, 11, 13, 13, 1, SelectionFlag | VisibleFlag | C::DefaultFlag | C::CacheFlag))
462                 << IndexArray(cacheIndexes) << ListArray(cacheLists)
463                 << IndexArray(defaultIndexes) << ListArray(defaultLists)
464                 << IndexArray(visibleIndexes) << ListArray(visibleLists)
465                 << IndexArray(selectionIndexes) << ListArray(selectionLists);
466     } { static const int cacheIndexes[] = {0,1,2,3,4,5,6,7,8,9,10,0};
467         static const void *cacheLists[] = {a,a,a,a,a,a,a,a,a,a, a,0};
468         static const int defaultIndexes[] = {0,1,2,3,4,5,6,7,8,9,10,11,0,0,0};
469         static const void *defaultLists[] = {a,a,a,a,a,a,a,a,a,a, a, a,0,0,0};
470         static const int visibleIndexes[] = {0,2,3,5,6,7,8,9,10,11,0,0,0};
471         static const void *visibleLists[] = {a,a,a,a,a,a,a,a, a, a,0,0,0};
472         static const int selectionIndexes[] = {0,1,4,5,6,7,8,9,10,11,0,0,0};
473         static const void *selectionLists[] = {a,a,a,a,a,a,a,a, a, a,0,0,0};
474         QTest::newRow("Cache, 11, 4, Cache")
475                 << (RangeList()
476                     << Range(a, 0, 1, int(C::PrependFlag | SelectionFlag | VisibleFlag | C::DefaultFlag  | C::CacheFlag))
477                     << Range(a, 1, 1, int(C::PrependFlag | SelectionFlag | C::DefaultFlag  | C::CacheFlag))
478                     << Range(a, 2, 2, int(C::PrependFlag | VisibleFlag | C::DefaultFlag  | C::CacheFlag))
479                     << Range(a, 4, 1, int(C::PrependFlag | SelectionFlag | C::DefaultFlag  | C::CacheFlag))
480                     << Range(a, 5, 7, int(C::AppendFlag | C::PrependFlag | SelectionFlag | VisibleFlag | C::DefaultFlag  | C::CacheFlag))
481                     << Range(0, 0, 1, int(C::CacheFlag))
482                     << Range(0, 0, 3, int(SelectionFlag | VisibleFlag | C::DefaultFlag | C::CacheFlag)))
483                 << C::Cache << 11 << 4 << int(C::CacheFlag)
484                 << (RemoveList())
485                 << IndexArray(cacheIndexes) << ListArray(cacheLists)
486                 << IndexArray(defaultIndexes) << ListArray(defaultLists)
487                 << IndexArray(visibleIndexes) << ListArray(visibleLists)
488                 << IndexArray(selectionIndexes) << ListArray(selectionLists);
489     } { static const int cacheIndexes[] = {0,1,2,3,4,5,6,7,8,9,10,0};
490         static const void *cacheLists[] = {a,a,a,a,a,a,a,a,a,a, a,0};
491         static const int defaultIndexes[] = {0,1,2,3,4,5,6,7,8,9,10,0};
492         static const void *defaultLists[] = {a,a,a,a,a,a,a,a,a,a, a,0};
493         static const int visibleIndexes[] = {0,2,3,5,6,7,8,9,10,0};
494         static const void *visibleLists[] = {a,a,a,a,a,a,a,a, a,0};
495         static const int selectionIndexes[] = {0,1,4,5,6,7,8,9,10,0};
496         static const void *selectionLists[] = {a,a,a,a,a,a,a,a, a,0};
497         QTest::newRow("Default, 11, 3, Default | Visible | Selection")
498                 << (RangeList()
499                     << Range(a, 0, 1, int(C::PrependFlag | SelectionFlag | VisibleFlag | C::DefaultFlag  | C::CacheFlag))
500                     << Range(a, 1, 1, int(C::PrependFlag | SelectionFlag | C::DefaultFlag  | C::CacheFlag))
501                     << Range(a, 2, 2, int(C::PrependFlag | VisibleFlag | C::DefaultFlag  | C::CacheFlag))
502                     << Range(a, 4, 1, int(C::PrependFlag | SelectionFlag | C::DefaultFlag  | C::CacheFlag))
503                     << Range(a, 5, 6, int(C::PrependFlag | SelectionFlag | VisibleFlag | C::DefaultFlag  | C::CacheFlag))
504                     << Range(a, 11, 1, int(C::AppendFlag | C::PrependFlag | SelectionFlag | VisibleFlag | C::DefaultFlag))
505                     << Range(0, 0, 2, int(SelectionFlag | VisibleFlag | C::DefaultFlag))
506                     << Range(0, 0, 1, int(SelectionFlag | VisibleFlag | C::DefaultFlag | C::CacheFlag)))
507                 << C::Default << 11 << 3 << int(C::DefaultFlag | VisibleFlag| SelectionFlag)
508                 << (RemoveList()
509                     << Remove(9, 9, 11, 11, 1, SelectionFlag | VisibleFlag | C::DefaultFlag)
510                     << Remove(9, 9, 11, 11, 2, SelectionFlag | VisibleFlag | C::DefaultFlag))
511                 << IndexArray(cacheIndexes) << ListArray(cacheLists)
512                 << IndexArray(defaultIndexes) << ListArray(defaultLists)
513                 << IndexArray(visibleIndexes) << ListArray(visibleLists)
514                 << IndexArray(selectionIndexes) << ListArray(selectionLists);
515     }
516 }
517
518 void tst_qdeclarativelistcompositor::clearFlags()
519 {
520     QFETCH(RangeList, ranges);
521     QFETCH(C::Group, group);
522     QFETCH(int, index);
523     QFETCH(int, count);
524     QFETCH(int, flags);
525     QFETCH(RemoveList, expectedRemoves);
526     QFETCH(IndexArray, cacheIndexes);
527     QFETCH(ListArray, cacheLists);
528     QFETCH(IndexArray, defaultIndexes);
529     QFETCH(ListArray, defaultLists);
530     QFETCH(IndexArray, visibleIndexes);
531     QFETCH(ListArray, visibleLists);
532     QFETCH(IndexArray, selectionIndexes);
533     QFETCH(ListArray, selectionLists);
534
535     QDeclarativeListCompositor compositor;
536     compositor.setGroupCount(4);
537     compositor.setDefaultGroups(VisibleFlag | C::DefaultFlag);
538
539     foreach (const Range &range, ranges)
540         compositor.append(range.list, range.index, range.count, range.flags);
541
542     QVector<C::Remove> removes;
543     compositor.clearFlags(group, index, count, flags, &removes);
544
545     QCOMPARE(removes, expectedRemoves);
546
547     QCOMPARE(compositor.count(C::Cache), cacheIndexes.count);
548     for (int i = 0; i < cacheIndexes.count; ++i) {
549         C::iterator it = compositor.find(C::Cache, i);
550         QCOMPARE(it->list, cacheLists[i]);
551         if (cacheLists[i])
552             QCOMPARE(it.modelIndex(), cacheIndexes[i]);
553     }
554     QCOMPARE(compositor.count(C::Default), defaultIndexes.count);
555     for (int i = 0; i < defaultIndexes.count; ++i) {
556         C::iterator it = compositor.find(C::Default, i);
557         QCOMPARE(it->list, defaultLists[i]);
558         if (defaultLists[i])
559             QCOMPARE(it.modelIndex(), defaultIndexes[i]);
560     }
561     QCOMPARE(compositor.count(Visible), visibleIndexes.count);
562     for (int i = 0; i < visibleIndexes.count; ++i) {
563         C::iterator it = compositor.find(Visible, i);
564         QCOMPARE(it->list, visibleLists[i]);
565         if (visibleLists[i])
566             QCOMPARE(it.modelIndex(), visibleIndexes[i]);
567     }
568     QCOMPARE(compositor.count(Selection), selectionIndexes.count);
569     for (int i = 0; i < selectionIndexes.count; ++i) {
570         C::iterator it = compositor.find(Selection, i);
571         QCOMPARE(it->list, selectionLists[i]);
572         if (selectionLists[i])
573             QCOMPARE(it.modelIndex(), selectionIndexes[i]);
574     }
575 }
576
577 void tst_qdeclarativelistcompositor::setFlags_data()
578 {
579     QTest::addColumn<RangeList>("ranges");
580     QTest::addColumn<C::Group>("group");
581     QTest::addColumn<int>("index");
582     QTest::addColumn<int>("count");
583     QTest::addColumn<int>("flags");
584     QTest::addColumn<InsertList>("expectedInserts");
585     QTest::addColumn<IndexArray>("cacheIndexes");
586     QTest::addColumn<ListArray>("cacheLists");
587     QTest::addColumn<IndexArray>("defaultIndexes");
588     QTest::addColumn<ListArray>("defaultLists");
589     QTest::addColumn<IndexArray>("visibleIndexes");
590     QTest::addColumn<ListArray>("visibleLists");
591     QTest::addColumn<IndexArray>("selectionIndexes");
592     QTest::addColumn<ListArray>("selectionLists");
593
594     int listA; void *a = &listA;
595
596     {   static const int cacheIndexes[] = {0,0,0,0};
597         static const void *cacheLists[] = {0,0,0,0};
598         static const int defaultIndexes[] = {0,1,2,3,4,5,6,7,8,9,10,11};
599         static const void *defaultLists[] = {a,a,a,a,a,a,a,a,a,a, a, a};
600         QTest::newRow("Default, 2, 2, Default")
601                 << (RangeList()
602                     << Range(a, 0, 12, C::DefaultFlag)
603                     << Range(0, 0, 4, C::CacheFlag))
604                 << C::Default << 2 << 2 << int(C::DefaultFlag)
605                 << (InsertList())
606                 << IndexArray(cacheIndexes) << ListArray(cacheLists)
607                 << IndexArray(defaultIndexes) << ListArray(defaultLists)
608                 << IndexArray() << ListArray()
609                 << IndexArray() << ListArray();
610     } { static const int cacheIndexes[] = {0,0,0,0};
611         static const void *cacheLists[] = {0,0,0,0};
612         static const int defaultIndexes[] = {0,1,2,3,4,5,6,7,8,9,10,11};
613         static const void *defaultLists[] = {a,a,a,a,a,a,a,a,a,a, a, a};
614         static const int visibleIndexes[] = {2,3};
615         static const void *visibleLists[] = {a,a};
616         QTest::newRow("Default, 2, 2, Visible")
617                 << (RangeList()
618                     << Range(a, 0, 12, C::DefaultFlag)
619                     << Range(0, 0, 4, C::CacheFlag))
620                 << C::Default << 2 << 2 << int(VisibleFlag)
621                 << (InsertList()
622                     << Insert(0, 0, 2, 0, 2, VisibleFlag))
623                 << IndexArray(cacheIndexes) << ListArray(cacheLists)
624                 << IndexArray(defaultIndexes) << ListArray(defaultLists)
625                 << IndexArray(visibleIndexes) << ListArray(visibleLists)
626                 << IndexArray() << ListArray();
627     } { static const int cacheIndexes[] = {3,6,0,0,0,0};
628         static const void *cacheLists[] = {a,a,0,0,0,0};
629         static const int defaultIndexes[] = {0,1,2,3,4,5,6,7,8,9,10,11};
630         static const void *defaultLists[] = {a,a,a,a,a,a,a,a,a,a, a, a};
631         static const int visibleIndexes[] = {2,3,6,7};
632         static const void *visibleLists[] = {a,a,a,a};
633         static const int selectionIndexes[] = {3,6};
634         static const void *selectionLists[] = {a,a};
635         QTest::newRow("Visible, 1, 2, Selection | Cache")
636                 << (RangeList()
637                     << Range(a, 0, 2, C::DefaultFlag)
638                     << Range(a, 2, 2, VisibleFlag | C::DefaultFlag)
639                     << Range(a, 4, 2, C::DefaultFlag)
640                     << Range(a, 6, 2, VisibleFlag | C::DefaultFlag)
641                     << Range(a, 8, 4, C::DefaultFlag)
642                     << Range(0, 0, 4, C::CacheFlag))
643                 << Visible << 1 << 2 << int(SelectionFlag | C::CacheFlag)
644                 << (InsertList()
645                     << Insert(0, 1, 3, 0, 1, SelectionFlag | C::CacheFlag)
646                     << Insert(1, 2, 6, 1, 1, SelectionFlag | C::CacheFlag))
647                 << IndexArray(cacheIndexes) << ListArray(cacheLists)
648                 << IndexArray(defaultIndexes) << ListArray(defaultLists)
649                 << IndexArray(visibleIndexes) << ListArray(visibleLists)
650                 << IndexArray(selectionIndexes) << ListArray(selectionLists);
651     } { static const int cacheIndexes[] = {3,6,0,0,0,0};
652         static const void *cacheLists[] = {a,a,0,0,0,0};
653         static const int defaultIndexes[] = {0,1,2,3,4,5,6,7,8,9,10,11};
654         static const void *defaultLists[] = {a,a,a,a,a,a,a,a,a,a, a, a};
655         static const int visibleIndexes[] = {2,3,6,7,0};
656         static const void *visibleLists[] = {a,a,a,a,0};
657         static const int selectionIndexes[] = {3,6};
658         static const void *selectionLists[] = {a,a};
659         QTest::newRow("Cache, 3, 1, Visible")
660                 << (RangeList()
661                     << Range(a, 0, 2, C::DefaultFlag)
662                     << Range(a, 2, 1, VisibleFlag | C::DefaultFlag)
663                     << Range(a, 3, 1, SelectionFlag | VisibleFlag | C::DefaultFlag | C::CacheFlag)
664                     << Range(a, 4, 2, C::DefaultFlag)
665                     << Range(a, 6, 1, SelectionFlag | VisibleFlag | C::DefaultFlag | C::CacheFlag)
666                     << Range(a, 7, 1, VisibleFlag | C::DefaultFlag)
667                     << Range(a, 8, 4, C::DefaultFlag)
668                     << Range(0, 0, 4, C::CacheFlag))
669                 << C::Cache << 3 << 1 << int(VisibleFlag)
670                 << (InsertList()
671                     << Insert(2, 4, 12, 3, 1, VisibleFlag | C::CacheFlag))
672                 << IndexArray(cacheIndexes) << ListArray(cacheLists)
673                 << IndexArray(defaultIndexes) << ListArray(defaultLists)
674                 << IndexArray(visibleIndexes) << ListArray(visibleLists)
675                 << IndexArray(selectionIndexes) << ListArray(selectionLists);
676     } { static const int cacheIndexes[] = {0,1,2,3,4,5,6,7,8,9,10,11};
677         static const void *cacheLists[] = {a,a,a,a,a,a,a,a,a,a, a, a};
678         static const int defaultIndexes[] = {0,1,2,3,4,5,6,7,8,9,10,11};
679         static const void *defaultLists[] = {a,a,a,a,a,a,a,a,a,a, a, a};
680         static const int visibleIndexes[] = {0,1,3,4,5,6,7,8,9,10,11};
681         static const void *visibleLists[] = {a,a,a,a,a,a,a,a,a, a, a};
682         static const int selectionIndexes[] = {2,6,7,8,9};
683         static const void *selectionLists[] = {a,a,a,a,a};
684         QTest::newRow("Existing flag, sparse selection")
685                 << (RangeList()
686                     << Range(a, 0, 2, C::PrependFlag | VisibleFlag | C::DefaultFlag | C::CacheFlag)
687                     << Range(a, 2, 1, C::PrependFlag | SelectionFlag | C::DefaultFlag | C::CacheFlag)
688                     << Range(a, 3, 3, C::PrependFlag | VisibleFlag | C::DefaultFlag | C::CacheFlag)
689                     << Range(a, 6, 4, C::PrependFlag | SelectionFlag | VisibleFlag | C::DefaultFlag | C::CacheFlag)
690                     << Range(a,10, 2, C::AppendFlag | C::PrependFlag | VisibleFlag | C::DefaultFlag | C::CacheFlag))
691                 << C::Cache << 3 << 1 << int(VisibleFlag)
692                 << InsertList()
693                 << IndexArray(cacheIndexes) << ListArray(cacheLists)
694                 << IndexArray(defaultIndexes) << ListArray(defaultLists)
695                 << IndexArray(visibleIndexes) << ListArray(visibleLists)
696                 << IndexArray(selectionIndexes) << ListArray(selectionLists);
697     }
698 }
699
700 void tst_qdeclarativelistcompositor::setFlags()
701 {
702     QFETCH(RangeList, ranges);
703     QFETCH(C::Group, group);
704     QFETCH(int, index);
705     QFETCH(int, count);
706     QFETCH(int, flags);
707     QFETCH(InsertList, expectedInserts);
708     QFETCH(IndexArray, cacheIndexes);
709     QFETCH(ListArray, cacheLists);
710     QFETCH(IndexArray, defaultIndexes);
711     QFETCH(ListArray, defaultLists);
712     QFETCH(IndexArray, visibleIndexes);
713     QFETCH(ListArray, visibleLists);
714     QFETCH(IndexArray, selectionIndexes);
715     QFETCH(ListArray, selectionLists);
716
717     QDeclarativeListCompositor compositor;
718     compositor.setGroupCount(4);
719     compositor.setDefaultGroups(VisibleFlag | C::DefaultFlag);
720
721     foreach (const Range &range, ranges)
722         compositor.append(range.list, range.index, range.count, range.flags);
723
724     QVector<C::Insert> inserts;
725     compositor.setFlags(group, index, count, flags, &inserts);
726
727     QCOMPARE(inserts, expectedInserts);
728
729     QCOMPARE(compositor.count(C::Cache), cacheIndexes.count);
730     for (int i = 0; i < cacheIndexes.count; ++i) {
731         C::iterator it = compositor.find(C::Cache, i);
732         QCOMPARE(it->list, cacheLists[i]);
733         if (cacheLists[i])
734             QCOMPARE(it.modelIndex(), cacheIndexes[i]);
735     }
736     QCOMPARE(compositor.count(C::Default), defaultIndexes.count);
737     for (int i = 0; i < defaultIndexes.count; ++i) {
738         C::iterator it = compositor.find(C::Default, i);
739         QCOMPARE(it->list, defaultLists[i]);
740         if (defaultLists[i])
741             QCOMPARE(it.modelIndex(), defaultIndexes[i]);
742     }
743     QCOMPARE(compositor.count(Visible), visibleIndexes.count);
744     for (int i = 0; i < visibleIndexes.count; ++i) {
745         C::iterator it = compositor.find(Visible, i);
746         QCOMPARE(it->list, visibleLists[i]);
747         if (visibleLists[i])
748             QCOMPARE(it.modelIndex(), visibleIndexes[i]);
749     }
750     QCOMPARE(compositor.count(Selection), selectionIndexes.count);
751     for (int i = 0; i < selectionIndexes.count; ++i) {
752         C::iterator it = compositor.find(Selection, i);
753         QCOMPARE(it->list, selectionLists[i]);
754         if (selectionLists[i])
755             QCOMPARE(it.modelIndex(), selectionIndexes[i]);
756     }
757 }
758
759 void tst_qdeclarativelistcompositor::move_data()
760 {
761     QTest::addColumn<RangeList>("ranges");
762     QTest::addColumn<C::Group>("fromGroup");
763     QTest::addColumn<int>("from");
764     QTest::addColumn<C::Group>("toGroup");
765     QTest::addColumn<int>("to");
766     QTest::addColumn<int>("count");
767     QTest::addColumn<RemoveList>("expectedRemoves");
768     QTest::addColumn<InsertList>("expectedInserts");
769     QTest::addColumn<IndexArray>("cacheIndexes");
770     QTest::addColumn<ListArray>("cacheLists");
771     QTest::addColumn<IndexArray>("defaultIndexes");
772     QTest::addColumn<ListArray>("defaultLists");
773     QTest::addColumn<IndexArray>("visibleIndexes");
774     QTest::addColumn<ListArray>("visibleLists");
775     QTest::addColumn<IndexArray>("selectionIndexes");
776     QTest::addColumn<ListArray>("selectionLists");
777
778     int listA; void *a = &listA;
779     int listB; void *b = &listB;
780     int listC; void *c = &listC;
781
782     {   static const int cacheIndexes[] = {0,0,0,0,2,3};
783         static const void *cacheLists[] = {0,0,0,0,c,c};
784         static const int defaultIndexes[] = {0,0,1,2,3,4,5,0,1,2,3,4,5,1,2,3,0,1,2,3,4,5};
785         static const void *defaultLists[] = {0,a,a,a,a,a,a,b,b,b,b,b,b,0,0,0,c,c,c,c,c,c};
786         QTest::newRow("15, 0, 1")
787                 << (RangeList()
788                     << Range(a, 0, 6, C::DefaultFlag)
789                     << Range(b, 0, 6, C::AppendFlag | C::PrependFlag | C::DefaultFlag)
790                     << Range(0, 0, 4, C::DefaultFlag | C::CacheFlag)
791                     << Range(c, 0, 2, C::PrependFlag | C::DefaultFlag)
792                     << Range(c, 2, 2, C::PrependFlag | C::DefaultFlag | C::CacheFlag)
793                     << Range(c, 4, 2, C::AppendFlag | C::PrependFlag | C::DefaultFlag))
794                 << C::Default << 15 << C::Default << 0 << 1
795                 << (RemoveList()
796                     << Remove(0, 0, 15, 3, 1, C::DefaultFlag | C::CacheFlag, 0))
797                 << (InsertList()
798                     << Insert(0, 0, 0, 0, 1, C::DefaultFlag | C::CacheFlag, 0))
799                 << IndexArray(cacheIndexes) << ListArray(cacheLists)
800                 << IndexArray(defaultIndexes) << ListArray(defaultLists)
801                 << IndexArray() << ListArray()
802                 << IndexArray() << ListArray();
803     } { static const int cacheIndexes[] = {0,0,0,0,2,3};
804         static const void *cacheLists[] = {0,0,0,0,c,c};
805         static const int defaultIndexes[] = {0,1,0,1,2,3,4,5,0,1,2,3,4,5,2,3,0,1,2,3,4,5};
806         static const void *defaultLists[] = {0,0,a,a,a,a,a,a,b,b,b,b,b,b,0,0,c,c,c,c,c,c};
807         QTest::newRow("15, 1, 1")
808                 << (RangeList()
809                     << Range(0, 0, 1, C::DefaultFlag | C::CacheFlag)
810                     << Range(a, 0, 6, C::DefaultFlag)
811                     << Range(b, 0, 6, C::AppendFlag | C::PrependFlag | C::DefaultFlag)
812                     << Range(0, 0, 3, C::DefaultFlag | C::CacheFlag)
813                     << Range(c, 0, 2, C::PrependFlag | C::DefaultFlag)
814                     << Range(c, 2, 2, C::PrependFlag | C::DefaultFlag | C::CacheFlag)
815                     << Range(c, 4, 2, C::AppendFlag | C::PrependFlag | C::DefaultFlag))
816                 << C::Default << 15 << C::Default << 1 << 1
817                 << (RemoveList()
818                     << Remove(0, 0, 15, 3, 1, C::DefaultFlag | C::CacheFlag, 0))
819                 << (InsertList()
820                     << Insert(0, 0, 1, 1, 1, C::DefaultFlag | C::CacheFlag, 0))
821                 << IndexArray(cacheIndexes) << ListArray(cacheLists)
822                 << IndexArray(defaultIndexes) << ListArray(defaultLists)
823                 << IndexArray() << ListArray()
824                 << IndexArray() << ListArray();
825     } { static const int cacheIndexes[] = {0,0,0,0,2,3};
826         static const void *cacheLists[] = {0,0,0,0,c,c};
827         static const int defaultIndexes[] = {0,1,2,0,1,3,4,5,0,1,2,3,4,5,2,3,0,1,2,3,4,5};
828         static const void *defaultLists[] = {a,a,a,0,0,a,a,a,b,b,b,b,b,b,0,0,c,c,c,c,c,c};
829         QTest::newRow("0, 3, 2")
830                 << (RangeList()
831                     << Range(0, 0, 2, C::DefaultFlag | C::CacheFlag)
832                     << Range(a, 0, 6, C::DefaultFlag)
833                     << Range(b, 0, 6, C::AppendFlag | C::PrependFlag | C::DefaultFlag)
834                     << Range(0, 0, 2, C::DefaultFlag | C::CacheFlag)
835                     << Range(c, 0, 2, C::PrependFlag | C::DefaultFlag)
836                     << Range(c, 2, 2, C::PrependFlag | C::DefaultFlag | C::CacheFlag)
837                     << Range(c, 4, 2, C::AppendFlag | C::PrependFlag | C::DefaultFlag))
838                 << C::Default << 0 << C::Default << 3 << 2
839                 << (RemoveList()
840                     << Remove(0, 0, 0, 0, 2, C::DefaultFlag | C::CacheFlag, 0))
841                 << (InsertList()
842                     << Insert(0, 0, 3, 0, 2, C::DefaultFlag | C::CacheFlag, 0))
843                 << IndexArray(cacheIndexes) << ListArray(cacheLists)
844                 << IndexArray(defaultIndexes) << ListArray(defaultLists)
845                 << IndexArray() << ListArray()
846                 << IndexArray() << ListArray();
847     } { static const int cacheIndexes[] = {0,0,0,0,2,3};
848         static const void *cacheLists[] = {0,0,0,0,c,c};
849         static const int defaultIndexes[] = {0,5,0,1,2,3,4,5,0,1,0,1,2,2,3,3,4,1,2,3,4,5};
850         static const void *defaultLists[] = {a,a,b,b,b,b,b,b,0,0,c,a,a,0,0,a,a,c,c,c,c,c};
851         QTest::newRow("7, 1, 10")
852                 << (RangeList()
853                     << Range(a, 0, 3, C::DefaultFlag)
854                     << Range(0, 0, 2, C::DefaultFlag | C::CacheFlag)
855                     << Range(a, 3, 3, C::DefaultFlag)
856                     << Range(b, 0, 6, C::AppendFlag | C::PrependFlag | C::DefaultFlag)
857                     << Range(0, 0, 2, C::DefaultFlag | C::CacheFlag)
858                     << Range(c, 0, 2, C::PrependFlag | C::DefaultFlag)
859                     << Range(c, 2, 2, C::PrependFlag | C::DefaultFlag | C::CacheFlag)
860                     << Range(c, 4, 2, C::AppendFlag | C::PrependFlag | C::DefaultFlag))
861                 << C::Default << 7 << C::Default << 1 << 10
862                 << (RemoveList()
863                     << Remove(0, 0, 7, 2, 1, C::DefaultFlag, 0)
864                     << Remove(0, 0, 7, 2, 6, C::DefaultFlag, 1)
865                     << Remove(0, 0, 7, 2, 2, C::DefaultFlag | C::CacheFlag, 2)
866                     << Remove(0, 0, 7, 2, 1, C::DefaultFlag, 3))
867                 << (InsertList()
868                     << Insert(0, 0, 1, 0, 1, C::DefaultFlag, 0)
869                     << Insert(0, 0, 2, 0, 6, C::DefaultFlag, 1)
870                     << Insert(0, 0, 8, 0, 2, C::DefaultFlag | C::CacheFlag, 2)
871                     << Insert(0, 0, 10, 2, 1, C::DefaultFlag, 3))
872                 << IndexArray(cacheIndexes) << ListArray(cacheLists)
873                 << IndexArray(defaultIndexes) << ListArray(defaultLists)
874                 << IndexArray() << ListArray()
875                 << IndexArray() << ListArray();
876     } { static const int cacheIndexes[] = {0,0,0,0,3,2};
877         static const void *cacheLists[] = {0,0,0,0,c,c};
878         static const int defaultIndexes[] = {0,5,0,1,2,3,4,5,0,1,0,1,2,2,3,3,4,3,4,5,1,2};
879         static const void *defaultLists[] = {a,a,b,b,b,b,b,b,0,0,c,a,a,0,0,a,a,c,c,c,c,c};
880         QTest::newRow("17, 20, 2")
881                 << (RangeList()
882                     << Range(a, 0, 1, C::DefaultFlag)
883                     << Range(a, 5, 1, C::DefaultFlag)
884                     << Range(b, 0, 6, C::DefaultFlag)
885                     << Range(0, 0, 2, C::DefaultFlag | C::CacheFlag)
886                     << Range(c, 0, 1, C::DefaultFlag)
887                     << Range(a, 1, 2, C::DefaultFlag)
888                     << Range(0, 0, 2, C::DefaultFlag | C::CacheFlag)
889                     << Range(a, 3, 2, C::DefaultFlag)
890                     << Range(b, 0, 6, C::AppendFlag | C::PrependFlag)
891                     << Range(c, 0, 1, C::PrependFlag)
892                     << Range(c, 1, 1, C::PrependFlag | C::DefaultFlag)
893                     << Range(c, 2, 2, C::PrependFlag | C::DefaultFlag | C::CacheFlag)
894                     << Range(c, 4, 2, C::AppendFlag | C::PrependFlag | C::DefaultFlag))
895                 << C::Default << 17 << C::Default << 20 << 2
896                 << (RemoveList()
897                     << Remove(0, 0, 17, 4, 1, C::DefaultFlag, 0)
898                     << Remove(0, 0, 17, 4, 1, C::DefaultFlag | C::CacheFlag, 1))
899                 << (InsertList()
900                     << Insert(0, 0, 20, 5, 1, C::DefaultFlag, 0)
901                     << Insert(0, 0, 21, 5, 1, C::DefaultFlag | C::CacheFlag, 1))
902                 << IndexArray(cacheIndexes) << ListArray(cacheLists)
903                 << IndexArray(defaultIndexes) << ListArray(defaultLists)
904                 << IndexArray() << ListArray()
905                 << IndexArray() << ListArray();
906     } { static const int cacheIndexes[] = {8,9,10,4,11,0,1,2,3,5,6,7};
907         static const void *cacheLists[] = {a,a, a,a, a,a,a,a,a,a,a,a};
908         static const int defaultIndexes[] = {8,9,10,4,11,0,1,2,3,5,6,7};
909         static const void *defaultLists[] = {a,a, a,a, a,a,a,a,a,a,a,a};
910         static const int visibleIndexes[] = {8,9,10,4,11,0,1,2,3,5,6,7};
911         static const void *visibleLists[] = {a,a, a,a, a,a,a,a,a,a,a,a};
912         QTest::newRow("3, 4, 5")
913                 << (RangeList()
914                     << Range(a, 8, 4, VisibleFlag | C::DefaultFlag | C::CacheFlag)
915                     << Range(a, 0, 2, C::PrependFlag | VisibleFlag | C::DefaultFlag | C::CacheFlag)
916                     << Range(a, 2, 1, C::PrependFlag)
917                     << Range(a, 2, 1, VisibleFlag | C::DefaultFlag | C::CacheFlag)
918                     << Range(a, 3, 5, C::PrependFlag | VisibleFlag | C::DefaultFlag | C::CacheFlag)
919                     << Range(a, 8, 4, C::AppendFlag | C::PrependFlag))
920                 << C::Default << 3 << C::Default << 4 << 5
921                 << (RemoveList()
922                     << Remove(0, 3, 3, 3, 1, VisibleFlag | C::DefaultFlag | C::CacheFlag, 0)
923                     << Remove(0, 3, 3, 3, 2, VisibleFlag | C::DefaultFlag | C::CacheFlag, 1)
924                     << Remove(0, 3, 3, 3, 1, VisibleFlag | C::DefaultFlag | C::CacheFlag, 2)
925                     << Remove(0, 3, 3, 3, 1, VisibleFlag | C::DefaultFlag | C::CacheFlag, 3))
926                 << (InsertList()
927                     << Insert(0, 4, 4, 4, 1, VisibleFlag | C::DefaultFlag | C::CacheFlag, 0)
928                     << Insert(0, 5, 5, 5, 2, VisibleFlag | C::DefaultFlag | C::CacheFlag, 1)
929                     << Insert(0, 7, 7, 7, 1, VisibleFlag | C::DefaultFlag | C::CacheFlag, 2)
930                     << Insert(0, 8, 8, 8, 1, VisibleFlag | C::DefaultFlag | C::CacheFlag, 3))
931                 << IndexArray(cacheIndexes) << ListArray(cacheLists)
932                 << IndexArray(defaultIndexes) << ListArray(defaultLists)
933                 << IndexArray(visibleIndexes) << ListArray(visibleLists)
934                 << IndexArray() << ListArray();
935     } { static const int cacheIndexes[] = {0,1};
936         static const void *cacheLists[] = {a,a};
937         static const int defaultIndexes[] = {0,1};
938         static const void *defaultLists[] = {a,a};
939         QTest::newRow("0, 1, 1")
940                 << (RangeList()
941                     << Range(a, 0, 1, C::PrependFlag)
942                     << Range(a, 1, 1, C::PrependFlag | C::DefaultFlag | C::CacheFlag)
943                     << Range(a, 2, 0, C::AppendFlag | C::PrependFlag)
944                     << Range(a, 0, 1, C::DefaultFlag | C::CacheFlag))
945                 << C::Default << 0 << C::Default << 1 << 1
946                 << (RemoveList()
947                     << Remove(0, 0, 0, 0, 1, C::DefaultFlag | C::CacheFlag, 0))
948                 << (InsertList()
949                     << Insert(0, 0, 1, 1, 1, C::DefaultFlag | C::CacheFlag, 0))
950                 << IndexArray(cacheIndexes) << ListArray(cacheLists)
951                 << IndexArray(defaultIndexes) << ListArray(defaultLists)
952                 << IndexArray() << ListArray()
953                 << IndexArray() << ListArray();
954     }
955 }
956
957 void tst_qdeclarativelistcompositor::move()
958 {
959     QFETCH(RangeList, ranges);
960     QFETCH(C::Group, fromGroup);
961     QFETCH(int, from);
962     QFETCH(C::Group, toGroup);
963     QFETCH(int, to);
964     QFETCH(int, count);
965     QFETCH(RemoveList, expectedRemoves);
966     QFETCH(InsertList, expectedInserts);
967     QFETCH(IndexArray, cacheIndexes);
968     QFETCH(ListArray, cacheLists);
969     QFETCH(IndexArray, defaultIndexes);
970     QFETCH(ListArray, defaultLists);
971     QFETCH(IndexArray, visibleIndexes);
972     QFETCH(ListArray, visibleLists);
973     QFETCH(IndexArray, selectionIndexes);
974     QFETCH(ListArray, selectionLists);
975
976     QDeclarativeListCompositor compositor;
977     compositor.setGroupCount(4);
978     compositor.setDefaultGroups(VisibleFlag | C::DefaultFlag);
979
980     foreach (const Range &range, ranges)
981         compositor.append(range.list, range.index, range.count, range.flags);
982
983     QVector<C::Remove> removes;
984     QVector<C::Insert> inserts;
985     compositor.move(fromGroup, from, toGroup, to, count, fromGroup, &removes, &inserts);
986
987     QCOMPARE(removes, expectedRemoves);
988     QCOMPARE(inserts, expectedInserts);
989
990     QCOMPARE(compositor.count(C::Cache), cacheIndexes.count);
991     for (int i = 0; i < cacheIndexes.count; ++i) {
992         C::iterator it = compositor.find(C::Cache, i);
993         QCOMPARE(it->list, cacheLists[i]);
994         if (cacheLists[i])
995             QCOMPARE(it.modelIndex(), cacheIndexes[i]);
996     }
997     QCOMPARE(compositor.count(C::Default), defaultIndexes.count);
998     for (int i = 0; i < defaultIndexes.count; ++i) {
999         C::iterator it = compositor.find(C::Default, i);
1000         QCOMPARE(it->list, defaultLists[i]);
1001         if (defaultLists[i])
1002             QCOMPARE(it.modelIndex(), defaultIndexes[i]);
1003     }
1004     QCOMPARE(compositor.count(Visible), visibleIndexes.count);
1005     for (int i = 0; i < visibleIndexes.count; ++i) {
1006         C::iterator it = compositor.find(Visible, i);
1007         QCOMPARE(it->list, visibleLists[i]);
1008         if (visibleLists[i])
1009             QCOMPARE(it.modelIndex(), visibleIndexes[i]);
1010     }
1011     QCOMPARE(compositor.count(Selection), selectionIndexes.count);
1012     for (int i = 0; i < selectionIndexes.count; ++i) {
1013         C::iterator it = compositor.find(Selection, i);
1014         QCOMPARE(it->list, selectionLists[i]);
1015         if (selectionLists[i])
1016             QCOMPARE(it.modelIndex(), selectionIndexes[i]);
1017     }
1018 }
1019
1020 void tst_qdeclarativelistcompositor::moveFromEnd()
1021 {
1022     int listA; void *a = &listA;
1023
1024     QDeclarativeListCompositor compositor;
1025     compositor.append(a, 0, 1, C::AppendFlag | C::PrependFlag | C::DefaultFlag);
1026
1027     // Moving an item anchors it to that position.
1028     compositor.move(C::Default, 0, C::Default, 0, 1, C::Default);
1029
1030     // The existing item is anchored at 0 so prepending an item to the source will append it here
1031     QVector<C::Insert> inserts;
1032     compositor.listItemsInserted(a, 0, 1, &inserts);
1033
1034     QCOMPARE(inserts.count(), 1);
1035     QCOMPARE(inserts.at(0).index[1], 1);
1036     QCOMPARE(inserts.at(0).count, 1);
1037
1038     C::iterator it;
1039     it = compositor.find(C::Default, 0);
1040     QCOMPARE(it.modelIndex(), 1);
1041
1042     it = compositor.find(C::Default, 1);
1043     QCOMPARE(it.modelIndex(), 0);
1044 }
1045
1046 void tst_qdeclarativelistcompositor::clear()
1047 {
1048     QDeclarativeListCompositor compositor;
1049     compositor.setGroupCount(4);
1050     compositor.setDefaultGroups(VisibleFlag | C::DefaultFlag);
1051
1052     int listA; void *a = &listA;
1053     int listB; void *b = &listB;
1054
1055     compositor.append(a, 0, 8, C::AppendFlag | C::PrependFlag | VisibleFlag | C::DefaultFlag);
1056     compositor.append(b, 4, 5,  VisibleFlag | C::DefaultFlag);
1057     compositor.append(0, 0, 3,  VisibleFlag | C::DefaultFlag | C::CacheFlag);
1058
1059     QCOMPARE(compositor.count(C::Default), 16);
1060     QCOMPARE(compositor.count(Visible), 16);
1061     QCOMPARE(compositor.count(C::Cache), 3);
1062
1063     compositor.clear();
1064     QCOMPARE(compositor.count(C::Default), 0);
1065     QCOMPARE(compositor.count(Visible), 0);
1066     QCOMPARE(compositor.count(C::Cache), 0);
1067 }
1068
1069 void tst_qdeclarativelistcompositor::listItemsInserted_data()
1070 {
1071     QTest::addColumn<RangeList>("ranges");
1072     QTest::addColumn<void *>("list");
1073     QTest::addColumn<int>("index");
1074     QTest::addColumn<int>("count");
1075     QTest::addColumn<InsertList>("expectedInserts");
1076     QTest::addColumn<IndexArray>("cacheIndexes");
1077     QTest::addColumn<IndexArray>("defaultIndexes");
1078     QTest::addColumn<IndexArray>("visibleIndexes");
1079     QTest::addColumn<IndexArray>("selectionIndexes");
1080
1081     int listA; void *a = &listA;
1082     int listB; void *b = &listB;
1083
1084     {   static const int defaultIndexes[] = {/*A*/0,1,5,6,/*B*/0,1,2,3,/*A*/2,3,4};
1085         QTest::newRow("A 10, 2")
1086                 << (RangeList()
1087                     << Range(a, 0, 2, C::PrependFlag | C::DefaultFlag)
1088                     << Range(a, 2, 3, C::PrependFlag)
1089                     << Range(a, 5, 2, C::AppendFlag | C::PrependFlag | C::DefaultFlag)
1090                     << Range(b, 0, 4, C::DefaultFlag)
1091                     << Range(a, 2, 3, C::DefaultFlag))
1092                 << a << 10 << 2
1093                 << InsertList()
1094                 << IndexArray()
1095                 << IndexArray(defaultIndexes)
1096                 << IndexArray()
1097                 << IndexArray();
1098     } { static const int defaultIndexes[] = {/*A*/0,1,5,6,/*B*/0,1,2,3,/*A*/2,3,4};
1099         QTest::newRow("B 10, 2")
1100                 << (RangeList()
1101                     << Range(a, 0, 2, C::PrependFlag | C::DefaultFlag)
1102                     << Range(a, 2, 3, C::PrependFlag)
1103                     << Range(a, 5, 2, C::AppendFlag | C::PrependFlag | C::DefaultFlag)
1104                     << Range(b, 0, 4, C::DefaultFlag)
1105                     << Range(a, 2, 3, C::DefaultFlag))
1106                 << b << 10 << 2
1107                 << InsertList()
1108                 << IndexArray()
1109                 << IndexArray(defaultIndexes)
1110                 << IndexArray()
1111                 << IndexArray();
1112     } { static const int defaultIndexes[] = {/*A*/0,1,2,3,7,8,/*B*/0,1,2,3,/*A*/4,5,6};
1113         static const int visibleIndexes[] = {/*A*/0,1};
1114         QTest::newRow("A 0, 2")
1115                 << (RangeList()
1116                     << Range(a, 0, 2, C::PrependFlag | C::DefaultFlag)
1117                     << Range(a, 2, 3, C::PrependFlag)
1118                     << Range(a, 5, 2, C::AppendFlag | C::PrependFlag | C::DefaultFlag)
1119                     << Range(b, 0, 4, C::DefaultFlag)
1120                     << Range(a, 2, 3, C::DefaultFlag))
1121                 << a << 0 << 2
1122                 << (InsertList()
1123                     << Insert(0, 0, 0, 0, 2, VisibleFlag | C::DefaultFlag))
1124                 << IndexArray()
1125                 << IndexArray(defaultIndexes)
1126                 << IndexArray(visibleIndexes)
1127                 << IndexArray();
1128     } { static const int defaultIndexes[] = {/*A*/0,1,2,3,5,8,9,/*B*/0,1,2,3,/*A*/4,6,7};
1129         static const int visibleIndexes[] = {/*A*/0,1,5};
1130         QTest::newRow("A 5, 1")
1131                 << (RangeList()
1132                     << Range(a, 0, 2, C::PrependFlag | VisibleFlag | C::DefaultFlag)
1133                     << Range(a, 2, 2, C::PrependFlag | C::DefaultFlag)
1134                     << Range(a, 4, 3, C::PrependFlag)
1135                     << Range(a, 7, 2, C::AppendFlag | C::PrependFlag | C::DefaultFlag)
1136                     << Range(b, 0, 4, C::DefaultFlag)
1137                     << Range(a, 4, 3, C::DefaultFlag))
1138                 << a << 5 << 1
1139                 << (InsertList()
1140                     << Insert(0, 2, 4, 0, 1, VisibleFlag | C::DefaultFlag))
1141                 << IndexArray()
1142                 << IndexArray(defaultIndexes)
1143                 << IndexArray(visibleIndexes)
1144                 << IndexArray();
1145     } { static const int defaultIndexes[] = {/*A*/0,1,2,3,5,8,9,10,11,/*B*/0,1,2,3,/*A*/4,6,7};
1146         static const int visibleIndexes[] = {/*A*/0,1,5,10,11};
1147         QTest::newRow("A 10, 2")
1148                 << (RangeList()
1149                     << Range(a, 0, 2, C::PrependFlag | VisibleFlag | C::DefaultFlag)
1150                     << Range(a, 2, 2, C::PrependFlag | C::DefaultFlag)
1151                     << Range(a, 4, 1, C::PrependFlag)
1152                     << Range(a, 5, 1, C::PrependFlag | VisibleFlag | C::DefaultFlag)
1153                     << Range(a, 6, 2, C::PrependFlag)
1154                     << Range(a, 8, 2, C::AppendFlag | C::PrependFlag | C::DefaultFlag)
1155                     << Range(b, 0, 4, C::DefaultFlag)
1156                     << Range(a, 4, 1, C::DefaultFlag)
1157                     << Range(a, 6, 2, C::DefaultFlag))
1158                 << a << 10 << 2
1159                 << (InsertList()
1160                     << Insert(0, 3, 7, 0, 2, VisibleFlag | C::DefaultFlag))
1161                 << IndexArray()
1162                 << IndexArray(defaultIndexes)
1163                 << IndexArray(visibleIndexes)
1164                 << IndexArray();
1165     } { static const int cacheIndexes[] = {/*A*/0,1,-1,-1,-1,2,5,6,7,8,9};
1166         static const int defaultIndexes[] = {/*A*/0,1,2,3,4,5,6,7,8,9};
1167         static const int visibleIndexes[] = {/*A*/3,4};
1168         QTest::newRow("Insert after remove")
1169                 << (RangeList()
1170                     << Range(a, 0, 2, C::PrependFlag | C::DefaultFlag | C::CacheFlag)
1171                     << Range(a, 2, 3, C::CacheFlag)
1172                     << Range(a, 2, 6, C::AppendFlag | C::PrependFlag | C::DefaultFlag | C::CacheFlag))
1173                 << a << 3 << 2
1174                 << (InsertList()
1175                     << Insert(0, 0, 3, 6, 2, VisibleFlag | C::DefaultFlag))
1176                 << IndexArray(cacheIndexes)
1177                 << IndexArray(defaultIndexes)
1178                 << IndexArray(visibleIndexes)
1179                 << IndexArray();
1180     } { static const int cacheIndexes[] = {/*A*/0,1,2,3,4};
1181         static const int defaultIndexes[] = {/*A*/0,1,2,3,4,5,6};
1182         static const int visibleIndexes[] = {/*A*/0,1,2,3,4,5,6};
1183         QTest::newRow("Consecutive appends")
1184                 << (RangeList()
1185                     << Range(a, 0, 5, C::PrependFlag | VisibleFlag | C::DefaultFlag | C::CacheFlag)
1186                     << Range(a, 5, 1, C::PrependFlag | VisibleFlag | C::DefaultFlag)
1187                     << Range(a, 6, 0, C::AppendFlag | VisibleFlag | C::PrependFlag | C::DefaultFlag | C::CacheFlag))
1188                 << a << 6 << 1
1189                 << (InsertList()
1190                     << Insert(0, 6, 6, 5, 1, VisibleFlag | C::DefaultFlag))
1191                 << IndexArray(cacheIndexes)
1192                 << IndexArray(defaultIndexes)
1193                 << IndexArray(visibleIndexes)
1194                 << IndexArray();
1195     }
1196 }
1197
1198 void tst_qdeclarativelistcompositor::listItemsInserted()
1199 {
1200     QFETCH(RangeList, ranges);
1201     QFETCH(void *, list);
1202     QFETCH(int, index);
1203     QFETCH(int, count);
1204     QFETCH(InsertList, expectedInserts);
1205     QFETCH(IndexArray, cacheIndexes);
1206     QFETCH(IndexArray, defaultIndexes);
1207     QFETCH(IndexArray, visibleIndexes);
1208     QFETCH(IndexArray, selectionIndexes);
1209
1210     QDeclarativeListCompositor compositor;
1211     compositor.setGroupCount(4);
1212     compositor.setDefaultGroups(VisibleFlag | C::DefaultFlag);
1213
1214     foreach (const Range &range, ranges)
1215         compositor.append(range.list, range.index, range.count, range.flags);
1216
1217     QVector<C::Insert> inserts;
1218     compositor.listItemsInserted(list, index, count, &inserts);
1219
1220     QCOMPARE(inserts, expectedInserts);
1221
1222     QCOMPARE(compositor.count(C::Cache), cacheIndexes.count);
1223     for (int i = 0; i < cacheIndexes.count; ++i) {
1224         if (cacheIndexes[i] != -1) {
1225             QCOMPARE(compositor.find(C::Cache, i).modelIndex(), cacheIndexes[i]);
1226         }
1227     }
1228     QCOMPARE(compositor.count(C::Default), defaultIndexes.count);
1229     for (int i = 0; i < defaultIndexes.count; ++i) {
1230         if (defaultIndexes[i] != -1) {
1231             QCOMPARE(compositor.find(C::Default, i).modelIndex(), defaultIndexes[i]);
1232         }
1233     }
1234     QCOMPARE(compositor.count(Visible), visibleIndexes.count);
1235     for (int i = 0; i < visibleIndexes.count; ++i) {
1236         if (visibleIndexes[i] != -1) {
1237             QCOMPARE(compositor.find(Visible, i).modelIndex(), visibleIndexes[i]);
1238         }
1239     }
1240     QCOMPARE(compositor.count(Selection), selectionIndexes.count);
1241     for (int i = 0; i < selectionIndexes.count; ++i) {
1242         if (selectionIndexes[i] != -1) {
1243             QCOMPARE(compositor.find(Selection, i).modelIndex(), selectionIndexes[i]);
1244         }
1245     }
1246 }
1247
1248 void tst_qdeclarativelistcompositor::listItemsRemoved_data()
1249 {
1250     QTest::addColumn<RangeList>("ranges");
1251     QTest::addColumn<void *>("list");
1252     QTest::addColumn<int>("index");
1253     QTest::addColumn<int>("count");
1254     QTest::addColumn<RemoveList>("expectedRemoves");
1255     QTest::addColumn<IndexArray>("cacheIndexes");
1256     QTest::addColumn<IndexArray>("defaultIndexes");
1257     QTest::addColumn<IndexArray>("visibleIndexes");
1258     QTest::addColumn<IndexArray>("selectionIndexes");
1259
1260     int listA; void *a = &listA;
1261     int listB; void *b = &listB;
1262
1263     {   static const int defaultIndexes[] = {/*A*/0,1,5,6,/*B*/0,1,2,3,/*A*/2,3,4};
1264         QTest::newRow("12, 2")
1265                 << (RangeList()
1266                     << Range(a, 0, 2, C::PrependFlag | C::DefaultFlag)
1267                     << Range(a, 2, 3, C::PrependFlag)
1268                     << Range(a, 5, 2, C::AppendFlag | C::PrependFlag | C::DefaultFlag)
1269                     << Range(b, 0, 4, C::DefaultFlag)
1270                     << Range(a, 2, 3, C::DefaultFlag))
1271                 << a << 12 << 2
1272                 << RemoveList()
1273                 << IndexArray()
1274                 << IndexArray(defaultIndexes)
1275                 << IndexArray()
1276                 << IndexArray();
1277     } {   static const int defaultIndexes[] = {/*A*/0,1,/*B*/0,1,2,3,/*A*/2,3};
1278         QTest::newRow("4, 3")
1279                 << (RangeList()
1280                     << Range(a, 0, 2, C::PrependFlag | C::DefaultFlag)
1281                     << Range(a, 2, 3, C::PrependFlag)
1282                     << Range(a, 5, 2, C::AppendFlag | C::PrependFlag | C::DefaultFlag)
1283                     << Range(b, 0, 4, C::DefaultFlag)
1284                     << Range(a, 2, 3, C::DefaultFlag))
1285                 << a << 4 << 3
1286                 << (RemoveList()
1287                     << Remove(0, 0, 2, 0, 2, C::DefaultFlag)
1288                     << Remove(0, 0, 8, 0, 1, C::DefaultFlag))
1289                 << IndexArray()
1290                 << IndexArray(defaultIndexes)
1291                 << IndexArray()
1292                 << IndexArray();
1293     } { static const int cacheIndexes[] = {/*A*/0,1,-1,-1,-1,2,-1,-1,3,4,5};
1294         static const int defaultIndexes[] = {/*A*/0,1,2,3,4,5};
1295         QTest::newRow("Remove after remove")
1296                 << (RangeList()
1297                     << Range(a, 0, 2, C::PrependFlag | C::DefaultFlag | C::CacheFlag)
1298                     << Range(a, 2, 3, C::CacheFlag)
1299                     << Range(a, 2, 6, C::AppendFlag | C::PrependFlag | C::DefaultFlag | C::CacheFlag))
1300                 << a << 3 << 2
1301                 << (RemoveList()
1302                     << Remove(0, 0, 3, 6, 2, C::DefaultFlag | C::CacheFlag))
1303                 << IndexArray(cacheIndexes)
1304                 << IndexArray(defaultIndexes)
1305                 << IndexArray()
1306                 << IndexArray();
1307     } { static const int cacheIndexes[] = {/*A*/-1,-1,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,1};
1308         static const int defaultIndexes[] = {/*A*/0,1,2,3,4,5,6};
1309         QTest::newRow("Sparse remove")
1310                 << (RangeList()
1311                     << Range(a,  0,  2, C::CacheFlag)
1312                     << Range(a,  0,  1, C::DefaultFlag | C::CacheFlag)
1313                     << Range(a,  0,  1, C::CacheFlag)
1314                     << Range(a,  1,  5, C::DefaultFlag | C::CacheFlag)
1315                     << Range(a,  0,  1, C::CacheFlag)
1316                     << Range(a,  6,  2, C::DefaultFlag | C::CacheFlag)
1317                     << Range(a,  0,  1, C::CacheFlag)
1318                     << Range(a,  8,  3, C::DefaultFlag | C::CacheFlag)
1319                     << Range(a,  0,  1, C::CacheFlag)
1320                     << Range(a, 11,  1, C::DefaultFlag | C::CacheFlag)
1321                     << Range(a, 12,  5, C::DefaultFlag))
1322                 << a << 1 << 10
1323                 << (RemoveList()
1324                     << Remove(0, 0, 1, 4, 5, C::DefaultFlag | C::CacheFlag)
1325                     << Remove(0, 0, 1,10, 2, C::DefaultFlag | C::CacheFlag)
1326                     << Remove(0, 0, 1,13, 3, C::DefaultFlag | C::CacheFlag))
1327                 << IndexArray(cacheIndexes)
1328                 << IndexArray(defaultIndexes)
1329                 << IndexArray()
1330                 << IndexArray();
1331     }
1332 }
1333
1334 void tst_qdeclarativelistcompositor::listItemsRemoved()
1335 {
1336     QFETCH(RangeList, ranges);
1337     QFETCH(void *, list);
1338     QFETCH(int, index);
1339     QFETCH(int, count);
1340     QFETCH(RemoveList, expectedRemoves);
1341     QFETCH(IndexArray, cacheIndexes);
1342     QFETCH(IndexArray, defaultIndexes);
1343     QFETCH(IndexArray, visibleIndexes);
1344     QFETCH(IndexArray, selectionIndexes);
1345
1346     QDeclarativeListCompositor compositor;
1347     compositor.setGroupCount(4);
1348     compositor.setDefaultGroups(VisibleFlag | C::DefaultFlag);
1349
1350     foreach (const Range &range, ranges)
1351         compositor.append(range.list, range.index, range.count, range.flags);
1352
1353     QVector<C::Remove> removes;
1354     compositor.listItemsRemoved(list, index, count, &removes);
1355
1356     QCOMPARE(removes, expectedRemoves);
1357
1358     QCOMPARE(compositor.count(C::Cache), cacheIndexes.count);
1359     for (int i = 0; i < cacheIndexes.count; ++i) {
1360         if (cacheIndexes[i] != -1) {
1361             QCOMPARE(compositor.find(C::Cache, i).modelIndex(), cacheIndexes[i]);
1362         }
1363     }
1364     QCOMPARE(compositor.count(C::Default), defaultIndexes.count);
1365     for (int i = 0; i < defaultIndexes.count; ++i) {
1366         if (defaultIndexes[i] != -1) {
1367             QCOMPARE(compositor.find(C::Default, i).modelIndex(), defaultIndexes[i]);
1368         }
1369     }
1370     QCOMPARE(compositor.count(Visible), visibleIndexes.count);
1371     for (int i = 0; i < visibleIndexes.count; ++i) {
1372         if (visibleIndexes[i] != -1) {
1373             QCOMPARE(compositor.find(Visible, i).modelIndex(), visibleIndexes[i]);
1374         }
1375     }
1376     QCOMPARE(compositor.count(Selection), selectionIndexes.count);
1377     for (int i = 0; i < selectionIndexes.count; ++i) {
1378         if (selectionIndexes[i] != -1) {
1379             QCOMPARE(compositor.find(Selection, i).modelIndex(), selectionIndexes[i]);
1380         }
1381     }
1382 }
1383
1384 void tst_qdeclarativelistcompositor::listItemsMoved_data()
1385 {
1386     QTest::addColumn<RangeList>("ranges");
1387     QTest::addColumn<void *>("list");
1388     QTest::addColumn<int>("from");
1389     QTest::addColumn<int>("to");
1390     QTest::addColumn<int>("count");
1391     QTest::addColumn<RemoveList>("expectedRemoves");
1392     QTest::addColumn<InsertList>("expectedInserts");
1393     QTest::addColumn<IndexArray>("cacheIndexes");
1394     QTest::addColumn<IndexArray>("defaultIndexes");
1395     QTest::addColumn<IndexArray>("visibleIndexes");
1396     QTest::addColumn<IndexArray>("selectionIndexes");
1397
1398     int listA; void *a = &listA;
1399     int listB; void *b = &listB;
1400
1401     {   static const int defaultIndexes[] = {/*A*/0,2,3,4,/*B*/0,1,2,3,/*A*/5,6,1};
1402         QTest::newRow("4, 1, 3")
1403                 << (RangeList()
1404                     << Range(a, 0, 2, C::PrependFlag | C::DefaultFlag)
1405                     << Range(a, 2, 3, C::PrependFlag)
1406                     << Range(a, 5, 2, C::AppendFlag | C::PrependFlag | C::DefaultFlag)
1407                     << Range(b, 0, 4, C::DefaultFlag)
1408                     << Range(a, 2, 3, C::DefaultFlag))
1409                 << a << 4 << 1 << 3
1410                 << (RemoveList()
1411                     << Remove(0, 0, 2, 0, 2, C::DefaultFlag, 0))
1412                 << (InsertList()
1413                     << Insert(0, 0, 1, 0, 2, C::DefaultFlag, 0))
1414                 << IndexArray()
1415                 << IndexArray(defaultIndexes)
1416                 << IndexArray()
1417                 << IndexArray();
1418     } { static const int defaultIndexes[] = {/*A*/1,2,3,6,/*B*/0,1,2,3,/*A*/4,5,0};
1419         QTest::newRow("0, 6, 1")
1420                 << (RangeList()
1421                     << Range(a, 0, 1, C::PrependFlag | C::DefaultFlag)
1422                     << Range(a, 1, 1, C::PrependFlag)
1423                     << Range(a, 2, 3, C::PrependFlag | C::DefaultFlag)
1424                     << Range(a, 5, 2, C::PrependFlag)
1425                     << Range(a, 7, 0, C::AppendFlag | C::PrependFlag | C::DefaultFlag)
1426                     << Range(b, 0, 4, C::DefaultFlag)
1427                     << Range(a, 5, 2, C::DefaultFlag)
1428                     << Range(a, 1, 1, C::DefaultFlag))
1429                 << a << 0 << 6 << 1
1430                 << (RemoveList()
1431                     << Remove(0, 0, 0, 0, 1, C::DefaultFlag, 0))
1432                 << (InsertList()
1433                     << Insert(0, 0, 3, 0, 1, C::DefaultFlag, 0))
1434                 << IndexArray()
1435                 << IndexArray(defaultIndexes)
1436                 << IndexArray()
1437                 << IndexArray();
1438     } { static const int cacheIndexes[] = {/*A*/0,1,3,4};
1439         static const int defaultIndexes[] = {/*A*/0,1,2,3,4,5,6,7};
1440         QTest::newRow("6, 2, 1")
1441                 << (RangeList()
1442                     << Range(a, 0, 4, C::PrependFlag | C::DefaultFlag | C::CacheFlag)
1443                     << Range(a, 4, 4, C::AppendFlag | C::PrependFlag | C::DefaultFlag))
1444                 << a << 6 << 2 << 1
1445                 << (RemoveList()
1446                     << Remove(0, 0, 6, 4, 1, C::DefaultFlag, 0))
1447                 << (InsertList()
1448                     << Insert(0, 0, 2, 2, 1, C::DefaultFlag, 0))
1449                 << IndexArray(cacheIndexes)
1450                 << IndexArray(defaultIndexes)
1451                 << IndexArray()
1452                 << IndexArray();
1453     } { static const int cacheIndexes[] = {/*A*/0,1,-1,-1,-1,2,3,4,5,6,7};
1454         static const int defaultIndexes[] = {/*A*/0,1,2,3,4,5,6,7};
1455         QTest::newRow("Move after remove")
1456                 << (RangeList()
1457                     << Range(a, 0, 2, C::PrependFlag | C::DefaultFlag | C::CacheFlag)
1458                     << Range(a, 2, 3, C::CacheFlag)
1459                     << Range(a, 2, 6, C::AppendFlag | C::PrependFlag | C::DefaultFlag | C::CacheFlag))
1460                 << a << 4 << 2 << 2
1461                 << (RemoveList()
1462                     << Remove(0, 0, 4, 7, 2, C::DefaultFlag | C::CacheFlag, 0))
1463                 << (InsertList()
1464                     << Insert(0, 0, 2, 5, 2, C::DefaultFlag | C::CacheFlag, 0))
1465                 << IndexArray(cacheIndexes)
1466                 << IndexArray(defaultIndexes)
1467                 << IndexArray()
1468                 << IndexArray();
1469     } { static const int cacheIndexes[] = {/*A*/0,1,5,6,7,8,9,10,11,12};
1470         static const int defaultIndexes[] = {/*A*/0,1,2,3,4,5,6,7,8,9,10,11,12};
1471         QTest::newRow("Move merge tail")
1472                 << (RangeList()
1473                     << Range(a, 0, 10, C::PrependFlag | C::DefaultFlag | C::CacheFlag)
1474                     << Range(a, 10, 3, C::PrependFlag | C::DefaultFlag)
1475                     << Range(a, 13, 0, C::AppendFlag | C::PrependFlag | C::DefaultFlag | C::CacheFlag))
1476                 << a << 8 << 0 << 5
1477                 << (RemoveList()
1478                     << Remove(0, 0, 8, 8, 2, C::DefaultFlag | C::CacheFlag, 0)
1479                     << Remove(0, 0, 8, 8, 3, C::DefaultFlag, 1))
1480                 << (InsertList()
1481                     << Insert(0, 0, 0, 0, 2, C::DefaultFlag | C::CacheFlag, 0)
1482                     << Insert(0, 0, 2, 2, 3, C::DefaultFlag, 1))
1483                 << IndexArray(cacheIndexes)
1484                 << IndexArray(defaultIndexes)
1485                 << IndexArray()
1486                 << IndexArray();
1487     } { static const int cacheIndexes[] = {/*A*/0,1,2,3};
1488         static const int defaultIndexes[] = {/*A*/0,1,2,3};
1489         static const int selectionIndexes[] = {/*A*/3};
1490         QTest::newRow("Move selection")
1491                 << (RangeList()
1492                     << Range(a, 0, 2, C::PrependFlag | C::DefaultFlag | C::CacheFlag)
1493                     << Range(a, 2, 1, C::PrependFlag | SelectionFlag | C::DefaultFlag | C::CacheFlag)
1494                     << Range(a, 3, 1, C::AppendFlag | C::PrependFlag | C::DefaultFlag | C::CacheFlag))
1495                 << a << 2 << 3 << 1
1496                 << (RemoveList()
1497                     << Remove(0, 0, 2, 2, 1, C::PrependFlag | SelectionFlag | C::DefaultFlag | C::CacheFlag, 0))
1498                 << (InsertList()
1499                     << Insert(0, 0, 3, 3, 1, C::PrependFlag | SelectionFlag | C::DefaultFlag | C::CacheFlag, 0))
1500                 << IndexArray(cacheIndexes)
1501                 << IndexArray(defaultIndexes)
1502                 << IndexArray()
1503                 << IndexArray(selectionIndexes);
1504     } { static const int cacheIndexes[] = {/*A*/0,1,2,3,4,5,8,9};
1505         static const int defaultIndexes[] = {/*A*/0,1,2,3,4,5,6,7,8,9,10,11};
1506         QTest::newRow("move mixed cached items")
1507                 << (RangeList()
1508                     << Range(a,  0,  1, C::PrependFlag | C::DefaultFlag | C::CacheFlag)
1509                     << Range(a,  1,  2, C::PrependFlag | C::DefaultFlag)
1510                     << Range(a,  3,  7, C::PrependFlag | C::DefaultFlag | C::CacheFlag)
1511                     << Range(a, 10,  2, C::PrependFlag | C::DefaultFlag))
1512                 << a << 1 << 6 << 3
1513                 << (RemoveList()
1514                     << Remove(0, 0, 1, 1, 2, C::PrependFlag | C::DefaultFlag, 0)
1515                     << Remove(0, 0, 1, 1, 1, C::PrependFlag | C::DefaultFlag | C::CacheFlag, 1))
1516                 << (InsertList()
1517                     << Insert(0, 0, 6, 6, 2, C::PrependFlag | C::DefaultFlag, 0)
1518                     << Insert(0, 0, 8, 6, 1, C::PrependFlag | C::DefaultFlag | C::CacheFlag, 1))
1519                 << IndexArray(cacheIndexes)
1520                 << IndexArray(defaultIndexes)
1521                 << IndexArray()
1522                 << IndexArray();
1523     }
1524 }
1525
1526 void tst_qdeclarativelistcompositor::listItemsMoved()
1527 {
1528     QFETCH(RangeList, ranges);
1529     QFETCH(void *, list);
1530     QFETCH(int, from);
1531     QFETCH(int, to);
1532     QFETCH(int, count);
1533     QFETCH(RemoveList, expectedRemoves);
1534     QFETCH(InsertList, expectedInserts);
1535     QFETCH(IndexArray, cacheIndexes);
1536     QFETCH(IndexArray, defaultIndexes);
1537     QFETCH(IndexArray, visibleIndexes);
1538     QFETCH(IndexArray, selectionIndexes);
1539
1540     QDeclarativeListCompositor compositor;
1541     compositor.setGroupCount(4);
1542     compositor.setDefaultGroups(VisibleFlag | C::DefaultFlag);
1543
1544     foreach (const Range &range, ranges)
1545         compositor.append(range.list, range.index, range.count, range.flags);
1546
1547     QVector<C::Remove> removes;
1548     QVector<C::Insert> inserts;
1549     compositor.listItemsMoved(list, from, to, count, &removes, &inserts);
1550
1551     QCOMPARE(removes, expectedRemoves);
1552     QCOMPARE(inserts, expectedInserts);
1553
1554     QCOMPARE(compositor.count(C::Cache), cacheIndexes.count);
1555     for (int i = 0; i < cacheIndexes.count; ++i) {
1556         if (cacheIndexes[i] != -1) {
1557             QCOMPARE(compositor.find(C::Cache, i).modelIndex(), cacheIndexes[i]);
1558         }
1559     }
1560     QCOMPARE(compositor.count(C::Default), defaultIndexes.count);
1561     for (int i = 0; i < defaultIndexes.count; ++i) {
1562         if (defaultIndexes[i] != -1) {
1563             QCOMPARE(compositor.find(C::Default, i).modelIndex(), defaultIndexes[i]);
1564         }
1565     }
1566     QCOMPARE(compositor.count(Visible), visibleIndexes.count);
1567     for (int i = 0; i < visibleIndexes.count; ++i) {
1568         if (visibleIndexes[i] != -1) {
1569             QCOMPARE(compositor.find(Visible, i).modelIndex(), visibleIndexes[i]);
1570         }
1571     }
1572     QCOMPARE(compositor.count(Selection), selectionIndexes.count);
1573     for (int i = 0; i < selectionIndexes.count; ++i) {
1574         if (selectionIndexes[i] != -1) {
1575             QCOMPARE(compositor.find(Selection, i).modelIndex(), selectionIndexes[i]);
1576         }
1577     }
1578 }
1579
1580 void tst_qdeclarativelistcompositor::listItemsChanged_data()
1581 {
1582     QTest::addColumn<RangeList>("ranges");
1583     QTest::addColumn<void *>("list");
1584     QTest::addColumn<int>("index");
1585     QTest::addColumn<int>("count");
1586     QTest::addColumn<ChangeList>("expectedChanges");
1587
1588     int listA; void *a = &listA;
1589     int listB; void *b = &listB;
1590
1591     QTest::newRow("overlapping")
1592             << (RangeList()
1593                 << Range(a, 0, 2, C::PrependFlag | C::DefaultFlag)
1594                 << Range(a, 2, 3, C::PrependFlag)
1595                 << Range(a, 5, 2, C::AppendFlag | C::PrependFlag | C::DefaultFlag)
1596                 << Range(b, 0, 4, C::DefaultFlag)
1597                 << Range(a, 2, 3, C::DefaultFlag))
1598             << a << 3 << 4
1599             << (ChangeList()
1600                 << Change(0, 0, 2, 0, 2, C::DefaultFlag)
1601                 << Change(0, 0, 9, 0, 2, C::DefaultFlag));
1602     QTest::newRow("Change after remove")
1603             << (RangeList()
1604                 << Range(a, 0, 2, C::PrependFlag | C::DefaultFlag | C::CacheFlag)
1605                 << Range(a, 2, 3, C::CacheFlag)
1606                 << Range(a, 2, 6, C::AppendFlag | C::PrependFlag | C::DefaultFlag | C::CacheFlag))
1607             << a << 3 << 2
1608             << (ChangeList()
1609                 << Change(0, 0, 3, 6, 2, C::DefaultFlag | C::CacheFlag));
1610 }
1611
1612 void tst_qdeclarativelistcompositor::listItemsChanged()
1613 {
1614     QFETCH(RangeList, ranges);
1615     QFETCH(void *, list);
1616     QFETCH(int, index);
1617     QFETCH(int, count);
1618     QFETCH(ChangeList, expectedChanges);
1619
1620     QDeclarativeListCompositor compositor;
1621     compositor.setGroupCount(4);
1622     compositor.setDefaultGroups(VisibleFlag | C::DefaultFlag);
1623
1624     foreach (const Range &range, ranges)
1625         compositor.append(range.list, range.index, range.count, range.flags);
1626
1627     QVector<C::Change> changes;
1628     compositor.listItemsChanged(list, index, count, &changes);
1629
1630     QCOMPARE(changes, expectedChanges);
1631 }
1632
1633 QTEST_MAIN(tst_qdeclarativelistcompositor)
1634
1635 #include "tst_qdeclarativelistcompositor.moc"
1636
1637