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

Provided by KDAB

Privacy Policy
Start learning QML with our Intro Training
Find out more

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