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