diff options
-rw-r--r-- | src/quick/items/qquicklistview.cpp | 168 | ||||
-rw-r--r-- | tests/auto/quick/qquicklistview/data/headerSnapToItem.qml | 67 | ||||
-rw-r--r-- | tests/auto/quick/qquicklistview/tst_qquicklistview.cpp | 597 |
3 files changed, 817 insertions, 15 deletions
diff --git a/src/quick/items/qquicklistview.cpp b/src/quick/items/qquicklistview.cpp index c4c22526f3..7ff39b1d88 100644 --- a/src/quick/items/qquicklistview.cpp +++ b/src/quick/items/qquicklistview.cpp @@ -138,6 +138,8 @@ public: bool flick(QQuickItemViewPrivate::AxisData &data, qreal minExtent, qreal maxExtent, qreal vSize, QQuickTimeLineCallback::Callback fixupCallback, qreal velocity) override; + void fixupHeader(); + void fixupHeaderCompleted(); QQuickListView::Orientation orient; qreal visiblePos; qreal averageSize; @@ -166,6 +168,12 @@ public: QString nextSection; qreal overshootDist; + + qreal desiredViewportPosition; + qreal fixupHeaderPosition; + bool headerNeedsSeparateFixup : 1; + bool desiredHeaderVisible : 1; + bool correctFlick : 1; bool inFlickCorrection : 1; @@ -179,7 +187,9 @@ public: , highlightPosAnimator(nullptr), highlightWidthAnimator(nullptr), highlightHeightAnimator(nullptr) , highlightMoveVelocity(400), highlightResizeVelocity(400), highlightResizeDuration(-1) , sectionCriteria(nullptr), currentSectionItem(nullptr), nextSectionItem(nullptr) - , overshootDist(0.0), correctFlick(false), inFlickCorrection(false) + , overshootDist(0.0), desiredViewportPosition(0.0), fixupHeaderPosition(0.0) + , headerNeedsSeparateFixup(false), desiredHeaderVisible(false) + , correctFlick(false), inFlickCorrection(false) { highlightMoveDuration = -1; //override default value set in base class } @@ -1387,6 +1397,31 @@ void QQuickListViewPrivate::updateFooter() emit q->footerItemChanged(); } +void QQuickListViewPrivate::fixupHeaderCompleted() +{ + headerNeedsSeparateFixup = false; + QObjectPrivate::disconnect(&timeline, &QQuickTimeLine::updated, this, &QQuickListViewPrivate::fixupHeader); +} + +void QQuickListViewPrivate::fixupHeader() +{ + FxListItemSG *listItem = static_cast<FxListItemSG*>(header); + const bool fixingUp = (orient == QQuickListView::Vertical ? vData : hData).fixingUp; + if (fixingUp && headerPositioning == QQuickListView::PullBackHeader && visibleItems.count()) { + int fixupDura = timeline.duration(); + if (fixupDura < 0) + fixupDura = fixupDuration/2; + const int t = timeline.time(); + + const qreal progress = qreal(t)/fixupDura; + const qreal ultimateHeaderPosition = desiredHeaderVisible ? desiredViewportPosition : desiredViewportPosition - headerSize(); + const qreal headerPosition = fixupHeaderPosition * (1 - progress) + ultimateHeaderPosition * progress; + const qreal viewPos = isContentFlowReversed() ? -position() - size() : position(); + const qreal clampedPos = qBound(originPosition() - headerSize(), headerPosition, lastPosition() - size()); + listItem->setPosition(qBound(viewPos - headerSize(), clampedPos, viewPos)); + } +} + void QQuickListViewPrivate::updateHeader() { Q_Q(QQuickListView); @@ -1404,9 +1439,14 @@ void QQuickListViewPrivate::updateHeader() if (headerPositioning == QQuickListView::OverlayHeader) { listItem->setPosition(isContentFlowReversed() ? -position() - size() : position()); } else if (visibleItems.count()) { + const bool fixingUp = (orient == QQuickListView::Vertical ? vData : hData).fixingUp; if (headerPositioning == QQuickListView::PullBackHeader) { - qreal viewPos = isContentFlowReversed() ? -position() - size() : position(); - qreal clampedPos = qBound(originPosition() - headerSize(), listItem->position(), lastPosition() - headerSize() - size()); + qreal headerPosition = listItem->position(); + const qreal viewPos = isContentFlowReversed() ? -position() - size() : position(); + // Make sure the header is not shown if we absolutely do not have any plans to show it + if (fixingUp && !headerNeedsSeparateFixup) + headerPosition = viewPos - headerSize(); + qreal clampedPos = qBound(originPosition() - headerSize(), headerPosition, lastPosition() - size()); listItem->setPosition(qBound(viewPos - headerSize(), clampedPos, viewPos)); } else { qreal startPos = originPosition(); @@ -1524,13 +1564,46 @@ void QQuickListViewPrivate::fixup(AxisData &data, qreal minExtent, qreal maxExte bias = -bias; tempPosition -= bias; } - FxViewItem *topItem = snapItemAt(tempPosition+highlightRangeStart); + + qreal snapOffset = 0; + qreal overlayHeaderOffset = 0; + bool isHeaderWithinBounds = false; + if (header) { + qreal visiblePartOfHeader = header->position() + header->size() - tempPosition; + isHeaderWithinBounds = visiblePartOfHeader > 0; + switch (headerPositioning) { + case QQuickListView::OverlayHeader: + snapOffset = header->size(); + overlayHeaderOffset = header->size(); + break; + case QQuickListView::InlineHeader: + if (isHeaderWithinBounds && tempPosition < originPosition()) + // For the inline header, we want to snap to the first item + // if we're more than halfway down the inline header. + // So if we look for an item halfway down of the header + snapOffset = header->size() / 2; + break; + case QQuickListView::PullBackHeader: + desiredHeaderVisible = visiblePartOfHeader > header->size()/2; + if (qFuzzyCompare(header->position(), tempPosition)) { + // header was pulled down; make sure it remains visible and snap items to bottom of header + snapOffset = header->size(); + } else if (desiredHeaderVisible) { + // More than 50% of the header is shown. Show it fully. + // Scroll the view so the next item snaps to the header. + snapOffset = header->size(); + overlayHeaderOffset = header->size(); + } + break; + } + } + FxViewItem *topItem = snapItemAt(tempPosition + snapOffset + highlightRangeStart); if (strictHighlightRange && currentItem && (!topItem || (topItem->index != currentIndex && fixupMode == Immediate))) { // StrictlyEnforceRange always keeps an item in range updateHighlight(); topItem = currentItem; } - FxViewItem *bottomItem = snapItemAt(tempPosition+highlightRangeEnd); + FxViewItem *bottomItem = snapItemAt(tempPosition + snapOffset + highlightRangeEnd); if (strictHighlightRange && currentItem && (!bottomItem || (bottomItem->index != currentIndex && fixupMode == Immediate))) { // StrictlyEnforceRange always keeps an item in range updateHighlight(); @@ -1538,27 +1611,92 @@ void QQuickListViewPrivate::fixup(AxisData &data, qreal minExtent, qreal maxExte } qreal pos; bool isInBounds = -position() > maxExtent && -position() <= minExtent; - if (topItem && (isInBounds || strictHighlightRange)) { - if (topItem->index == 0 && header && tempPosition+highlightRangeStart < header->position()+header->size()/2 && !strictHighlightRange) { - pos = isContentFlowReversed() ? - header->position() + highlightRangeStart - size() : header->position() - highlightRangeStart; + + if (header && !topItem && isInBounds) { + // We are trying to pull back further than needed + switch (headerPositioning) { + case QQuickListView::OverlayHeader: + pos = startPosition() - overlayHeaderOffset; + break; + case QQuickListView::InlineHeader: + pos = isContentFlowReversed() ? header->size() - size() : header->position(); + break; + case QQuickListView::PullBackHeader: + pos = isContentFlowReversed() ? -size() : startPosition(); + break; + } + } else if (topItem && (isInBounds || strictHighlightRange)) { + if (topItem->index == 0 && header && !hasStickyHeader() && tempPosition+highlightRangeStart < header->position()+header->size()/2 && !strictHighlightRange) { + pos = isContentFlowReversed() ? -header->position() + highlightRangeStart - size() : (header->position() - highlightRangeStart + header->size()); } else { - if (isContentFlowReversed()) - pos = qMax(qMin(-static_cast<FxListItemSG*>(topItem)->itemPosition() + highlightRangeStart - size(), -maxExtent), -minExtent); - else - pos = qMax(qMin(static_cast<FxListItemSG*>(topItem)->itemPosition() - highlightRangeStart, -maxExtent), -minExtent); + if (header && headerPositioning == QQuickListView::PullBackHeader) { + // We pulled down the header. If it isn't pulled all way down, we need to snap + // the header. + if (qFuzzyCompare(tempPosition, header->position())) { + // It is pulled all way down. Scroll-snap the content, but not the header. + if (isContentFlowReversed()) + pos = -static_cast<FxListItemSG*>(topItem)->itemPosition() + highlightRangeStart - size() + snapOffset; + else + pos = static_cast<FxListItemSG*>(topItem)->itemPosition() - highlightRangeStart - snapOffset; + } else { + // Header is not pulled all way down, make it completely visible or hide it. + // Depends on how much of the header is visible. + if (desiredHeaderVisible) { + // More than half of the header is visible - show it. + // Scroll so that the topItem is aligned to a fully visible header + if (isContentFlowReversed()) + pos = -static_cast<FxListItemSG*>(topItem)->itemPosition() + highlightRangeStart - size() + headerSize(); + else + pos = static_cast<FxListItemSG*>(topItem)->itemPosition() - highlightRangeStart - headerSize(); + } else { + // Less than half is visible - hide the header. Scroll so + // that the topItem is aligned to the top of the view + if (isContentFlowReversed()) + pos = -static_cast<FxListItemSG*>(topItem)->itemPosition() + highlightRangeStart - size(); + else + pos = static_cast<FxListItemSG*>(topItem)->itemPosition() - highlightRangeStart; + } + } + + headerNeedsSeparateFixup = isHeaderWithinBounds || desiredHeaderVisible; + if (headerNeedsSeparateFixup) { + // We need to animate the header independently if it starts visible or should end as visible, + // since the header should not necessarily follow the content. + // Store the desired viewport position. + // Also store the header position so we know where to animate the header from (fixupHeaderPosition). + // We deduce the desired header position from the desiredViewportPosition variable. + pos = qBound(-minExtent, pos, -maxExtent); + desiredViewportPosition = isContentFlowReversed() ? -pos - size() : pos; + + FxListItemSG *headerItem = static_cast<FxListItemSG*>(header); + fixupHeaderPosition = headerItem->position(); + + // follow the same fixup timeline + QObjectPrivate::connect(&timeline, &QQuickTimeLine::updated, this, &QQuickListViewPrivate::fixupHeader); + QObjectPrivate::connect(&timeline, &QQuickTimeLine::completed, this, &QQuickListViewPrivate::fixupHeaderCompleted); + } + } else if (isContentFlowReversed()) { + pos = -static_cast<FxListItemSG*>(topItem)->itemPosition() + highlightRangeStart - size() + overlayHeaderOffset; + } else { + pos = static_cast<FxListItemSG*>(topItem)->itemPosition() - highlightRangeStart - overlayHeaderOffset; + } } } else if (bottomItem && isInBounds) { if (isContentFlowReversed()) - pos = qMax(qMin(-static_cast<FxListItemSG*>(bottomItem)->itemPosition() + highlightRangeEnd - size(), -maxExtent), -minExtent); + pos = -static_cast<FxListItemSG*>(bottomItem)->itemPosition() + highlightRangeEnd - size() + overlayHeaderOffset; else - pos = qMax(qMin(static_cast<FxListItemSG*>(bottomItem)->itemPosition() - highlightRangeEnd, -maxExtent), -minExtent); + pos = static_cast<FxListItemSG*>(bottomItem)->itemPosition() - highlightRangeEnd - overlayHeaderOffset; } else { QQuickItemViewPrivate::fixup(data, minExtent, maxExtent); return; } + pos = qBound(-minExtent, pos, -maxExtent); qreal dist = qAbs(data.move + pos); - if (dist > 0) { + if (dist >= 0) { + // Even if dist == 0 we still start the timeline, because we use the same timeline for + // moving the header. And we might need to move the header while the content does not + // need moving timeline.reset(data.move); if (fixupMode != Immediate) { timeline.move(data.move, -pos, QEasingCurve(QEasingCurve::InOutQuad), fixupDuration/2); diff --git a/tests/auto/quick/qquicklistview/data/headerSnapToItem.qml b/tests/auto/quick/qquicklistview/data/headerSnapToItem.qml new file mode 100644 index 0000000000..1e5a811630 --- /dev/null +++ b/tests/auto/quick/qquicklistview/data/headerSnapToItem.qml @@ -0,0 +1,67 @@ +import QtQuick 2.12 + +Rectangle { + + width: 240 + height: 320 + color: "#ffffff" + + Component { + id: myDelegate + Rectangle { + id: wrapper + objectName: "wrapper" + width: list.orientation == ListView.Vertical ? 240 : 20 + height: list.orientation == ListView.Vertical ? 20 : 240 + border.width: 1 + border.color: "black" + Text { + text: index + ":" + (list.orientation == ListView.Vertical ? parent.y : parent.x).toFixed(0) + } + color: ListView.isCurrentItem ? "lightsteelblue" : "white" + } + } + + ListView { + id: list + objectName: "list" + focus: true + width: 240 + height: 200 + clip: true + snapMode: ListView.SnapToItem + headerPositioning: ListView.OverlayHeader + model: 30 + delegate: myDelegate + orientation: ListView.Vertical + verticalLayoutDirection: ListView.BottomToTop + + header: Rectangle { + width: list.orientation == Qt.Vertical ? 240 : 30 + height: list.orientation == Qt.Vertical ? 30 : 240 + objectName: "header"; + color: "green" + z: 11 + Text { + anchors.centerIn: parent + text: "header " + (list.orientation == ListView.Vertical ? parent.y : parent.x).toFixed(1) + } + } + } + + Rectangle { + color: "red" + opacity: 0.5 + width: txt.implicitWidth + 50 + height: txt.implicitHeight + anchors.bottom: parent.bottom + anchors.right: parent.right + + Text { + id: txt + anchors.centerIn: parent + text: "header position: " + (list.orientation == ListView.Vertical ? list.headerItem.y : list.headerItem.x).toFixed(1) + + "\ncontent position: " + (list.orientation == ListView.Vertical ? list.contentY : list.contentX).toFixed(1) + } + } +} diff --git a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp index 25212b06f6..be3f2601d6 100644 --- a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp +++ b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp @@ -30,6 +30,7 @@ #include <QtCore/QStringListModel> #include <QtCore/QSortFilterProxyModel> #include <QtGui/QStandardItemModel> +#include <QtGui/QStyleHints> #include <QtQuick/qquickview.h> #include <QtQml/qqmlengine.h> #include <QtQml/qqmlcontext.h> @@ -181,6 +182,8 @@ private slots: void creationContext(); void snapToItem_data(); void snapToItem(); + void headerSnapToItem_data(); + void headerSnapToItem(); void snapToItemWithSpacing_QTBUG_59852(); void snapOneItemResize_QTBUG_43555(); void snapOneItem_data(); @@ -5364,6 +5367,600 @@ void tst_QQuickListView::snapToItemWithSpacing_QTBUG_59852() releaseView(window); } +static void drag_helper(QWindow *window, QPoint *startPos, const QPoint &delta) +{ + QPoint pos = *startPos; + int dragDistance = delta.manhattanLength(); + Q_ASSERT(qAbs(delta.x()) >= 1 || qAbs(delta.y()) >= 1); + + const int stepSize = 8; + QPoint unitVector(0, 0); + if (delta.x()) + unitVector.setX(qBound(-1, delta.x(), 1)); + if (delta.y()) + unitVector.setY(qBound(-1, delta.y(), 1)); + QPoint dragStepSize = unitVector * stepSize; + int nDragSteps = qAbs(dragDistance/stepSize); + + for (int i = 0 ; i < nDragSteps; ++i) { + QTest::mouseMove(window, pos); + pos += dragStepSize; + } + // Move to the final position + pos = *startPos + delta; + QTest::mouseMove(window, pos); + *startPos = pos; +} + +static void dragtwice(QWindow *window, QPoint *startPos, const QPoint &delta1, const QPoint &delta2) +{ + const int dragThreshold = QGuiApplication::styleHints()->startDragDistance(); + QPoint &pos = *startPos; + QPoint unitVector(0, 0); + if (delta1.x()) + unitVector.setX(qBound(-1, delta1.x(), 1)); + if (delta1.y()) + unitVector.setY(qBound(-1, delta1.y(), 1)); + + // go just beyond the drag theshold + drag_helper(window, &pos, unitVector * (dragThreshold + 1)); + drag_helper(window, &pos, unitVector); + + // next drag will actually scroll the listview + if (delta1.manhattanLength() >= 1) + drag_helper(window, &pos, delta1); + if (delta2.manhattanLength() >= 1) + drag_helper(window, &pos, delta2); +} + +struct MyListView : public QQuickListView{ + qreal contentPosition() const + { + return (orientation() == QQuickListView::Horizontal ? contentX(): contentY()); + } + + qreal headerPosition() const + { + return (orientation() == QQuickListView::Horizontal ? headerItem()->x() : headerItem()->y()); + } +}; + +void tst_QQuickListView::headerSnapToItem() +{ + QFETCH(QQuickItemView::LayoutDirection, layoutDirection); + QFETCH(QQuickListView::HeaderPositioning, headerPositioning); + QFETCH(int, firstDragDistance); + QFETCH(int, secondDragDistance); + QFETCH(int, expectedContentPosition); + QFETCH(int, expectedHeaderPosition); + + QQuickView *window = getView(); + window->setSource(testFileUrl("headerSnapToItem.qml")); + window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window)); + + MyListView *listview = static_cast<MyListView *>(findItem<QQuickListView>(window->rootObject(), "list")); + QVERIFY(listview != nullptr); + + const bool horizontal = layoutDirection < QQuickItemView::VerticalTopToBottom; + listview->setOrientation(horizontal ? QQuickListView::Horizontal : QQuickListView::Vertical); + + if (horizontal) + listview->setLayoutDirection(static_cast<Qt::LayoutDirection>(layoutDirection)); + else + listview->setVerticalLayoutDirection(static_cast<QQuickItemView::VerticalLayoutDirection>(layoutDirection)); + + listview->setHeaderPositioning(headerPositioning); + QTest::qWaitFor([&]() { return !QQuickItemPrivate::get(listview)->polishScheduled; }); + + QQuickItem *contentItem = listview->contentItem(); + QVERIFY(contentItem != nullptr); + QQuickItem *header = findItem<QQuickItem>(contentItem, "header"); + QVERIFY(header != nullptr); + QCOMPARE(header, listview->headerItem()); + + QPoint startPos = (QPointF(listview->width(), listview->height())/2).toPoint(); + QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, startPos, 200); + + QPoint firstDragDelta = horizontal ? QPoint(firstDragDistance, 0) : QPoint(0, firstDragDistance); + QPoint secondDragDelta = horizontal ? QPoint(secondDragDistance, 0) : QPoint(0, secondDragDistance); + + dragtwice(window, &startPos, firstDragDelta, secondDragDelta); + + QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, startPos, 200); // Wait 200 ms before we release to avoid trigger a flick + + // wait for the "fixup" animation to finish + QTest::qWaitFor([&]() + { return !listview->isMoving();} + ); + + QCOMPARE(listview->contentPosition(), expectedContentPosition); + QCOMPARE(listview->headerPosition(), expectedHeaderPosition); +} + +void tst_QQuickListView::headerSnapToItem_data() +{ + QTest::addColumn<QQuickItemView::LayoutDirection>("layoutDirection"); + QTest::addColumn<QQuickListView::HeaderPositioning>("headerPositioning"); + QTest::addColumn<int>("firstDragDistance"); + QTest::addColumn<int>("secondDragDistance"); + QTest::addColumn<int>("expectedContentPosition"); + QTest::addColumn<int>("expectedHeaderPosition"); + + // -------------------- + // InlineHeader TopToBottom + QTest::newRow("InlineHeader TopToBottom -10") << QQuickItemView::VerticalTopToBottom + << QQuickListView::InlineHeader + << -10 << 0 + << -30 << -30; + + QTest::newRow("InlineHeader TopToBottom -14") << QQuickItemView::VerticalTopToBottom + << QQuickListView::InlineHeader + << -14 << 0 + << -30 << -30; + + QTest::newRow("InlineHeader TopToBottom -16") << QQuickItemView::VerticalTopToBottom + << QQuickListView::InlineHeader + << -16 << 0 + << 0 << -30; + + QTest::newRow("InlineHeader TopToBottom -30") << QQuickItemView::VerticalTopToBottom + << QQuickListView::InlineHeader + << -30 << 0 + << 0 << -30; + + QTest::newRow("InlineHeader TopToBottom -39") << QQuickItemView::VerticalTopToBottom + << QQuickListView::InlineHeader + << -39 << 0 + << 0 << -30; + + QTest::newRow("InlineHeader TopToBottom -41") << QQuickItemView::VerticalTopToBottom + << QQuickListView::InlineHeader + << -41 << 0 + << 20 << -30; + + QTest::newRow("InlineHeader TopToBottom -65+10") << QQuickItemView::VerticalTopToBottom + << QQuickListView::InlineHeader + << -65 << 10 + << 20 << -30; + + // -------------------- + // InlineHeader BottomToTop + QTest::newRow("InlineHeader BottomToTop +10") << QQuickItemView::VerticalBottomToTop + << QQuickListView::InlineHeader + << 10 << 0 + << -170 << 0; + + QTest::newRow("InlineHeader BottomToTop +14") << QQuickItemView::VerticalBottomToTop + << QQuickListView::InlineHeader + << 14 << 0 + << -170 << 0; + + QTest::newRow("InlineHeader BottomToTop +16") << QQuickItemView::VerticalBottomToTop + << QQuickListView::InlineHeader + << 16 << 0 + << -200 << 0; + + QTest::newRow("InlineHeader BottomToTop +30") << QQuickItemView::VerticalBottomToTop + << QQuickListView::InlineHeader + << 30 << 0 + << -200 << 0; + + QTest::newRow("InlineHeader BottomToTop +39") << QQuickItemView::VerticalBottomToTop + << QQuickListView::InlineHeader + << 39 << 0 + << -200 << 0; + + QTest::newRow("InlineHeader BottomToTop +41") << QQuickItemView::VerticalBottomToTop + << QQuickListView::InlineHeader + << 41 << 0 + << -220 << 0; + + QTest::newRow("InlineHeader BottomToTop +65-10") << QQuickItemView::VerticalBottomToTop + << QQuickListView::InlineHeader + << 65 << -10 + << -220 << 0; + + // -------------------- + // InlineHeader LeftToRight + QTest::newRow("InlineHeader LeftToRight -10") << QQuickItemView::LeftToRight + << QQuickListView::InlineHeader + << -10 << 0 + << -30 << -30; + + QTest::newRow("InlineHeader LeftToRight -14") << QQuickItemView::LeftToRight + << QQuickListView::InlineHeader + << -14 << 0 + << -30 << -30; + + QTest::newRow("InlineHeader LeftToRight -16") << QQuickItemView::LeftToRight + << QQuickListView::InlineHeader + << -16 << 0 + << 0 << -30; + + QTest::newRow("InlineHeader LeftToRight -30") << QQuickItemView::LeftToRight + << QQuickListView::InlineHeader + << -30 << 0 + << 0 << -30; + + QTest::newRow("InlineHeader LeftToRight -39") << QQuickItemView::LeftToRight + << QQuickListView::InlineHeader + << -39 << 0 + << 0 << -30; + + QTest::newRow("InlineHeader LeftToRight -41") << QQuickItemView::LeftToRight + << QQuickListView::InlineHeader + << -41 << 0 + << 20 << -30; + + QTest::newRow("InlineHeader LeftToRight -65+10") << QQuickItemView::LeftToRight + << QQuickListView::InlineHeader + << -65 << 10 + << 20 << -30; + + // -------------------- + // InlineHeader RightToLeft + QTest::newRow("InlineHeader RightToLeft +10") << QQuickItemView::RightToLeft + << QQuickListView::InlineHeader + << 10 << 0 + << -210 << 0; + + QTest::newRow("InlineHeader RightToLeft +14") << QQuickItemView::RightToLeft + << QQuickListView::InlineHeader + << 14 << 0 + << -210 << 0; + + QTest::newRow("InlineHeader RightToLeft +16") << QQuickItemView::RightToLeft + << QQuickListView::InlineHeader + << 16 << 0 + << -240 << 0; + + QTest::newRow("InlineHeader RightToLeft +30") << QQuickItemView::RightToLeft + << QQuickListView::InlineHeader + << 30 << 0 + << -240 << 0; + + QTest::newRow("InlineHeader RightToLeft +39") << QQuickItemView::RightToLeft + << QQuickListView::InlineHeader + << 39 << 0 + << -240 << 0; + + QTest::newRow("InlineHeader RightToLeft +41") << QQuickItemView::RightToLeft + << QQuickListView::InlineHeader + << 41 << 0 + << -260 << 0; + + QTest::newRow("InlineHeader RightToLeft +65-10") << QQuickItemView::RightToLeft + << QQuickListView::InlineHeader + << 65 << -10 + << -260 << 0; + + // -------------------- + // OverlayHeader TopToBottom + QTest::newRow("OverlayHeader TopToBottom +9") << QQuickItemView::VerticalTopToBottom + << QQuickListView::OverlayHeader + << 9 << 0 + << -30 << -30; + + QTest::newRow("OverlayHeader TopToBottom -9") << QQuickItemView::VerticalTopToBottom + << QQuickListView::OverlayHeader + << -9 << 0 + << -30 << -30; + + QTest::newRow("OverlayHeader TopToBottom -11") << QQuickItemView::VerticalTopToBottom + << QQuickListView::OverlayHeader + << -11 << 0 + << -10 << -10; + + QTest::newRow("OverlayHeader TopToBottom -29") << QQuickItemView::VerticalTopToBottom + << QQuickListView::OverlayHeader + << -29 << 0 + << -10 << -10; + + QTest::newRow("OverlayHeader TopToBottom -31") << QQuickItemView::VerticalTopToBottom + << QQuickListView::OverlayHeader + << -31 << 0 + << 10 << 10; + + // -------------------- + // OverlayHeader BottomToTop + QTest::newRow("OverlayHeader BottomToTop -9") << QQuickItemView::VerticalBottomToTop + << QQuickListView::OverlayHeader + << -9 << 0 + << -170 << 0; + + QTest::newRow("OverlayHeader BottomToTop +9") << QQuickItemView::VerticalBottomToTop + << QQuickListView::OverlayHeader + << 9 << 0 + << -170 << 0; + + QTest::newRow("OverlayHeader BottomToTop +11") << QQuickItemView::VerticalBottomToTop + << QQuickListView::OverlayHeader + << 11 << 0 + << -190 << -20; + + QTest::newRow("OverlayHeader BottomToTop +29") << QQuickItemView::VerticalBottomToTop + << QQuickListView::OverlayHeader + << 29 << 0 + << -190 << -20; + + QTest::newRow("OverlayHeader BottomToTop +31") << QQuickItemView::VerticalBottomToTop + << QQuickListView::OverlayHeader + << 31 << 0 + << -210 << -40; + + // -------------------- + // OverlayHeader LeftToRight + QTest::newRow("OverlayHeader LeftToRight +9") << QQuickItemView::LeftToRight + << QQuickListView::OverlayHeader + << 9 << 0 + << -30 << -30; + + QTest::newRow("OverlayHeader LeftToRight -9") << QQuickItemView::LeftToRight + << QQuickListView::OverlayHeader + << -9 << 0 + << -30 << -30; + + QTest::newRow("OverlayHeader LeftToRight -11") << QQuickItemView::LeftToRight + << QQuickListView::OverlayHeader + << -11 << 0 + << -10 << -10; + + QTest::newRow("OverlayHeader LeftToRight -29") << QQuickItemView::LeftToRight + << QQuickListView::OverlayHeader + << -29 << 0 + << -10 << -10; + + QTest::newRow("OverlayHeader LeftToRight -31") << QQuickItemView::LeftToRight + << QQuickListView::OverlayHeader + << -31 << 0 + << 10 << 10; + + // -------------------- + // OverlayHeader RightToLeft + QTest::newRow("OverlayHeader RightToLeft -9") << QQuickItemView::RightToLeft + << QQuickListView::OverlayHeader + << -9 << 0 + << -210 << 0; + + QTest::newRow("OverlayHeader RightToLeft +9") << QQuickItemView::RightToLeft + << QQuickListView::OverlayHeader + << 9 << 0 + << -210 << 0; + + QTest::newRow("OverlayHeader RightToLeft +11") << QQuickItemView::RightToLeft + << QQuickListView::OverlayHeader + << 11 << 0 + << -230 << -20; + + QTest::newRow("OverlayHeader RightToLeft +29") << QQuickItemView::RightToLeft + << QQuickListView::OverlayHeader + << 29 << 0 + << -230 << -20; + + QTest::newRow("OverlayHeader RightToLeft +31") << QQuickItemView::RightToLeft + << QQuickListView::OverlayHeader + << 31 << 0 + << -250 << -40; + + // -------------------- + // PullbackHeader TopToBottom + QTest::newRow("PullbackHeader TopToBottom -2") << QQuickItemView::VerticalTopToBottom + << QQuickListView::PullBackHeader + << -2 << 0 + << -30 << -30; + + QTest::newRow("PullbackHeader TopToBottom -10") << QQuickItemView::VerticalTopToBottom + << QQuickListView::PullBackHeader + << -10 << 0 + << -30 << -30; + + QTest::newRow("PullbackHeader TopToBottom -11") << QQuickItemView::VerticalTopToBottom + << QQuickListView::PullBackHeader + << -11 << 0 + << -10 << -10; + + QTest::newRow("PullbackHeader TopToBottom -14") << QQuickItemView::VerticalTopToBottom + << QQuickListView::PullBackHeader + << -14 << 0 + << -10 << -10; + + QTest::newRow("PullbackHeader TopToBottom -16") << QQuickItemView::VerticalTopToBottom + << QQuickListView::PullBackHeader + << -16 << 0 + << 0 << -30; + + QTest::newRow("PullbackHeader TopToBottom -20") << QQuickItemView::VerticalTopToBottom + << QQuickListView::PullBackHeader + << -20 << 0 + << 0 << -30; + + QTest::newRow("PullbackHeader TopToBottom -65+10") << QQuickItemView::VerticalTopToBottom + << QQuickListView::PullBackHeader + << -65 << 10 + << 20 << -10; + + QTest::newRow("PullbackHeader TopToBottom -65+20") << QQuickItemView::VerticalTopToBottom + << QQuickListView::PullBackHeader + << -65 << 20 + << 10 << 10; + + // Should move header even if contentY doesn't move (its aligned with top) + QTest::newRow("PullbackHeader TopToBottom -55+5") << QQuickItemView::VerticalTopToBottom + << QQuickListView::PullBackHeader + << -55 << 5 + << 20 << -10; + + // Should move header even if contentY doesn't move (it's aligned with header) + QTest::newRow("PullbackHeader TopToBottom -76+16") << QQuickItemView::VerticalTopToBottom + << QQuickListView::PullBackHeader + << -76 << 16 + << 30 << 30; + + // -------------------- + // PullbackHeader BottomToTop + QTest::newRow("PullbackHeader BottomToTop +2") << QQuickItemView::VerticalBottomToTop + << QQuickListView::PullBackHeader + << +2 << 0 + << -170 << 0; + + QTest::newRow("PullbackHeader BottomToTop +9") << QQuickItemView::VerticalBottomToTop + << QQuickListView::PullBackHeader + << +9 << 0 + << -170 << 0; + + QTest::newRow("PullbackHeader BottomToTop +11") << QQuickItemView::VerticalBottomToTop + << QQuickListView::PullBackHeader + << +11 << 0 + << -190 << -20; + + QTest::newRow("PullbackHeader BottomToTop +14") << QQuickItemView::VerticalBottomToTop + << QQuickListView::PullBackHeader + << +14 << 0 + << -190 << -20; + + QTest::newRow("PullbackHeader BottomToTop +16") << QQuickItemView::VerticalBottomToTop + << QQuickListView::PullBackHeader + << +16 << 0 + << -200 << 0; + + QTest::newRow("PullbackHeader BottomToTop +20") << QQuickItemView::VerticalBottomToTop + << QQuickListView::PullBackHeader + << +20 << 0 + << -200 << 0; + + QTest::newRow("PullbackHeader BottomToTop +65-10") << QQuickItemView::VerticalBottomToTop + << QQuickListView::PullBackHeader + << +65 << -10 + << -220 << -20; + + QTest::newRow("PullbackHeader BottomToTop +65-20") << QQuickItemView::VerticalBottomToTop + << QQuickListView::PullBackHeader + << +65 << -20 + << -210 << -40; + + // Should move header even if contentY doesn't move (it's aligned with top) + QTest::newRow("PullbackHeader BottomToTop +55-5") << QQuickItemView::VerticalBottomToTop + << QQuickListView::PullBackHeader + << 55 << -5 + << -220 << -20; + + // Should move header even if contentY doesn't move (it's aligned with header) + QTest::newRow("PullbackHeader BottomToTop +76-16") << QQuickItemView::VerticalBottomToTop + << QQuickListView::PullBackHeader + << 76 << -16 + << -230 << -60; + + // -------------------- + // PullbackHeader LeftToRight + QTest::newRow("PullbackHeader LeftToRight -2") << QQuickItemView::LeftToRight + << QQuickListView::PullBackHeader + << -2 << 0 + << -30 << -30; + + QTest::newRow("PullbackHeader LeftToRight -10") << QQuickItemView::LeftToRight + << QQuickListView::PullBackHeader + << -10 << 0 + << -30 << -30; + + QTest::newRow("PullbackHeader LeftToRight -11") << QQuickItemView::LeftToRight + << QQuickListView::PullBackHeader + << -11 << 0 + << -10 << -10; + + QTest::newRow("PullbackHeader LeftToRight -14") << QQuickItemView::LeftToRight + << QQuickListView::PullBackHeader + << -14 << 0 + << -10 << -10; + + QTest::newRow("PullbackHeader LeftToRight -16") << QQuickItemView::LeftToRight + << QQuickListView::PullBackHeader + << -16 << 0 + << 0 << -30; + + QTest::newRow("PullbackHeader LeftToRight -20") << QQuickItemView::LeftToRight + << QQuickListView::PullBackHeader + << -20 << 0 + << 0 << -30; + + QTest::newRow("PullbackHeader LeftToRight -65+10") << QQuickItemView::LeftToRight + << QQuickListView::PullBackHeader + << -65 << 10 + << 20 << -10; + + QTest::newRow("PullbackHeader LeftToRight -65+20") << QQuickItemView::LeftToRight + << QQuickListView::PullBackHeader + << -65 << 20 + << 10 << 10; + + // Should move header even if contentX doesn't move (its aligned with top) + QTest::newRow("PullbackHeader LeftToRight -55+5") << QQuickItemView::LeftToRight + << QQuickListView::PullBackHeader + << -55 << 5 + << 20 << -10; + + // Should move header even if contentX doesn't move (it's aligned with header) + QTest::newRow("PullbackHeader LeftToRight -76+16") << QQuickItemView::LeftToRight + << QQuickListView::PullBackHeader + << -76 << 16 + << 30 << 30; + + // -------------------- + // PullbackHeader RightToLeft + QTest::newRow("PullbackHeader RightToLeft +2") << QQuickItemView::RightToLeft + << QQuickListView::PullBackHeader + << +2 << 0 + << -210 << 0; + + QTest::newRow("PullbackHeader RightToLeft +9") << QQuickItemView::RightToLeft + << QQuickListView::PullBackHeader + << +9 << 0 + << -210 << 0; + + QTest::newRow("PullbackHeader RightToLeft +11") << QQuickItemView::RightToLeft + << QQuickListView::PullBackHeader + << +11 << 0 + << -230 << -20; + + QTest::newRow("PullbackHeader RightToLeft +14") << QQuickItemView::RightToLeft + << QQuickListView::PullBackHeader + << +14 << 0 + << -230 << -20; + + QTest::newRow("PullbackHeader RightToLeft +16") << QQuickItemView::RightToLeft + << QQuickListView::PullBackHeader + << +16 << 0 + << -240 << 0; + + QTest::newRow("PullbackHeader RightToLeft +20") << QQuickItemView::RightToLeft + << QQuickListView::PullBackHeader + << +20 << 0 + << -240 << 0; + + QTest::newRow("PullbackHeader RightToLeft +65-10") << QQuickItemView::RightToLeft + << QQuickListView::PullBackHeader + << +65 << -10 + << -260 << -20; + + QTest::newRow("PullbackHeader RightToLeft +65-20") << QQuickItemView::RightToLeft + << QQuickListView::PullBackHeader + << +65 << -20 + << -250 << -40; + + // Should move header even if contentX doesn't move (it's aligned with top) + QTest::newRow("PullbackHeader RightToLeft +55-5") << QQuickItemView::RightToLeft + << QQuickListView::PullBackHeader + << 55 << -5 + << -260 << -20; + + // Should move header even if contentX doesn't move (it's aligned with header) + QTest::newRow("PullbackHeader RightToLeft +76-16") << QQuickItemView::RightToLeft + << QQuickListView::PullBackHeader + << 76 << -16 + << -270 << -60; + +} + void tst_QQuickListView::snapOneItemResize_QTBUG_43555() { QScopedPointer<QQuickView> window(createView()); |