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

source code of qtdeclarative/src/qmlmodels/qqmllistcompositor_p.h