732 qreal itemEnd = visiblePos;
733 if (visibleItems.size()) {
734 visiblePos = (*visibleItems.constBegin())->position();
735 itemEnd = (*(visibleItems.constEnd() - 1))->endPosition() + spacing;
738 int modelIndex = findLastVisibleIndex();
739 bool haveValidItems = modelIndex >= 0;
740 modelIndex = modelIndex < 0 ? visibleIndex : modelIndex + 1;
742 if (haveValidItems && (bufferFrom > itemEnd+averageSize+spacing
743 || bufferTo < visiblePos - averageSize - spacing)) {
746 int count = (fillFrom - itemEnd) / (averageSize + spacing);
747 int newModelIdx = qBound(0, modelIndex + count, model->count());
748 count = newModelIdx - modelIndex;
750 releaseVisibleItems(reusableFlag);
751 modelIndex = newModelIdx;
752 visibleIndex = modelIndex;
753 visiblePos = itemEnd + count * (averageSize + spacing);
754 itemEnd = visiblePos;
758 QQmlIncubator::IncubationMode incubationMode = doBuffer ? QQmlIncubator::Asynchronous : QQmlIncubator::AsynchronousIfNested;
760 bool changed =
false;
763 while (modelIndex < model->count() && pos <= fillTo) {
764 if (!(item =
static_cast<
FxListItemSG*>(createItem(modelIndex, incubationMode))))
766 qCDebug(lcItemViewDelegateLifecycle) <<
"refill: append item" << modelIndex <<
"pos" << pos <<
"buffer" << doBuffer <<
"item" << (QObject *)(item->item);
767#if QT_CONFIG(quick_viewtransitions)
768 if (!transitioner || !transitioner->canTransition(QQuickItemViewTransitioner::PopulateTransition,
true))
770 item->setPosition(pos,
true);
772 QQuickItemPrivate::get(item->item)->setCulled(doBuffer);
773 pos += item->size() + spacing;
774 visibleItems.append(item);
779 if (doBuffer && requestedIndex != -1)
782 while (visibleIndex > 0 && visibleIndex <= model->count() && visiblePos > fillFrom) {
783 if (!(item =
static_cast<
FxListItemSG*>(createItem(visibleIndex-1, incubationMode))))
785 qCDebug(lcItemViewDelegateLifecycle) <<
"refill: prepend item" << visibleIndex-1 <<
"current top pos" << visiblePos <<
"buffer" << doBuffer <<
"item" << (QObject *)(item->item);
787 visiblePos -= item->size() + spacing;
788#if QT_CONFIG(quick_viewtransitions)
789 if (!transitioner || !transitioner->canTransition(QQuickItemViewTransitioner::PopulateTransition,
true))
791 item->setPosition(visiblePos,
true);
793 QQuickItemPrivate::get(item->item)->setCulled(doBuffer);
794 visibleItems.prepend(item);
881 if (!visibleItems.isEmpty()) {
882 const qreal from = isContentFlowReversed() ? -position()-displayMarginBeginning-size() : position()-displayMarginBeginning;
883 const qreal to = isContentFlowReversed() ? -position()+displayMarginEnd : position()+size()+displayMarginEnd;
885 FxListItemSG *firstItem =
static_cast<FxListItemSG *>(visibleItems.constFirst());
886 bool fixedCurrent = currentItem && firstItem->item == currentItem->item;
888#if QT_CONFIG(quick_viewtransitions)
890
891 if (transitioner && transitioner->canTransition(QQuickItemViewTransitioner::PopulateTransition,
true))
892 resetFirstItemPosition(isContentFlowReversed() ? -firstItem->position()-firstItem->size() : firstItem->position());
895 firstVisibleItemPosition = firstItem->position();
896 qreal sum = firstItem->size();
897 qreal pos = firstItem->position() + firstItem->size() + spacing;
898 firstItem->setVisible(firstItem->endPosition() >= from && firstItem->position() <= to);
903 firstItem->setPosition(firstItem->position());
905 for (
int i=1; i < visibleItems.size(); ++i) {
906 FxListItemSG *item =
static_cast<FxListItemSG*>(visibleItems.at(i));
907 if (item->index >= fromModelIndex) {
908 item->setPosition(pos);
909 item->setVisible(item->endPosition() >= from && item->position() <= to);
911 pos += item->size() + spacing;
913 fixedCurrent = fixedCurrent || (currentItem && item->item == currentItem->item);
915 averageSize = qRound(sum / visibleItems.size());
918 if (currentIndex >= 0 && currentItem && !fixedCurrent)
919 static_cast<FxListItemSG*>(currentItem)->setPosition(positionAt(currentIndex));
974 bool changed =
false;
976 if (trackedItem == highlight.get())
977 trackedItem =
nullptr;
980 highlightPosAnimator.reset();
981 highlightWidthAnimator.reset();
982 highlightHeightAnimator.reset();
983 highlightPosAnimator =
nullptr;
984 highlightWidthAnimator =
nullptr;
985 highlightHeightAnimator =
nullptr;
995 QQuickItem *item = createHighlightItem();
997 std::unique_ptr<FxListItemSG> newHighlight
998 = std::make_unique<FxListItemSG>(item, q,
true);
999 newHighlight->trackGeometry(
true);
1001 if (autoHighlight) {
1002 newHighlight->setSize(
static_cast<FxListItemSG*>(currentItem)->itemSize());
1003 newHighlight->setPosition(
static_cast<FxListItemSG*>(currentItem)->itemPosition());
1005 const QLatin1String posProp(orient == QQuickListView::Vertical ?
"y" :
"x");
1006 highlightPosAnimator = std::make_unique<QSmoothedAnimation>();
1007 highlightPosAnimator->target = QQmlProperty(item, posProp);
1008 highlightPosAnimator->velocity = highlightMoveVelocity;
1009 highlightPosAnimator->userDuration = highlightMoveDuration;
1011 highlightWidthAnimator = std::make_unique<QSmoothedAnimation>();
1012 highlightWidthAnimator->velocity = highlightResizeVelocity;
1013 highlightWidthAnimator->userDuration = highlightResizeDuration;
1014 highlightWidthAnimator->target = QQmlProperty(item, QStringLiteral(
"width"));
1016 highlightHeightAnimator = std::make_unique<QSmoothedAnimation>();
1017 highlightHeightAnimator->velocity = highlightResizeVelocity;
1018 highlightHeightAnimator->userDuration = highlightResizeDuration;
1019 highlightHeightAnimator->target = QQmlProperty(item, QStringLiteral(
"height"));
1021 highlight = std::move(newHighlight);
1026 emit q->highlightItemChanged();
1080 Q_Q(QQuickListView);
1081 QQuickItem *sectionItem =
nullptr;
1088 sectionItem->setVisible(
true);
1089 QQmlContext *context = QQmlEngine::contextForObject(sectionItem)->parentContext();
1090 setSectionHelper(context, sectionItem, section);
1092 QQmlComponent* delegate = sectionCriteria->delegate();
1093 const bool reuseExistingContext = delegate->isBound();
1094 auto delegatePriv = QQmlComponentPrivate::get(delegate);
1095 QQmlPropertyCache::ConstPtr rootPropertyCache;
1097 QQmlContext *creationContext = sectionCriteria->delegate()->creationContext();
1098 auto baseContext = creationContext ? creationContext : qmlContext(q);
1100 QQmlContext *context = reuseExistingContext ? baseContext :
new QQmlContext(baseContext);
1101 QObject *nobj = delegate->beginCreate(context);
1103 if (delegatePriv->hadTopLevelRequiredProperties()) {
1104 delegate->setInitialProperties(nobj, {{QLatin1String(
"section"), section}});
1105 }
else if (!reuseExistingContext) {
1106 context->setContextProperty(QLatin1String(
"section"), section);
1108 if (!reuseExistingContext)
1109 QQml_setParent_noEvent(context, nobj);
1110 sectionItem = qobject_cast<QQuickItem *>(nobj);
1114 if (qFuzzyIsNull(sectionItem->z()))
1115 sectionItem->setZ(2);
1116 QQml_setParent_noEvent(sectionItem, contentItem);
1117 sectionItem->setParentItem(contentItem);
1120 auto *attached =
static_cast<QQuickListViewAttached*>(qmlAttachedPropertiesObject<QQuickListView>(sectionItem));
1121 attached->setView(q);
1122 }
else if (!reuseExistingContext) {
1125 sectionCriteria->delegate()->completeCreate();
1129 QQuickItemPrivate::get(sectionItem)->addItemChangeListener(
this, QQuickItemPrivate::Geometry);
1196 if (!sectionCriteria || !sectionCriteria->delegate()
1197 || (!sectionCriteria->labelPositioning() && !currentSectionItem && !nextSectionItem))
1201 qreal viewPos = isFlowReversed ? -position()-size() : position();
1202 qreal startPos = hasStickyHeader() ? header->endPosition() : viewPos;
1203 qreal endPos = hasStickyFooter() ? footer->position() : viewPos + size();
1205 QQuickItem *sectionItem =
nullptr;
1206 QQuickItem *lastSectionItem =
nullptr;
1208 while (index < visibleItems.size()) {
1209 if (QQuickItem *section =
static_cast<FxListItemSG *>(visibleItems.at(index))->section()) {
1212 qreal sectionPos = orient == QQuickListView::Vertical ? section->y() : section->x();
1213 qreal sectionSize = orient == QQuickListView::Vertical ? section->height() : section->width();
1215 if (sectionCriteria->labelPositioning() & QQuickViewSection::CurrentLabelAtStart)
1216 visTop = isFlowReversed ? -sectionPos-sectionSize >= startPos : sectionPos >= startPos;
1218 if (sectionCriteria->labelPositioning() & QQuickViewSection::NextLabelAtEnd)
1219 visBot = isFlowReversed ? -sectionPos <= endPos : sectionPos + sectionSize < endPos;
1220 section->setVisible(visBot && visTop);
1221 if (visTop && !sectionItem)
1222 sectionItem = section;
1223 if (isFlowReversed) {
1224 if (-sectionPos <= endPos)
1225 lastSectionItem = section;
1227 if (sectionPos + sectionSize < endPos)
1228 lastSectionItem = section;
1235 if (sectionCriteria->labelPositioning() & QQuickViewSection::CurrentLabelAtStart && isValid() && visibleItems.size()) {
1237 currentSectionItem = getSectionItem(currentSection);
1238 }
else if (QString::compare(currentStickySection, currentSection, Qt::CaseInsensitive)) {
1239 QQmlContext *context = QQmlEngine::contextForObject(currentSectionItem)->parentContext();
1242 currentStickySection = currentSection;
1246 qreal sectionSize = orient == QQuickListView::Vertical ? currentSectionItem->height() : currentSectionItem->width();
1247 bool atBeginning = orient == QQuickListView::Vertical ? (isBottomToTop() ? vData.atEnd : vData.atBeginning) : (isRightToLeft() ? hData.atEnd : hData.atBeginning);
1249 currentSectionItem->setVisible(!atBeginning && (!header || hasStickyHeader() || header->endPosition() < viewPos));
1250 qreal pos = isFlowReversed ? position() + size() - sectionSize : startPos;
1252 pos = isFlowReversed ? qMin(-header->endPosition() - sectionSize, pos) : qMax(header->endPosition(), pos);
1254 qreal sectionPos = orient == QQuickListView::Vertical ? sectionItem->y() : sectionItem->x();
1255 pos = isFlowReversed ? qMax(pos, sectionPos + sectionSize) : qMin(pos, sectionPos - sectionSize);
1258 pos = isFlowReversed ? qMax(-footer->position(), pos) : qMin(footer->position() - sectionSize, pos);
1259 if (orient == QQuickListView::Vertical)
1269 if (sectionCriteria->labelPositioning() & QQuickViewSection::NextLabelAtEnd && isValid() && visibleItems.size()) {
1271 nextSectionItem = getSectionItem(nextSection);
1272 }
else if (QString::compare(nextStickySection, nextSection, Qt::CaseInsensitive)) {
1273 QQmlContext *context = QQmlEngine::contextForObject(nextSectionItem)->parentContext();
1276 nextStickySection = nextSection;
1280 qreal sectionSize = orient == QQuickListView::Vertical ? nextSectionItem->height() : nextSectionItem->width();
1282 qreal pos = isFlowReversed ? position() : endPos - sectionSize;
1284 pos = isFlowReversed ? qMax(-footer->position(), pos) : qMin(footer->position() - sectionSize, pos);
1285 if (lastSectionItem) {
1286 qreal sectionPos = orient == QQuickListView::Vertical ? lastSectionItem->y() : lastSectionItem->x();
1287 pos = isFlowReversed ? qMin(pos, sectionPos - sectionSize) : qMax(pos, sectionPos + sectionSize);
1290 pos = isFlowReversed ? qMin(-header->endPosition() - sectionSize, pos) : qMax(header->endPosition(), pos);
1291 if (orient == QQuickListView::Vertical)
1344 Q_Q(QQuickListView);
1345 if (!sectionCriteria || visibleItems.isEmpty()) {
1346 if (!currentSection.isEmpty()) {
1347 currentSection.clear();
1348 emit q->currentSectionChanged();
1352 bool inlineSections = sectionCriteria->labelPositioning() & QQuickViewSection::InlineLabels;
1353 qreal viewPos = isContentFlowReversed() ? -position()-size() : position();
1354 qreal startPos = hasStickyHeader() ? header->endPosition() : viewPos;
1356 int modelIndex = visibleIndex;
1357 while (index < visibleItems.size()) {
1358 FxViewItem *item = visibleItems.at(index);
1359 if (item->endPosition() > startPos)
1361 if (item->index != -1)
1362 modelIndex = item->index;
1366 QString newSection = currentSection;
1367 if (index < visibleItems.size())
1368 newSection = visibleItems.at(index)->attached->section();
1370 newSection = (*visibleItems.constBegin())->attached->section();
1371 if (newSection != currentSection) {
1372 currentSection = newSection;
1374 emit q->currentSectionChanged();
1377 if (sectionCriteria->labelPositioning() & QQuickViewSection::NextLabelAtEnd) {
1382 QString lastSection = currentSection;
1383 qreal endPos = hasStickyFooter() ? footer->position() : viewPos + size();
1384 if (nextSectionItem && !inlineSections)
1385 endPos -= orient == QQuickListView::Vertical ? nextSectionItem->height() : nextSectionItem->width();
1386 while (index < visibleItems.size()) {
1387 FxListItemSG *listItem =
static_cast<FxListItemSG *>(visibleItems.at(index));
1388 if (listItem->itemPosition() >= endPos)
1390 if (listItem->index != -1)
1391 modelIndex = listItem->index;
1392 lastSection = listItem->attached->section();
1396 if (lastVisibleSection != lastSection) {
1397 nextSection = QString();
1398 lastVisibleSection = lastSection;
1399 for (
int i = modelIndex; i < itemCount; ++i) {
1400 QString section = sectionAt(i);
1401 if (section != lastSection) {
1402 nextSection = section;
1534 Q_Q(QQuickListView);
1535 bool created =
false;
1537 QQuickItem *item = createComponentItem(headerComponent, 1.0);
1540 header =
new FxListItemSG(item, q,
true);
1541 header->trackGeometry(
true);
1545 FxListItemSG *listItem =
static_cast<FxListItemSG*>(header);
1546 if (headerPositioning == QQuickListView::OverlayHeader) {
1548 }
else if (visibleItems.size()) {
1549 const bool fixingUp = (orient == QQuickListView::Vertical ? vData : hData).fixingUp;
1550 if (headerPositioning == QQuickListView::PullBackHeader) {
1551 qreal headerPosition = listItem->position();
1554 if (fixingUp && !headerNeedsSeparateFixup)
1555 headerPosition = viewPos - headerSize();
1558 qreal clampedPos = qMax(originPosition() - headerSize(), qMin(headerPosition, lastPosition() - size()));
1559 listItem->setPosition(qBound(viewPos - headerSize(), clampedPos, viewPos),
false,
false);
1561 qreal startPos = originPosition();
1562 if (visibleIndex == 0) {
1563 listItem->setPosition(startPos - headerSize(),
false,
false);
1565 if (position() <= startPos || listItem->position() > startPos - headerSize())
1566 listItem->setPosition(startPos - headerSize(),
false,
false);
1570 listItem->setPosition(-headerSize(),
false,
false);
1574 emit q->headerItemChanged();
1596 const QRectF &oldGeometry)
1598 Q_Q(QQuickListView);
1600 QQuickItemViewPrivate::itemGeometryChanged(item, change, oldGeometry);
1601 if (!q->isComponentComplete())
1604 if (currentItem && currentItem->item == item) {
1606 const qreal pos = position();
1607 const qreal sz = size();
1608 const qreal from = contentFlowReversed ? -pos - displayMarginBeginning - sz : pos - displayMarginBeginning;
1609 const qreal to = contentFlowReversed ? -pos + displayMarginEnd : pos + sz + displayMarginEnd;
1610 QQuickItemPrivate::get(currentItem->item)->setCulled(currentItem->endPosition() < from || currentItem->position() > to);
1613 if (item != contentItem && (!highlight || item != highlight->item)) {
1614 if ((orient == QQuickListView::Vertical && change.heightChange())
1615 || (orient == QQuickListView::Horizontal && change.widthChange())) {
1619 if (visibleItems.size() && item == visibleItems.constFirst()->item) {
1620 FxListItemSG *listItem =
static_cast<FxListItemSG*>(visibleItems.constFirst());
1621#if QT_CONFIG(quick_viewtransitions)
1622 if (listItem->transitionScheduledOrRunning())
1625 if (orient == QQuickListView::Vertical) {
1626 const qreal oldItemEndPosition = verticalLayoutDirection == QQuickItemView::BottomToTop ? -oldGeometry.y() : oldGeometry.y() + oldGeometry.height();
1627 const qreal heightDiff = item->height() - oldGeometry.height();
1628 if (verticalLayoutDirection == QQuickListView::TopToBottom && oldItemEndPosition < q->contentY())
1629 listItem->setPosition(listItem->position() - heightDiff,
true);
1630 else if (verticalLayoutDirection == QQuickListView::BottomToTop && oldItemEndPosition > q->contentY())
1631 listItem->setPosition(listItem->position() + heightDiff,
true);
1633 const qreal oldItemEndPosition = q->effectiveLayoutDirection() == Qt::RightToLeft ? -oldGeometry.x() : oldGeometry.x() + oldGeometry.width();
1634 const qreal widthDiff = item->width() - oldGeometry.width();
1635 if (q->effectiveLayoutDirection() == Qt::LeftToRight && oldItemEndPosition < q->contentX())
1636 listItem->setPosition(listItem->position() - widthDiff,
true);
1637 else if (q->effectiveLayoutDirection() == Qt::RightToLeft && oldItemEndPosition > q->contentX())
1638 listItem->setPosition(listItem->position() + widthDiff,
true);
1641 forceLayoutPolish();
1657 if (orient == QQuickListView::Horizontal && &data == &vData) {
1658 if (flickableDirection != QQuickFlickable::HorizontalFlick)
1659 QQuickItemViewPrivate::fixup(data, minExtent, maxExtent);
1661 }
else if (orient == QQuickListView::Vertical && &data == &hData) {
1662 if (flickableDirection != QQuickFlickable::VerticalFlick)
1663 QQuickItemViewPrivate::fixup(data, minExtent, maxExtent);
1668 if (visibleItems.size() == 0)
1672 fixupMode = moveReason == Mouse ? fixupMode : Immediate;
1673 bool strictHighlightRange = haveHighlightRange && highlightRange == QQuickListView::StrictlyEnforceRange;
1675 qreal viewPos = isContentFlowReversed() ? -position()-size() : position();
1677 if (snapMode != QQuickListView::NoSnap && moveReason != QQuickListViewPrivate::SetIndex) {
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694 qreal tempPosition = isContentFlowReversed() ? -position()-size() : position();
1695 if (snapMode == QQuickListView::SnapOneItem && moveReason == Mouse) {
1697 qreal dist = data.move.value() - data.pressPos;
1700 bias = averageSize/2;
1702 bias = -averageSize/2;
1703 if (isContentFlowReversed())
1705 tempPosition -= bias;
1708 qreal snapOffset = 0;
1709 qreal overlayHeaderOffset = 0;
1710 bool isHeaderWithinBounds =
false;
1712 qreal visiblePartOfHeader = header->position() + header->size() - tempPosition;
1713 isHeaderWithinBounds = visiblePartOfHeader > 0;
1714 switch (headerPositioning) {
1715 case QQuickListView::OverlayHeader:
1716 snapOffset = header->size();
1717 overlayHeaderOffset = header->size();
1719 case QQuickListView::InlineHeader:
1720 if (isHeaderWithinBounds && tempPosition < originPosition())
1724 snapOffset = header->size() / 2;
1726 case QQuickListView::PullBackHeader:
1727 desiredHeaderVisible = visiblePartOfHeader > header->size()/2;
1728 if (qFuzzyCompare(header->position(), tempPosition)) {
1730 snapOffset = header->size();
1734 snapOffset = header->size();
1735 overlayHeaderOffset = header->size();
1744 if (strictHighlightRange)
1747 FxViewItem *topItem =
nullptr;
1748 FxViewItem *bottomItem =
nullptr;
1750 topItem = visibleItem(snapResizeTargetIndex);
1751 bottomItem = topItem;
1754 topItem = snapItemAt(tempPosition + snapOffset + highlightRangeStart);
1756 bottomItem = snapItemAt(tempPosition + snapOffset + highlightRangeEnd);
1757 if (strictHighlightRange && currentItem) {
1759 if (!topItem || (topItem->index != currentIndex && fixupMode == Immediate))
1760 topItem = currentItem;
1761 if (!bottomItem || (bottomItem->index != currentIndex && fixupMode == Immediate))
1762 bottomItem = currentItem;
1766 bool isInBounds = -position() > maxExtent && -position() <= minExtent;
1768 if (header && !topItem && isInBounds) {
1770 switch (headerPositioning) {
1771 case QQuickListView::OverlayHeader:
1772 pos = startPosition() - overlayHeaderOffset;
1774 case QQuickListView::InlineHeader:
1775 pos = isContentFlowReversed() ? header->size() - size() : header->position();
1777 case QQuickListView::PullBackHeader:
1778 pos = isContentFlowReversed() ? -size() : startPosition();
1781 }
else if (topItem && (isInBounds || strictHighlightRange)) {
1782 if (topItem->index == 0 && header && !hasStickyHeader() && tempPosition+highlightRangeStart < header->position()+header->size()/2 && !strictHighlightRange) {
1783 pos = isContentFlowReversed() ? -header->position() + highlightRangeStart - size() : (header->position() - highlightRangeStart + header->size());
1785 if (header && headerPositioning == QQuickListView::PullBackHeader) {
1788 if (qFuzzyCompare(tempPosition, header->position())) {
1790 if (isContentFlowReversed())
1791 pos = -
static_cast<FxListItemSG*>(topItem)->itemPosition() + highlightRangeStart - size() + snapOffset;
1793 pos =
static_cast<FxListItemSG*>(topItem)->itemPosition() - highlightRangeStart - snapOffset;
1800 if (isContentFlowReversed())
1801 pos = -
static_cast<FxListItemSG*>(topItem)->itemPosition() + highlightRangeStart - size() + headerSize();
1803 pos =
static_cast<FxListItemSG*>(topItem)->itemPosition() - highlightRangeStart - headerSize();
1807 if (isContentFlowReversed())
1808 pos = -
static_cast<FxListItemSG*>(topItem)->itemPosition() + highlightRangeStart - size();
1810 pos =
static_cast<FxListItemSG*>(topItem)->itemPosition() - highlightRangeStart;
1821 pos = qBound(-minExtent, pos, -maxExtent);
1822 desiredViewportPosition = isContentFlowReversed() ? -pos - size() : pos;
1824 FxListItemSG *headerItem =
static_cast<FxListItemSG*>(header);
1825 fixupHeaderPosition = headerItem->position();
1828 QObjectPrivate::connect(&timeline, &QQuickTimeLine::updated,
this, &QQuickListViewPrivate::fixupHeader);
1829 QObjectPrivate::connect(&timeline, &QQuickTimeLine::completed,
this, &QQuickListViewPrivate::fixupHeaderCompleted);
1832 pos = -
static_cast<FxListItemSG*>(topItem)->itemPosition() + highlightRangeStart - size() + overlayHeaderOffset;
1834 pos =
static_cast<FxListItemSG*>(topItem)->itemPosition() - highlightRangeStart - overlayHeaderOffset;
1837 }
else if (bottomItem && isInBounds) {
1838 if (isContentFlowReversed())
1839 pos = -
static_cast<FxListItemSG*>(bottomItem)->itemPosition() + highlightRangeEnd - size() + overlayHeaderOffset;
1841 pos =
static_cast<FxListItemSG*>(bottomItem)->itemPosition() - highlightRangeEnd - overlayHeaderOffset;
1843 QQuickItemViewPrivate::fixup(data, minExtent, maxExtent);
1849 && (sectionCriteria->labelPositioning() & QQuickViewSection::CurrentLabelAtStart)
1850 && currentSectionItem) {
1851 auto sectionSize = (orient == QQuickListView::Vertical) ? currentSectionItem->height()
1852 : currentSectionItem->width();
1853 if (isContentFlowReversed())
1859 pos = qBound(-minExtent, pos, -maxExtent);
1861 qreal dist = qAbs(data.move + pos);
1866 timeline.reset(data.move);
1867 if (fixupMode != Immediate) {
1868 timeline.move(data.move, -pos, QEasingCurve(QEasingCurve::InOutQuad), fixupDuration/2);
1869 data.fixingUp =
true;
1871 timeline.set(data.move, -pos);
1873 vTime = timeline.time();
1875 }
else if (currentItem && strictHighlightRange && moveReason != QQuickListViewPrivate::SetIndex) {
1877 qreal pos =
static_cast<FxListItemSG*>(currentItem)->itemPosition();
1878 if (viewPos < pos +
static_cast<FxListItemSG*>(currentItem)->itemSize() - highlightRangeEnd)
1879 viewPos = pos +
static_cast<FxListItemSG*>(currentItem)->itemSize() - highlightRangeEnd;
1880 if (viewPos > pos - highlightRangeStart)
1881 viewPos = pos - highlightRangeStart;
1882 if (isContentFlowReversed())
1883 viewPos = -viewPos-size();
1885 timeline.reset(data.move);
1886 if (viewPos != position()) {
1887 if (fixupMode != Immediate) {
1888 if (fixupMode == ExtentChanged && data.fixingUp)
1889 timeline.move(data.move, -viewPos, QEasingCurve(QEasingCurve::OutQuad), fixupDuration/2);
1891 timeline.move(data.move, -viewPos, QEasingCurve(QEasingCurve::InOutQuad), fixupDuration/2);
1892 data.fixingUp =
true;
1894 timeline.set(data.move, -viewPos);
1897 vTime = timeline.time();
1899 QQuickItemViewPrivate::fixup(data, minExtent, maxExtent);
1901 data.inOvershoot =
false;
1906 QQuickTimeLineCallback::Callback fixupCallback, QEvent::Type eventType, qreal velocity)
1908 data.fixingUp =
false;
1910 if ((!haveHighlightRange || highlightRange != QQuickListView::StrictlyEnforceRange) && snapMode == QQuickListView::NoSnap) {
1912 return QQuickItemViewPrivate::flick(data, minExtent, maxExtent, vSize, fixupCallback, eventType, velocity);
1914 qreal maxDistance = 0;
1915 const qreal dataValue =
1920 if (data.move.value() < minExtent) {
1921 if (snapMode == QQuickListView::SnapOneItem && !hData.flicking && !vData.flicking) {
1923 qreal bias = averageSize / 2 + 1 - (pressed ? data.pressPos : 0);
1924 if (isContentFlowReversed())
1926 data.flickTarget = -snapPosAt(-(dataValue - highlightRangeStart) - bias) + highlightRangeStart;
1927 maxDistance = qAbs(data.flickTarget - data.move.value());
1928 velocity = maxVelocity;
1930 maxDistance = qAbs(minExtent - data.move.value());
1933 if (snapMode == QQuickListView::NoSnap && highlightRange != QQuickListView::StrictlyEnforceRange)
1934 data.flickTarget = minExtent;
1936 if (data.move.value() > maxExtent) {
1937 if (snapMode == QQuickListView::SnapOneItem && !hData.flicking && !vData.flicking) {
1939 qreal bias = averageSize / 2 + 1 - (pressed ? data.pressPos : 0);
1940 if (isContentFlowReversed())
1943 -snapPosAt(-(dataValue - highlightRangeStart) + bias) + highlightRangeStart;
1944 maxDistance = qAbs(data.flickTarget - data.move.value());
1945 velocity = -maxVelocity;
1947 maxDistance = qAbs(maxExtent - data.move.value());
1950 if (snapMode == QQuickListView::NoSnap && highlightRange != QQuickListView::StrictlyEnforceRange)
1951 data.flickTarget = maxExtent;
1953 bool overShoot = boundsBehavior & QQuickFlickable::OvershootBounds;
1954 if (maxDistance > 0 || overShoot) {
1960 if (maxVelocity != -1 && maxVelocity < qAbs(v)) {
1966 if (!hData.flicking && !vData.flicking) {
1968 qreal accel = eventType == QEvent::Wheel ? wheelDeceleration : deceleration;
1970 overshootDist = 0.0;
1972 qreal dist = v2 / (accel * 2.0) + averageSize/4;
1973 if (maxDistance > 0)
1974 dist = qMin(dist, maxDistance);
1977 if ((maxDistance > 0.0 && v2 / (2.0f * maxDistance) < accel) || snapMode == QQuickListView::SnapOneItem) {
1978 if (snapMode != QQuickListView::SnapOneItem) {
1979 qreal distTemp = isContentFlowReversed() ? -dist : dist;
1980 data.flickTarget = -snapPosAt(-(dataValue - highlightRangeStart) + distTemp) + highlightRangeStart;
1984 if (data.flickTarget > minExtent) {
1985 overshootDist = overShootDistance(vSize);
1986 data.flickTarget += overshootDist;
1987 }
else if (data.flickTarget < maxExtent) {
1988 overshootDist = overShootDistance(vSize);
1989 data.flickTarget -= overshootDist;
1992 qreal adjDist = -data.flickTarget + data.move.value();
1993 if (qAbs(adjDist) > qAbs(dist)) {
1995 qreal adjv2 = accel * 2.0f * qAbs(adjDist);
2004 accel = v2 / (2.0f * qAbs(dist));
2005 }
else if (overShoot) {
2006 data.flickTarget = data.move.value() - dist;
2007 if (data.flickTarget > minExtent) {
2008 overshootDist = overShootDistance(vSize);
2009 data.flickTarget += overshootDist;
2010 }
else if (data.flickTarget < maxExtent) {
2011 overshootDist = overShootDistance(vSize);
2012 data.flickTarget -= overshootDist;
2015 timeline.reset(data.move);
2016 timeline.accel(data.move, v, accel, maxDistance + overshootDist);
2017 timeline.callback(QQuickTimeLineCallback(&data.move, fixupCallback,
this));
2022 qreal newtarget = data.flickTarget;
2023 if (snapMode != QQuickListView::NoSnap || highlightRange == QQuickListView::StrictlyEnforceRange) {
2024 qreal tempFlickTarget = isContentFlowReversed() ? -data.flickTarget+size() : data.flickTarget;
2025 newtarget = -snapPosAt(-(tempFlickTarget - highlightRangeStart)) + highlightRangeStart;
2026 newtarget = isContentFlowReversed() ? -newtarget+size() : newtarget;
2028 if (velocity < 0 && newtarget <= maxExtent)
2029 newtarget = maxExtent - overshootDist;
2030 else if (velocity > 0 && newtarget >= minExtent)
2031 newtarget = minExtent + overshootDist;
2032 if (newtarget == data.flickTarget) {
2033 if (qAbs(velocity) < _q_MinimumFlickVelocity)
2037 data.flickTarget = newtarget;
2038 qreal dist = -newtarget + data.move.value();
2039 if ((v < 0 && dist < 0) || (v > 0 && dist > 0)) {
2041 timeline.reset(data.move);
2042 fixup(data, minExtent, maxExtent);
2045 timeline.reset(data.move);
2046 timeline.accelDistance(data.move, v, -dist);
2047 timeline.callback(QQuickTimeLineCallback(&data.move, fixupCallback,
this));
2052 timeline.reset(data.move);
2053 fixup(data, minExtent, maxExtent);
3523void QQuickListView::viewportMoved(Qt::Orientations orient)
3525 Q_D(QQuickListView);
3526 QQuickItemView::viewportMoved(orient);
3528 if (!d->itemCount) {
3529 if (d->hasStickyHeader())
3531 if (d->hasStickyFooter())
3537 if (d->inViewportMoved)
3539 d->inViewportMoved =
true;
3542 if (d->isBottomToTop())
3543 d->bufferMode = d->vData.smoothVelocity < 0 ? QQuickListViewPrivate::BufferAfter : QQuickListViewPrivate::BufferBefore;
3545 d->bufferMode = d->vData.smoothVelocity < 0 ? QQuickListViewPrivate::BufferBefore : QQuickListViewPrivate::BufferAfter;
3547 if (d->isRightToLeft())
3548 d->bufferMode = d->hData.smoothVelocity < 0 ? QQuickListViewPrivate::BufferAfter : QQuickListViewPrivate::BufferBefore;
3550 d->bufferMode = d->hData.smoothVelocity < 0 ? QQuickListViewPrivate::BufferBefore : QQuickListViewPrivate::BufferAfter;
3553 d->refillOrLayout();
3556 qreal from = d->isContentFlowReversed() ? -d->position()-d->displayMarginBeginning-d->size() : d->position()-d->displayMarginBeginning;
3557 qreal to = d->isContentFlowReversed() ? -d->position()+d->displayMarginEnd : d->position()+d->size()+d->displayMarginEnd;
3558 for (FxViewItem *item : std::as_const(d->visibleItems)) {
3560 QQuickItemPrivate::get(item->item)->setCulled(item->endPosition() < from || item->position() > to);
3563 QQuickItemPrivate::get(d->currentItem->item)->setCulled(d->currentItem->endPosition() < from || d->currentItem->position() > to);
3565 if (d->hData.flicking || d->vData.flicking || d->hData.moving || d->vData.moving)
3566 d->moveReason = QQuickListViewPrivate::Mouse;
3567 if (d->moveReason != QQuickListViewPrivate::SetIndex) {
3568 if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange && d->highlight) {
3570 qreal pos = d->highlight->position();
3571 qreal viewPos = d->isContentFlowReversed() ? -d->position()-d->size() : d->position();
3572 if (pos > viewPos + d->highlightRangeEnd - d->highlight->size())
3573 pos = viewPos + d->highlightRangeEnd - d->highlight->size();
3574 if (pos < viewPos + d->highlightRangeStart)
3575 pos = viewPos + d->highlightRangeStart;
3576 if (pos != d->highlight->position()) {
3577 d->highlightPosAnimator->stop();
3578 static_cast<FxListItemSG*>(d->highlight.get())->setPosition(pos);
3580 d->updateHighlight();
3584 if (FxViewItem *snapItem = d->snapItemAt(d->highlight->position())) {
3585 if (snapItem->index >= 0 && snapItem->index != d->currentIndex)
3586 d->updateCurrent(snapItem->index);
3591 if ((d->hData.flicking || d->vData.flicking) && d->correctFlick && !d->inFlickCorrection) {
3592 d->inFlickCorrection =
true;
3595 if (yflick() && !d->vData.inOvershoot) {
3596 if (d->vData.velocity > 0) {
3597 const qreal minY = minYExtent();
3598 if ((minY - d->vData.move.value() < height()/2 || d->vData.flickTarget - d->vData.move.value() < height()/2)
3599 && minY != d->vData.flickTarget)
3600 d->flickY(QEvent::TouchUpdate, -d->vData.smoothVelocity.value());
3601 }
else if (d->vData.velocity < 0) {
3602 const qreal maxY = maxYExtent();
3603 if ((d->vData.move.value() - maxY < height()/2 || d->vData.move.value() - d->vData.flickTarget < height()/2)
3604 && maxY != d->vData.flickTarget)
3605 d->flickY(QEvent::TouchUpdate, -d->vData.smoothVelocity.value());
3609 if (xflick() && !d->hData.inOvershoot) {
3610 if (d->hData.velocity > 0) {
3611 const qreal minX = minXExtent();
3612 if ((minX - d->hData.move.value() < width()/2 || d->hData.flickTarget - d->hData.move.value() < width()/2)
3613 && minX != d->hData.flickTarget)
3614 d->flickX(QEvent::TouchUpdate, -d->hData.smoothVelocity.value());
3615 }
else if (d->hData.velocity < 0) {
3616 const qreal maxX = maxXExtent();
3617 if ((d->hData.move.value() - maxX < width()/2 || d->hData.move.value() - d->hData.flickTarget < width()/2)
3618 && maxX != d->hData.flickTarget)
3619 d->flickX(QEvent::TouchUpdate, -d->hData.smoothVelocity.value());
3622 d->inFlickCorrection =
false;
3624 if (d->hasStickyHeader())
3626 if (d->hasStickyFooter())
3628 if (d->sectionCriteria) {
3629 d->updateCurrentSection();
3630 d->updateStickySections();
3632 d->inViewportMoved =
false;
3799 Q_Q(QQuickListView);
3800#if !QT_CONFIG(quick_viewtransitions)
3801 Q_UNUSED(movingIntoView)
3803 int modelIndex = change.index;
3804 int count = change.count;
3806 if (q->size().isNull() && visibleItems.isEmpty())
3809 qreal tempPos = isContentFlowReversed() ? -position()-size() : position();
3810 int index = visibleItems.size() ? mapFromModel(modelIndex) : 0;
3811 qreal lastVisiblePos = buffer + displayMarginEnd + tempPos + size();
3814 int i = visibleItems.size() - 1;
3815 while (i > 0 && visibleItems.at(i)->index == -1)
3817 if (i == 0 && visibleItems.constFirst()->index == -1) {
3819 index = visibleItems.size();
3820 }
else if (visibleItems.at(i)->index + 1 == modelIndex
3821 && visibleItems.at(i)->endPosition() <= lastVisiblePos) {
3823 index = visibleItems.size();
3825 if (modelIndex < visibleIndex) {
3827 visibleIndex += count;
3828 for (FxViewItem *item : std::as_const(visibleItems)) {
3829 if (item->index != -1 && item->index >= modelIndex)
3830 item->index += count;
3839 if (visibleItems.size()) {
3840 pos = index < visibleItems.size() ? visibleItems.at(index)->position()
3841 : visibleItems.constLast()->endPosition() + spacing;
3845 for (FxViewItem *item : std::as_const(visibleItems)) {
3846 if (item->index != -1 && item->index >= modelIndex) {
3847 item->index += count;
3848#if QT_CONFIG(quick_viewtransitions)
3849 if (change.isMove())
3850 item->transitionNextReposition(transitioner, QQuickItemViewTransitioner::MoveTransition,
false);
3852 item->transitionNextReposition(transitioner, QQuickItemViewTransitioner::AddTransition,
false);
3857 bool visibleAffected =
false;
3858 if (insertResult->visiblePos.isValid() && pos < insertResult->visiblePos) {
3860 int insertionIdx = index;
3861 qreal from = tempPos - displayMarginBeginning - buffer;
3863 if (insertionIdx < visibleIndex) {
3866 insertResult->sizeChangesBeforeVisiblePos += count * (averageSize + spacing);
3870 for (; it.hasNext() && pos >= from; it
.next()) {
3872 FxViewItem *item =
nullptr;
3873 if (change.isMove() && (item = currentChanges.removedItems.take(change.moveKey(it.index))))
3874 item->index = it.index;
3876 item = createItem(it.index, QQmlIncubator::Synchronous);
3882 visibleAffected =
true;
3883 visibleItems.insert(insertionIdx, item);
3884 if (insertionIdx == 0)
3885 insertResult->changedFirstItem =
true;
3886 if (!change.isMove()) {
3887 addedItems->append(item);
3888#if QT_CONFIG(quick_viewtransitions)
3890 item->transitionNextReposition(transitioner, QQuickItemViewTransitioner::AddTransition,
true);
3893 static_cast<FxListItemSG *>(item)->setPosition(pos,
true);
3895 insertResult->sizeChangesBeforeVisiblePos += item->size() + spacing;
3896 pos -= item->size() + spacing;
3901 int firstOkIdx = -1;
3902 for (
int i = 0; i <= insertionIdx && i < visibleItems.size() - 1; i++) {
3903 if (visibleItems.at(i)->index + 1 != visibleItems.at(i + 1)->index) {
3908 for (
int i = 0; i < firstOkIdx; i++) {
3909 FxViewItem *nvItem = visibleItems.takeFirst();
3910 addedItems->removeOne(nvItem);
3916 for (; it.hasNext() && pos <= lastVisiblePos; it
.next()) {
3917 visibleAffected =
true;
3918 FxViewItem *item =
nullptr;
3919 if (change.isMove() && (item = currentChanges.removedItems.take(change.moveKey(it.index))))
3920 item->index = it.index;
3921#if QT_CONFIG(quick_viewtransitions)
3922 bool newItem = !item;
3926 item = createItem(it.index, QQmlIncubator::Synchronous);
3930 releaseItem(item, reusableFlag);
3934 if (index < visibleItems.size())
3935 visibleItems.insert(index, item);
3937 visibleItems.append(item);
3939 insertResult->changedFirstItem =
true;
3940 if (change.isMove()) {
3943#if QT_CONFIG(quick_viewtransitions)
3944 if (newItem && transitioner && transitioner->canTransition(QQuickItemViewTransitioner::MoveTransition,
true))
3945 movingIntoView->append(MovedItem(item, change.moveKey(item->index)));
3948 addedItems->append(item);
3949#if QT_CONFIG(quick_viewtransitions)
3951 item->transitionNextReposition(transitioner, QQuickItemViewTransitioner::AddTransition,
true);
3954 static_cast<FxListItemSG *>(item)->setPosition(pos,
true);
3956 insertResult->sizeChangesAfterVisiblePos += item->size() + spacing;
3957 pos += item->size() + spacing;
3962 if (0 < index && index < visibleItems.size()) {
3963 FxViewItem *prevItem = visibleItems.at(index - 1);
3964 FxViewItem *item = visibleItems.at(index);
3965 if (prevItem->index != item->index - 1) {
3967#if QT_CONFIG(quick_viewtransitions)
3968 qreal prevPos = prevItem->position();
3970 while (i < visibleItems.size()) {
3971 FxListItemSG *nvItem =
static_cast<FxListItemSG *>(visibleItems.takeLast());
3972 insertResult->sizeChangesAfterVisiblePos -= nvItem->size() + spacing;
3973 addedItems->removeOne(nvItem);
3974#if QT_CONFIG(quick_viewtransitions)
3975 if (nvItem->transitionScheduledOrRunning())
3976 nvItem->setPosition(prevPos + (nvItem->index - prevItem->index) * averageSize);
3984 updateVisibleIndex();
3986 return visibleAffected;