aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/src/declarative/whatsnew.qdoc5
-rw-r--r--src/declarative/items/qsggridview.cpp77
-rw-r--r--src/declarative/items/qsgitemview.cpp42
-rw-r--r--src/declarative/items/qsglistview.cpp70
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativegridview.cpp23
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativelistview.cpp2
-rw-r--r--tests/auto/declarative/qsggridview/data/snapToRow.qml49
-rw-r--r--tests/auto/declarative/qsggridview/tst_qsggridview.cpp116
-rw-r--r--tests/auto/declarative/qsglistview/data/snapToItem.qml49
-rw-r--r--tests/auto/declarative/qsglistview/tst_qsglistview.cpp117
10 files changed, 406 insertions, 144 deletions
diff --git a/doc/src/declarative/whatsnew.qdoc b/doc/src/declarative/whatsnew.qdoc
index 84245a565f..4c44166472 100644
--- a/doc/src/declarative/whatsnew.qdoc
+++ b/doc/src/declarative/whatsnew.qdoc
@@ -117,8 +117,9 @@ Text improvements:
PathView now has a \c currentItem property
-ListView and GridView now have headerItem and footerItem properties (the instantiated
-header and footer items).
+ListView and GridView:
+ - now have headerItem and footerItem properties (the instantiated header and footer items).
+ - In RightToLeft layout the preferredHighlightBegin/End are now also reversed.
ListView section.labelPositioning property added to allow keeping the current section label
at the start and/or next section label at the end of the view.
diff --git a/src/declarative/items/qsggridview.cpp b/src/declarative/items/qsggridview.cpp
index fd2742c2f3..6b01583497 100644
--- a/src/declarative/items/qsggridview.cpp
+++ b/src/declarative/items/qsggridview.cpp
@@ -334,7 +334,10 @@ qreal QSGGridViewPrivate::snapPosAt(qreal pos) const
Q_Q(const QSGGridView);
qreal snapPos = 0;
if (!visibleItems.isEmpty()) {
- qreal highlightStart = isRightToLeftTopToBottom() && highlightRangeStartValid ? size()-highlightRangeEnd : highlightRangeStart;
+ qreal highlightStart = highlightRangeStart;
+ if (isRightToLeftTopToBottom())
+ highlightStart = highlightRangeEndValid ? -size() + highlightRangeEnd : -size();
+
pos += highlightStart;
pos += rowSize()/2;
snapPos = static_cast<FxGridItemSG*>(visibleItems.first())->rowPos() - visibleIndex / columns * rowSize();
@@ -807,19 +810,7 @@ void QSGGridViewPrivate::fixup(AxisData &data, qreal minExtent, qreal maxExtent)
fixupMode = moveReason == Mouse ? fixupMode : Immediate;
- qreal highlightStart;
- qreal highlightEnd;
- qreal viewPos;
- if (isRightToLeftTopToBottom()) {
- // Handle Right-To-Left exceptions
- viewPos = -position()-size();
- highlightStart = highlightRangeStartValid ? size()-highlightRangeEnd : highlightRangeStart;
- highlightEnd = highlightRangeEndValid ? size()-highlightRangeStart : highlightRangeEnd;
- } else {
- viewPos = position();
- highlightStart = highlightRangeStart;
- highlightEnd = highlightRangeEnd;
- }
+ qreal viewPos = isRightToLeftTopToBottom() ? -position()-size() : position();
bool strictHighlightRange = haveHighlightRange && highlightRange == QSGGridView::StrictlyEnforceRange;
if (snapMode != QSGGridView::NoSnap) {
@@ -836,40 +827,35 @@ void QSGGridViewPrivate::fixup(AxisData &data, qreal minExtent, qreal maxExtent)
bias = -bias;
tempPosition -= bias;
}
- FxViewItem *topItem = snapItemAt(tempPosition+highlightStart);
+ FxViewItem *topItem = snapItemAt(tempPosition+highlightRangeStart);
if (!topItem && strictHighlightRange && currentItem) {
// StrictlyEnforceRange always keeps an item in range
updateHighlight();
topItem = currentItem;
}
- FxViewItem *bottomItem = snapItemAt(tempPosition+highlightEnd);
+ FxViewItem *bottomItem = snapItemAt(tempPosition+highlightRangeEnd);
if (!bottomItem && strictHighlightRange && currentItem) {
// StrictlyEnforceRange always keeps an item in range
updateHighlight();
bottomItem = currentItem;
}
qreal pos;
- if (topItem && bottomItem && strictHighlightRange) {
- qreal topPos = qMin(topItem->position() - highlightStart, -maxExtent);
- qreal bottomPos = qMax(bottomItem->position() - highlightEnd, -minExtent);
- pos = qAbs(data.move + topPos) < qAbs(data.move + bottomPos) ? topPos : bottomPos;
- } else if (topItem) {
- qreal headerPos = 0;
- if (header)
- headerPos = isRightToLeftTopToBottom() ? static_cast<FxGridItemSG*>(header)->rowPos() + cellWidth - headerSize() : static_cast<FxGridItemSG*>(header)->rowPos();
- if (topItem->index == 0 && header && tempPosition+highlightStart < headerPos+headerSize()/2 && !strictHighlightRange) {
- pos = isRightToLeftTopToBottom() ? - headerPos + highlightStart - size() : headerPos - highlightStart;
+ bool isInBounds = -position() > maxExtent && -position() <= minExtent;
+ if (topItem && (isInBounds || strictHighlightRange)) {
+ qreal headerPos = header ? static_cast<FxGridItemSG*>(header)->rowPos() : 0;
+ if (topItem->index == 0 && header && tempPosition+highlightRangeStart < headerPos+headerSize()/2 && !strictHighlightRange) {
+ pos = isRightToLeftTopToBottom() ? - headerPos + highlightRangeStart - size() : headerPos - highlightRangeStart;
} else {
if (isRightToLeftTopToBottom())
- pos = qMax(qMin(-topItem->position() + highlightStart - size(), -maxExtent), -minExtent);
+ pos = qMax(qMin(-topItem->position() + highlightRangeStart - size(), -maxExtent), -minExtent);
else
- pos = qMax(qMin(topItem->position() - highlightStart, -maxExtent), -minExtent);
+ pos = qMax(qMin(topItem->position() - highlightRangeStart, -maxExtent), -minExtent);
}
- } else if (bottomItem) {
+ } else if (bottomItem && isInBounds) {
if (isRightToLeftTopToBottom())
- pos = qMax(qMin(-bottomItem->position() + highlightEnd - size(), -maxExtent), -minExtent);
+ pos = qMax(qMin(-bottomItem->position() + highlightRangeEnd - size(), -maxExtent), -minExtent);
else
- pos = qMax(qMin(bottomItem->position() - highlightEnd, -maxExtent), -minExtent);
+ pos = qMax(qMin(bottomItem->position() - highlightRangeEnd, -maxExtent), -minExtent);
} else {
QSGItemViewPrivate::fixup(data, minExtent, maxExtent);
return;
@@ -890,10 +876,10 @@ void QSGGridViewPrivate::fixup(AxisData &data, qreal minExtent, qreal maxExtent)
if (currentItem) {
updateHighlight();
qreal pos = static_cast<FxGridItemSG*>(currentItem)->rowPos();
- if (viewPos < pos + rowSize() - highlightEnd)
- viewPos = pos + rowSize() - highlightEnd;
- if (viewPos > pos - highlightStart)
- viewPos = pos - highlightStart;
+ if (viewPos < pos + rowSize() - highlightRangeEnd)
+ viewPos = pos + rowSize() - highlightRangeEnd;
+ if (viewPos > pos - highlightRangeStart)
+ viewPos = pos - highlightRangeStart;
if (isRightToLeftTopToBottom())
viewPos = -viewPos-size();
timeline.reset(data.move);
@@ -1543,22 +1529,11 @@ void QSGGridView::viewportMoved()
if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange && d->highlight) {
// reposition highlight
qreal pos = d->highlight->position();
- qreal viewPos;
- qreal highlightStart;
- qreal highlightEnd;
- if (d->isRightToLeftTopToBottom()) {
- viewPos = -d->position()-d->size();
- highlightStart = d->highlightRangeStartValid ? d->size()-d->highlightRangeEnd : d->highlightRangeStart;
- highlightEnd = d->highlightRangeEndValid ? d->size()-d->highlightRangeStart : d->highlightRangeEnd;
- } else {
- viewPos = d->position();
- highlightStart = d->highlightRangeStart;
- highlightEnd = d->highlightRangeEnd;
- }
- if (pos > viewPos + highlightEnd - d->highlight->size())
- pos = viewPos + highlightEnd - d->highlight->size();
- if (pos < viewPos + highlightStart)
- pos = viewPos + highlightStart;
+ qreal viewPos = d->isRightToLeftTopToBottom() ? -d->position()-d->size() : d->position();
+ if (pos > viewPos + d->highlightRangeEnd - d->highlight->size())
+ pos = viewPos + d->highlightRangeEnd - d->highlight->size();
+ if (pos < viewPos + d->highlightRangeStart)
+ pos = viewPos + d->highlightRangeStart;
if (pos != d->highlight->position()) {
d->highlightXAnimator->stop();
diff --git a/src/declarative/items/qsgitemview.cpp b/src/declarative/items/qsgitemview.cpp
index 075024db0f..5b95097dcc 100644
--- a/src/declarative/items/qsgitemview.cpp
+++ b/src/declarative/items/qsgitemview.cpp
@@ -821,30 +821,14 @@ void QSGItemView::trackedPositionChanged()
if (d->trackedItem != d->currentItem) {
trackedSize += d->currentItem->sectionSize();
}
- qreal viewPos;
- qreal highlightStart;
- qreal highlightEnd;
- if (d->isContentFlowReversed()) {
- viewPos = -d->position()-d->size();
- highlightStart = d->highlightRangeStartValid ? d->size()-d->highlightRangeEnd : d->highlightRangeStart;
- highlightEnd = d->highlightRangeEndValid ? d->size()-d->highlightRangeStart : d->highlightRangeEnd;
- } else {
- viewPos = d->position();
- highlightStart = d->highlightRangeStart;
- highlightEnd = d->highlightRangeEnd;
- }
+ qreal viewPos = d->isContentFlowReversed() ? -d->position()-d->size() : d->position();
qreal pos = viewPos;
if (d->haveHighlightRange) {
- if (d->highlightRange == StrictlyEnforceRange) {
- if (trackedPos > pos + highlightEnd - d->trackedItem->size())
- pos = trackedPos - highlightEnd + d->trackedItem->size();
- if (trackedPos < pos + highlightStart)
- pos = trackedPos - highlightStart;
- } else {
- if (trackedPos > pos + highlightEnd - trackedSize)
- pos = trackedPos - highlightEnd + trackedSize;
- if (trackedPos < pos + highlightStart)
- pos = trackedPos - highlightStart;
+ if (trackedPos > pos + d->highlightRangeEnd - trackedSize)
+ pos = trackedPos - d->highlightRangeEnd + trackedSize;
+ if (trackedPos < pos + d->highlightRangeStart)
+ pos = trackedPos - d->highlightRangeStart;
+ if (d->highlightRange != StrictlyEnforceRange) {
if (pos > d->endPosition() - d->size())
pos = d->endPosition() - d->size();
if (pos < d->startPosition())
@@ -967,10 +951,8 @@ qreal QSGItemView::minXExtent() const
endPositionFirstItem = d->positionAt(d->model->count()-1);
else if (d->header)
d->minExtent += d->headerSize();
- highlightStart = d->highlightRangeStartValid
- ? d->highlightRangeStart - (d->lastPosition()-endPositionFirstItem)
- : d->size() - (d->lastPosition()-endPositionFirstItem);
- highlightEnd = d->highlightRangeEndValid ? d->highlightRangeEnd : d->size();
+ highlightStart = d->highlightRangeEndValid ? d->size() - d->highlightRangeEnd : d->size();
+ highlightEnd = d->highlightRangeStartValid ? d->size() - d->highlightRangeStart : d->size();
if (d->footer)
d->minExtent += d->footerSize();
qreal maxX = maxXExtent();
@@ -986,7 +968,9 @@ qreal QSGItemView::minXExtent() const
}
if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
d->minExtent += highlightStart;
- d->minExtent = qMax(d->minExtent, -(endPositionFirstItem - highlightEnd));
+ d->minExtent = d->isContentFlowReversed()
+ ? qMin(d->minExtent, endPositionFirstItem + highlightEnd)
+ : qMax(d->minExtent, -(endPositionFirstItem - highlightEnd));
}
d->hData.minExtentDirty = false;
}
@@ -1006,8 +990,8 @@ qreal QSGItemView::maxXExtent() const
qreal lastItemPosition = 0;
d->maxExtent = 0;
if (d->isContentFlowReversed()) {
- highlightStart = d->highlightRangeStartValid ? d->highlightRangeEnd : d->size();
- highlightEnd = d->highlightRangeEndValid ? d->highlightRangeStart : d->size();
+ highlightStart = d->highlightRangeEndValid ? d->size() - d->highlightRangeEnd : d->size();
+ highlightEnd = d->highlightRangeStartValid ? d->size() - d->highlightRangeStart : d->size();
lastItemPosition = d->endPosition();
} else {
highlightStart = d->highlightRangeStart;
diff --git a/src/declarative/items/qsglistview.cpp b/src/declarative/items/qsglistview.cpp
index 75472c2a79..5ea9efe274 100644
--- a/src/declarative/items/qsglistview.cpp
+++ b/src/declarative/items/qsglistview.cpp
@@ -1251,19 +1251,7 @@ void QSGListViewPrivate::fixup(AxisData &data, qreal minExtent, qreal maxExtent)
fixupMode = moveReason == Mouse ? fixupMode : Immediate;
bool strictHighlightRange = haveHighlightRange && highlightRange == QSGListView::StrictlyEnforceRange;
- qreal highlightStart;
- qreal highlightEnd;
- qreal viewPos;
- if (isRightToLeft()) {
- // Handle Right-To-Left exceptions
- viewPos = -position()-size();
- highlightStart = highlightRangeStartValid ? size() - highlightRangeEnd : highlightRangeStart;
- highlightEnd = highlightRangeEndValid ? size() - highlightRangeStart : highlightRangeEnd;
- } else {
- viewPos = position();
- highlightStart = highlightRangeStart;
- highlightEnd = highlightRangeEnd;
- }
+ qreal viewPos = isRightToLeft() ? -position()-size() : position();
if (snapMode != QSGListView::NoSnap && moveReason != QSGListViewPrivate::SetIndex) {
qreal tempPosition = isRightToLeft() ? -position()-size() : position();
@@ -1279,13 +1267,13 @@ void QSGListViewPrivate::fixup(AxisData &data, qreal minExtent, qreal maxExtent)
bias = -bias;
tempPosition -= bias;
}
- FxViewItem *topItem = snapItemAt(tempPosition+highlightStart);
+ FxViewItem *topItem = snapItemAt(tempPosition+highlightRangeStart);
if (!topItem && strictHighlightRange && currentItem) {
// StrictlyEnforceRange always keeps an item in range
updateHighlight();
topItem = currentItem;
}
- FxViewItem *bottomItem = snapItemAt(tempPosition+highlightEnd);
+ FxViewItem *bottomItem = snapItemAt(tempPosition+highlightRangeEnd);
if (!bottomItem && strictHighlightRange && currentItem) {
// StrictlyEnforceRange always keeps an item in range
updateHighlight();
@@ -1294,19 +1282,19 @@ void QSGListViewPrivate::fixup(AxisData &data, qreal minExtent, qreal maxExtent)
qreal pos;
bool isInBounds = -position() > maxExtent && -position() <= minExtent;
if (topItem && (isInBounds || strictHighlightRange)) {
- if (topItem->index == 0 && header && tempPosition+highlightStart < header->position()+header->size()/2 && !strictHighlightRange) {
- pos = isRightToLeft() ? - header->position() + highlightStart - size() : header->position() - highlightStart;
+ if (topItem->index == 0 && header && tempPosition+highlightRangeStart < header->position()+header->size()/2 && !strictHighlightRange) {
+ pos = isRightToLeft() ? - header->position() + highlightRangeStart - size() : header->position() - highlightRangeStart;
} else {
if (isRightToLeft())
- pos = qMax(qMin(-topItem->position() + highlightStart - size(), -maxExtent), -minExtent);
+ pos = qMax(qMin(-topItem->position() + highlightRangeStart - size(), -maxExtent), -minExtent);
else
- pos = qMax(qMin(topItem->position() - highlightStart, -maxExtent), -minExtent);
+ pos = qMax(qMin(topItem->position() - highlightRangeStart, -maxExtent), -minExtent);
}
} else if (bottomItem && isInBounds) {
if (isRightToLeft())
- pos = qMax(qMin(-bottomItem->position() + highlightEnd - size(), -maxExtent), -minExtent);
+ pos = qMax(qMin(-bottomItem->position() + highlightRangeEnd - size(), -maxExtent), -minExtent);
else
- pos = qMax(qMin(bottomItem->position() - highlightEnd, -maxExtent), -minExtent);
+ pos = qMax(qMin(bottomItem->position() - highlightRangeEnd, -maxExtent), -minExtent);
} else {
QSGItemViewPrivate::fixup(data, minExtent, maxExtent);
return;
@@ -1326,10 +1314,10 @@ void QSGListViewPrivate::fixup(AxisData &data, qreal minExtent, qreal maxExtent)
} else if (currentItem && strictHighlightRange && moveReason != QSGListViewPrivate::SetIndex) {
updateHighlight();
qreal pos = static_cast<FxListItemSG*>(currentItem)->itemPosition();
- if (viewPos < pos + static_cast<FxListItemSG*>(currentItem)->itemSize() - highlightEnd)
- viewPos = pos + static_cast<FxListItemSG*>(currentItem)->itemSize() - highlightEnd;
- if (viewPos > pos - highlightStart)
- viewPos = pos - highlightStart;
+ if (viewPos < pos + static_cast<FxListItemSG*>(currentItem)->itemSize() - highlightRangeEnd)
+ viewPos = pos + static_cast<FxListItemSG*>(currentItem)->itemSize() - highlightRangeEnd;
+ if (viewPos > pos - highlightRangeStart)
+ viewPos = pos - highlightRangeStart;
if (isRightToLeft())
viewPos = -viewPos-size();
@@ -1364,7 +1352,7 @@ void QSGListViewPrivate::flick(AxisData &data, qreal minExtent, qreal maxExtent,
}
qreal maxDistance = 0;
qreal dataValue = isRightToLeft() ? -data.move.value()+size() : data.move.value();
- qreal highlightStart = isRightToLeft() && highlightRangeStartValid ? size()-highlightRangeEnd : highlightRangeStart;
+
// -ve velocity means list is moving up/left
if (velocity > 0) {
if (data.move.value() < minExtent) {
@@ -1374,7 +1362,7 @@ void QSGListViewPrivate::flick(AxisData &data, qreal minExtent, qreal maxExtent,
qreal bias = dist < averageSize/2 ? averageSize/2 : 0;
if (isRightToLeft())
bias = -bias;
- data.flickTarget = -snapPosAt(-(dataValue - highlightStart) - bias) + highlightStart;
+ data.flickTarget = -snapPosAt(-(dataValue - highlightRangeStart) - bias) + highlightRangeStart;
maxDistance = qAbs(data.flickTarget - data.move.value());
velocity = maxVelocity;
} else {
@@ -1391,7 +1379,7 @@ void QSGListViewPrivate::flick(AxisData &data, qreal minExtent, qreal maxExtent,
qreal bias = -dist < averageSize/2 ? averageSize/2 : 0;
if (isRightToLeft())
bias = -bias;
- data.flickTarget = -snapPosAt(-(dataValue - highlightStart) + bias) + highlightStart;
+ data.flickTarget = -snapPosAt(-(dataValue - highlightRangeStart) + bias) + highlightRangeStart;
maxDistance = qAbs(data.flickTarget - data.move.value());
velocity = -maxVelocity;
} else {
@@ -1428,7 +1416,7 @@ void QSGListViewPrivate::flick(AxisData &data, qreal minExtent, qreal maxExtent,
if ((maxDistance > 0.0 && v2 / (2.0f * maxDistance) < accel) || snapMode == QSGListView::SnapOneItem) {
if (snapMode != QSGListView::SnapOneItem) {
qreal distTemp = isRightToLeft() ? -dist : dist;
- data.flickTarget = -snapPosAt(-(dataValue - highlightStart) + distTemp) + highlightStart;
+ data.flickTarget = -snapPosAt(-(dataValue - highlightRangeStart) + distTemp) + highlightRangeStart;
}
data.flickTarget = isRightToLeft() ? -data.flickTarget+size() : data.flickTarget;
if (overShoot) {
@@ -1484,7 +1472,7 @@ void QSGListViewPrivate::flick(AxisData &data, qreal minExtent, qreal maxExtent,
qreal newtarget = data.flickTarget;
if (snapMode != QSGListView::NoSnap || highlightRange == QSGListView::StrictlyEnforceRange) {
qreal tempFlickTarget = isRightToLeft() ? -data.flickTarget+size() : data.flickTarget;
- newtarget = -snapPosAt(-(tempFlickTarget - highlightStart)) + highlightStart;
+ newtarget = -snapPosAt(-(tempFlickTarget - highlightRangeStart)) + highlightRangeStart;
newtarget = isRightToLeft() ? -newtarget+size() : newtarget;
}
if (velocity < 0 && newtarget <= maxExtent)
@@ -2167,23 +2155,11 @@ void QSGListView::viewportMoved()
if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange && d->highlight) {
// reposition highlight
qreal pos = d->highlight->position();
- qreal viewPos;
- qreal highlightStart;
- qreal highlightEnd;
- if (d->isRightToLeft()) {
- // Handle Right-To-Left exceptions
- viewPos = -d->position()-d->size();
- highlightStart = d->highlightRangeStartValid ? d->size()-d->highlightRangeEnd : d->highlightRangeStart;
- highlightEnd = d->highlightRangeEndValid ? d->size()-d->highlightRangeStart : d->highlightRangeEnd;
- } else {
- viewPos = d->position();
- highlightStart = d->highlightRangeStart;
- highlightEnd = d->highlightRangeEnd;
- }
- if (pos > viewPos + highlightEnd - d->highlight->size())
- pos = viewPos + highlightEnd - d->highlight->size();
- if (pos < viewPos + highlightStart)
- pos = viewPos + highlightStart;
+ qreal viewPos = d->isRightToLeft() ? -d->position()-d->size() : d->position();
+ if (pos > viewPos + d->highlightRangeEnd - d->highlight->size())
+ pos = viewPos + d->highlightRangeEnd - d->highlight->size();
+ if (pos < viewPos + d->highlightRangeStart)
+ pos = viewPos + d->highlightRangeStart;
if (pos != d->highlight->position()) {
d->highlightPosAnimator->stop();
static_cast<FxListItemSG*>(d->highlight)->setPosition(pos);
diff --git a/src/qtquick1/graphicsitems/qdeclarativegridview.cpp b/src/qtquick1/graphicsitems/qdeclarativegridview.cpp
index feabbf0387..2ed1ca1782 100644
--- a/src/qtquick1/graphicsitems/qdeclarativegridview.cpp
+++ b/src/qtquick1/graphicsitems/qdeclarativegridview.cpp
@@ -1095,23 +1095,17 @@ void QDeclarative1GridViewPrivate::fixup(AxisData &data, qreal minExtent, qreal
bottomItem = currentItem;
}
qreal pos;
- if (topItem && bottomItem && strictHighlightRange) {
- qreal topPos = qMin(topItem->rowPos() - highlightStart, -maxExtent);
- qreal bottomPos = qMax(bottomItem->rowPos() - highlightEnd, -minExtent);
- pos = qAbs(data.move + topPos) < qAbs(data.move + bottomPos) ? topPos : bottomPos;
- } else if (topItem) {
- qreal headerPos = 0;
- if (header)
- headerPos = isRightToLeftTopToBottom() ? header->rowPos() + cellWidth - headerSize() : header->rowPos();
- if (topItem->index == 0 && header && tempPosition+highlightStart < headerPos+headerSize()/2 && !strictHighlightRange) {
- pos = isRightToLeftTopToBottom() ? - headerPos + highlightStart - size() : headerPos - highlightStart;
+ bool isInBounds = -position() > maxExtent && -position() <= minExtent;
+ if (topItem && (isInBounds || strictHighlightRange)) {
+ if (topItem->index == 0 && header && tempPosition+highlightStart < header->rowPos()+headerSize()/2 && !strictHighlightRange) {
+ pos = isRightToLeftTopToBottom() ? - header->rowPos() + highlightStart - size() : header->rowPos() - highlightStart;
} else {
if (isRightToLeftTopToBottom())
pos = qMax(qMin(-topItem->rowPos() + highlightStart - size(), -maxExtent), -minExtent);
else
pos = qMax(qMin(topItem->rowPos() - highlightStart, -maxExtent), -minExtent);
}
- } else if (bottomItem) {
+ } else if (bottomItem && isInBounds) {
if (isRightToLeftTopToBottom())
pos = qMax(qMin(-bottomItem->rowPos() + highlightEnd - size(), -maxExtent), -minExtent);
else
@@ -2267,9 +2261,10 @@ qreal QDeclarative1GridView::minXExtent() const
qreal extent = -d->startPosition();
qreal highlightStart;
qreal highlightEnd;
- qreal endPositionFirstItem;
+ qreal endPositionFirstItem = 0;
if (d->isRightToLeftTopToBottom()) {
- endPositionFirstItem = d->rowPosAt(d->model->count()-1);
+ if (d->model && d->model->count())
+ endPositionFirstItem = d->rowPosAt(d->model->count()-1);
highlightStart = d->highlightRangeStartValid
? d->highlightRangeStart - (d->lastPosition()-endPositionFirstItem)
: d->size() - (d->lastPosition()-endPositionFirstItem);
@@ -2284,7 +2279,7 @@ qreal QDeclarative1GridView::minXExtent() const
extent += d->header->item->width();
}
if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
- extent += highlightStart;
+ extent += d->isRightToLeftTopToBottom() ? -highlightStart : highlightStart;
extent = qMax(extent, -(endPositionFirstItem - highlightEnd));
}
return extent;
diff --git a/src/qtquick1/graphicsitems/qdeclarativelistview.cpp b/src/qtquick1/graphicsitems/qdeclarativelistview.cpp
index 7b9cb12e90..6430f6a071 100644
--- a/src/qtquick1/graphicsitems/qdeclarativelistview.cpp
+++ b/src/qtquick1/graphicsitems/qdeclarativelistview.cpp
@@ -2773,7 +2773,7 @@ qreal QDeclarative1ListView::minXExtent() const
d->minExtent += d->header->size();
}
if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
- d->minExtent += highlightStart;
+ d->minExtent += d->isRightToLeft() ? -highlightStart : highlightStart;
d->minExtent = qMax(d->minExtent, -(endPositionFirstItem - highlightEnd + 1));
}
d->minExtentDirty = false;
diff --git a/tests/auto/declarative/qsggridview/data/snapToRow.qml b/tests/auto/declarative/qsggridview/data/snapToRow.qml
new file mode 100644
index 0000000000..f079a048f0
--- /dev/null
+++ b/tests/auto/declarative/qsggridview/data/snapToRow.qml
@@ -0,0 +1,49 @@
+import QtQuick 2.0
+
+Rectangle {
+ id: root
+ width: 240
+ height: 240
+ color: "#ffffff"
+
+ Component {
+ id: myDelegate
+ Rectangle {
+ id: wrapper
+ objectName: "wrapper"
+ height: 80
+ width: 80
+ Column {
+ Text {
+ text: index
+ }
+ Text {
+ text: wrapper.x + ", " + wrapper.y
+ }
+ }
+ color: GridView.isCurrentItem ? "lightsteelblue" : "transparent"
+ }
+ }
+ GridView {
+ id: grid
+ objectName: "grid"
+ anchors.fill: parent
+ cellWidth: 80
+ cellHeight: 80
+ preferredHighlightBegin: 20
+ preferredHighlightEnd: 100
+ snapMode: GridView.SnapToRow
+ layoutDirection: Qt.RightToLeft
+ flow: GridView.TopToBottom
+ highlightRangeMode: GridView.StrictlyEnforceRange
+ highlight: Rectangle { width: 80; height: 80; color: "yellow" }
+ model: 54
+ delegate: myDelegate
+ }
+
+ Text {
+ anchors.right: parent.right
+ anchors.bottom: parent.bottom
+ text: grid.contentX + ", " + grid.contentY
+ }
+}
diff --git a/tests/auto/declarative/qsggridview/tst_qsggridview.cpp b/tests/auto/declarative/qsggridview/tst_qsggridview.cpp
index 03975e295d..b6a601d8d7 100644
--- a/tests/auto/declarative/qsggridview/tst_qsggridview.cpp
+++ b/tests/auto/declarative/qsggridview/tst_qsggridview.cpp
@@ -110,9 +110,12 @@ private slots:
void columnCount();
void margins();
void creationContext();
+ void snapToRow_data();
+ void snapToRow();
private:
QSGView *createView();
+ void flick(QSGView *canvas, const QPoint &from, const QPoint &to, int duration);
template<typename T>
T *findItem(QSGItem *parent, const QString &id, int index=-1);
template<typename T>
@@ -3121,6 +3124,101 @@ void tst_QSGGridView::creationContext()
QCOMPARE(item->property("text").toString(), QString("Hello!"));
}
+void tst_QSGGridView::snapToRow_data()
+{
+ QTest::addColumn<QSGGridView::Flow>("flow");
+ QTest::addColumn<Qt::LayoutDirection>("layoutDirection");
+ QTest::addColumn<int>("highlightRangeMode");
+ QTest::addColumn<QPoint>("flickStart");
+ QTest::addColumn<QPoint>("flickEnd");
+ QTest::addColumn<qreal>("snapAlignment");
+ QTest::addColumn<qreal>("endExtent");
+ QTest::addColumn<qreal>("startExtent");
+
+ QTest::newRow("vertical, left to right") << QSGGridView::LeftToRight << Qt::LeftToRight << int(QSGItemView::NoHighlightRange)
+ << QPoint(20, 200) << QPoint(20, 20) << 60.0 << 1200.0 << 0.0;
+
+ QTest::newRow("horizontal, left to right") << QSGGridView::TopToBottom << Qt::LeftToRight << int(QSGItemView::NoHighlightRange)
+ << QPoint(200, 20) << QPoint(20, 20) << 60.0 << 1200.0 << 0.0;
+
+ QTest::newRow("horizontal, right to left") << QSGGridView::TopToBottom << Qt::RightToLeft << int(QSGItemView::NoHighlightRange)
+ << QPoint(20, 20) << QPoint(200, 20) << -60.0 << -1200.0 - 240.0 << -240.0;
+
+ QTest::newRow("vertical, left to right, enforce range") << QSGGridView::LeftToRight << Qt::LeftToRight << int(QSGItemView::StrictlyEnforceRange)
+ << QPoint(20, 200) << QPoint(20, 20) << 60.0 << 1340.0 << -20.0;
+
+ QTest::newRow("horizontal, left to right, enforce range") << QSGGridView::TopToBottom << Qt::LeftToRight << int(QSGItemView::StrictlyEnforceRange)
+ << QPoint(200, 20) << QPoint(20, 20) << 60.0 << 1340.0 << -20.0;
+
+ QTest::newRow("horizontal, right to left, enforce range") << QSGGridView::TopToBottom << Qt::RightToLeft << int(QSGItemView::StrictlyEnforceRange)
+ << QPoint(20, 20) << QPoint(200, 20) << -60.0 << -1200.0 - 240.0 - 140.0 << -220.0;
+}
+
+void tst_QSGGridView::snapToRow()
+{
+ QFETCH(QSGGridView::Flow, flow);
+ QFETCH(Qt::LayoutDirection, layoutDirection);
+ QFETCH(int, highlightRangeMode);
+ QFETCH(QPoint, flickStart);
+ QFETCH(QPoint, flickEnd);
+ QFETCH(qreal, snapAlignment);
+ QFETCH(qreal, endExtent);
+ QFETCH(qreal, startExtent);
+
+ QSGView *canvas = createView();
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("snapToRow.qml")));
+ canvas->show();
+ qApp->processEvents();
+
+ QSGGridView *gridview = findItem<QSGGridView>(canvas->rootObject(), "grid");
+ QTRY_VERIFY(gridview != 0);
+
+ gridview->setFlow(flow);
+ gridview->setLayoutDirection(layoutDirection);
+ gridview->setHighlightRangeMode(QSGItemView::HighlightRangeMode(highlightRangeMode));
+
+ QSGItem *contentItem = gridview->contentItem();
+ QTRY_VERIFY(contentItem != 0);
+
+ // confirm that a flick hits an item boundary
+ flick(canvas, flickStart, flickEnd, 180);
+ QTRY_VERIFY(gridview->isMoving() == false); // wait until it stops
+ if (flow == QSGGridView::LeftToRight)
+ QCOMPARE(qreal(fmod(gridview->contentY(),80.0)), snapAlignment);
+ else
+ QCOMPARE(qreal(fmod(gridview->contentX(),80.0)), snapAlignment);
+
+ // flick to end
+ do {
+ flick(canvas, flickStart, flickEnd, 180);
+ QTRY_VERIFY(gridview->isMoving() == false); // wait until it stops
+ } while (flow == QSGGridView::LeftToRight
+ ? !gridview->isAtYEnd()
+ : layoutDirection == Qt::LeftToRight ? !gridview->isAtXEnd() : !gridview->isAtXBeginning());
+
+ if (flow == QSGGridView::LeftToRight)
+ QCOMPARE(gridview->contentY(), endExtent);
+ else
+ QCOMPARE(gridview->contentX(), endExtent);
+
+ // flick to start
+ do {
+ flick(canvas, flickEnd, flickStart, 180);
+ QTRY_VERIFY(gridview->isMoving() == false); // wait until it stops
+ } while (flow == QSGGridView::LeftToRight
+ ? !gridview->isAtYBeginning()
+ : layoutDirection == Qt::LeftToRight ? !gridview->isAtXBeginning() : !gridview->isAtXEnd());
+
+ if (flow == QSGGridView::LeftToRight)
+ QCOMPARE(gridview->contentY(), startExtent);
+ else
+ QCOMPARE(gridview->contentX(), startExtent);
+
+ delete canvas;
+}
+
+
QSGView *tst_QSGGridView::createView()
{
QSGView *canvas = new QSGView(0);
@@ -3129,6 +3227,24 @@ QSGView *tst_QSGGridView::createView()
return canvas;
}
+void tst_QSGGridView::flick(QSGView *canvas, const QPoint &from, const QPoint &to, int duration)
+{
+ const int pointCount = 5;
+ QPoint diff = to - from;
+
+ // send press, five equally spaced moves, and release.
+ QTest::mousePress(canvas, Qt::LeftButton, 0, from);
+
+ for (int i = 0; i < pointCount; ++i) {
+ QMouseEvent mv(QEvent::MouseMove, from + (i+1)*diff/pointCount, Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
+ QApplication::sendEvent(canvas, &mv);
+ QTest::qWait(duration/pointCount);
+ QCoreApplication::processEvents();
+ }
+
+ QTest::mouseRelease(canvas, Qt::LeftButton, 0, to);
+}
+
/*
Find an item with the specified objectName. If index is supplied then the
item must also evaluate the {index} expression equal to index
diff --git a/tests/auto/declarative/qsglistview/data/snapToItem.qml b/tests/auto/declarative/qsglistview/data/snapToItem.qml
new file mode 100644
index 0000000000..6f201072f0
--- /dev/null
+++ b/tests/auto/declarative/qsglistview/data/snapToItem.qml
@@ -0,0 +1,49 @@
+import QtQuick 2.0
+
+Rectangle {
+ id: root
+ width: 240
+ height: 240
+ color: "#ffffff"
+
+ Component {
+ id: myDelegate
+ Rectangle {
+ id: wrapper
+ objectName: "wrapper"
+ height: 80
+ width: 80
+ Column {
+ Text {
+ text: index
+ }
+ Text {
+ text: wrapper.x + ", " + wrapper.y
+ }
+ }
+ color: ListView.isCurrentItem ? "lightsteelblue" : "transparent"
+ }
+ }
+ ListView {
+ id: list
+ objectName: "list"
+ anchors.fill: parent
+// preferredHighlightBegin: 20
+// preferredHighlightEnd: 100
+ preferredHighlightBegin: 20
+ preferredHighlightEnd: 100
+ snapMode: ListView.SnapToItem
+ orientation: ListView.Horizontal
+ layoutDirection: Qt.RightToLeft
+ highlightRangeMode: ListView.StrictlyEnforceRange
+ highlight: Rectangle { width: 80; height: 80; color: "yellow" }
+ model: 18
+ delegate: myDelegate
+ }
+
+ Text {
+ anchors.right: parent.right
+ anchors.bottom: parent.bottom
+ text: list.contentX + ", " + list.contentY
+ }
+}
diff --git a/tests/auto/declarative/qsglistview/tst_qsglistview.cpp b/tests/auto/declarative/qsglistview/tst_qsglistview.cpp
index 386a03b81a..be297122ba 100644
--- a/tests/auto/declarative/qsglistview/tst_qsglistview.cpp
+++ b/tests/auto/declarative/qsglistview/tst_qsglistview.cpp
@@ -55,6 +55,7 @@
#include "../shared/util.h"
#include "../../../shared/util.h"
#include "incrementalmodel.h"
+#include <math.h>
Q_DECLARE_METATYPE(Qt::LayoutDirection)
Q_DECLARE_METATYPE(QSGListView::Orientation)
@@ -139,6 +140,8 @@ private slots:
void test_mirroring();
void margins();
void creationContext();
+ void snapToItem_data();
+ void snapToItem();
private:
template <class T> void items();
@@ -149,6 +152,7 @@ private:
template <class T> void moved();
template <class T> void clear();
QSGView *createView();
+ void flick(QSGView *canvas, const QPoint &from, const QPoint &to, int duration);
QSGItem *findVisibleChild(QSGItem *parent, const QString &objectName);
template<typename T>
T *findItem(QSGItem *parent, const QString &id, int index=-1);
@@ -3800,6 +3804,100 @@ void tst_QSGListView::margins()
delete canvas;
}
+void tst_QSGListView::snapToItem_data()
+{
+ QTest::addColumn<QSGListView::Orientation>("orientation");
+ QTest::addColumn<Qt::LayoutDirection>("layoutDirection");
+ QTest::addColumn<int>("highlightRangeMode");
+ QTest::addColumn<QPoint>("flickStart");
+ QTest::addColumn<QPoint>("flickEnd");
+ QTest::addColumn<qreal>("snapAlignment");
+ QTest::addColumn<qreal>("endExtent");
+ QTest::addColumn<qreal>("startExtent");
+
+ QTest::newRow("vertical, left to right") << QSGListView::Vertical << Qt::LeftToRight << int(QSGItemView::NoHighlightRange)
+ << QPoint(20, 200) << QPoint(20, 20) << 60.0 << 1200.0 << 0.0;
+
+ QTest::newRow("horizontal, left to right") << QSGListView::Horizontal << Qt::LeftToRight << int(QSGItemView::NoHighlightRange)
+ << QPoint(200, 20) << QPoint(20, 20) << 60.0 << 1200.0 << 0.0;
+
+ QTest::newRow("horizontal, right to left") << QSGListView::Horizontal << Qt::RightToLeft << int(QSGItemView::NoHighlightRange)
+ << QPoint(20, 20) << QPoint(200, 20) << -60.0 << -1200.0 - 240.0 << -240.0;
+
+ QTest::newRow("vertical, left to right, enforce range") << QSGListView::Vertical << Qt::LeftToRight << int(QSGItemView::StrictlyEnforceRange)
+ << QPoint(20, 200) << QPoint(20, 20) << 60.0 << 1340.0 << -20.0;
+
+ QTest::newRow("horizontal, left to right, enforce range") << QSGListView::Horizontal << Qt::LeftToRight << int(QSGItemView::StrictlyEnforceRange)
+ << QPoint(200, 20) << QPoint(20, 20) << 60.0 << 1340.0 << -20.0;
+
+ QTest::newRow("horizontal, right to left, enforce range") << QSGListView::Horizontal << Qt::RightToLeft << int(QSGItemView::StrictlyEnforceRange)
+ << QPoint(20, 20) << QPoint(200, 20) << -60.0 << -1200.0 - 240.0 - 140.0 << -220.0;
+}
+
+void tst_QSGListView::snapToItem()
+{
+ QFETCH(QSGListView::Orientation, orientation);
+ QFETCH(Qt::LayoutDirection, layoutDirection);
+ QFETCH(int, highlightRangeMode);
+ QFETCH(QPoint, flickStart);
+ QFETCH(QPoint, flickEnd);
+ QFETCH(qreal, snapAlignment);
+ QFETCH(qreal, endExtent);
+ QFETCH(qreal, startExtent);
+
+ QSGView *canvas = createView();
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("snapToItem.qml")));
+ canvas->show();
+ qApp->processEvents();
+
+ QSGListView *listview = findItem<QSGListView>(canvas->rootObject(), "list");
+ QTRY_VERIFY(listview != 0);
+
+ listview->setOrientation(orientation);
+ listview->setLayoutDirection(layoutDirection);
+ listview->setHighlightRangeMode(QSGItemView::HighlightRangeMode(highlightRangeMode));
+
+ QSGItem *contentItem = listview->contentItem();
+ QTRY_VERIFY(contentItem != 0);
+
+ // confirm that a flick hits an item boundary
+ flick(canvas, flickStart, flickEnd, 180);
+ QTRY_VERIFY(listview->isMoving() == false); // wait until it stops
+ if (orientation == QSGListView::Vertical)
+ QCOMPARE(qreal(fmod(listview->contentY(),80.0)), snapAlignment);
+ else
+ QCOMPARE(qreal(fmod(listview->contentX(),80.0)), snapAlignment);
+
+ // flick to end
+ do {
+ flick(canvas, flickStart, flickEnd, 180);
+ QTRY_VERIFY(listview->isMoving() == false); // wait until it stops
+ } while (orientation == QSGListView::Vertical
+ ? !listview->isAtYEnd()
+ : layoutDirection == Qt::LeftToRight ? !listview->isAtXEnd() : !listview->isAtXBeginning());
+
+ if (orientation == QSGListView::Vertical)
+ QCOMPARE(listview->contentY(), endExtent);
+ else
+ QCOMPARE(listview->contentX(), endExtent);
+
+ // flick to start
+ do {
+ flick(canvas, flickEnd, flickStart, 180);
+ QTRY_VERIFY(listview->isMoving() == false); // wait until it stops
+ } while (orientation == QSGListView::Vertical
+ ? !listview->isAtYBeginning()
+ : layoutDirection == Qt::LeftToRight ? !listview->isAtXBeginning() : !listview->isAtXEnd());
+
+ if (orientation == QSGListView::Vertical)
+ QCOMPARE(listview->contentY(), startExtent);
+ else
+ QCOMPARE(listview->contentX(), startExtent);
+
+ delete canvas;
+}
+
void tst_QSGListView::qListModelInterface_items()
{
items<TestModel>();
@@ -3922,6 +4020,25 @@ QSGView *tst_QSGListView::createView()
return canvas;
}
+void tst_QSGListView::flick(QSGView *canvas, const QPoint &from, const QPoint &to, int duration)
+{
+ const int pointCount = 5;
+ QPoint diff = to - from;
+
+ // send press, five equally spaced moves, and release.
+ QTest::mousePress(canvas, Qt::LeftButton, 0, from);
+
+ for (int i = 0; i < pointCount; ++i) {
+ QMouseEvent mv(QEvent::MouseMove, from + (i+1)*diff/pointCount, Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
+ QApplication::sendEvent(canvas, &mv);
+ QTest::qWait(duration/pointCount);
+ QCoreApplication::processEvents();
+ }
+
+ QTest::mouseRelease(canvas, Qt::LeftButton, 0, to);
+}
+
+
QSGItem *tst_QSGListView::findVisibleChild(QSGItem *parent, const QString &objectName)
{
QSGItem *item = 0;