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

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