Say hello to QtQuick module
[profile/ivi/qtdeclarative.git] / src / quick / util / qdeclarativelistcompositor.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of the QtDeclarative module 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
42 #include "qdeclarativelistcompositor_p.h"
43
44 #include <QtCore/qvarlengtharray.h>
45
46 //#define QT_DECLARATIVE_VERIFY_MINIMAL
47 //#define QT_DECLARATIVE_VERIFY_INTEGRITY
48
49 QT_BEGIN_NAMESPACE
50
51 #ifdef QT_DECLARATIVE_VERIFY_MINIMAL
52 #define QT_DECLARATIVE_VERIFY_INTEGRITY
53 static bool qt_verifyMinimal(
54         const QDeclarativeListCompositor::iterator &begin,
55         const QDeclarativeListCompositor::iterator &end)
56 {
57     bool minimal = true;
58     int index = 0;
59
60     for (const QDeclarativeListCompositor::Range *range = begin->next; range != *end; range = range->next, ++index) {
61         if (range->previous->list == range->list
62                 && range->previous->flags == (range->flags & ~QDeclarativeListCompositor::AppendFlag)
63                 && range->previous->end() == range->index) {
64             qWarning() << index << "Consecutive ranges";
65             qWarning() << *range->previous;
66             qWarning() << *range;
67             minimal = false;
68         }
69     }
70
71     return minimal;
72 }
73
74 #endif
75
76 #ifdef QT_DECLARATIVE_VERIFY_INTEGRITY
77 static bool qt_printInfo(const QDeclarativeListCompositor &compositor)
78 {
79     qWarning() << compositor;
80     return true;
81 }
82
83 static bool qt_verifyIntegrity(
84         const QDeclarativeListCompositor::iterator &begin,
85         const QDeclarativeListCompositor::iterator &end,
86         const QDeclarativeListCompositor::iterator &cachedIt)
87 {
88     bool valid = true;
89
90     int index = 0;
91     QDeclarativeListCompositor::iterator it;
92     for (it = begin; *it != *end; *it = it->next) {
93         if (it->count == 0 && !it->append()) {
94             qWarning() << index << "Empty non-append range";
95             valid = false;
96         }
97         if (it->count < 0) {
98             qWarning() << index << "Negative count";
99             valid = false;
100         }
101         if (it->list && it->flags != QDeclarativeListCompositor::CacheFlag && it->index < 0) {
102             qWarning() << index <<"Negative index";
103             valid = false;
104         }
105         if (it->previous->next != it.range) {
106             qWarning() << index << "broken list: it->previous->next != it.range";
107             valid = false;
108         }
109         if (it->next->previous != it.range) {
110             qWarning() << index << "broken list: it->next->previous != it.range";
111             valid = false;
112         }
113         if (*it == *cachedIt) {
114             for (int i = 0; i < end.groupCount; ++i) {
115                 int groupIndex = it.index[i];
116                 if (cachedIt->flags & (1 << i))
117                     groupIndex += cachedIt.offset;
118                 if (groupIndex != cachedIt.index[i]) {
119                     qWarning() << index
120                             << "invalid cached index"
121                             << QDeclarativeListCompositor::Group(i)
122                             << "Expected:"
123                             << groupIndex
124                             << "Actual"
125                             << cachedIt.index[i]
126                             << cachedIt;
127                     valid = false;
128                 }
129             }
130         }
131         it.incrementIndexes(it->count);
132         ++index;
133     }
134
135     for (int i = 0; i < end.groupCount; ++i) {
136         if (end.index[i] != it.index[i]) {
137             qWarning() << "Group" << i << "count invalid. Expected:" << end.index[i] << "Actual:" << it.index[i];
138             valid = false;
139         }
140     }
141     return valid;
142 }
143 #endif
144
145 #if defined(QT_DECLARATIVE_VERIFY_MINIMAL)
146 #   define QT_DECLARATIVE_VERIFY_LISTCOMPOSITOR Q_ASSERT(!(!(qt_verifyIntegrity(iterator(m_ranges.next, 0, Default, m_groupCount), m_end, m_cacheIt) \
147             && qt_verifyMinimal(iterator(m_ranges.next, 0, Default, m_groupCount), m_end)) \
148             && qt_printInfo(*this)));
149 #elif defined(QT_DECLARATIVE_VERIFY_INTEGRITY)
150 #   define QT_DECLARATIVE_VERIFY_LISTCOMPOSITOR Q_ASSERT(!(!qt_verifyIntegrity(iterator(m_ranges.next, 0, Default, m_groupCount), m_end, m_cacheIt) \
151             && qt_printInfo(*this)));
152 #else
153 #   define QT_DECLARATIVE_VERIFY_LISTCOMPOSITOR
154 #endif
155
156 //#define QT_DECLARATIVE_TRACE_LISTCOMPOSITOR(args) qDebug() << m_end.index[1] << m_end.index[0] << Q_FUNC_INFO args;
157 #define QT_DECLARATIVE_TRACE_LISTCOMPOSITOR(args)
158
159 QDeclarativeListCompositor::iterator &QDeclarativeListCompositor::iterator::operator +=(int difference)
160 {
161     Q_ASSERT(difference >= 0);
162     while (!(range->flags & groupFlag)) {
163         incrementIndexes(range->count - offset);
164         offset = 0;
165         range = range->next;
166     }
167     decrementIndexes(offset);
168     offset += difference;
169     while (offset >= range->count || !(range->flags & groupFlag)) {
170         if (range->flags & groupFlag)
171             offset -= range->count;
172         incrementIndexes(range->count);
173         range = range->next;
174     }
175     incrementIndexes(offset);
176     return *this;
177 }
178
179 QDeclarativeListCompositor::iterator &QDeclarativeListCompositor::iterator::operator -=(int difference)
180 {
181     Q_ASSERT(difference >= 0);
182     while (!(range->flags & groupFlag)) {
183         decrementIndexes(offset);
184         range = range->previous;
185         offset = range->count;
186     }
187     decrementIndexes(offset);
188     offset -= difference;
189     while (offset < 0) {
190         range = range->previous;
191         if (range->flags & groupFlag)
192             offset += range->count;
193         decrementIndexes(range->count);
194     }
195     incrementIndexes(offset);
196     return *this;
197 }
198
199 QDeclarativeListCompositor::insert_iterator &QDeclarativeListCompositor::insert_iterator::operator +=(int difference)
200 {
201     Q_ASSERT(difference >= 0);
202     while (!(range->flags & groupFlag)) {
203         incrementIndexes(range->count - offset);
204         offset = 0;
205         range = range->next;
206     }
207     decrementIndexes(offset);
208     offset += difference;
209     while (offset > range->count
210             || (offset == range->count && !range->append() && offset > 0)
211             || (!(range->flags & groupFlag) && offset > 0)) {
212         if (range->flags & groupFlag)
213             offset -= range->count;
214         incrementIndexes(range->count);
215         range = range->next;
216     }
217     incrementIndexes(offset);
218     return *this;
219 }
220
221 QDeclarativeListCompositor::insert_iterator &QDeclarativeListCompositor::insert_iterator::operator -=(int difference)
222 {
223     Q_ASSERT(difference >= 0);
224     while (!(range->flags & groupFlag) && range->previous->flags) {
225         decrementIndexes(offset);
226         range = range->previous;
227         offset = (range->flags & (GroupMask | CacheFlag)) ? range->count : 0;
228     }
229     decrementIndexes(offset);
230     offset -= difference;
231     while (offset < 0) {
232         range = range->previous;
233         if (range->flags & groupFlag)
234             offset += range->count;
235         decrementIndexes(range->count);
236     }
237     incrementIndexes(offset);
238     for (Range *previous = range->previous; offset == 0 && previous->prepend(); previous = previous->previous) {
239         if (previous->append() && previous->inGroup()) {
240             offset = previous->count;
241             range = previous;
242         } else if (!previous->inGroup()) {
243             break;
244         }
245     }
246
247     return *this;
248 }
249
250 QDeclarativeListCompositor::QDeclarativeListCompositor()
251     : m_end(m_ranges.next, 0, Default, 2)
252     , m_cacheIt(m_end)
253     , m_groupCount(2)
254     , m_defaultFlags(PrependFlag | DefaultFlag)
255     , m_removeFlags(AppendFlag | PrependFlag | GroupMask)
256 {
257 }
258
259 QDeclarativeListCompositor::~QDeclarativeListCompositor()
260 {
261     for (Range *next, *range = m_ranges.next; range != &m_ranges; range = next) {
262         next = range->next;
263         delete range;
264     }
265 }
266
267 inline QDeclarativeListCompositor::Range *QDeclarativeListCompositor::insert(
268         Range *before, void *list, int index, int count, int flags)
269 {
270     return new Range(before, list, index, count, flags);
271 }
272
273 inline QDeclarativeListCompositor::Range *QDeclarativeListCompositor::erase(
274         Range *range)
275 {
276     Range *next = range->next;
277     next->previous = range->previous;
278     next->previous->next = range->next;
279     delete range;
280     return next;
281 }
282
283 void QDeclarativeListCompositor::setGroupCount(int count)
284 {
285     m_groupCount = count;
286     m_end = iterator(&m_ranges, 0, Default, m_groupCount);
287     m_cacheIt = m_end;
288 }
289
290 int QDeclarativeListCompositor::count(Group group) const
291 {
292     return m_end.index[group];
293 }
294
295 QDeclarativeListCompositor::iterator QDeclarativeListCompositor::find(Group group, int index)
296 {
297     QT_DECLARATIVE_TRACE_LISTCOMPOSITOR(<< group << index)
298     Q_ASSERT(index >=0 && index < count(group));
299     if (m_cacheIt == m_end) {
300         m_cacheIt = iterator(m_ranges.next, 0, group, m_groupCount);
301         m_cacheIt += index;
302     } else {
303         const int offset = index - m_cacheIt.index[group];
304         m_cacheIt.setGroup(group);
305         if (offset > 0) {
306             m_cacheIt += offset;
307         } else if (offset < 0) {
308             m_cacheIt -= -offset;
309         } else if (offset == 0) {
310             m_cacheIt -= 0;
311             m_cacheIt += 0;
312         }
313     }
314     Q_ASSERT(m_cacheIt.index[group] == index);
315     Q_ASSERT(m_cacheIt->inGroup(group));
316     QT_DECLARATIVE_VERIFY_LISTCOMPOSITOR
317     return m_cacheIt;
318 }
319
320 QDeclarativeListCompositor::iterator QDeclarativeListCompositor::find(Group group, int index) const
321 {
322     return const_cast<QDeclarativeListCompositor *>(this)->find(group, index);
323 }
324
325 QDeclarativeListCompositor::insert_iterator QDeclarativeListCompositor::findInsertPosition(Group group, int index)
326 {
327     QT_DECLARATIVE_TRACE_LISTCOMPOSITOR(<< group << index)
328     Q_ASSERT(index >=0 && index <= count(group));
329     insert_iterator it;
330     if (m_cacheIt == m_end) {
331         it = iterator(m_ranges.next, 0, group, m_groupCount);
332         it += index;
333     } else {
334         const int offset = index - m_cacheIt.index[group];
335         it = m_cacheIt;
336         it.setGroup(group);
337         if (offset > 0) {
338             it += offset;
339         } else if (offset < 0) {
340             it -= -offset;
341         } else if (offset == 0) {
342             it -= 0;
343             it += 0;
344         }
345     }
346     Q_ASSERT(it.index[group] == index);
347     return it;
348 }
349
350 QDeclarativeListCompositor::iterator QDeclarativeListCompositor::begin(Group group)
351 {
352     QT_DECLARATIVE_TRACE_LISTCOMPOSITOR(<< group)
353     m_cacheIt = iterator(m_ranges.next, 0, group, m_groupCount);
354     m_cacheIt += 0;
355     return m_cacheIt;
356 }
357
358 void QDeclarativeListCompositor::append(
359         void *list, int index, int count, int flags, QVector<Insert> *inserts)
360 {
361     QT_DECLARATIVE_TRACE_LISTCOMPOSITOR(<< list << index << count << flags)
362     insert(m_end, list, index, count, flags, inserts);
363 }
364
365 void QDeclarativeListCompositor::insert(
366         Group group, int before, void *list, int index, int count, int flags, QVector<Insert> *inserts)
367 {
368     QT_DECLARATIVE_TRACE_LISTCOMPOSITOR(<< group << before << list << index << count << flags)
369     insert(findInsertPosition(group, before), list, index, count, flags, inserts);
370 }
371
372 QDeclarativeListCompositor::iterator QDeclarativeListCompositor::insert(
373         iterator before, void *list, int index, int count, int flags, QVector<Insert> *inserts)
374 {
375     QT_DECLARATIVE_TRACE_LISTCOMPOSITOR(<< before << list << index << count << flags)
376     if (inserts) {
377         inserts->append(Insert(before, count, flags & GroupMask));
378     }
379     if (before.offset > 0) {
380         *before = insert(
381                 *before, before->list, before->index, before.offset, before->flags & ~AppendFlag)->next;
382         before->index += before.offset;
383         before->count -= before.offset;
384         before.offset = 0;
385     }
386
387     if (!(flags & AppendFlag) && *before != m_ranges.next
388             && before->previous->list == list
389             && before->previous->flags == flags
390             && (!list || before->previous->end() == index)) {
391         before->previous->count += count;
392         before.incrementIndexes(count, flags);
393     } else {
394         *before = insert(*before, list, index, count, flags);
395         before.offset = 0;
396     }
397
398     if (!(flags & AppendFlag) && before->next != &m_ranges
399             && before->list == before->next->list
400             && before->flags == before->next->flags
401             && (!list || before->end() == before->next->index)) {
402         before->next->index = before->index;
403         before->next->count += before->count;
404         *before = erase(*before);
405     }
406
407     m_end.incrementIndexes(count, flags);
408     m_cacheIt = before;
409     QT_DECLARATIVE_VERIFY_LISTCOMPOSITOR
410     return before;
411 }
412
413 void QDeclarativeListCompositor::setFlags(
414         Group group, int index, int count, int flags, QVector<Insert> *inserts)
415 {
416     QT_DECLARATIVE_TRACE_LISTCOMPOSITOR(<< group << index << count << flags)
417     setFlags(find(group, index), count, flags, inserts);
418 }
419
420 void QDeclarativeListCompositor::setFlags(
421         iterator from, int count, int flags, QVector<Insert> *inserts)
422 {
423     QT_DECLARATIVE_TRACE_LISTCOMPOSITOR(<< from << count << flags)
424     if (!flags || !count)
425         return;
426
427     if (from.offset > 0) {
428         *from = insert(*from, from->list, from->index, from.offset, from->flags & ~AppendFlag)->next;
429         from->index += from.offset;
430         from->count -= from.offset;
431         from.offset = 0;
432     }
433
434     for (; count > 0; *from = from->next) {
435         if (from != from.group) {
436             from.incrementIndexes(from->count);
437             continue;
438         }
439         const int difference = qMin(count, from->count);
440         count -= difference;
441
442         const int insertFlags = ~from->flags & flags;
443         const int setFlags = (from->flags | flags) & ~AppendFlag;
444         if (insertFlags && inserts)
445             inserts->append(Insert(from, difference, insertFlags | (from->flags & CacheFlag)));
446         m_end.incrementIndexes(difference, insertFlags);
447         from.incrementIndexes(difference, setFlags);
448
449         if (from->previous != &m_ranges
450                 && from->previous->list == from->list
451                 && (!from->list || from->previous->end() == from->index)
452                 && from->previous->flags == setFlags) {
453             from->previous->count += difference;
454             from->index += difference;
455             from->count -= difference;
456             if (from->count == 0) {
457                 if (from->append())
458                     from->previous->flags |= AppendFlag;
459                 *from = erase(*from)->previous;
460                 continue;
461             } else {
462                 break;
463             }
464         } else if (!insertFlags) {
465             from.incrementIndexes(from->count - difference);
466             continue;
467         } else if (difference < from->count) {
468             *from = insert(*from, from->list, from->index, difference, setFlags)->next;
469             from->index += difference;
470             from->count -= difference;
471         } else {
472             from->flags |= flags;
473             continue;
474         }
475         from.incrementIndexes(from->count);
476     }
477
478     if (from->previous != &m_ranges
479             && from->previous->list == from->list
480             && (!from->list || from->previous->end() == from->index)
481             && from->previous->flags == (from->flags & ~AppendFlag)) {
482         from.offset = from->previous->count;
483         from->previous->count += from->count;
484         from->previous->flags = from->flags;
485         *from = erase(*from)->previous;
486     }
487     m_cacheIt = from;
488     QT_DECLARATIVE_VERIFY_LISTCOMPOSITOR
489 }
490
491 void QDeclarativeListCompositor::clearFlags(
492         Group group, int index, int count, int flags, QVector<Remove> *removes)
493 {
494     QT_DECLARATIVE_TRACE_LISTCOMPOSITOR(<< group << index << count << flags)
495     clearFlags(find(group, index), count, flags, removes);
496 }
497
498 void QDeclarativeListCompositor::clearFlags(
499         iterator from, int count, int flags, QVector<Remove> *removes)
500 {
501     QT_DECLARATIVE_TRACE_LISTCOMPOSITOR(<< from << count << flags)
502     if (!flags || !count)
503         return;
504
505     const bool clearCache = flags & CacheFlag;
506
507     if (from.offset > 0) {
508         *from = insert(*from, from->list, from->index, from.offset, from->flags & ~AppendFlag)->next;
509         from->index += from.offset;
510         from->count -= from.offset;
511         from.offset = 0;
512     }
513
514     for (; count > 0; *from = from->next) {
515         if (from != from.group) {
516             from.incrementIndexes(from->count);
517             continue;
518         }
519         const int difference = qMin(count, from->count);
520         count -= difference;
521
522         const int removeFlags = from->flags & flags & ~(AppendFlag | PrependFlag);
523         const int clearedFlags = from->flags & ~(flags | AppendFlag);
524         if (removeFlags && removes) {
525             const int maskedFlags = clearCache
526                     ? (removeFlags & ~CacheFlag)
527                     : (removeFlags | (from->flags & CacheFlag));
528             if (maskedFlags)
529                 removes->append(Remove(from, difference, maskedFlags));
530         }
531         m_end.decrementIndexes(difference, removeFlags);
532         from.incrementIndexes(difference, clearedFlags);
533
534         if (from->previous != &m_ranges
535                 && from->previous->list == from->list
536                 && (!from->list || clearedFlags == CacheFlag || from->previous->end() == from->index)
537                 && from->previous->flags == clearedFlags) {
538             from->previous->count += difference;
539             from->index += difference;
540             from->count -= difference;
541             if (from->count == 0) {
542                 if (from->append())
543                     from->previous->flags |= AppendFlag;
544                 *from = erase(*from)->previous;
545             } else {
546                 from.incrementIndexes(from->count);
547             }
548         } else if (difference < from->count) {
549             if (clearedFlags)
550                 *from = insert(*from, from->list, from->index, difference, clearedFlags)->next;
551             from->index += difference;
552             from->count -= difference;
553             from.incrementIndexes(from->count);
554         } else if (clearedFlags) {
555             from->flags &= ~flags;
556         } else {
557             *from = erase(*from)->previous;
558         }
559     }
560
561     if (*from != &m_ranges && from->previous != &m_ranges
562             && from->previous->list == from->list
563             && (!from->list || from->previous->end() == from->index)
564             && from->previous->flags == (from->flags & ~AppendFlag)) {
565         from.offset = from->previous->count;
566         from->previous->count += from->count;
567         from->previous->flags = from->flags;
568         *from = erase(*from)->previous;
569     }
570     m_cacheIt = from;
571     QT_DECLARATIVE_VERIFY_LISTCOMPOSITOR
572 }
573
574 void QDeclarativeListCompositor::removeList(void *list, QVector<Remove> *removes, bool destroyed)
575 {
576     QT_DECLARATIVE_TRACE_LISTCOMPOSITOR(<< list << destroyed)
577     for (iterator it(m_ranges.next, 0, Default, m_groupCount); *it != &m_ranges; *it = it->next) {
578         if (it->list == list) {
579             const int flags = it->flags & (GroupMask | CacheFlag);
580             if (flags) {
581                 removes->append(Remove(it, it->count, flags));
582                 m_end.decrementIndexes(it->count, flags);
583             }
584             if (destroyed)
585                 it->list = 0;
586             if (it->inCache()) {
587                 it->flags = CacheFlag;
588                 it.cacheIndex += it->count;
589             } else {
590                 *it = erase(*it)->previous;
591             }
592         } else {
593             it.incrementIndexes(it->count);
594         }
595     }
596     m_cacheIt = m_end;
597     QT_DECLARATIVE_VERIFY_LISTCOMPOSITOR
598 }
599
600 bool QDeclarativeListCompositor::verifyMoveTo(
601         Group fromGroup, int from, Group toGroup, int to, int count) const
602 {
603     if (fromGroup != toGroup) {
604         // determine how many items from the destination group intersect with the source group.
605         iterator fromIt = find(fromGroup, from);
606
607         int intersectingCount = 0;
608
609         for (; count > 0; *fromIt = fromIt->next) {
610             if (*fromIt == &m_ranges)
611                 return false;
612             if (!fromIt->inGroup(fromGroup))
613                 continue;
614             if (fromIt->inGroup(toGroup))
615                 intersectingCount += qMin(count, fromIt->count - fromIt.offset);
616             count -= fromIt->count - fromIt.offset;
617             fromIt.offset = 0;
618         }
619         count = intersectingCount;
620     }
621
622     return to >= 0 && to + count <= m_end.index[toGroup];
623 }
624
625 void QDeclarativeListCompositor::move(
626         Group fromGroup,
627         int from,
628         Group toGroup,
629         int to,
630         int count,
631         QVector<Remove> *removes,
632         QVector<Insert> *inserts)
633 {
634     QT_DECLARATIVE_TRACE_LISTCOMPOSITOR(<< fromGroup << from << toGroup << to << count)
635     Q_ASSERT(count != 0);
636     Q_ASSERT(from >=0 && from + count <= m_end.index[toGroup]);
637     Q_ASSERT(verifyMoveTo(fromGroup, from, toGroup, to, count));
638
639     iterator fromIt = find(fromGroup, from);
640     if (fromIt.offset > 0) {
641         *fromIt = insert(
642                 *fromIt, fromIt->list, fromIt->index, fromIt.offset, fromIt->flags & ~AppendFlag)->next;
643         fromIt->index += fromIt.offset;
644         fromIt->count -= fromIt.offset;
645         fromIt.offset = 0;
646     }
647
648     Range movedFlags;
649     for (int moveId = 0; count > 0;) {
650         if (fromIt != fromIt.group) {
651             fromIt.incrementIndexes(fromIt->count);
652             *fromIt = fromIt->next;
653             continue;
654         }
655         int difference = qMin(count, fromIt->count);
656
657         new Range(
658                 &movedFlags,
659                 fromIt->list,
660                 fromIt->index,
661                 difference,
662                 fromIt->flags & ~(PrependFlag | AppendFlag));
663         if (removes)
664             removes->append(Remove(fromIt, difference, fromIt->flags, moveId++));
665         count -= difference;
666         fromIt->count -= difference;
667
668         int removeIndex = fromIt->index;
669         if (fromIt->prepend()
670                 && fromIt->previous != &m_ranges
671                 && fromIt->previous->flags == PrependFlag
672                 && fromIt->previous->list == fromIt->list
673                 && fromIt->previous->end() == fromIt->index) {
674             fromIt->previous->count += difference;
675         } else if (fromIt->prepend()) {
676             *fromIt = insert(*fromIt, fromIt->list, removeIndex, difference, PrependFlag)->next;
677         }
678         fromIt->index += difference;
679
680         if (fromIt->count == 0) {
681             if (fromIt->append())
682                 fromIt->previous->flags |= AppendFlag;
683             *fromIt = erase(*fromIt);
684
685             if (*fromIt != m_ranges.next && fromIt->flags == PrependFlag
686                     && fromIt->previous != &m_ranges
687                     && fromIt->previous->flags == PrependFlag
688                     && fromIt->previous->list == fromIt->list
689                     && fromIt->previous->end() == fromIt->index) {
690                 fromIt.incrementIndexes(fromIt->count);
691                 fromIt->previous->count += fromIt->count;
692                 *fromIt = erase(*fromIt);
693             }
694         } else if (count > 0) {
695             *fromIt = fromIt->next;
696         }
697     }
698
699     if (*fromIt != m_ranges.next
700             && *fromIt != &m_ranges
701             && fromIt->previous->list == fromIt->list
702             && (!fromIt->list || fromIt->previous->end() == fromIt->index)
703             && fromIt->previous->flags == (fromIt->flags & ~AppendFlag)) {
704         if (fromIt == fromIt.group)
705             fromIt.offset = fromIt->previous->count;
706         fromIt.offset = fromIt->previous->count;
707         fromIt->previous->count += fromIt->count;
708         fromIt->previous->flags = fromIt->flags;
709         *fromIt = erase(*fromIt)->previous;
710     }
711
712     insert_iterator toIt = fromIt;
713     toIt.setGroup(toGroup);
714     const int difference = to - toIt.index[toGroup];
715     if (difference > 0)
716         toIt += difference;
717     else
718         toIt -= -difference;
719
720     if (toIt.offset > 0) {
721         *toIt = insert(*toIt, toIt->list, toIt->index, toIt.offset, toIt->flags & ~AppendFlag)->next;
722         toIt->index += toIt.offset;
723         toIt->count -= toIt.offset;
724         toIt.offset = 0;
725     }
726
727     for (Range *range = movedFlags.previous; range != &movedFlags; range = range->previous) {
728         if (*toIt != &m_ranges
729                 && range->list == toIt->list
730                 && (!range->list || range->end() == toIt->index)
731                 && range->flags == (toIt->flags & ~AppendFlag)) {
732             toIt->index -= range->count;
733             toIt->count += range->count;
734         } else {
735             *toIt = insert(*toIt, range->list, range->index, range->count, range->flags);
736         }
737     }
738
739     if (*toIt != m_ranges.next
740             && toIt->previous->list == toIt->list
741             && (!toIt->list || (toIt->previous->end() == toIt->index && toIt->previous->flags == (toIt->flags & ~AppendFlag)))) {
742         toIt.offset = toIt->previous->count;
743         toIt->previous->count += toIt->count;
744         toIt->previous->flags = toIt->flags;
745         *toIt = erase(*toIt)->previous;
746     }
747     Insert insert(toIt, 0, 0, 0);
748     for (Range *next, *range = movedFlags.next; range != &movedFlags; range = next) {
749         insert.count = range->count;
750         insert.flags = range->flags;
751         if (inserts)
752             inserts->append(insert);
753         for (int i = 0; i < m_groupCount; ++i) {
754             if (insert.inGroup(i))
755                 insert.index[i] += range->count;
756         }
757         ++insert.moveId;
758         next = range->next;
759         delete range;
760     }
761
762     m_cacheIt = toIt;
763     QT_DECLARATIVE_VERIFY_LISTCOMPOSITOR
764 }
765
766 void QDeclarativeListCompositor::clear()
767 {
768     QT_DECLARATIVE_TRACE_LISTCOMPOSITOR( )
769     for (Range *range = m_ranges.next; range != &m_ranges; range = erase(range)) {}
770     m_end = iterator(m_ranges.next, 0, Default, m_groupCount);
771     m_cacheIt = m_end;
772 }
773
774 void QDeclarativeListCompositor::listItemsInserted(
775         QVector<Insert> *translatedInsertions,
776         void *list,
777         const QVector<QDeclarativeChangeSet::Insert> &insertions,
778         const QVector<MovedFlags> *movedFlags)
779 {
780     QT_DECLARATIVE_TRACE_LISTCOMPOSITOR(<< list << insertions)
781     for (iterator it(m_ranges.next, 0, Default, m_groupCount); *it != &m_ranges; *it = it->next) {
782         if (it->list != list || it->flags == CacheFlag) {
783             it.incrementIndexes(it->count);
784             continue;
785         } else if (it->flags & MovedFlag) {
786             it->flags &= ~MovedFlag;
787             it.incrementIndexes(it->count);
788             continue;
789         }
790         foreach (const QDeclarativeChangeSet::Insert &insertion, insertions) {
791             int offset = insertion.index - it->index;
792             if ((offset > 0 && offset < it->count)
793                     || (offset == 0 && it->prepend())
794                     || (offset == it->count && it->append())) {
795                 if (it->prepend()) {
796                     int flags = m_defaultFlags;
797                     if (insertion.isMove()) {
798                         for (QVector<MovedFlags>::const_iterator move = movedFlags->begin();
799                                 move != movedFlags->end();
800                                 ++move) {
801                             if (move->moveId == insertion.moveId) {
802                                 flags = move->flags;
803                                 break;
804                             }
805                         }
806                     }
807                     if (flags & ~(AppendFlag | PrependFlag)) {
808                         Insert translatedInsert(it, insertion.count, flags, insertion.moveId);
809                         for (int i = 0; i < m_groupCount; ++i) {
810                             if (it->inGroup(i))
811                                 translatedInsert.index[i] += offset;
812                         }
813                         translatedInsertions->append(translatedInsert);
814                     }
815                     if ((it->flags & ~AppendFlag) == flags) {
816                         it->count += insertion.count;
817                     } else if (offset == 0
818                             && it->previous != &m_ranges
819                             && it->previous->list == list
820                             && it->previous->end() == insertion.index
821                             && it->previous->flags == flags) {
822                         it->previous->count += insertion.count;
823                         it->index += insertion.count;
824                         it.incrementIndexes(insertion.count);
825                     } else {
826                         if (offset > 0) {
827                             it.incrementIndexes(offset);
828                             *it = insert(*it, it->list, it->index, offset, it->flags & ~AppendFlag)->next;
829                         }
830                         *it = insert(*it, it->list, insertion.index, insertion.count, flags)->next;
831                         it.incrementIndexes(insertion.count, flags);
832                         it->index += offset + insertion.count;
833                         it->count -= offset;
834                     }
835                     m_end.incrementIndexes(insertion.count, flags);
836                 } else {
837                     if (offset > 0) {
838                         *it = insert(*it, it->list, it->index, offset, it->flags)->next;
839                         it->index += offset;
840                         it->count -= offset;
841                     }
842                     it->index += insertion.count;
843                 }
844             } else if (offset <= 0) {
845                 it->index += insertion.count;
846             }
847         }
848         it.incrementIndexes(it->count);
849     }
850     m_cacheIt = m_end;
851     QT_DECLARATIVE_VERIFY_LISTCOMPOSITOR
852 }
853
854 void QDeclarativeListCompositor::listItemsInserted(
855         void *list, int index, int count, QVector<Insert> *translatedInsertions)
856 {
857     QT_DECLARATIVE_TRACE_LISTCOMPOSITOR(<< list << index << count)
858     Q_ASSERT(count > 0);
859
860     QVector<QDeclarativeChangeSet::Insert> insertions;
861     insertions.append(QDeclarativeChangeSet::Insert(index, count));
862
863     listItemsInserted(translatedInsertions, list, insertions);
864 }
865
866 void QDeclarativeListCompositor::listItemsRemoved(
867         QVector<Remove> *translatedRemovals,
868         void *list,
869         QVector<QDeclarativeChangeSet::Remove> *removals,
870         QVector<QDeclarativeChangeSet::Insert> *insertions,
871         QVector<MovedFlags> *movedFlags, int moveId)
872 {
873     QT_DECLARATIVE_TRACE_LISTCOMPOSITOR(<< list << *removals)
874
875     for (iterator it(m_ranges.next, 0, Default, m_groupCount);
876             *it != &m_ranges && !removals->isEmpty();
877             *it = it->next) {
878         if (it->list != list || it->flags == CacheFlag) {
879             it.incrementIndexes(it->count);
880             continue;
881         }
882         bool removed = false;
883         for (QVector<QDeclarativeChangeSet::Remove>::iterator removal = removals->begin();
884                 !removed && removal != removals->end();
885                 ++removal) {
886             int relativeIndex = removal->index - it->index;
887             int itemsRemoved = removal->count;
888             if (relativeIndex + removal->count > 0 && relativeIndex < it->count) {
889                 const int offset = qMax(0, relativeIndex);
890                 int removeCount = qMin(it->count, relativeIndex + removal->count) - offset;
891                 it->count -= removeCount;
892                 int removeFlags = it->flags & m_removeFlags;
893                 Remove translatedRemoval(it, removeCount, it->flags);
894                 for (int i = 0; i < m_groupCount; ++i) {
895                     if (it->inGroup(i))
896                         translatedRemoval.index[i] += offset;
897                 }
898                 if (removal->isMove()) {
899                     QVector<QDeclarativeChangeSet::Insert>::iterator insertion = insertions->begin();
900                     for (; insertion != insertions->end() && insertion->moveId != removal->moveId;
901                             ++insertion) {}
902                     Q_ASSERT(insertion != insertions->end());
903                     Q_ASSERT(insertion->count == removal->count);
904
905                     if (relativeIndex < 0) {
906                         int splitMoveId = ++moveId;
907                         removal = removals->insert(removal, QDeclarativeChangeSet::Remove(
908                                 removal->index, -relativeIndex, splitMoveId));
909                         ++removal;
910                         removal->count -= -relativeIndex;
911                         insertion = insertions->insert(insertion, QDeclarativeChangeSet::Insert(
912                                 insertion->index, -relativeIndex, splitMoveId));
913                         ++insertion;
914                         insertion->index += -relativeIndex;
915                         insertion->count -= -relativeIndex;
916                     }
917
918                     if (it->prepend()) {
919                         removeFlags |= it->flags & CacheFlag;
920                         translatedRemoval.moveId = ++moveId;
921                         movedFlags->append(MovedFlags(moveId, it->flags & ~AppendFlag));
922
923                         removal = removals->insert(removal, QDeclarativeChangeSet::Remove(
924                                 removal->index, removeCount, translatedRemoval.moveId));
925                         ++removal;
926                         insertion = insertions->insert(insertion, QDeclarativeChangeSet::Insert(
927                                 insertion->index, removeCount, translatedRemoval.moveId));
928                         ++insertion;
929
930                         removal->count -= removeCount;
931                         insertion->index += removeCount;
932                         insertion->count -= removeCount;
933                         if (removal->count == 0) {
934                             removal = removals->erase(removal);
935                             insertion = insertions->erase(insertion);
936                             --removal;
937                             --insertion;
938                         }
939                     } else {
940                         if (offset > 0) {
941                             *it = insert(*it, it->list, it->index, offset, it->flags & ~AppendFlag)->next;
942                             it->index += offset;
943                             it->count -= offset;
944                             it.incrementIndexes(offset);
945                         }
946                         if (it->previous != &m_ranges
947                                 && it->previous->list == it->list
948                                 && it->end() == insertion->index
949                                 && it->previous->flags == (it->flags | MovedFlag)) {
950                             it->previous->count += removeCount;
951                         } else {
952                             *it = insert(*it, it->list, insertion->index, removeCount, it->flags | MovedFlag)->next;
953                         }
954                         translatedRemoval.flags = 0;
955                         removeFlags = 0;
956                     }
957                 } else if (it->inCache()) {
958                     if (offset > 0) {
959                         *it = insert(*it, it->list, it->index, offset, it->flags & ~AppendFlag)->next;
960                         it->index += offset;
961                         it->count -= offset;
962                         it.incrementIndexes(offset);
963                     }
964                     if (it->previous != &m_ranges
965                             && it->previous->list == it->list
966                             && it->previous->flags == CacheFlag) {
967                         it->previous->count += removeCount;
968                     } else {
969                         *it = insert(*it, it->list, -1, removeCount, CacheFlag)->next;
970                     }
971                     it.index[Cache] += removeCount;
972                 }
973                 if (removeFlags & GroupMask)
974                     translatedRemovals->append(translatedRemoval);
975                 m_end.decrementIndexes(removeCount, removeFlags);
976                 if (it->count == 0 && !it->append()) {
977                     *it = erase(*it)->previous;
978                     removed = true;
979                 } else if (relativeIndex <= 0) {
980                     it->index = removal->index;
981                 }
982             } else if (relativeIndex < 0) {
983                 it->index -= itemsRemoved;
984
985                 if (it->previous != &m_ranges
986                         && it->previous->list == it->list
987                         && it->previous->end() == it->index
988                         && it->previous->flags == (it->flags & ~AppendFlag)) {
989                     it->previous->count += it->count;
990                     it->previous->flags = it->flags;
991                     it.incrementIndexes(it->count);
992                     *it = erase(*it);
993                     removed = true;
994                 }
995             }
996         }
997         if (it->flags == CacheFlag && it->next->flags == CacheFlag && it->next->list == it->list) {
998             it.index[Cache] += it->next->count;
999             it->count += it->next->count;
1000             erase(it->next);
1001         } else if (!removed) {
1002             it.incrementIndexes(it->count);
1003         }
1004     }
1005     m_cacheIt = m_end;
1006     QT_DECLARATIVE_VERIFY_LISTCOMPOSITOR
1007 }
1008
1009 void QDeclarativeListCompositor::listItemsRemoved(
1010         void *list, int index, int count, QVector<Remove> *translatedRemovals)
1011 {
1012     QT_DECLARATIVE_TRACE_LISTCOMPOSITOR(<< list << index << count)
1013     Q_ASSERT(count >= 0);
1014
1015     QVector<QDeclarativeChangeSet::Remove> removals;
1016     removals.append(QDeclarativeChangeSet::Remove(index, count));
1017     listItemsRemoved(translatedRemovals, list, &removals, 0, 0, 0);
1018 }
1019
1020 void QDeclarativeListCompositor::listItemsMoved(
1021         void *list,
1022         int from,
1023         int to,
1024         int count,
1025         QVector<Remove> *translatedRemovals,
1026         QVector<Insert> *translatedInsertions)
1027 {
1028     QT_DECLARATIVE_TRACE_LISTCOMPOSITOR(<< list << from << to << count)
1029     Q_ASSERT(count >= 0);
1030
1031     QVector<QDeclarativeChangeSet::Remove> removals;
1032     QVector<QDeclarativeChangeSet::Insert> insertions;
1033     QVector<MovedFlags> movedFlags;
1034     removals.append(QDeclarativeChangeSet::Remove(from, count, 0));
1035     insertions.append(QDeclarativeChangeSet::Insert(to, count, 0));
1036
1037     listItemsRemoved(translatedRemovals, list, &removals, &insertions, &movedFlags, 0);
1038     listItemsInserted(translatedInsertions, list, insertions, &movedFlags);
1039 }
1040
1041 void QDeclarativeListCompositor::listItemsChanged(
1042         QVector<Change> *translatedChanges,
1043         void *list,
1044         const QVector<QDeclarativeChangeSet::Change> &changes)
1045 {
1046     QT_DECLARATIVE_TRACE_LISTCOMPOSITOR(<< list << changes)
1047     for (iterator it(m_ranges.next, 0, Default, m_groupCount); *it != &m_ranges; *it = it->next) {
1048         if (it->list != list || it->flags == CacheFlag) {
1049             it.incrementIndexes(it->count);
1050             continue;
1051         } else if (!it->inGroup()) {
1052             continue;
1053         }
1054         foreach (const QDeclarativeChangeSet::Change &change, changes) {
1055             const int offset = change.index - it->index;
1056             if (offset + change.count > 0 && offset < it->count) {
1057                 const int changeOffset = qMax(0, offset);
1058                 const int changeCount = qMin(it->count, offset + change.count) - changeOffset;
1059
1060                 Change translatedChange(it, changeCount, it->flags);
1061                 for (int i = 0; i < m_groupCount; ++i) {
1062                     if (it->inGroup(i))
1063                         translatedChange.index[i] += changeOffset;
1064                 }
1065                 translatedChanges->append(translatedChange);
1066             }
1067         }
1068         it.incrementIndexes(it->count);
1069     }
1070 }
1071
1072 void QDeclarativeListCompositor::listItemsChanged(
1073         void *list, int index, int count, QVector<Change> *translatedChanges)
1074 {
1075     QT_DECLARATIVE_TRACE_LISTCOMPOSITOR(<< list << index << count)
1076     Q_ASSERT(count >= 0);
1077     QVector<QDeclarativeChangeSet::Change> changes;
1078     changes.append(QDeclarativeChangeSet::Change(index, count));
1079     listItemsChanged(translatedChanges, list, changes);
1080 }
1081
1082 void QDeclarativeListCompositor::listChanged(
1083         void *list,
1084         const QDeclarativeChangeSet &changeSet,
1085         QVector<Remove> *translatedRemovals,
1086         QVector<Insert> *translatedInsertions,
1087         QVector<Change> *translatedChanges)
1088 {
1089     QVector<QDeclarativeChangeSet::Remove> removals = changeSet.removes();
1090     QVector<QDeclarativeChangeSet::Insert> insertions = changeSet.inserts();
1091     QVector<MovedFlags> movedFlags;
1092     listItemsRemoved(translatedRemovals, list, &removals, &insertions, &movedFlags, changeSet.moveCounter());
1093     listItemsInserted(translatedInsertions, list, insertions, &movedFlags);
1094     listItemsChanged(translatedChanges, list, changeSet.changes());
1095 }
1096
1097 void QDeclarativeListCompositor::transition(
1098         Group from,
1099         Group to,
1100         QVector<QDeclarativeChangeSet::Remove> *removes,
1101         QVector<QDeclarativeChangeSet::Insert> *inserts)
1102 {
1103     int removeCount = 0;
1104     for (iterator it(m_ranges.next, 0, Default, m_groupCount); *it != &m_ranges; *it = it->next) {
1105         if (it == from && it != to) {
1106             removes->append(QDeclarativeChangeSet::Remove(it.index[from]- removeCount, it->count));
1107             removeCount += it->count;
1108         } else if (it != from && it == to) {
1109             inserts->append(QDeclarativeChangeSet::Insert(it.index[to], it->count));
1110         }
1111         it.incrementIndexes(it->count);
1112     }
1113 }
1114
1115 QDebug operator <<(QDebug debug, const QDeclarativeListCompositor::Group &group)
1116 {
1117     switch (group) {
1118     case QDeclarativeListCompositor::Cache:   return debug << "Cache";
1119     case QDeclarativeListCompositor::Default: return debug << "Default";
1120     default: return (debug.nospace() << "Group" << int(group)).space();
1121     }
1122
1123 }
1124
1125 QDebug operator <<(QDebug debug, const QDeclarativeListCompositor::Range &range)
1126 {
1127     (debug.nospace()
1128             << "Range("
1129             << range.list) << " "
1130             << range.index << " "
1131             << range.count << " "
1132             << (range.append() ? "A" : "0")
1133             << (range.prepend() ? "P" : "0");
1134     for (int i = QDeclarativeListCompositor::MaximumGroupCount - 1; i >= 2; --i)
1135         debug << (range.inGroup(i) ? "1" : "0");
1136     return (debug
1137             << (range.inGroup(QDeclarativeListCompositor::Default) ? "D" : "0")
1138             << (range.inGroup(QDeclarativeListCompositor::Cache) ? "C" : "0"));
1139 }
1140
1141 static void qt_print_indexes(QDebug &debug, int count, const int *indexes)
1142 {
1143     for (int i = count - 1; i >= 0; --i)
1144         debug << indexes[i];
1145 }
1146
1147 QDebug operator <<(QDebug debug, const QDeclarativeListCompositor::iterator &it)
1148 {
1149     (debug.nospace() << "iterator(" << it.group).space() << "offset:" << it.offset;
1150     qt_print_indexes(debug, it.groupCount, it.index);
1151     return ((debug << **it).nospace() << ")").space();
1152 }
1153
1154 static QDebug qt_print_change(QDebug debug, const char *name, const QDeclarativeListCompositor::Change &change)
1155 {
1156     debug.nospace() << name << "(" << change.moveId << " " << change.count << " ";
1157     for (int i = QDeclarativeListCompositor::MaximumGroupCount - 1; i >= 2; --i)
1158         debug << (change.inGroup(i) ? "1" : "0");
1159     debug << (change.inGroup(QDeclarativeListCompositor::Default) ? "D" : "0")
1160             << (change.inGroup(QDeclarativeListCompositor::Cache) ? "C" : "0");
1161     int i = QDeclarativeListCompositor::MaximumGroupCount - 1;
1162     for (; i >= 0 && !change.inGroup(i); --i) {}
1163     for (; i >= 0; --i)
1164         debug << " " << change.index[i];
1165     return (debug << ")").maybeSpace();
1166 }
1167
1168 QDebug operator <<(QDebug debug, const QDeclarativeListCompositor::Change &change)
1169 {
1170     return qt_print_change(debug, "Change", change);
1171 }
1172
1173 QDebug operator <<(QDebug debug, const QDeclarativeListCompositor::Remove &remove)
1174 {
1175     return qt_print_change(debug, "Remove", remove);
1176 }
1177
1178 QDebug operator <<(QDebug debug, const QDeclarativeListCompositor::Insert &insert)
1179 {
1180     return qt_print_change(debug, "Insert", insert);
1181 }
1182
1183 QDebug operator <<(QDebug debug, const QDeclarativeListCompositor &list)
1184 {
1185     int indexes[QDeclarativeListCompositor::MaximumGroupCount];
1186     for (int i = 0; i < QDeclarativeListCompositor::MaximumGroupCount; ++i)
1187         indexes[i] = 0;
1188     debug.nospace() << "QDeclarativeListCompositor(";
1189     qt_print_indexes(debug, list.m_groupCount, list.m_end.index);
1190     for (QDeclarativeListCompositor::Range *range = list.m_ranges.next; range != &list.m_ranges; range = range->next) {
1191         (debug << "\n").space();
1192         qt_print_indexes(debug, list.m_groupCount, indexes);
1193         debug << " " << *range;
1194
1195         for (int i = 0; i < list.m_groupCount; ++i) {
1196             if (range->inGroup(i))
1197                 indexes[i] += range->count;
1198         }
1199     }
1200     return (debug << ")").maybeSpace();
1201 }
1202
1203 QT_END_NAMESPACE