Cannot flick to the end of a horizontal ListView with LayoutMirroring
Forward port of fix for QTBUG-21756. minXExtent calculated the offset due to highlight range incorrectly (reversed) when mirroring enabled. Also us same algorithm for fixup() in GridView and ListView uses. For QtQuick 2, this change also reverses the beginning and end highlight range, as it should be, i.e. the preferredHighlightBegin is from the right side in RightToLeft mode. Also added snapping tests. Task-number: QTBUG-21756 Change-Id: Ica0ba4ab5db0ce9c77f2da75e9f8293550bd37d1 Reviewed-by: Martin Jones <martin.jones@nokia.com>
This commit is contained in:
parent
063c08ab82
commit
9bd6361400
|
@ -117,8 +117,9 @@ Text improvements:
|
||||||
|
|
||||||
PathView now has a \c currentItem property
|
PathView now has a \c currentItem property
|
||||||
|
|
||||||
ListView and GridView now have headerItem and footerItem properties (the instantiated
|
ListView and GridView:
|
||||||
header and footer items).
|
- 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
|
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.
|
at the start and/or next section label at the end of the view.
|
||||||
|
|
|
@ -334,7 +334,10 @@ qreal QSGGridViewPrivate::snapPosAt(qreal pos) const
|
||||||
Q_Q(const QSGGridView);
|
Q_Q(const QSGGridView);
|
||||||
qreal snapPos = 0;
|
qreal snapPos = 0;
|
||||||
if (!visibleItems.isEmpty()) {
|
if (!visibleItems.isEmpty()) {
|
||||||
qreal highlightStart = isRightToLeftTopToBottom() && highlightRangeStartValid ? size()-highlightRangeEnd : highlightRangeStart;
|
qreal highlightStart = highlightRangeStart;
|
||||||
|
if (isRightToLeftTopToBottom())
|
||||||
|
highlightStart = highlightRangeEndValid ? -size() + highlightRangeEnd : -size();
|
||||||
|
|
||||||
pos += highlightStart;
|
pos += highlightStart;
|
||||||
pos += rowSize()/2;
|
pos += rowSize()/2;
|
||||||
snapPos = static_cast<FxGridItemSG*>(visibleItems.first())->rowPos() - visibleIndex / columns * rowSize();
|
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;
|
fixupMode = moveReason == Mouse ? fixupMode : Immediate;
|
||||||
|
|
||||||
qreal highlightStart;
|
qreal viewPos = isRightToLeftTopToBottom() ? -position()-size() : position();
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool strictHighlightRange = haveHighlightRange && highlightRange == QSGGridView::StrictlyEnforceRange;
|
bool strictHighlightRange = haveHighlightRange && highlightRange == QSGGridView::StrictlyEnforceRange;
|
||||||
if (snapMode != QSGGridView::NoSnap) {
|
if (snapMode != QSGGridView::NoSnap) {
|
||||||
|
@ -836,40 +827,35 @@ void QSGGridViewPrivate::fixup(AxisData &data, qreal minExtent, qreal maxExtent)
|
||||||
bias = -bias;
|
bias = -bias;
|
||||||
tempPosition -= bias;
|
tempPosition -= bias;
|
||||||
}
|
}
|
||||||
FxViewItem *topItem = snapItemAt(tempPosition+highlightStart);
|
FxViewItem *topItem = snapItemAt(tempPosition+highlightRangeStart);
|
||||||
if (!topItem && strictHighlightRange && currentItem) {
|
if (!topItem && strictHighlightRange && currentItem) {
|
||||||
// StrictlyEnforceRange always keeps an item in range
|
// StrictlyEnforceRange always keeps an item in range
|
||||||
updateHighlight();
|
updateHighlight();
|
||||||
topItem = currentItem;
|
topItem = currentItem;
|
||||||
}
|
}
|
||||||
FxViewItem *bottomItem = snapItemAt(tempPosition+highlightEnd);
|
FxViewItem *bottomItem = snapItemAt(tempPosition+highlightRangeEnd);
|
||||||
if (!bottomItem && strictHighlightRange && currentItem) {
|
if (!bottomItem && strictHighlightRange && currentItem) {
|
||||||
// StrictlyEnforceRange always keeps an item in range
|
// StrictlyEnforceRange always keeps an item in range
|
||||||
updateHighlight();
|
updateHighlight();
|
||||||
bottomItem = currentItem;
|
bottomItem = currentItem;
|
||||||
}
|
}
|
||||||
qreal pos;
|
qreal pos;
|
||||||
if (topItem && bottomItem && strictHighlightRange) {
|
bool isInBounds = -position() > maxExtent && -position() <= minExtent;
|
||||||
qreal topPos = qMin(topItem->position() - highlightStart, -maxExtent);
|
if (topItem && (isInBounds || strictHighlightRange)) {
|
||||||
qreal bottomPos = qMax(bottomItem->position() - highlightEnd, -minExtent);
|
qreal headerPos = header ? static_cast<FxGridItemSG*>(header)->rowPos() : 0;
|
||||||
pos = qAbs(data.move + topPos) < qAbs(data.move + bottomPos) ? topPos : bottomPos;
|
if (topItem->index == 0 && header && tempPosition+highlightRangeStart < headerPos+headerSize()/2 && !strictHighlightRange) {
|
||||||
} else if (topItem) {
|
pos = isRightToLeftTopToBottom() ? - headerPos + highlightRangeStart - size() : headerPos - highlightRangeStart;
|
||||||
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;
|
|
||||||
} else {
|
} else {
|
||||||
if (isRightToLeftTopToBottom())
|
if (isRightToLeftTopToBottom())
|
||||||
pos = qMax(qMin(-topItem->position() + highlightStart - size(), -maxExtent), -minExtent);
|
pos = qMax(qMin(-topItem->position() + highlightRangeStart - size(), -maxExtent), -minExtent);
|
||||||
else
|
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())
|
if (isRightToLeftTopToBottom())
|
||||||
pos = qMax(qMin(-bottomItem->position() + highlightEnd - size(), -maxExtent), -minExtent);
|
pos = qMax(qMin(-bottomItem->position() + highlightRangeEnd - size(), -maxExtent), -minExtent);
|
||||||
else
|
else
|
||||||
pos = qMax(qMin(bottomItem->position() - highlightEnd, -maxExtent), -minExtent);
|
pos = qMax(qMin(bottomItem->position() - highlightRangeEnd, -maxExtent), -minExtent);
|
||||||
} else {
|
} else {
|
||||||
QSGItemViewPrivate::fixup(data, minExtent, maxExtent);
|
QSGItemViewPrivate::fixup(data, minExtent, maxExtent);
|
||||||
return;
|
return;
|
||||||
|
@ -890,10 +876,10 @@ void QSGGridViewPrivate::fixup(AxisData &data, qreal minExtent, qreal maxExtent)
|
||||||
if (currentItem) {
|
if (currentItem) {
|
||||||
updateHighlight();
|
updateHighlight();
|
||||||
qreal pos = static_cast<FxGridItemSG*>(currentItem)->rowPos();
|
qreal pos = static_cast<FxGridItemSG*>(currentItem)->rowPos();
|
||||||
if (viewPos < pos + rowSize() - highlightEnd)
|
if (viewPos < pos + rowSize() - highlightRangeEnd)
|
||||||
viewPos = pos + rowSize() - highlightEnd;
|
viewPos = pos + rowSize() - highlightRangeEnd;
|
||||||
if (viewPos > pos - highlightStart)
|
if (viewPos > pos - highlightRangeStart)
|
||||||
viewPos = pos - highlightStart;
|
viewPos = pos - highlightRangeStart;
|
||||||
if (isRightToLeftTopToBottom())
|
if (isRightToLeftTopToBottom())
|
||||||
viewPos = -viewPos-size();
|
viewPos = -viewPos-size();
|
||||||
timeline.reset(data.move);
|
timeline.reset(data.move);
|
||||||
|
@ -1543,22 +1529,11 @@ void QSGGridView::viewportMoved()
|
||||||
if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange && d->highlight) {
|
if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange && d->highlight) {
|
||||||
// reposition highlight
|
// reposition highlight
|
||||||
qreal pos = d->highlight->position();
|
qreal pos = d->highlight->position();
|
||||||
qreal viewPos;
|
qreal viewPos = d->isRightToLeftTopToBottom() ? -d->position()-d->size() : d->position();
|
||||||
qreal highlightStart;
|
if (pos > viewPos + d->highlightRangeEnd - d->highlight->size())
|
||||||
qreal highlightEnd;
|
pos = viewPos + d->highlightRangeEnd - d->highlight->size();
|
||||||
if (d->isRightToLeftTopToBottom()) {
|
if (pos < viewPos + d->highlightRangeStart)
|
||||||
viewPos = -d->position()-d->size();
|
pos = viewPos + d->highlightRangeStart;
|
||||||
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;
|
|
||||||
|
|
||||||
if (pos != d->highlight->position()) {
|
if (pos != d->highlight->position()) {
|
||||||
d->highlightXAnimator->stop();
|
d->highlightXAnimator->stop();
|
||||||
|
|
|
@ -821,30 +821,14 @@ void QSGItemView::trackedPositionChanged()
|
||||||
if (d->trackedItem != d->currentItem) {
|
if (d->trackedItem != d->currentItem) {
|
||||||
trackedSize += d->currentItem->sectionSize();
|
trackedSize += d->currentItem->sectionSize();
|
||||||
}
|
}
|
||||||
qreal viewPos;
|
qreal viewPos = d->isContentFlowReversed() ? -d->position()-d->size() : d->position();
|
||||||
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 pos = viewPos;
|
qreal pos = viewPos;
|
||||||
if (d->haveHighlightRange) {
|
if (d->haveHighlightRange) {
|
||||||
if (d->highlightRange == StrictlyEnforceRange) {
|
if (trackedPos > pos + d->highlightRangeEnd - trackedSize)
|
||||||
if (trackedPos > pos + highlightEnd - d->trackedItem->size())
|
pos = trackedPos - d->highlightRangeEnd + trackedSize;
|
||||||
pos = trackedPos - highlightEnd + d->trackedItem->size();
|
if (trackedPos < pos + d->highlightRangeStart)
|
||||||
if (trackedPos < pos + highlightStart)
|
pos = trackedPos - d->highlightRangeStart;
|
||||||
pos = trackedPos - highlightStart;
|
if (d->highlightRange != StrictlyEnforceRange) {
|
||||||
} else {
|
|
||||||
if (trackedPos > pos + highlightEnd - trackedSize)
|
|
||||||
pos = trackedPos - highlightEnd + trackedSize;
|
|
||||||
if (trackedPos < pos + highlightStart)
|
|
||||||
pos = trackedPos - highlightStart;
|
|
||||||
if (pos > d->endPosition() - d->size())
|
if (pos > d->endPosition() - d->size())
|
||||||
pos = d->endPosition() - d->size();
|
pos = d->endPosition() - d->size();
|
||||||
if (pos < d->startPosition())
|
if (pos < d->startPosition())
|
||||||
|
@ -967,10 +951,8 @@ qreal QSGItemView::minXExtent() const
|
||||||
endPositionFirstItem = d->positionAt(d->model->count()-1);
|
endPositionFirstItem = d->positionAt(d->model->count()-1);
|
||||||
else if (d->header)
|
else if (d->header)
|
||||||
d->minExtent += d->headerSize();
|
d->minExtent += d->headerSize();
|
||||||
highlightStart = d->highlightRangeStartValid
|
highlightStart = d->highlightRangeEndValid ? d->size() - d->highlightRangeEnd : d->size();
|
||||||
? d->highlightRangeStart - (d->lastPosition()-endPositionFirstItem)
|
highlightEnd = d->highlightRangeStartValid ? d->size() - d->highlightRangeStart : d->size();
|
||||||
: d->size() - (d->lastPosition()-endPositionFirstItem);
|
|
||||||
highlightEnd = d->highlightRangeEndValid ? d->highlightRangeEnd : d->size();
|
|
||||||
if (d->footer)
|
if (d->footer)
|
||||||
d->minExtent += d->footerSize();
|
d->minExtent += d->footerSize();
|
||||||
qreal maxX = maxXExtent();
|
qreal maxX = maxXExtent();
|
||||||
|
@ -986,7 +968,9 @@ qreal QSGItemView::minXExtent() const
|
||||||
}
|
}
|
||||||
if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
|
if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
|
||||||
d->minExtent += highlightStart;
|
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;
|
d->hData.minExtentDirty = false;
|
||||||
}
|
}
|
||||||
|
@ -1006,8 +990,8 @@ qreal QSGItemView::maxXExtent() const
|
||||||
qreal lastItemPosition = 0;
|
qreal lastItemPosition = 0;
|
||||||
d->maxExtent = 0;
|
d->maxExtent = 0;
|
||||||
if (d->isContentFlowReversed()) {
|
if (d->isContentFlowReversed()) {
|
||||||
highlightStart = d->highlightRangeStartValid ? d->highlightRangeEnd : d->size();
|
highlightStart = d->highlightRangeEndValid ? d->size() - d->highlightRangeEnd : d->size();
|
||||||
highlightEnd = d->highlightRangeEndValid ? d->highlightRangeStart : d->size();
|
highlightEnd = d->highlightRangeStartValid ? d->size() - d->highlightRangeStart : d->size();
|
||||||
lastItemPosition = d->endPosition();
|
lastItemPosition = d->endPosition();
|
||||||
} else {
|
} else {
|
||||||
highlightStart = d->highlightRangeStart;
|
highlightStart = d->highlightRangeStart;
|
||||||
|
|
|
@ -1251,19 +1251,7 @@ void QSGListViewPrivate::fixup(AxisData &data, qreal minExtent, qreal maxExtent)
|
||||||
fixupMode = moveReason == Mouse ? fixupMode : Immediate;
|
fixupMode = moveReason == Mouse ? fixupMode : Immediate;
|
||||||
bool strictHighlightRange = haveHighlightRange && highlightRange == QSGListView::StrictlyEnforceRange;
|
bool strictHighlightRange = haveHighlightRange && highlightRange == QSGListView::StrictlyEnforceRange;
|
||||||
|
|
||||||
qreal highlightStart;
|
qreal viewPos = isRightToLeft() ? -position()-size() : position();
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (snapMode != QSGListView::NoSnap && moveReason != QSGListViewPrivate::SetIndex) {
|
if (snapMode != QSGListView::NoSnap && moveReason != QSGListViewPrivate::SetIndex) {
|
||||||
qreal tempPosition = isRightToLeft() ? -position()-size() : position();
|
qreal tempPosition = isRightToLeft() ? -position()-size() : position();
|
||||||
|
@ -1279,13 +1267,13 @@ void QSGListViewPrivate::fixup(AxisData &data, qreal minExtent, qreal maxExtent)
|
||||||
bias = -bias;
|
bias = -bias;
|
||||||
tempPosition -= bias;
|
tempPosition -= bias;
|
||||||
}
|
}
|
||||||
FxViewItem *topItem = snapItemAt(tempPosition+highlightStart);
|
FxViewItem *topItem = snapItemAt(tempPosition+highlightRangeStart);
|
||||||
if (!topItem && strictHighlightRange && currentItem) {
|
if (!topItem && strictHighlightRange && currentItem) {
|
||||||
// StrictlyEnforceRange always keeps an item in range
|
// StrictlyEnforceRange always keeps an item in range
|
||||||
updateHighlight();
|
updateHighlight();
|
||||||
topItem = currentItem;
|
topItem = currentItem;
|
||||||
}
|
}
|
||||||
FxViewItem *bottomItem = snapItemAt(tempPosition+highlightEnd);
|
FxViewItem *bottomItem = snapItemAt(tempPosition+highlightRangeEnd);
|
||||||
if (!bottomItem && strictHighlightRange && currentItem) {
|
if (!bottomItem && strictHighlightRange && currentItem) {
|
||||||
// StrictlyEnforceRange always keeps an item in range
|
// StrictlyEnforceRange always keeps an item in range
|
||||||
updateHighlight();
|
updateHighlight();
|
||||||
|
@ -1294,19 +1282,19 @@ void QSGListViewPrivate::fixup(AxisData &data, qreal minExtent, qreal maxExtent)
|
||||||
qreal pos;
|
qreal pos;
|
||||||
bool isInBounds = -position() > maxExtent && -position() <= minExtent;
|
bool isInBounds = -position() > maxExtent && -position() <= minExtent;
|
||||||
if (topItem && (isInBounds || strictHighlightRange)) {
|
if (topItem && (isInBounds || strictHighlightRange)) {
|
||||||
if (topItem->index == 0 && header && tempPosition+highlightStart < header->position()+header->size()/2 && !strictHighlightRange) {
|
if (topItem->index == 0 && header && tempPosition+highlightRangeStart < header->position()+header->size()/2 && !strictHighlightRange) {
|
||||||
pos = isRightToLeft() ? - header->position() + highlightStart - size() : header->position() - highlightStart;
|
pos = isRightToLeft() ? - header->position() + highlightRangeStart - size() : header->position() - highlightRangeStart;
|
||||||
} else {
|
} else {
|
||||||
if (isRightToLeft())
|
if (isRightToLeft())
|
||||||
pos = qMax(qMin(-topItem->position() + highlightStart - size(), -maxExtent), -minExtent);
|
pos = qMax(qMin(-topItem->position() + highlightRangeStart - size(), -maxExtent), -minExtent);
|
||||||
else
|
else
|
||||||
pos = qMax(qMin(topItem->position() - highlightStart, -maxExtent), -minExtent);
|
pos = qMax(qMin(topItem->position() - highlightRangeStart, -maxExtent), -minExtent);
|
||||||
}
|
}
|
||||||
} else if (bottomItem && isInBounds) {
|
} else if (bottomItem && isInBounds) {
|
||||||
if (isRightToLeft())
|
if (isRightToLeft())
|
||||||
pos = qMax(qMin(-bottomItem->position() + highlightEnd - size(), -maxExtent), -minExtent);
|
pos = qMax(qMin(-bottomItem->position() + highlightRangeEnd - size(), -maxExtent), -minExtent);
|
||||||
else
|
else
|
||||||
pos = qMax(qMin(bottomItem->position() - highlightEnd, -maxExtent), -minExtent);
|
pos = qMax(qMin(bottomItem->position() - highlightRangeEnd, -maxExtent), -minExtent);
|
||||||
} else {
|
} else {
|
||||||
QSGItemViewPrivate::fixup(data, minExtent, maxExtent);
|
QSGItemViewPrivate::fixup(data, minExtent, maxExtent);
|
||||||
return;
|
return;
|
||||||
|
@ -1326,10 +1314,10 @@ void QSGListViewPrivate::fixup(AxisData &data, qreal minExtent, qreal maxExtent)
|
||||||
} else if (currentItem && strictHighlightRange && moveReason != QSGListViewPrivate::SetIndex) {
|
} else if (currentItem && strictHighlightRange && moveReason != QSGListViewPrivate::SetIndex) {
|
||||||
updateHighlight();
|
updateHighlight();
|
||||||
qreal pos = static_cast<FxListItemSG*>(currentItem)->itemPosition();
|
qreal pos = static_cast<FxListItemSG*>(currentItem)->itemPosition();
|
||||||
if (viewPos < pos + static_cast<FxListItemSG*>(currentItem)->itemSize() - highlightEnd)
|
if (viewPos < pos + static_cast<FxListItemSG*>(currentItem)->itemSize() - highlightRangeEnd)
|
||||||
viewPos = pos + static_cast<FxListItemSG*>(currentItem)->itemSize() - highlightEnd;
|
viewPos = pos + static_cast<FxListItemSG*>(currentItem)->itemSize() - highlightRangeEnd;
|
||||||
if (viewPos > pos - highlightStart)
|
if (viewPos > pos - highlightRangeStart)
|
||||||
viewPos = pos - highlightStart;
|
viewPos = pos - highlightRangeStart;
|
||||||
if (isRightToLeft())
|
if (isRightToLeft())
|
||||||
viewPos = -viewPos-size();
|
viewPos = -viewPos-size();
|
||||||
|
|
||||||
|
@ -1364,7 +1352,7 @@ void QSGListViewPrivate::flick(AxisData &data, qreal minExtent, qreal maxExtent,
|
||||||
}
|
}
|
||||||
qreal maxDistance = 0;
|
qreal maxDistance = 0;
|
||||||
qreal dataValue = isRightToLeft() ? -data.move.value()+size() : data.move.value();
|
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
|
// -ve velocity means list is moving up/left
|
||||||
if (velocity > 0) {
|
if (velocity > 0) {
|
||||||
if (data.move.value() < minExtent) {
|
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;
|
qreal bias = dist < averageSize/2 ? averageSize/2 : 0;
|
||||||
if (isRightToLeft())
|
if (isRightToLeft())
|
||||||
bias = -bias;
|
bias = -bias;
|
||||||
data.flickTarget = -snapPosAt(-(dataValue - highlightStart) - bias) + highlightStart;
|
data.flickTarget = -snapPosAt(-(dataValue - highlightRangeStart) - bias) + highlightRangeStart;
|
||||||
maxDistance = qAbs(data.flickTarget - data.move.value());
|
maxDistance = qAbs(data.flickTarget - data.move.value());
|
||||||
velocity = maxVelocity;
|
velocity = maxVelocity;
|
||||||
} else {
|
} else {
|
||||||
|
@ -1391,7 +1379,7 @@ void QSGListViewPrivate::flick(AxisData &data, qreal minExtent, qreal maxExtent,
|
||||||
qreal bias = -dist < averageSize/2 ? averageSize/2 : 0;
|
qreal bias = -dist < averageSize/2 ? averageSize/2 : 0;
|
||||||
if (isRightToLeft())
|
if (isRightToLeft())
|
||||||
bias = -bias;
|
bias = -bias;
|
||||||
data.flickTarget = -snapPosAt(-(dataValue - highlightStart) + bias) + highlightStart;
|
data.flickTarget = -snapPosAt(-(dataValue - highlightRangeStart) + bias) + highlightRangeStart;
|
||||||
maxDistance = qAbs(data.flickTarget - data.move.value());
|
maxDistance = qAbs(data.flickTarget - data.move.value());
|
||||||
velocity = -maxVelocity;
|
velocity = -maxVelocity;
|
||||||
} else {
|
} 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 ((maxDistance > 0.0 && v2 / (2.0f * maxDistance) < accel) || snapMode == QSGListView::SnapOneItem) {
|
||||||
if (snapMode != QSGListView::SnapOneItem) {
|
if (snapMode != QSGListView::SnapOneItem) {
|
||||||
qreal distTemp = isRightToLeft() ? -dist : dist;
|
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;
|
data.flickTarget = isRightToLeft() ? -data.flickTarget+size() : data.flickTarget;
|
||||||
if (overShoot) {
|
if (overShoot) {
|
||||||
|
@ -1484,7 +1472,7 @@ void QSGListViewPrivate::flick(AxisData &data, qreal minExtent, qreal maxExtent,
|
||||||
qreal newtarget = data.flickTarget;
|
qreal newtarget = data.flickTarget;
|
||||||
if (snapMode != QSGListView::NoSnap || highlightRange == QSGListView::StrictlyEnforceRange) {
|
if (snapMode != QSGListView::NoSnap || highlightRange == QSGListView::StrictlyEnforceRange) {
|
||||||
qreal tempFlickTarget = isRightToLeft() ? -data.flickTarget+size() : data.flickTarget;
|
qreal tempFlickTarget = isRightToLeft() ? -data.flickTarget+size() : data.flickTarget;
|
||||||
newtarget = -snapPosAt(-(tempFlickTarget - highlightStart)) + highlightStart;
|
newtarget = -snapPosAt(-(tempFlickTarget - highlightRangeStart)) + highlightRangeStart;
|
||||||
newtarget = isRightToLeft() ? -newtarget+size() : newtarget;
|
newtarget = isRightToLeft() ? -newtarget+size() : newtarget;
|
||||||
}
|
}
|
||||||
if (velocity < 0 && newtarget <= maxExtent)
|
if (velocity < 0 && newtarget <= maxExtent)
|
||||||
|
@ -2167,23 +2155,11 @@ void QSGListView::viewportMoved()
|
||||||
if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange && d->highlight) {
|
if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange && d->highlight) {
|
||||||
// reposition highlight
|
// reposition highlight
|
||||||
qreal pos = d->highlight->position();
|
qreal pos = d->highlight->position();
|
||||||
qreal viewPos;
|
qreal viewPos = d->isRightToLeft() ? -d->position()-d->size() : d->position();
|
||||||
qreal highlightStart;
|
if (pos > viewPos + d->highlightRangeEnd - d->highlight->size())
|
||||||
qreal highlightEnd;
|
pos = viewPos + d->highlightRangeEnd - d->highlight->size();
|
||||||
if (d->isRightToLeft()) {
|
if (pos < viewPos + d->highlightRangeStart)
|
||||||
// Handle Right-To-Left exceptions
|
pos = viewPos + d->highlightRangeStart;
|
||||||
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;
|
|
||||||
if (pos != d->highlight->position()) {
|
if (pos != d->highlight->position()) {
|
||||||
d->highlightPosAnimator->stop();
|
d->highlightPosAnimator->stop();
|
||||||
static_cast<FxListItemSG*>(d->highlight)->setPosition(pos);
|
static_cast<FxListItemSG*>(d->highlight)->setPosition(pos);
|
||||||
|
|
|
@ -1095,23 +1095,17 @@ void QDeclarative1GridViewPrivate::fixup(AxisData &data, qreal minExtent, qreal
|
||||||
bottomItem = currentItem;
|
bottomItem = currentItem;
|
||||||
}
|
}
|
||||||
qreal pos;
|
qreal pos;
|
||||||
if (topItem && bottomItem && strictHighlightRange) {
|
bool isInBounds = -position() > maxExtent && -position() <= minExtent;
|
||||||
qreal topPos = qMin(topItem->rowPos() - highlightStart, -maxExtent);
|
if (topItem && (isInBounds || strictHighlightRange)) {
|
||||||
qreal bottomPos = qMax(bottomItem->rowPos() - highlightEnd, -minExtent);
|
if (topItem->index == 0 && header && tempPosition+highlightStart < header->rowPos()+headerSize()/2 && !strictHighlightRange) {
|
||||||
pos = qAbs(data.move + topPos) < qAbs(data.move + bottomPos) ? topPos : bottomPos;
|
pos = isRightToLeftTopToBottom() ? - header->rowPos() + highlightStart - size() : header->rowPos() - highlightStart;
|
||||||
} 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;
|
|
||||||
} else {
|
} else {
|
||||||
if (isRightToLeftTopToBottom())
|
if (isRightToLeftTopToBottom())
|
||||||
pos = qMax(qMin(-topItem->rowPos() + highlightStart - size(), -maxExtent), -minExtent);
|
pos = qMax(qMin(-topItem->rowPos() + highlightStart - size(), -maxExtent), -minExtent);
|
||||||
else
|
else
|
||||||
pos = qMax(qMin(topItem->rowPos() - highlightStart, -maxExtent), -minExtent);
|
pos = qMax(qMin(topItem->rowPos() - highlightStart, -maxExtent), -minExtent);
|
||||||
}
|
}
|
||||||
} else if (bottomItem) {
|
} else if (bottomItem && isInBounds) {
|
||||||
if (isRightToLeftTopToBottom())
|
if (isRightToLeftTopToBottom())
|
||||||
pos = qMax(qMin(-bottomItem->rowPos() + highlightEnd - size(), -maxExtent), -minExtent);
|
pos = qMax(qMin(-bottomItem->rowPos() + highlightEnd - size(), -maxExtent), -minExtent);
|
||||||
else
|
else
|
||||||
|
@ -2267,9 +2261,10 @@ qreal QDeclarative1GridView::minXExtent() const
|
||||||
qreal extent = -d->startPosition();
|
qreal extent = -d->startPosition();
|
||||||
qreal highlightStart;
|
qreal highlightStart;
|
||||||
qreal highlightEnd;
|
qreal highlightEnd;
|
||||||
qreal endPositionFirstItem;
|
qreal endPositionFirstItem = 0;
|
||||||
if (d->isRightToLeftTopToBottom()) {
|
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
|
highlightStart = d->highlightRangeStartValid
|
||||||
? d->highlightRangeStart - (d->lastPosition()-endPositionFirstItem)
|
? d->highlightRangeStart - (d->lastPosition()-endPositionFirstItem)
|
||||||
: d->size() - (d->lastPosition()-endPositionFirstItem);
|
: d->size() - (d->lastPosition()-endPositionFirstItem);
|
||||||
|
@ -2284,7 +2279,7 @@ qreal QDeclarative1GridView::minXExtent() const
|
||||||
extent += d->header->item->width();
|
extent += d->header->item->width();
|
||||||
}
|
}
|
||||||
if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
|
if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
|
||||||
extent += highlightStart;
|
extent += d->isRightToLeftTopToBottom() ? -highlightStart : highlightStart;
|
||||||
extent = qMax(extent, -(endPositionFirstItem - highlightEnd));
|
extent = qMax(extent, -(endPositionFirstItem - highlightEnd));
|
||||||
}
|
}
|
||||||
return extent;
|
return extent;
|
||||||
|
|
|
@ -2773,7 +2773,7 @@ qreal QDeclarative1ListView::minXExtent() const
|
||||||
d->minExtent += d->header->size();
|
d->minExtent += d->header->size();
|
||||||
}
|
}
|
||||||
if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
|
if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
|
||||||
d->minExtent += highlightStart;
|
d->minExtent += d->isRightToLeft() ? -highlightStart : highlightStart;
|
||||||
d->minExtent = qMax(d->minExtent, -(endPositionFirstItem - highlightEnd + 1));
|
d->minExtent = qMax(d->minExtent, -(endPositionFirstItem - highlightEnd + 1));
|
||||||
}
|
}
|
||||||
d->minExtentDirty = false;
|
d->minExtentDirty = false;
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
|
@ -110,9 +110,12 @@ private slots:
|
||||||
void columnCount();
|
void columnCount();
|
||||||
void margins();
|
void margins();
|
||||||
void creationContext();
|
void creationContext();
|
||||||
|
void snapToRow_data();
|
||||||
|
void snapToRow();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QSGView *createView();
|
QSGView *createView();
|
||||||
|
void flick(QSGView *canvas, const QPoint &from, const QPoint &to, int duration);
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T *findItem(QSGItem *parent, const QString &id, int index=-1);
|
T *findItem(QSGItem *parent, const QString &id, int index=-1);
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
@ -3121,6 +3124,101 @@ void tst_QSGGridView::creationContext()
|
||||||
QCOMPARE(item->property("text").toString(), QString("Hello!"));
|
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 *tst_QSGGridView::createView()
|
||||||
{
|
{
|
||||||
QSGView *canvas = new QSGView(0);
|
QSGView *canvas = new QSGView(0);
|
||||||
|
@ -3129,6 +3227,24 @@ QSGView *tst_QSGGridView::createView()
|
||||||
return canvas;
|
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
|
Find an item with the specified objectName. If index is supplied then the
|
||||||
item must also evaluate the {index} expression equal to index
|
item must also evaluate the {index} expression equal to index
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
|
@ -55,6 +55,7 @@
|
||||||
#include "../shared/util.h"
|
#include "../shared/util.h"
|
||||||
#include "../../../shared/util.h"
|
#include "../../../shared/util.h"
|
||||||
#include "incrementalmodel.h"
|
#include "incrementalmodel.h"
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(Qt::LayoutDirection)
|
Q_DECLARE_METATYPE(Qt::LayoutDirection)
|
||||||
Q_DECLARE_METATYPE(QSGListView::Orientation)
|
Q_DECLARE_METATYPE(QSGListView::Orientation)
|
||||||
|
@ -139,6 +140,8 @@ private slots:
|
||||||
void test_mirroring();
|
void test_mirroring();
|
||||||
void margins();
|
void margins();
|
||||||
void creationContext();
|
void creationContext();
|
||||||
|
void snapToItem_data();
|
||||||
|
void snapToItem();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template <class T> void items();
|
template <class T> void items();
|
||||||
|
@ -149,6 +152,7 @@ private:
|
||||||
template <class T> void moved();
|
template <class T> void moved();
|
||||||
template <class T> void clear();
|
template <class T> void clear();
|
||||||
QSGView *createView();
|
QSGView *createView();
|
||||||
|
void flick(QSGView *canvas, const QPoint &from, const QPoint &to, int duration);
|
||||||
QSGItem *findVisibleChild(QSGItem *parent, const QString &objectName);
|
QSGItem *findVisibleChild(QSGItem *parent, const QString &objectName);
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T *findItem(QSGItem *parent, const QString &id, int index=-1);
|
T *findItem(QSGItem *parent, const QString &id, int index=-1);
|
||||||
|
@ -3800,6 +3804,100 @@ void tst_QSGListView::margins()
|
||||||
delete canvas;
|
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()
|
void tst_QSGListView::qListModelInterface_items()
|
||||||
{
|
{
|
||||||
items<TestModel>();
|
items<TestModel>();
|
||||||
|
@ -3922,6 +4020,25 @@ QSGView *tst_QSGListView::createView()
|
||||||
return canvas;
|
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 *tst_QSGListView::findVisibleChild(QSGItem *parent, const QString &objectName)
|
||||||
{
|
{
|
||||||
QSGItem *item = 0;
|
QSGItem *item = 0;
|
||||||
|
|
Loading…
Reference in New Issue