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 QtQuick 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 QQUICKITEMVIEW_P_P_H
41#define QQUICKITEMVIEW_P_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 <QtQuick/private/qtquickglobal_p.h>
55
56QT_REQUIRE_CONFIG(quick_itemview);
57
58#include "qquickitemview_p.h"
59#include "qquickitemviewfxitem_p_p.h"
60#include "qquickitemviewtransition_p.h"
61#include "qquickflickable_p_p.h"
62#include <QtQmlModels/private/qqmlobjectmodel_p.h>
63#include <QtQmlModels/private/qqmldelegatemodel_p.h>
64#include <QtQmlModels/private/qqmlchangeset_p.h>
65
66
67QT_BEGIN_NAMESPACE
68
69class Q_AUTOTEST_EXPORT FxViewItem : public QQuickItemViewFxItem
70{
71public:
72 FxViewItem(QQuickItem *, QQuickItemView *, bool own, QQuickItemViewAttached *attached);
73
74 QQuickItemView *view;
75 QQuickItemViewAttached *attached;
76};
77
78
79class QQuickItemViewChangeSet
80{
81public:
82 QQuickItemViewChangeSet();
83
84 bool hasPendingChanges() const;
85 void prepare(int currentIndex, int count);
86 void reset();
87
88 void applyChanges(const QQmlChangeSet &changeSet);
89
90 void applyBufferedChanges(const QQuickItemViewChangeSet &other);
91
92 int itemCount;
93 int newCurrentIndex;
94 QQmlChangeSet pendingChanges;
95 QMultiHash<QQmlChangeSet::MoveKey, FxViewItem *> removedItems;
96
97 bool active : 1;
98 bool currentChanged : 1;
99 bool currentRemoved : 1;
100};
101
102
103class Q_AUTOTEST_EXPORT QQuickItemViewPrivate : public QQuickFlickablePrivate, public QQuickItemViewTransitionChangeListener, public QAnimationJobChangeListener
104{
105 Q_DECLARE_PUBLIC(QQuickItemView)
106public:
107 QQuickItemViewPrivate();
108 ~QQuickItemViewPrivate();
109
110 static inline QQuickItemViewPrivate *get(QQuickItemView *o) { return o->d_func(); }
111
112 struct ChangeResult {
113 QQmlNullableValue<qreal> visiblePos;
114 bool changedFirstItem;
115 qreal sizeChangesBeforeVisiblePos;
116 qreal sizeChangesAfterVisiblePos;
117 int countChangeBeforeVisible;
118 int countChangeAfterVisibleItems;
119
120 ChangeResult()
121 : visiblePos(0), changedFirstItem(false),
122 sizeChangesBeforeVisiblePos(0), sizeChangesAfterVisiblePos(0),
123 countChangeBeforeVisible(0), countChangeAfterVisibleItems(0) {}
124
125 ChangeResult(const QQmlNullableValue<qreal> &p)
126 : visiblePos(p), changedFirstItem(false),
127 sizeChangesBeforeVisiblePos(0), sizeChangesAfterVisiblePos(0),
128 countChangeBeforeVisible(0), countChangeAfterVisibleItems(0) {}
129
130 ChangeResult &operator+=(const ChangeResult &other) {
131 if (&other == this)
132 return *this;
133 changedFirstItem &= other.changedFirstItem;
134 sizeChangesBeforeVisiblePos += other.sizeChangesBeforeVisiblePos;
135 sizeChangesAfterVisiblePos += other.sizeChangesAfterVisiblePos;
136 countChangeBeforeVisible += other.countChangeBeforeVisible;
137 countChangeAfterVisibleItems += other.countChangeAfterVisibleItems;
138 return *this;
139 }
140
141 void reset() {
142 changedFirstItem = false;
143 sizeChangesBeforeVisiblePos = 0.0;
144 sizeChangesAfterVisiblePos = 0.0;
145 countChangeBeforeVisible = 0;
146 countChangeAfterVisibleItems = 0;
147 }
148 };
149
150 enum BufferMode { NoBuffer = 0x00, BufferBefore = 0x01, BufferAfter = 0x02 };
151 enum MovementReason { Other, SetIndex, Mouse };
152
153 bool isValid() const;
154 qreal position() const;
155 qreal size() const;
156 qreal startPosition() const;
157 qreal endPosition() const;
158 qreal contentStartOffset() const;
159 int findLastVisibleIndex(int defaultValue = -1) const;
160 FxViewItem *visibleItem(int modelIndex) const;
161 FxViewItem *firstItemInView() const;
162 int findLastIndexInView() const;
163 int mapFromModel(int modelIndex) const;
164
165 virtual void init();
166 virtual void clear(bool onDestruction=false);
167 virtual void updateViewport();
168
169 void regenerate(bool orientationChanged=false);
170 void layout();
171 void animationFinished(QAbstractAnimationJob *) override;
172 void refill();
173 void refill(qreal from, qreal to);
174 void mirrorChange() override;
175
176 FxViewItem *createItem(int modelIndex,QQmlIncubator::IncubationMode incubationMode = QQmlIncubator::AsynchronousIfNested);
177 virtual bool releaseItem(FxViewItem *item, QQmlInstanceModel::ReusableFlag reusableFlag);
178
179 QQuickItem *createHighlightItem() const;
180 QQuickItem *createComponentItem(QQmlComponent *component, qreal zValue, bool createDefault = false) const;
181
182 void updateCurrent(int modelIndex);
183 void updateTrackedItem();
184 void updateUnrequestedIndexes();
185 void updateUnrequestedPositions();
186 void updateVisibleIndex();
187 void positionViewAtIndex(int index, int mode);
188
189 qreal minExtentForAxis(const AxisData &axisData, bool forXAxis) const;
190 qreal maxExtentForAxis(const AxisData &axisData, bool forXAxis) const;
191 qreal calculatedMinExtent() const;
192 qreal calculatedMaxExtent() const;
193
194 void applyDelegateChange();
195
196 void applyPendingChanges();
197 bool applyModelChanges(ChangeResult *insertionResult, ChangeResult *removalResult);
198 bool applyRemovalChange(const QQmlChangeSet::Change &removal, ChangeResult *changeResult, int *removedCount);
199 void removeItem(FxViewItem *item, const QQmlChangeSet::Change &removal, ChangeResult *removeResult);
200 virtual void updateSizeChangesBeforeVisiblePos(FxViewItem *item, ChangeResult *removeResult);
201 void repositionFirstItem(FxViewItem *prevVisibleItemsFirst, qreal prevVisibleItemsFirstPos,
202 FxViewItem *prevFirstVisible, ChangeResult *insertionResult, ChangeResult *removalResult);
203
204 void createTransitioner();
205 void prepareVisibleItemTransitions();
206 void prepareRemoveTransitions(QMultiHash<QQmlChangeSet::MoveKey, FxViewItem *> *removedItems);
207 bool prepareNonVisibleItemTransition(FxViewItem *item, const QRectF &viewBounds);
208 void viewItemTransitionFinished(QQuickItemViewTransitionableItem *item) override;
209
210 int findMoveKeyIndex(QQmlChangeSet::MoveKey key, const QVector<QQmlChangeSet::Change> &changes) const;
211
212 void checkVisible() const;
213 void showVisibleItems() const;
214
215 void markExtentsDirty() {
216 if (layoutOrientation() == Qt::Vertical)
217 vData.markExtentsDirty();
218 else
219 hData.markExtentsDirty();
220 }
221
222 bool hasPendingChanges() const {
223 return currentChanges.hasPendingChanges()
224 || bufferedChanges.hasPendingChanges()
225 ||runDelayedRemoveTransition;
226 }
227
228 void refillOrLayout() {
229 if (hasPendingChanges())
230 layout();
231 else
232 refill();
233 }
234
235 void forceLayoutPolish() {
236 Q_Q(QQuickItemView);
237 forceLayout = true;
238 q->polish();
239 }
240
241 void releaseVisibleItems(QQmlInstanceModel::ReusableFlag reusableFlag) {
242 // make a copy and clear the visibleItems first to avoid destroyed
243 // items being accessed during the loop (QTBUG-61294)
244 const QList<FxViewItem *> oldVisible = visibleItems;
245 visibleItems.clear();
246 for (FxViewItem *item : oldVisible)
247 releaseItem(item, reusableFlag);
248 }
249
250 virtual QQuickItemViewAttached *getAttachedObject(const QObject *) const { return nullptr; }
251
252 QPointer<QQmlInstanceModel> model;
253 QVariant modelVariant;
254 int itemCount;
255 int buffer;
256 int bufferMode;
257 int displayMarginBeginning;
258 int displayMarginEnd;
259 Qt::LayoutDirection layoutDirection;
260 QQuickItemView::VerticalLayoutDirection verticalLayoutDirection;
261
262 MovementReason moveReason;
263
264 QList<FxViewItem *> visibleItems;
265 qreal firstVisibleItemPosition = 0;
266 void storeFirstVisibleItemPosition() {
267 if (!visibleItems.isEmpty()) {
268 firstVisibleItemPosition = visibleItems.constFirst()->position();
269 }
270 }
271 int visibleIndex;
272 int currentIndex;
273 FxViewItem *currentItem;
274 FxViewItem *trackedItem;
275 QHash<QQuickItem*,int> unrequestedItems;
276 int requestedIndex;
277 QQuickItemViewChangeSet currentChanges;
278 QQuickItemViewChangeSet bufferedChanges;
279 QPauseAnimationJob bufferPause;
280
281 QQmlComponent *highlightComponent;
282 FxViewItem *highlight;
283 int highlightRange; // enum value
284 qreal highlightRangeStart;
285 qreal highlightRangeEnd;
286 int highlightMoveDuration;
287
288 QQmlComponent *headerComponent;
289 FxViewItem *header;
290 QQmlComponent *footerComponent;
291 FxViewItem *footer;
292
293 // Reusing delegate items cannot be on by default for backwards compatibility.
294 // Reusing an item will e.g mean that Component.onCompleted will only be called for an
295 // item when it's created and not when it's reused, which will break legacy applications.
296 QQmlInstanceModel::ReusableFlag reusableFlag = QQmlInstanceModel::NotReusable;
297
298 struct MovedItem {
299 FxViewItem *item;
300 QQmlChangeSet::MoveKey moveKey;
301 MovedItem(FxViewItem *i, QQmlChangeSet::MoveKey k)
302 : item(i), moveKey(k) {}
303 };
304 QQuickItemViewTransitioner *transitioner;
305 QVector<FxViewItem *> releasePendingTransition;
306
307 mutable qreal minExtent;
308 mutable qreal maxExtent;
309
310 bool ownModel : 1;
311 bool wrap : 1;
312 bool keyNavigationEnabled : 1;
313 bool explicitKeyNavigationEnabled : 1;
314 bool inLayout : 1;
315 bool inViewportMoved : 1;
316 bool forceLayout : 1;
317 bool currentIndexCleared : 1;
318 bool haveHighlightRange : 1;
319 bool autoHighlight : 1;
320 bool highlightRangeStartValid : 1;
321 bool highlightRangeEndValid : 1;
322 bool fillCacheBuffer : 1;
323 bool inRequest : 1;
324 bool runDelayedRemoveTransition : 1;
325 bool delegateValidated : 1;
326 bool isClearing : 1;
327
328protected:
329 virtual Qt::Orientation layoutOrientation() const = 0;
330 virtual bool isContentFlowReversed() const = 0;
331
332 virtual qreal positionAt(int index) const = 0;
333 virtual qreal endPositionAt(int index) const = 0;
334 virtual qreal originPosition() const = 0;
335 virtual qreal lastPosition() const = 0;
336
337 virtual qreal headerSize() const = 0;
338 virtual qreal footerSize() const = 0;
339 virtual bool showHeaderForIndex(int index) const = 0;
340 virtual bool showFooterForIndex(int index) const = 0;
341 virtual void updateHeader() = 0;
342 virtual void updateFooter() = 0;
343 virtual bool hasStickyHeader() const { return false; }
344 virtual bool hasStickyFooter() const { return false; }
345
346 virtual void createHighlight(bool onDestruction = false) = 0;
347 virtual void updateHighlight() = 0;
348 virtual void resetHighlightPosition() = 0;
349 virtual bool movingFromHighlight() { return false; }
350
351 virtual void setPosition(qreal pos) = 0;
352 virtual void fixupPosition() = 0;
353
354 virtual bool addVisibleItems(qreal fillFrom, qreal fillTo, qreal bufferFrom, qreal bufferTo, bool doBuffer) = 0;
355 virtual bool removeNonVisibleItems(qreal bufferFrom, qreal bufferTo) = 0;
356 virtual void visibleItemsChanged() {}
357
358 virtual FxViewItem *newViewItem(int index, QQuickItem *item) = 0;
359 virtual void repositionItemAt(FxViewItem *item, int index, qreal sizeBuffer) = 0;
360 virtual void repositionPackageItemAt(QQuickItem *item, int index) = 0;
361 virtual void resetFirstItemPosition(qreal pos = 0.0) = 0;
362 virtual void adjustFirstItem(qreal forwards, qreal backwards, int changeBeforeVisible) = 0;
363
364 virtual void layoutVisibleItems(int fromModelIndex = 0) = 0;
365 virtual void changedVisibleIndex(int newIndex) = 0;
366
367 virtual bool applyInsertionChange(const QQmlChangeSet::Change &insert, ChangeResult *changeResult,
368 QList<FxViewItem *> *newItems, QList<MovedItem> *movingIntoView) = 0;
369
370 virtual bool needsRefillForAddedOrRemovedIndex(int) const { return false; }
371 virtual void translateAndTransitionItemsAfter(int afterIndex, const ChangeResult &insertionResult, const ChangeResult &removalResult) = 0;
372
373 virtual void initializeViewItem(FxViewItem *) {}
374 virtual void initializeCurrentItem() {}
375 virtual void updateSectionCriteria() {}
376 virtual void updateSections() {}
377
378 void itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, const QRectF &) override;
379};
380
381
382QT_END_NAMESPACE
383
384#endif // QQUICKITEMVIEW_P_P_H
385

source code of qtdeclarative/src/quick/items/qquickitemview_p_p.h