1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the QtDeclarative module of the Qt Toolkit.
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.
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.
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.
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.
40 ****************************************************************************/
42 #include "qdeclarativelistcompositor_p.h"
44 #include <QtCore/qvarlengtharray.h>
46 //#define QT_DECLARATIVE_VERIFY_MINIMAL
47 //#define QT_DECLARATIVE_VERIFY_INTEGRITY
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)
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;
76 #ifdef QT_DECLARATIVE_VERIFY_INTEGRITY
77 static bool qt_printInfo(const QDeclarativeListCompositor &compositor)
79 qWarning() << compositor;
83 static bool qt_verifyIntegrity(
84 const QDeclarativeListCompositor::iterator &begin,
85 const QDeclarativeListCompositor::iterator &end,
86 const QDeclarativeListCompositor::iterator &cachedIt)
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";
98 qWarning() << index << "Negative count";
101 if (it->list && it->flags != QDeclarativeListCompositor::CacheFlag && it->index < 0) {
102 qWarning() << index <<"Negative index";
105 if (it->previous->next != it.range) {
106 qWarning() << index << "broken list: it->previous->next != it.range";
109 if (it->next->previous != it.range) {
110 qWarning() << index << "broken list: it->next->previous != it.range";
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]) {
120 << "invalid cached index"
121 << QDeclarativeListCompositor::Group(i)
131 it.incrementIndexes(it->count);
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];
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)));
153 # define QT_DECLARATIVE_VERIFY_LISTCOMPOSITOR
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)
159 QDeclarativeListCompositor::iterator &QDeclarativeListCompositor::iterator::operator +=(int difference)
161 Q_ASSERT(difference >= 0);
162 while (!(range->flags & groupFlag)) {
163 incrementIndexes(range->count - offset);
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);
175 incrementIndexes(offset);
179 QDeclarativeListCompositor::iterator &QDeclarativeListCompositor::iterator::operator -=(int difference)
181 Q_ASSERT(difference >= 0);
182 while (!(range->flags & groupFlag)) {
183 decrementIndexes(offset);
184 range = range->previous;
185 offset = range->count;
187 decrementIndexes(offset);
188 offset -= difference;
190 range = range->previous;
191 if (range->flags & groupFlag)
192 offset += range->count;
193 decrementIndexes(range->count);
195 incrementIndexes(offset);
199 QDeclarativeListCompositor::insert_iterator &QDeclarativeListCompositor::insert_iterator::operator +=(int difference)
201 Q_ASSERT(difference >= 0);
202 while (!(range->flags & groupFlag)) {
203 incrementIndexes(range->count - offset);
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);
217 incrementIndexes(offset);
221 QDeclarativeListCompositor::insert_iterator &QDeclarativeListCompositor::insert_iterator::operator -=(int difference)
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;
229 decrementIndexes(offset);
230 offset -= difference;
232 range = range->previous;
233 if (range->flags & groupFlag)
234 offset += range->count;
235 decrementIndexes(range->count);
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;
242 } else if (!previous->inGroup()) {
250 QDeclarativeListCompositor::QDeclarativeListCompositor()
251 : m_end(m_ranges.next, 0, Default, 2)
254 , m_defaultFlags(PrependFlag | DefaultFlag)
255 , m_removeFlags(AppendFlag | PrependFlag | GroupMask)
259 QDeclarativeListCompositor::~QDeclarativeListCompositor()
261 for (Range *next, *range = m_ranges.next; range != &m_ranges; range = next) {
267 inline QDeclarativeListCompositor::Range *QDeclarativeListCompositor::insert(
268 Range *before, void *list, int index, int count, int flags)
270 return new Range(before, list, index, count, flags);
273 inline QDeclarativeListCompositor::Range *QDeclarativeListCompositor::erase(
276 Range *next = range->next;
277 next->previous = range->previous;
278 next->previous->next = range->next;
283 void QDeclarativeListCompositor::setGroupCount(int count)
285 m_groupCount = count;
286 m_end = iterator(&m_ranges, 0, Default, m_groupCount);
290 int QDeclarativeListCompositor::count(Group group) const
292 return m_end.index[group];
295 QDeclarativeListCompositor::iterator QDeclarativeListCompositor::find(Group group, int index)
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);
303 const int offset = index - m_cacheIt.index[group];
304 m_cacheIt.setGroup(group);
307 } else if (offset < 0) {
308 m_cacheIt -= -offset;
309 } else if (offset == 0) {
314 Q_ASSERT(m_cacheIt.index[group] == index);
315 Q_ASSERT(m_cacheIt->inGroup(group));
316 QT_DECLARATIVE_VERIFY_LISTCOMPOSITOR
320 QDeclarativeListCompositor::iterator QDeclarativeListCompositor::find(Group group, int index) const
322 return const_cast<QDeclarativeListCompositor *>(this)->find(group, index);
325 QDeclarativeListCompositor::insert_iterator QDeclarativeListCompositor::findInsertPosition(Group group, int index)
327 QT_DECLARATIVE_TRACE_LISTCOMPOSITOR(<< group << index)
328 Q_ASSERT(index >=0 && index <= count(group));
330 if (m_cacheIt == m_end) {
331 it = iterator(m_ranges.next, 0, group, m_groupCount);
334 const int offset = index - m_cacheIt.index[group];
339 } else if (offset < 0) {
341 } else if (offset == 0) {
346 Q_ASSERT(it.index[group] == index);
350 QDeclarativeListCompositor::iterator QDeclarativeListCompositor::begin(Group group)
352 QT_DECLARATIVE_TRACE_LISTCOMPOSITOR(<< group)
353 m_cacheIt = iterator(m_ranges.next, 0, group, m_groupCount);
358 void QDeclarativeListCompositor::append(
359 void *list, int index, int count, int flags, QVector<Insert> *inserts)
361 QT_DECLARATIVE_TRACE_LISTCOMPOSITOR(<< list << index << count << flags)
362 insert(m_end, list, index, count, flags, inserts);
365 void QDeclarativeListCompositor::insert(
366 Group group, int before, void *list, int index, int count, int flags, QVector<Insert> *inserts)
368 QT_DECLARATIVE_TRACE_LISTCOMPOSITOR(<< group << before << list << index << count << flags)
369 insert(findInsertPosition(group, before), list, index, count, flags, inserts);
372 QDeclarativeListCompositor::iterator QDeclarativeListCompositor::insert(
373 iterator before, void *list, int index, int count, int flags, QVector<Insert> *inserts)
375 QT_DECLARATIVE_TRACE_LISTCOMPOSITOR(<< before << list << index << count << flags)
377 inserts->append(Insert(before, count, flags & GroupMask));
379 if (before.offset > 0) {
381 *before, before->list, before->index, before.offset, before->flags & ~AppendFlag)->next;
382 before->index += before.offset;
383 before->count -= before.offset;
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);
394 *before = insert(*before, list, index, count, flags);
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);
407 m_end.incrementIndexes(count, flags);
409 QT_DECLARATIVE_VERIFY_LISTCOMPOSITOR
413 void QDeclarativeListCompositor::setFlags(
414 Group group, int index, int count, int flags, QVector<Insert> *inserts)
416 QT_DECLARATIVE_TRACE_LISTCOMPOSITOR(<< group << index << count << flags)
417 setFlags(find(group, index), count, flags, inserts);
420 void QDeclarativeListCompositor::setFlags(
421 iterator from, int count, int flags, QVector<Insert> *inserts)
423 QT_DECLARATIVE_TRACE_LISTCOMPOSITOR(<< from << count << flags)
424 if (!flags || !count)
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;
434 for (; count > 0; *from = from->next) {
435 if (from != from.group) {
436 from.incrementIndexes(from->count);
439 const int difference = qMin(count, from->count);
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);
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) {
458 from->previous->flags |= AppendFlag;
459 *from = erase(*from)->previous;
464 } else if (!insertFlags) {
465 from.incrementIndexes(from->count - difference);
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;
472 from->flags |= flags;
475 from.incrementIndexes(from->count);
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;
488 QT_DECLARATIVE_VERIFY_LISTCOMPOSITOR
491 void QDeclarativeListCompositor::clearFlags(
492 Group group, int index, int count, int flags, QVector<Remove> *removes)
494 QT_DECLARATIVE_TRACE_LISTCOMPOSITOR(<< group << index << count << flags)
495 clearFlags(find(group, index), count, flags, removes);
498 void QDeclarativeListCompositor::clearFlags(
499 iterator from, int count, int flags, QVector<Remove> *removes)
501 QT_DECLARATIVE_TRACE_LISTCOMPOSITOR(<< from << count << flags)
502 if (!flags || !count)
505 const bool clearCache = flags & CacheFlag;
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;
514 for (; count > 0; *from = from->next) {
515 if (from != from.group) {
516 from.incrementIndexes(from->count);
519 const int difference = qMin(count, from->count);
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));
529 removes->append(Remove(from, difference, maskedFlags));
531 m_end.decrementIndexes(difference, removeFlags);
532 from.incrementIndexes(difference, clearedFlags);
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) {
543 from->previous->flags |= AppendFlag;
544 *from = erase(*from)->previous;
546 from.incrementIndexes(from->count);
548 } else if (difference < from->count) {
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;
557 *from = erase(*from)->previous;
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;
571 QT_DECLARATIVE_VERIFY_LISTCOMPOSITOR
574 void QDeclarativeListCompositor::removeList(void *list, QVector<Remove> *removes, bool destroyed)
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);
581 removes->append(Remove(it, it->count, flags));
582 m_end.decrementIndexes(it->count, flags);
587 it->flags = CacheFlag;
588 it.cacheIndex += it->count;
590 *it = erase(*it)->previous;
593 it.incrementIndexes(it->count);
597 QT_DECLARATIVE_VERIFY_LISTCOMPOSITOR
600 bool QDeclarativeListCompositor::verifyMoveTo(
601 Group fromGroup, int from, Group toGroup, int to, int count) const
603 if (fromGroup != toGroup) {
604 // determine how many items from the destination group intersect with the source group.
605 iterator fromIt = find(fromGroup, from);
607 int intersectingCount = 0;
609 for (; count > 0; *fromIt = fromIt->next) {
610 if (*fromIt == &m_ranges)
612 if (!fromIt->inGroup(fromGroup))
614 if (fromIt->inGroup(toGroup))
615 intersectingCount += qMin(count, fromIt->count - fromIt.offset);
616 count -= fromIt->count - fromIt.offset;
619 count = intersectingCount;
622 return to >= 0 && to + count <= m_end.index[toGroup];
625 void QDeclarativeListCompositor::move(
631 QVector<Remove> *removes,
632 QVector<Insert> *inserts)
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));
639 iterator fromIt = find(fromGroup, from);
640 if (fromIt.offset > 0) {
642 *fromIt, fromIt->list, fromIt->index, fromIt.offset, fromIt->flags & ~AppendFlag)->next;
643 fromIt->index += fromIt.offset;
644 fromIt->count -= fromIt.offset;
649 for (int moveId = 0; count > 0;) {
650 if (fromIt != fromIt.group) {
651 fromIt.incrementIndexes(fromIt->count);
652 *fromIt = fromIt->next;
655 int difference = qMin(count, fromIt->count);
662 fromIt->flags & ~(PrependFlag | AppendFlag));
664 removes->append(Remove(fromIt, difference, fromIt->flags, moveId++));
666 fromIt->count -= difference;
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;
678 fromIt->index += difference;
680 if (fromIt->count == 0) {
681 if (fromIt->append())
682 fromIt->previous->flags |= AppendFlag;
683 *fromIt = erase(*fromIt);
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);
694 } else if (count > 0) {
695 *fromIt = fromIt->next;
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;
712 insert_iterator toIt = fromIt;
713 toIt.setGroup(toGroup);
714 const int difference = to - toIt.index[toGroup];
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;
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;
735 *toIt = insert(*toIt, range->list, range->index, range->count, range->flags);
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;
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;
752 inserts->append(insert);
753 for (int i = 0; i < m_groupCount; ++i) {
754 if (insert.inGroup(i))
755 insert.index[i] += range->count;
763 QT_DECLARATIVE_VERIFY_LISTCOMPOSITOR
766 void QDeclarativeListCompositor::clear()
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);
774 void QDeclarativeListCompositor::listItemsInserted(
775 QVector<Insert> *translatedInsertions,
777 const QVector<QDeclarativeChangeSet::Insert> &insertions,
778 const QVector<MovedFlags> *movedFlags)
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);
785 } else if (it->flags & MovedFlag) {
786 it->flags &= ~MovedFlag;
787 it.incrementIndexes(it->count);
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())) {
796 int flags = m_defaultFlags;
797 if (insertion.isMove()) {
798 for (QVector<MovedFlags>::const_iterator move = movedFlags->begin();
799 move != movedFlags->end();
801 if (move->moveId == insertion.moveId) {
807 if (flags & ~(AppendFlag | PrependFlag)) {
808 Insert translatedInsert(it, insertion.count, flags, insertion.moveId);
809 for (int i = 0; i < m_groupCount; ++i) {
811 translatedInsert.index[i] += offset;
813 translatedInsertions->append(translatedInsert);
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);
827 it.incrementIndexes(offset);
828 *it = insert(*it, it->list, it->index, offset, it->flags & ~AppendFlag)->next;
830 *it = insert(*it, it->list, insertion.index, insertion.count, flags)->next;
831 it.incrementIndexes(insertion.count, flags);
832 it->index += offset + insertion.count;
835 m_end.incrementIndexes(insertion.count, flags);
838 *it = insert(*it, it->list, it->index, offset, it->flags)->next;
842 it->index += insertion.count;
844 } else if (offset <= 0) {
845 it->index += insertion.count;
848 it.incrementIndexes(it->count);
851 QT_DECLARATIVE_VERIFY_LISTCOMPOSITOR
854 void QDeclarativeListCompositor::listItemsInserted(
855 void *list, int index, int count, QVector<Insert> *translatedInsertions)
857 QT_DECLARATIVE_TRACE_LISTCOMPOSITOR(<< list << index << count)
860 QVector<QDeclarativeChangeSet::Insert> insertions;
861 insertions.append(QDeclarativeChangeSet::Insert(index, count));
863 listItemsInserted(translatedInsertions, list, insertions);
866 void QDeclarativeListCompositor::listItemsRemoved(
867 QVector<Remove> *translatedRemovals,
869 QVector<QDeclarativeChangeSet::Remove> *removals,
870 QVector<QDeclarativeChangeSet::Insert> *insertions,
871 QVector<MovedFlags> *movedFlags, int moveId)
873 QT_DECLARATIVE_TRACE_LISTCOMPOSITOR(<< list << *removals)
875 for (iterator it(m_ranges.next, 0, Default, m_groupCount);
876 *it != &m_ranges && !removals->isEmpty();
878 if (it->list != list || it->flags == CacheFlag) {
879 it.incrementIndexes(it->count);
882 bool removed = false;
883 for (QVector<QDeclarativeChangeSet::Remove>::iterator removal = removals->begin();
884 !removed && removal != removals->end();
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) {
896 translatedRemoval.index[i] += offset;
898 if (removal->isMove()) {
899 QVector<QDeclarativeChangeSet::Insert>::iterator insertion = insertions->begin();
900 for (; insertion != insertions->end() && insertion->moveId != removal->moveId;
902 Q_ASSERT(insertion != insertions->end());
903 Q_ASSERT(insertion->count == removal->count);
905 if (relativeIndex < 0) {
906 int splitMoveId = ++moveId;
907 removal = removals->insert(removal, QDeclarativeChangeSet::Remove(
908 removal->index, -relativeIndex, splitMoveId));
910 removal->count -= -relativeIndex;
911 insertion = insertions->insert(insertion, QDeclarativeChangeSet::Insert(
912 insertion->index, -relativeIndex, splitMoveId));
914 insertion->index += -relativeIndex;
915 insertion->count -= -relativeIndex;
919 removeFlags |= it->flags & CacheFlag;
920 translatedRemoval.moveId = ++moveId;
921 movedFlags->append(MovedFlags(moveId, it->flags & ~AppendFlag));
923 removal = removals->insert(removal, QDeclarativeChangeSet::Remove(
924 removal->index, removeCount, translatedRemoval.moveId));
926 insertion = insertions->insert(insertion, QDeclarativeChangeSet::Insert(
927 insertion->index, removeCount, translatedRemoval.moveId));
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);
941 *it = insert(*it, it->list, it->index, offset, it->flags & ~AppendFlag)->next;
944 it.incrementIndexes(offset);
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;
952 *it = insert(*it, it->list, insertion->index, removeCount, it->flags | MovedFlag)->next;
954 translatedRemoval.flags = 0;
957 } else if (it->inCache()) {
959 *it = insert(*it, it->list, it->index, offset, it->flags & ~AppendFlag)->next;
962 it.incrementIndexes(offset);
964 if (it->previous != &m_ranges
965 && it->previous->list == it->list
966 && it->previous->flags == CacheFlag) {
967 it->previous->count += removeCount;
969 *it = insert(*it, it->list, -1, removeCount, CacheFlag)->next;
971 it.index[Cache] += removeCount;
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;
979 } else if (relativeIndex <= 0) {
980 it->index = removal->index;
982 } else if (relativeIndex < 0) {
983 it->index -= itemsRemoved;
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);
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;
1001 } else if (!removed) {
1002 it.incrementIndexes(it->count);
1006 QT_DECLARATIVE_VERIFY_LISTCOMPOSITOR
1009 void QDeclarativeListCompositor::listItemsRemoved(
1010 void *list, int index, int count, QVector<Remove> *translatedRemovals)
1012 QT_DECLARATIVE_TRACE_LISTCOMPOSITOR(<< list << index << count)
1013 Q_ASSERT(count >= 0);
1015 QVector<QDeclarativeChangeSet::Remove> removals;
1016 removals.append(QDeclarativeChangeSet::Remove(index, count));
1017 listItemsRemoved(translatedRemovals, list, &removals, 0, 0, 0);
1020 void QDeclarativeListCompositor::listItemsMoved(
1025 QVector<Remove> *translatedRemovals,
1026 QVector<Insert> *translatedInsertions)
1028 QT_DECLARATIVE_TRACE_LISTCOMPOSITOR(<< list << from << to << count)
1029 Q_ASSERT(count >= 0);
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));
1037 listItemsRemoved(translatedRemovals, list, &removals, &insertions, &movedFlags, 0);
1038 listItemsInserted(translatedInsertions, list, insertions, &movedFlags);
1041 void QDeclarativeListCompositor::listItemsChanged(
1042 QVector<Change> *translatedChanges,
1044 const QVector<QDeclarativeChangeSet::Change> &changes)
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);
1051 } else if (!it->inGroup()) {
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;
1060 Change translatedChange(it, changeCount, it->flags);
1061 for (int i = 0; i < m_groupCount; ++i) {
1063 translatedChange.index[i] += changeOffset;
1065 translatedChanges->append(translatedChange);
1068 it.incrementIndexes(it->count);
1072 void QDeclarativeListCompositor::listItemsChanged(
1073 void *list, int index, int count, QVector<Change> *translatedChanges)
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);
1082 void QDeclarativeListCompositor::listChanged(
1084 const QDeclarativeChangeSet &changeSet,
1085 QVector<Remove> *translatedRemovals,
1086 QVector<Insert> *translatedInsertions,
1087 QVector<Change> *translatedChanges)
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());
1097 void QDeclarativeListCompositor::transition(
1100 QVector<QDeclarativeChangeSet::Remove> *removes,
1101 QVector<QDeclarativeChangeSet::Insert> *inserts)
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));
1111 it.incrementIndexes(it->count);
1115 QDebug operator <<(QDebug debug, const QDeclarativeListCompositor::Group &group)
1118 case QDeclarativeListCompositor::Cache: return debug << "Cache";
1119 case QDeclarativeListCompositor::Default: return debug << "Default";
1120 default: return (debug.nospace() << "Group" << int(group)).space();
1125 QDebug operator <<(QDebug debug, const QDeclarativeListCompositor::Range &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");
1137 << (range.inGroup(QDeclarativeListCompositor::Default) ? "D" : "0")
1138 << (range.inGroup(QDeclarativeListCompositor::Cache) ? "C" : "0"));
1141 static void qt_print_indexes(QDebug &debug, int count, const int *indexes)
1143 for (int i = count - 1; i >= 0; --i)
1144 debug << indexes[i];
1147 QDebug operator <<(QDebug debug, const QDeclarativeListCompositor::iterator &it)
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();
1154 static QDebug qt_print_change(QDebug debug, const char *name, const QDeclarativeListCompositor::Change &change)
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) {}
1164 debug << " " << change.index[i];
1165 return (debug << ")").maybeSpace();
1168 QDebug operator <<(QDebug debug, const QDeclarativeListCompositor::Change &change)
1170 return qt_print_change(debug, "Change", change);
1173 QDebug operator <<(QDebug debug, const QDeclarativeListCompositor::Remove &remove)
1175 return qt_print_change(debug, "Remove", remove);
1178 QDebug operator <<(QDebug debug, const QDeclarativeListCompositor::Insert &insert)
1180 return qt_print_change(debug, "Insert", insert);
1183 QDebug operator <<(QDebug debug, const QDeclarativeListCompositor &list)
1185 int indexes[QDeclarativeListCompositor::MaximumGroupCount];
1186 for (int i = 0; i < QDeclarativeListCompositor::MaximumGroupCount; ++i)
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;
1195 for (int i = 0; i < list.m_groupCount; ++i) {
1196 if (range->inGroup(i))
1197 indexes[i] += range->count;
1200 return (debug << ")").maybeSpace();