Declare change set and compositor structs as movable primative types.
[profile/ivi/qtdeclarative.git] / src / quick / util / qquicklistcompositor_p.h
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the QtQml module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #ifndef QQUICKLISTCOMPOSITOR_P_H
43 #define QQUICKLISTCOMPOSITOR_P_H
44
45 //
46 //  W A R N I N G
47 //  -------------
48 //
49 // This file is not part of the Qt API.  It exists purely as an
50 // implementation detail.  This header file may change from version to
51 // version without notice, or even be removed.
52 //
53 // We mean it.
54 //
55
56 #include <QtCore/qglobal.h>
57 #include <QtCore/qvector.h>
58
59 #include <private/qquickchangeset_p.h>
60
61 #include <QtCore/qdebug.h>
62
63 QT_BEGIN_NAMESPACE
64
65 class Q_AUTOTEST_EXPORT QQuickListCompositor
66 {
67 public:
68     enum { MinimumGroupCount = 3, MaximumGroupCount = 11 };
69
70     enum Group
71     {
72         Cache   = 0,
73         Default = 1,
74         Persisted = 2
75     };
76
77     enum Flag
78     {
79         CacheFlag       = 1 << Cache,
80         DefaultFlag     = 1 << Default,
81         PersistedFlag   = 1 << Persisted,
82         PrependFlag     = 0x10000000,
83         AppendFlag      = 0x20000000,
84         UnresolvedFlag  = 0x40000000,
85         MovedFlag       = 0x80000000,
86         GroupMask       = ~(PrependFlag | AppendFlag | UnresolvedFlag | MovedFlag | CacheFlag)
87     };
88
89     class Range
90     {
91     public:
92         Range() : next(this), previous(this), list(0), index(0), count(0), flags(0) {}
93         Range(Range *next, void *list, int index, int count, uint flags)
94             : next(next), previous(next->previous), list(list), index(index), count(count), flags(flags) {
95             next->previous = this; previous->next = this; }
96
97         Range *next;
98         Range *previous;
99         void *list;
100         int index;
101         int count;
102         uint flags;
103
104         inline int start() const { return index; }
105         inline int end() const { return index + count; }
106
107         inline int groups() const { return flags & GroupMask; }
108
109         inline bool inGroup() const { return flags & GroupMask; }
110         inline bool inCache() const { return flags & CacheFlag; }
111         inline bool inGroup(int group) const { return flags & (1 << group); }
112         inline bool isUnresolved() const { return flags & UnresolvedFlag; }
113
114         inline bool prepend() const { return flags & PrependFlag; }
115         inline bool append() const { return flags & AppendFlag; }
116     };
117
118     class Q_AUTOTEST_EXPORT iterator
119     {
120     public:
121         inline iterator();
122         inline iterator(const iterator &it);
123         inline iterator(Range *range, int offset, Group group, int groupCount);
124         inline ~iterator() {}
125
126         bool operator ==(const iterator &it) const { return range == it.range && offset == it.offset; }
127         bool operator !=(const iterator &it) const { return range != it.range || offset != it.offset; }
128
129         bool operator ==(Group group) const { return range->flags & (1 << group); }
130         bool operator !=(Group group) const { return !(range->flags & (1 << group)); }
131
132         Range *&operator *() { return range; }
133         Range * const &operator *() const { return range; }
134         Range *operator ->() { return range; }
135         const Range *operator ->() const { return range; }
136
137         iterator &operator +=(int difference);
138         iterator &operator -=(int difference);
139
140         template<typename T> T *list() const { return static_cast<T *>(range->list); }
141         int modelIndex() const { return range->index + offset; }
142
143         void incrementIndexes(int difference) { incrementIndexes(difference, range->flags); }
144         void decrementIndexes(int difference) { decrementIndexes(difference, range->flags); }
145
146         inline void incrementIndexes(int difference, uint flags);
147         inline void decrementIndexes(int difference, uint flags);
148
149         void setGroup(Group g) { group = g; groupFlag = 1 << g; }
150
151         Range *range;
152         int offset;
153         Group group;
154         int groupFlag;
155         int groupCount;
156         union {
157             struct {
158                 int cacheIndex;
159             };
160             int index[MaximumGroupCount];
161         };
162     };
163
164     class Q_AUTOTEST_EXPORT insert_iterator : public iterator
165     {
166     public:
167         inline insert_iterator() {}
168         inline insert_iterator(const iterator &it) : iterator(it) {}
169         inline insert_iterator(Range *, int, Group, int);
170         inline ~insert_iterator() {}
171
172         insert_iterator &operator +=(int difference);
173         insert_iterator &operator -=(int difference);
174     };
175
176     struct Change
177     {
178         inline Change() {}
179         inline Change(iterator it, int count, uint flags, int moveId = -1);
180         int count;
181         uint flags;
182         int moveId;
183         union {
184             struct {
185                 int cacheIndex;
186             };
187             int index[MaximumGroupCount];
188         };
189
190         inline bool isMove() const { return moveId >= 0; }
191         inline bool inCache() const { return flags & CacheFlag; }
192         inline bool inGroup() const { return flags & GroupMask; }
193         inline bool inGroup(int group) const { return flags & (CacheFlag << group); }
194
195         inline int groups() const { return flags & GroupMask; }
196     };
197
198     struct Insert : public Change
199     {
200         Insert() {}
201         Insert(iterator it, int count, uint flags, int moveId = -1)
202             : Change(it, count, flags, moveId) {}
203     };
204
205     struct Remove : public Change
206     {
207         Remove() {}
208         Remove(iterator it, int count, uint flags, int moveId = -1)
209             : Change(it, count, flags, moveId) {}
210     };
211
212     QQuickListCompositor();
213     ~QQuickListCompositor();
214
215     int defaultGroups() const { return m_defaultFlags & ~PrependFlag; }
216     void setDefaultGroups(int groups) { m_defaultFlags = groups | PrependFlag; }
217     void setDefaultGroup(Group group) { m_defaultFlags |= (1 << group); }
218     void clearDefaultGroup(Group group) { m_defaultFlags &= ~(1 << group); }
219     void setRemoveGroups(int groups) { m_removeFlags = PrependFlag | AppendFlag | groups; }
220     void setGroupCount(int count);
221
222     int count(Group group) const;
223     iterator find(Group group, int index);
224     iterator find(Group group, int index) const;
225     insert_iterator findInsertPosition(Group group, int index);
226
227     iterator begin(Group group);
228     const iterator &end() { return m_end; }
229
230     void append(void *list, int index, int count, uint flags, QVector<Insert> *inserts = 0);
231     void insert(Group group, int before, void *list, int index, int count, uint flags, QVector<Insert> *inserts = 0);
232     iterator insert(iterator before, void *list, int index, int count, uint flags, QVector<Insert> *inserts = 0);
233
234     void setFlags(Group fromGroup, int from, int count, Group group, int flags, QVector<Insert> *inserts = 0);
235     void setFlags(iterator from, int count, Group group, uint flags, QVector<Insert> *inserts = 0);
236     void setFlags(Group fromGroup, int from, int count, uint flags, QVector<Insert> *inserts = 0) {
237         setFlags(fromGroup, from, count, fromGroup, flags, inserts); }
238     void setFlags(iterator from, int count, uint flags, QVector<Insert> *inserts = 0) {
239         setFlags(from, count, from.group, flags, inserts); }
240
241     void clearFlags(Group fromGroup, int from, int count, Group group, uint flags, QVector<Remove> *removals = 0);
242     void clearFlags(iterator from, int count, Group group, uint flags, QVector<Remove> *removals = 0);
243     void clearFlags(Group fromGroup, int from, int count, uint flags, QVector<Remove> *removals = 0) {
244         clearFlags(fromGroup, from, count, fromGroup, flags, removals); }
245     void clearFlags(iterator from, int count, uint flags, QVector<Remove> *removals = 0) {
246         clearFlags(from, count, from.group, flags, removals); }
247
248     void removeList(void *list, QVector<Remove> *removals, bool destroyed);
249
250     bool verifyMoveTo(Group fromGroup, int from, Group toGroup, int to, int count, Group group) const;
251
252     void move(
253             Group fromGroup,
254             int from,
255             Group toGroup,
256             int to,
257             int count,
258             Group group,
259             QVector<Remove> *removals = 0,
260             QVector<Insert> *inserts = 0);
261     void clear();
262
263     void listItemsInserted(void *list, int index, int count, QVector<Insert> *inserts);
264     void listItemsRemoved(void *list, int index, int count, QVector<Remove> *removals);
265     void listItemsMoved(void *list, int from, int to, int count, QVector<Remove> *removals, QVector<Insert> *inserts);
266     void listItemsChanged(void *list, int index, int count, QVector<Change> *changes);
267     void listChanged(
268             void *list,
269             const QQuickChangeSet &changeSet,
270             QVector<Remove> *removals,
271             QVector<Insert> *inserts,
272             QVector<Change> *changes);
273
274     void transition(
275             Group from,
276             Group to,
277             QVector<QQuickChangeSet::Remove> *removes,
278             QVector<QQuickChangeSet::Insert> *inserts);
279
280 private:
281     Range m_ranges;
282     iterator m_end;
283     iterator m_cacheIt;
284     int m_groupCount;
285     int m_defaultFlags;
286     int m_removeFlags;
287
288     inline Range *insert(Range *before, void *list, int index, int count, uint flags);
289     inline Range *erase(Range *range);
290
291     struct MovedFlags
292     {
293         MovedFlags() {}
294         MovedFlags(int moveId, uint flags) : moveId(moveId), flags(flags) {}
295
296         int moveId;
297         uint flags;
298     };
299
300     void listItemsRemoved(
301             QVector<Remove> *translatedRemovals,
302             void *list,
303             QVector<QQuickChangeSet::Remove> *removals,
304             QVector<QQuickChangeSet::Insert> *insertions = 0,
305             QVector<MovedFlags> *movedFlags = 0,
306             int moveId = 0);
307     void listItemsInserted(
308             QVector<Insert> *translatedInsertions,
309             void *list,
310             const QVector<QQuickChangeSet::Insert> &insertions,
311             const QVector<MovedFlags> *movedFlags = 0);
312     void listItemsChanged(
313             QVector<Change> *translatedChanges,
314             void *list,
315             const QVector<QQuickChangeSet::Change> &changes);
316
317     friend Q_AUTOTEST_EXPORT QDebug operator <<(QDebug debug, const QQuickListCompositor &list);
318 };
319
320 Q_DECLARE_TYPEINFO(QQuickListCompositor::Change, Q_PRIMITIVE_TYPE);
321 Q_DECLARE_TYPEINFO(QQuickListCompositor::Remove, Q_PRIMITIVE_TYPE);
322 Q_DECLARE_TYPEINFO(QQuickListCompositor::Insert, Q_PRIMITIVE_TYPE);
323
324 inline QQuickListCompositor::iterator::iterator()
325     : range(0), offset(0), group(Default), groupCount(0) {}
326 inline QQuickListCompositor::iterator::iterator(const iterator &it)
327     : range(it.range)
328     , offset(it.offset)
329     , group(it.group)
330     , groupFlag(it.groupFlag)
331     , groupCount(it.groupCount)
332 {
333     for (int i = 0; i < groupCount; ++i)
334         index[i] = it.index[i];
335 }
336
337 inline QQuickListCompositor::iterator::iterator(
338         Range *range, int offset, Group group, int groupCount)
339     : range(range)
340     , offset(offset)
341     , group(group)
342     , groupFlag(1 << group)
343     , groupCount(groupCount)
344 {
345     for (int i = 0; i < groupCount; ++i)
346         index[i] = 0;
347 }
348
349 inline void QQuickListCompositor::iterator::incrementIndexes(int difference, uint flags)
350 {
351     for (int i = 0; i < groupCount; ++i) {
352         if (flags & (1 << i))
353             index[i] += difference;
354     }
355 }
356
357 inline void QQuickListCompositor::iterator::decrementIndexes(int difference, uint flags)
358 {
359     for (int i = 0; i < groupCount; ++i) {
360         if (flags & (1 << i))
361             index[i] -= difference;
362     }
363 }
364
365 inline QQuickListCompositor::insert_iterator::insert_iterator(
366         Range *range, int offset, Group group, int groupCount)
367     : iterator(range, offset, group, groupCount) {}
368
369 inline QQuickListCompositor::Change::Change(iterator it, int count, uint flags, int moveId)
370     : count(count), flags(flags), moveId(moveId)
371 {
372     for (int i = 0; i < MaximumGroupCount; ++i)
373         index[i] = it.index[i];
374 }
375
376 Q_AUTOTEST_EXPORT QDebug operator <<(QDebug debug, const QQuickListCompositor::Group &group);
377 Q_AUTOTEST_EXPORT QDebug operator <<(QDebug debug, const QQuickListCompositor::Range &range);
378 Q_AUTOTEST_EXPORT QDebug operator <<(QDebug debug, const QQuickListCompositor::iterator &it);
379 Q_AUTOTEST_EXPORT QDebug operator <<(QDebug debug, const QQuickListCompositor::Change &change);
380 Q_AUTOTEST_EXPORT QDebug operator <<(QDebug debug, const QQuickListCompositor::Remove &remove);
381 Q_AUTOTEST_EXPORT QDebug operator <<(QDebug debug, const QQuickListCompositor::Insert &insert);
382 Q_AUTOTEST_EXPORT QDebug operator <<(QDebug debug, const QQuickListCompositor &list);
383
384 QT_END_NAMESPACE
385
386 #endif