aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Arve Sæther <jan-arve.saether@qt.io>2019-12-03 11:52:55 +0100
committerJan Arve Sæther <jan-arve.saether@qt.io>2020-01-31 23:06:22 +0100
commite9b4fac4e1765ea8789b17948a0a22fad7db50c0 (patch)
tree7975421211f031372cac050b1a570485c6558465
parent30b0bf3bf3097045d1027603ab9102712ac2d512 (diff)
Fix some ListView bugs related to snapping when it had a header
Most bugs were related to the PullBackHeader header positining mode, for instance the old code did not take into consideration that for the PullBackHeader it was sometimes not sufficient to scroll the view. The header also had to be scrolled independently from the view: We achieve this by hooking on to the same timeline that is used for scrolling the view. (This way, both animations are synchronized, and they start and end at the same time). Change-Id: I75708c0fd8d4741032c04ad9ee144d7a49cf3359 Fixes: QTBUG-76362 Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io> (cherry picked from commit 01660fbb67c39c74b2e1eeae1e3d1b97c8886cdb)
-rw-r--r--src/quick/items/qquicklistview.cpp168
-rw-r--r--tests/auto/quick/qquicklistview/data/headerSnapToItem.qml67
-rw-r--r--tests/auto/quick/qquicklistview/tst_qquicklistview.cpp597
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());