From: Martin Jones Date: Mon, 26 Sep 2011 03:13:02 +0000 (+1000) Subject: Manually apply SnapOneItem/Row changes from Qt 4.7 X-Git-Url: http://git.silmor.de/gitweb/?a=commitdiff_plain;h=40864ee84e41d53c412dd1b350624dcde07b009a;p=konrad%2Fqtdeclarative.git Manually apply SnapOneItem/Row changes from Qt 4.7 Apply following changes to Qt 5 for both QtQuick1 and QtQuick2 items: cf23188de237009136fa1480ab8fd9e3ca364769 f85819fe083ae7c6804c884de68e906d153a6d11 09cd2f818208a83489fae034b80e6497b7cc83af Task-number: QTBUG-20683 Change-Id: I974764e57e3004514bb4c9f46c5152ad07c136a7 Reviewed-on: http://codereview.qt-project.org/5484 Reviewed-by: Bea Lam --- diff --git a/src/declarative/items/qsgflickable.cpp b/src/declarative/items/qsgflickable.cpp index 91a93b6..09bb8e3 100644 --- a/src/declarative/items/qsgflickable.cpp +++ b/src/declarative/items/qsgflickable.cpp @@ -171,9 +171,7 @@ QSGFlickablePrivate::QSGFlickablePrivate() : contentItem(new QSGItem) , hData(this, &QSGFlickablePrivate::setViewportX) , vData(this, &QSGFlickablePrivate::setViewportY) - , flickingHorizontally(false), flickingVertically(false) , hMoved(false), vMoved(false) - , movingHorizontally(false), movingVertically(false) , stealMouse(false), pressed(false), interactive(true), calcVelocity(false) , pixelAligned(false) , deceleration(QML_FLICK_DEFAULTDECELERATION) @@ -286,18 +284,18 @@ void QSGFlickablePrivate::flick(AxisData &data, qreal minExtent, qreal maxExtent else timeline.accel(data.move, v, deceleration, maxDistance); timeline.callback(QDeclarativeTimeLineCallback(&data.move, fixupCallback, this)); - if (!flickingHorizontally && q->xflick()) { - flickingHorizontally = true; + if (!hData.flicking && q->xflick()) { + hData.flicking = true; emit q->flickingChanged(); emit q->flickingHorizontallyChanged(); - if (!flickingVertically) + if (!vData.flicking) emit q->flickStarted(); } - if (!flickingVertically && q->yflick()) { - flickingVertically = true; + if (!vData.flicking && q->yflick()) { + vData.flicking = true; emit q->flickingChanged(); emit q->flickingVerticallyChanged(); - if (!flickingHorizontally) + if (!hData.flicking) emit q->flickStarted(); } } else { @@ -645,11 +643,11 @@ void QSGFlickable::setInteractive(bool interactive) Q_D(QSGFlickable); if (interactive != d->interactive) { d->interactive = interactive; - if (!interactive && (d->flickingHorizontally || d->flickingVertically)) { + if (!interactive && (d->hData.flicking || d->vData.flicking)) { d->timeline.clear(); d->vTime = d->timeline.time(); - d->flickingHorizontally = false; - d->flickingVertically = false; + d->hData.flicking = false; + d->vData.flicking = false; emit flickingChanged(); emit flickingHorizontallyChanged(); emit flickingVerticallyChanged(); @@ -819,8 +817,8 @@ void QSGFlickablePrivate::handleMousePressEvent(QMouseEvent *event) pressPos = event->localPos(); hData.pressPos = hData.move.value(); vData.pressPos = vData.move.value(); - flickingHorizontally = false; - flickingVertically = false; + hData.flicking = false; + vData.flicking = false; QSGItemPrivate::start(pressTime); QSGItemPrivate::start(velocityTime); } @@ -944,13 +942,10 @@ void QSGFlickablePrivate::handleMouseReleaseEvent(QMouseEvent *event) pressed = false; // if we drag then pause before release we should not cause a flick. - if (QSGItemPrivate::elapsed(lastPosTime) < 100) { - vData.updateVelocity(); - hData.updateVelocity(); - } else { - hData.velocity = 0.0; - vData.velocity = 0.0; - } + qint64 elapsed = QSGItemPrivate::elapsed(lastPosTime); + + vData.updateVelocity(); + hData.updateVelocity(); draggingEnding(); @@ -959,7 +954,7 @@ void QSGFlickablePrivate::handleMouseReleaseEvent(QMouseEvent *event) vTime = timeline.time(); - qreal velocity = vData.velocity; + qreal velocity = elapsed < 100 ? vData.velocity : 0; if (vData.atBeginning || vData.atEnd) velocity /= 2; if (q->yflick() && qAbs(velocity) > MinimumFlickVelocity && qAbs(event->localPos().y() - pressPos.y()) > FlickThreshold) { @@ -970,7 +965,7 @@ void QSGFlickablePrivate::handleMouseReleaseEvent(QMouseEvent *event) fixupY(); } - velocity = hData.velocity; + velocity = elapsed < 100 ? hData.velocity : 0; if (hData.atBeginning || hData.atEnd) velocity /= 2; if (q->xflick() && qAbs(velocity) > MinimumFlickVelocity && qAbs(event->localPos().x() - pressPos.x()) > FlickThreshold) { @@ -1036,9 +1031,9 @@ void QSGFlickable::wheelEvent(QWheelEvent *event) valid = true; } if (valid) { - d->flickingVertically = false; + d->vData.flicking = false; d->flickY(d->vData.velocity); - if (d->flickingVertically) { + if (d->vData.flicking) { d->vMoved = true; movementStarting(); } @@ -1054,9 +1049,9 @@ void QSGFlickable::wheelEvent(QWheelEvent *event) valid = true; } if (valid) { - d->flickingHorizontally = false; + d->hData.flicking = false; d->flickX(d->hData.velocity); - if (d->flickingHorizontally) { + if (d->hData.flicking) { d->hMoved = true; movementStarting(); } @@ -1202,7 +1197,7 @@ void QSGFlickable::viewportMoved() } } - if (!d->vData.inOvershoot && !d->vData.fixingUp && d->flickingVertically + if (!d->vData.inOvershoot && !d->vData.fixingUp && d->vData.flicking && (d->vData.move.value() > minYExtent() || d->vData.move.value() < maxYExtent()) && qAbs(d->vData.smoothVelocity.value()) > 100) { // Increase deceleration if we've passed a bound @@ -1212,7 +1207,7 @@ void QSGFlickable::viewportMoved() d->timeline.accel(d->vData.move, -d->vData.smoothVelocity.value(), d->deceleration*QML_FLICK_OVERSHOOTFRICTION, maxDistance); d->timeline.callback(QDeclarativeTimeLineCallback(&d->vData.move, d->fixupY_callback, d)); } - if (!d->hData.inOvershoot && !d->hData.fixingUp && d->flickingHorizontally + if (!d->hData.inOvershoot && !d->hData.fixingUp && d->hData.flicking && (d->hData.move.value() > minXExtent() || d->hData.move.value() < maxXExtent()) && qAbs(d->hData.smoothVelocity.value()) > 100) { // Increase deceleration if we've passed a bound @@ -1244,7 +1239,7 @@ void QSGFlickable::geometryChanged(const QRectF &newGeometry, emit contentWidthChanged(); } // Make sure that we're entirely in view. - if (!d->pressed && !d->movingHorizontally && !d->movingVertically) { + if (!d->pressed && !d->hData.moving && !d->vData.moving) { d->fixupMode = QSGFlickablePrivate::Immediate; d->fixupX(); } @@ -1257,7 +1252,7 @@ void QSGFlickable::geometryChanged(const QRectF &newGeometry, emit contentHeightChanged(); } // Make sure that we're entirely in view. - if (!d->pressed && !d->movingHorizontally && !d->movingVertically) { + if (!d->pressed && !d->hData.moving && !d->vData.moving) { d->fixupMode = QSGFlickablePrivate::Immediate; d->fixupY(); } @@ -1388,7 +1383,7 @@ void QSGFlickable::setContentWidth(qreal w) d->contentItem->setWidth(w); d->hData.markExtentsDirty(); // Make sure that we're entirely in view. - if (!d->pressed && !d->movingHorizontally && !d->movingVertically) { + if (!d->pressed && !d->hData.moving && !d->vData.moving) { d->fixupMode = QSGFlickablePrivate::Immediate; d->fixupX(); } else if (!d->pressed && d->hData.fixingUp) { @@ -1417,7 +1412,7 @@ void QSGFlickable::setContentHeight(qreal h) d->contentItem->setHeight(h); d->vData.markExtentsDirty(); // Make sure that we're entirely in view. - if (!d->pressed && !d->movingHorizontally && !d->movingVertically) { + if (!d->pressed && !d->hData.moving && !d->vData.moving) { d->fixupMode = QSGFlickablePrivate::Immediate; d->fixupY(); } else if (!d->pressed && d->vData.fixingUp) { @@ -1452,7 +1447,7 @@ void QSGFlickable::setTopMargin(qreal m) return; d->vData.startMargin = m; d->vData.markExtentsDirty(); - if (!d->pressed && !d->movingHorizontally && !d->movingVertically) { + if (!d->pressed && !d->hData.moving && !d->vData.moving) { d->fixupMode = QSGFlickablePrivate::Immediate; d->fixupY(); } @@ -1473,7 +1468,7 @@ void QSGFlickable::setBottomMargin(qreal m) return; d->vData.endMargin = m; d->vData.markExtentsDirty(); - if (!d->pressed && !d->movingHorizontally && !d->movingVertically) { + if (!d->pressed && !d->hData.moving && !d->vData.moving) { d->fixupMode = QSGFlickablePrivate::Immediate; d->fixupY(); } @@ -1494,7 +1489,7 @@ void QSGFlickable::setLeftMargin(qreal m) return; d->hData.startMargin = m; d->hData.markExtentsDirty(); - if (!d->pressed && !d->movingHorizontally && !d->movingVertically) { + if (!d->pressed && !d->hData.moving && !d->vData.moving) { d->fixupMode = QSGFlickablePrivate::Immediate; d->fixupX(); } @@ -1515,7 +1510,7 @@ void QSGFlickable::setRightMargin(qreal m) return; d->hData.endMargin = m; d->hData.markExtentsDirty(); - if (!d->pressed && !d->movingHorizontally && !d->movingVertically) { + if (!d->pressed && !d->hData.moving && !d->vData.moving) { d->fixupMode = QSGFlickablePrivate::Immediate; d->fixupX(); } @@ -1776,7 +1771,7 @@ void QSGFlickable::setFlickDeceleration(qreal deceleration) bool QSGFlickable::isFlicking() const { Q_D(const QSGFlickable); - return d->flickingHorizontally || d->flickingVertically; + return d->hData.flicking || d->vData.flicking; } /*! @@ -1790,13 +1785,13 @@ bool QSGFlickable::isFlicking() const bool QSGFlickable::isFlickingHorizontally() const { Q_D(const QSGFlickable); - return d->flickingHorizontally; + return d->hData.flicking; } bool QSGFlickable::isFlickingVertically() const { Q_D(const QSGFlickable); - return d->flickingVertically; + return d->vData.flicking; } /*! @@ -1903,36 +1898,36 @@ void QSGFlickable::setPressDelay(int delay) bool QSGFlickable::isMoving() const { Q_D(const QSGFlickable); - return d->movingHorizontally || d->movingVertically; + return d->hData.moving || d->vData.moving; } bool QSGFlickable::isMovingHorizontally() const { Q_D(const QSGFlickable); - return d->movingHorizontally; + return d->hData.moving; } bool QSGFlickable::isMovingVertically() const { Q_D(const QSGFlickable); - return d->movingVertically; + return d->vData.moving; } void QSGFlickable::movementStarting() { Q_D(QSGFlickable); - if (d->hMoved && !d->movingHorizontally) { - d->movingHorizontally = true; + if (d->hMoved && !d->hData.moving) { + d->hData.moving = true; emit movingChanged(); emit movingHorizontallyChanged(); - if (!d->movingVertically) + if (!d->vData.moving) emit movementStarted(); } - else if (d->vMoved && !d->movingVertically) { - d->movingVertically = true; + else if (d->vMoved && !d->vData.moving) { + d->vData.moving = true; emit movingChanged(); emit movingVerticallyChanged(); - if (!d->movingHorizontally) + if (!d->hData.moving) emit movementStarted(); } } @@ -1949,20 +1944,20 @@ void QSGFlickable::movementEnding() void QSGFlickable::movementXEnding() { Q_D(QSGFlickable); - if (d->flickingHorizontally) { - d->flickingHorizontally = false; + if (d->hData.flicking) { + d->hData.flicking = false; emit flickingChanged(); emit flickingHorizontallyChanged(); - if (!d->flickingVertically) + if (!d->vData.flicking) emit flickEnded(); } if (!d->pressed && !d->stealMouse) { - if (d->movingHorizontally) { - d->movingHorizontally = false; + if (d->hData.moving) { + d->hData.moving = false; d->hMoved = false; emit movingChanged(); emit movingHorizontallyChanged(); - if (!d->movingVertically) + if (!d->vData.moving) emit movementEnded(); } } @@ -1972,20 +1967,20 @@ void QSGFlickable::movementXEnding() void QSGFlickable::movementYEnding() { Q_D(QSGFlickable); - if (d->flickingVertically) { - d->flickingVertically = false; + if (d->vData.flicking) { + d->vData.flicking = false; emit flickingChanged(); emit flickingVerticallyChanged(); - if (!d->flickingHorizontally) + if (!d->hData.flicking) emit flickEnded(); } if (!d->pressed && !d->stealMouse) { - if (d->movingVertically) { - d->movingVertically = false; + if (d->vData.moving) { + d->vData.moving = false; d->vMoved = false; emit movingChanged(); emit movingVerticallyChanged(); - if (!d->movingHorizontally) + if (!d->hData.moving) emit movementEnded(); } } diff --git a/src/declarative/items/qsgflickable_p_p.h b/src/declarative/items/qsgflickable_p_p.h index b3690b4..b7a91a0 100644 --- a/src/declarative/items/qsgflickable_p_p.h +++ b/src/declarative/items/qsgflickable_p_p.h @@ -60,6 +60,7 @@ #include #include +#include "qplatformdefs.h" #include #include @@ -97,7 +98,8 @@ public: AxisData(QSGFlickablePrivate *fp, void (QSGFlickablePrivate::*func)(qreal)) : move(fp, func), viewSize(-1), startMargin(0), endMargin(0) , smoothVelocity(fp), atEnd(false), atBeginning(true) - , fixingUp(false), inOvershoot(false), dragging(false), extentsChanged(false) + , fixingUp(false), inOvershoot(false), moving(false), flicking(false) + , dragging(false), extentsChanged(false) , explicitValue(false), minExtentDirty(true), maxExtentDirty(true) {} @@ -133,6 +135,8 @@ public: bool atBeginning : 1; bool fixingUp : 1; bool inOvershoot : 1; + bool moving : 1; + bool flicking : 1; bool dragging : 1; bool extentsChanged : 1; bool explicitValue : 1; @@ -172,12 +176,8 @@ public: AxisData vData; QDeclarativeTimeLine timeline; - bool flickingHorizontally : 1; - bool flickingVertically : 1; bool hMoved : 1; bool vMoved : 1; - bool movingHorizontally : 1; - bool movingVertically : 1; bool stealMouse : 1; bool pressed : 1; bool interactive : 1; diff --git a/src/declarative/items/qsggridview.cpp b/src/declarative/items/qsggridview.cpp index 4d794aa..dfcd1b2 100644 --- a/src/declarative/items/qsggridview.cpp +++ b/src/declarative/items/qsggridview.cpp @@ -51,9 +51,14 @@ #include #include #include +#include "qplatformdefs.h" QT_BEGIN_NAMESPACE +#ifndef QML_FLICK_SNAPONETHRESHOLD +#define QML_FLICK_SNAPONETHRESHOLD 30 +#endif + //---------------------------------------------------------------------------- class FxGridItemSG : public FxViewItem @@ -329,9 +334,12 @@ qreal QSGGridViewPrivate::snapPosAt(qreal pos) const Q_Q(const QSGGridView); qreal snapPos = 0; if (!visibleItems.isEmpty()) { + qreal highlightStart = isRightToLeftTopToBottom() && highlightRangeStartValid ? size()-highlightRangeEnd : highlightRangeStart; + pos += highlightStart; pos += rowSize()/2; snapPos = static_cast(visibleItems.first())->rowPos() - visibleIndex / columns * rowSize(); snapPos = pos - fmodf(pos - snapPos, qreal(rowSize())); + snapPos -= highlightStart; qreal maxExtent; qreal minExtent; if (isRightToLeftTopToBottom()) { @@ -810,12 +818,35 @@ void QSGGridViewPrivate::fixup(AxisData &data, qreal minExtent, qreal maxExtent) highlightEnd = highlightRangeEnd; } + bool strictHighlightRange = haveHighlightRange && highlightRange == QSGGridView::StrictlyEnforceRange; if (snapMode != QSGGridView::NoSnap) { qreal tempPosition = isRightToLeftTopToBottom() ? -position()-size() : position(); + if (snapMode == QSGGridView::SnapOneRow && moveReason == Mouse) { + // if we've been dragged < rowSize()/2 then bias towards the next row + qreal dist = data.move.value() - (data.pressPos - data.dragStartOffset); + qreal bias = 0; + if (data.velocity > 0 && dist > QML_FLICK_SNAPONETHRESHOLD && dist < rowSize()/2) + bias = rowSize()/2; + else if (data.velocity < 0 && dist < -QML_FLICK_SNAPONETHRESHOLD && dist > -rowSize()/2) + bias = -rowSize()/2; + if (isRightToLeftTopToBottom()) + bias = -bias; + tempPosition -= bias; + } FxViewItem *topItem = snapItemAt(tempPosition+highlightStart); + if (!topItem && strictHighlightRange && currentItem) { + // StrictlyEnforceRange always keeps an item in range + updateHighlight(); + topItem = currentItem; + } FxViewItem *bottomItem = snapItemAt(tempPosition+highlightEnd); + if (!bottomItem && strictHighlightRange && currentItem) { + // StrictlyEnforceRange always keeps an item in range + updateHighlight(); + bottomItem = currentItem; + } qreal pos; - if (topItem && bottomItem && haveHighlightRange && highlightRange == QSGGridView::StrictlyEnforceRange) { + 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; @@ -823,7 +854,7 @@ void QSGGridViewPrivate::fixup(AxisData &data, qreal minExtent, qreal maxExtent) qreal headerPos = 0; if (header) headerPos = isRightToLeftTopToBottom() ? static_cast(header)->rowPos() + cellWidth - headerSize() : static_cast(header)->rowPos(); - if (topItem->index == 0 && header && tempPosition+highlightStart < headerPos+headerSize()/2) { + if (topItem->index == 0 && header && tempPosition+highlightStart < headerPos+headerSize()/2 && !strictHighlightRange) { pos = isRightToLeftTopToBottom() ? - headerPos + highlightStart - size() : headerPos - highlightStart; } else { if (isRightToLeftTopToBottom()) @@ -833,25 +864,13 @@ void QSGGridViewPrivate::fixup(AxisData &data, qreal minExtent, qreal maxExtent) } } else if (bottomItem) { if (isRightToLeftTopToBottom()) - pos = qMax(qMin(-bottomItem->position() + highlightStart - size(), -maxExtent), -minExtent); + pos = qMax(qMin(-bottomItem->position() + highlightEnd - size(), -maxExtent), -minExtent); else - pos = qMax(qMin(bottomItem->position() - highlightStart, -maxExtent), -minExtent); + pos = qMax(qMin(bottomItem->position() - highlightEnd, -maxExtent), -minExtent); } else { QSGItemViewPrivate::fixup(data, minExtent, maxExtent); return; } - if (currentItem && haveHighlightRange && highlightRange == QSGGridView::StrictlyEnforceRange) { - updateHighlight(); - qreal currPos = static_cast(currentItem)->rowPos(); - if (isRightToLeftTopToBottom()) - pos = -pos-size(); // Transform Pos if required - if (pos < currPos + rowSize() - highlightEnd) - pos = currPos + rowSize() - highlightEnd; - if (pos > currPos - highlightStart) - pos = currPos - highlightStart; - if (isRightToLeftTopToBottom()) - pos = -pos-size(); // Untransform - } qreal dist = qAbs(data.move + pos); if (dist > 0) { @@ -909,8 +928,14 @@ void QSGGridViewPrivate::flick(AxisData &data, qreal minExtent, qreal maxExtent, if (velocity > 0) { if (data.move.value() < minExtent) { if (snapMode == QSGGridView::SnapOneRow) { - if (FxViewItem *item = firstVisibleItem()) - maxDistance = qAbs(item->position() + dataValue); + // if we've been dragged < averageSize/2 then bias towards the next item + qreal dist = data.move.value() - (data.pressPos - data.dragStartOffset); + qreal bias = dist < rowSize()/2 ? rowSize()/2 : 0; + if (isRightToLeftTopToBottom()) + bias = -bias; + data.flickTarget = -snapPosAt(-dataValue - bias); + maxDistance = qAbs(data.flickTarget - data.move.value()); + velocity = maxVelocity; } else { maxDistance = qAbs(minExtent - data.move.value()); } @@ -920,8 +945,14 @@ void QSGGridViewPrivate::flick(AxisData &data, qreal minExtent, qreal maxExtent, } else { if (data.move.value() > maxExtent) { if (snapMode == QSGGridView::SnapOneRow) { - qreal pos = snapPosAt(-dataValue) + (isRightToLeftTopToBottom() ? 0 : rowSize()); - maxDistance = qAbs(pos + dataValue); + // if we've been dragged < averageSize/2 then bias towards the next item + qreal dist = data.move.value() - (data.pressPos - data.dragStartOffset); + qreal bias = -dist < rowSize()/2 ? rowSize()/2 : 0; + if (isRightToLeftTopToBottom()) + bias = -bias; + data.flickTarget = -snapPosAt(-dataValue + bias); + maxDistance = qAbs(data.flickTarget - data.move.value()); + velocity = -maxVelocity; } else { maxDistance = qAbs(maxExtent - data.move.value()); } @@ -930,7 +961,6 @@ void QSGGridViewPrivate::flick(AxisData &data, qreal minExtent, qreal maxExtent, data.flickTarget = maxExtent; } bool overShoot = boundsBehavior == QSGFlickable::DragAndOvershootBounds; - qreal highlightStart = isRightToLeftTopToBottom() && highlightRangeStartValid ? size()-highlightRangeEnd : highlightRangeStart; if (maxDistance > 0 || overShoot) { // This mode requires the grid to stop exactly on a row boundary. qreal v = velocity; @@ -949,9 +979,20 @@ void QSGGridViewPrivate::flick(AxisData &data, qreal minExtent, qreal maxExtent, dist = qMin(dist, maxDistance); if (v > 0) dist = -dist; - qreal distTemp = isRightToLeftTopToBottom() ? -dist : dist; - data.flickTarget = -snapPosAt(-(dataValue - highlightStart) + distTemp) + highlightStart; + if (snapMode != QSGGridView::SnapOneRow) { + qreal distTemp = isRightToLeftTopToBottom() ? -dist : dist; + data.flickTarget = -snapPosAt(-dataValue + distTemp); + } data.flickTarget = isRightToLeftTopToBottom() ? -data.flickTarget+size() : data.flickTarget; + if (overShoot) { + if (data.flickTarget >= minExtent) { + overshootDist = overShootDistance(vSize); + data.flickTarget += overshootDist; + } else if (data.flickTarget <= maxExtent) { + overshootDist = overShootDistance(vSize); + data.flickTarget -= overshootDist; + } + } qreal adjDist = -data.flickTarget + data.move.value(); if (qAbs(adjDist) > qAbs(dist)) { // Prevent painfully slow flicking - adjust velocity to suit flickDeceleration @@ -972,14 +1013,14 @@ void QSGGridViewPrivate::flick(AxisData &data, qreal minExtent, qreal maxExtent, timeline.reset(data.move); timeline.accel(data.move, v, accel, maxDistance + overshootDist); timeline.callback(QDeclarativeTimeLineCallback(&data.move, fixupCallback, this)); - if (!flickingHorizontally && q->xflick()) { - flickingHorizontally = true; + if (!hData.flicking && q->xflick()) { + hData.flicking = true; emit q->flickingChanged(); emit q->flickingHorizontallyChanged(); emit q->flickStarted(); } - if (!flickingVertically && q->yflick()) { - flickingVertically = true; + if (!vData.flicking && q->yflick()) { + vData.flicking = true; emit q->flickingChanged(); emit q->flickingVerticallyChanged(); emit q->flickStarted(); @@ -1477,7 +1518,7 @@ void QSGGridView::viewportMoved() d->inViewportMoved = true; d->lazyRelease = true; - if (d->flickingHorizontally || d->flickingVertically) { + if (d->hData.flicking || d->vData.flicking) { if (yflick()) { if (d->vData.velocity > 0) d->bufferMode = QSGGridViewPrivate::BufferBefore; @@ -1493,7 +1534,7 @@ void QSGGridView::viewportMoved() } } d->refill(); - if (d->flickingHorizontally || d->flickingVertically || d->movingHorizontally || d->movingVertically) + if (d->hData.flicking || d->vData.flicking || d->hData.moving || d->vData.moving) d->moveReason = QSGGridViewPrivate::Mouse; if (d->moveReason != QSGGridViewPrivate::SetIndex) { if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange && d->highlight) { diff --git a/src/declarative/items/qsglistview.cpp b/src/declarative/items/qsglistview.cpp index f4d1392..b38c682 100644 --- a/src/declarative/items/qsglistview.cpp +++ b/src/declarative/items/qsglistview.cpp @@ -52,9 +52,14 @@ #include #include +#include "qplatformdefs.h" QT_BEGIN_NAMESPACE +#ifndef QML_FLICK_SNAPONETHRESHOLD +#define QML_FLICK_SNAPONETHRESHOLD 30 +#endif + class FxListItemSG; class QSGListViewPrivate : public QSGItemViewPrivate @@ -72,7 +77,6 @@ public: virtual qreal originPosition() const; virtual qreal lastPosition() const; - FxViewItem *nextVisibleItem() const; FxViewItem *itemBefore(int modelIndex) const; QString sectionAt(int modelIndex); qreal snapPosAt(qreal pos); @@ -327,22 +331,6 @@ bool QSGListViewPrivate::isRightToLeft() const return orient == QSGListView::Horizontal && q->effectiveLayoutDirection() == Qt::RightToLeft; } -FxViewItem *QSGListViewPrivate::nextVisibleItem() const -{ - const qreal pos = isRightToLeft() ? -position()-size() : position(); - bool foundFirst = false; - for (int i = 0; i < visibleItems.count(); ++i) { - FxViewItem *item = visibleItems.at(i); - if (item->index != -1) { - if (foundFirst) - return item; - else if (item->position() < pos && item->endPosition() >= pos) - foundFirst = true; - } - } - return 0; -} - // Returns the item before modelIndex, if created. // May return an item marked for removal. FxViewItem *QSGListViewPrivate::itemBefore(int modelIndex) const @@ -1261,6 +1249,7 @@ void QSGListViewPrivate::fixup(AxisData &data, qreal minExtent, qreal maxExtent) correctFlick = false; fixupMode = moveReason == Mouse ? fixupMode : Immediate; + bool strictHighlightRange = haveHighlightRange && highlightRange == QSGListView::StrictlyEnforceRange; qreal highlightStart; qreal highlightEnd; @@ -1276,35 +1265,36 @@ void QSGListViewPrivate::fixup(AxisData &data, qreal minExtent, qreal maxExtent) highlightEnd = highlightRangeEnd; } - if (currentItem && haveHighlightRange && highlightRange == QSGListView::StrictlyEnforceRange - && moveReason != QSGListViewPrivate::SetIndex) { - updateHighlight(); - qreal pos = static_cast(currentItem)->itemPosition(); - if (viewPos < pos + static_cast(currentItem)->itemSize() - highlightEnd) - viewPos = pos + static_cast(currentItem)->itemSize() - highlightEnd; - if (viewPos > pos - highlightStart) - viewPos = pos - highlightStart; - if (isRightToLeft()) - viewPos = -viewPos-size(); - - timeline.reset(data.move); - if (viewPos != position()) { - if (fixupMode != Immediate) { - timeline.move(data.move, -viewPos, QEasingCurve(QEasingCurve::InOutQuad), fixupDuration/2); - data.fixingUp = true; - } else { - timeline.set(data.move, -viewPos); - } - } - vTime = timeline.time(); - } else if (snapMode != QSGListView::NoSnap && moveReason != QSGListViewPrivate::SetIndex) { + if (snapMode != QSGListView::NoSnap && moveReason != QSGListViewPrivate::SetIndex) { qreal tempPosition = isRightToLeft() ? -position()-size() : position(); + if (snapMode == QSGListView::SnapOneItem && moveReason == Mouse) { + // if we've been dragged < averageSize/2 then bias towards the next item + qreal dist = data.move.value() - (data.pressPos - data.dragStartOffset); + qreal bias = 0; + if (data.velocity > 0 && dist > QML_FLICK_SNAPONETHRESHOLD && dist < averageSize/2) + bias = averageSize/2; + else if (data.velocity < 0 && dist < -QML_FLICK_SNAPONETHRESHOLD && dist > -averageSize/2) + bias = -averageSize/2; + if (isRightToLeft()) + bias = -bias; + tempPosition -= bias; + } FxViewItem *topItem = snapItemAt(tempPosition+highlightStart); + if (!topItem && strictHighlightRange && currentItem) { + // StrictlyEnforceRange always keeps an item in range + updateHighlight(); + topItem = currentItem; + } FxViewItem *bottomItem = snapItemAt(tempPosition+highlightEnd); + if (!bottomItem && strictHighlightRange && currentItem) { + // StrictlyEnforceRange always keeps an item in range + updateHighlight(); + bottomItem = currentItem; + } qreal pos; - bool isInBounds = -position() > maxExtent && -position() < minExtent; - if (topItem && isInBounds) { - if (topItem->index == 0 && header && tempPosition+highlightStart < header->position()+headerSize()/2) { + 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; } else { if (isRightToLeft()) @@ -1314,9 +1304,9 @@ void QSGListViewPrivate::fixup(AxisData &data, qreal minExtent, qreal maxExtent) } } else if (bottomItem && isInBounds) { if (isRightToLeft()) - pos = qMax(qMin(-bottomItem->position() + highlightStart - size(), -maxExtent), -minExtent); + pos = qMax(qMin(-bottomItem->position() + highlightEnd - size(), -maxExtent), -minExtent); else - pos = qMax(qMin(bottomItem->position() - highlightStart, -maxExtent), -minExtent); + pos = qMax(qMin(bottomItem->position() - highlightEnd, -maxExtent), -minExtent); } else { QSGItemViewPrivate::fixup(data, minExtent, maxExtent); return; @@ -1333,6 +1323,26 @@ void QSGListViewPrivate::fixup(AxisData &data, qreal minExtent, qreal maxExtent) } vTime = timeline.time(); } + } else if (currentItem && strictHighlightRange && moveReason != QSGListViewPrivate::SetIndex) { + updateHighlight(); + qreal pos = static_cast(currentItem)->itemPosition(); + if (viewPos < pos + static_cast(currentItem)->itemSize() - highlightEnd) + viewPos = pos + static_cast(currentItem)->itemSize() - highlightEnd; + if (viewPos > pos - highlightStart) + viewPos = pos - highlightStart; + if (isRightToLeft()) + viewPos = -viewPos-size(); + + timeline.reset(data.move); + if (viewPos != position()) { + if (fixupMode != Immediate) { + timeline.move(data.move, -viewPos, QEasingCurve(QEasingCurve::InOutQuad), fixupDuration/2); + data.fixingUp = true; + } else { + timeline.set(data.move, -viewPos); + } + } + vTime = timeline.time(); } else { QSGItemViewPrivate::fixup(data, minExtent, maxExtent); } @@ -1354,12 +1364,19 @@ 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) { - if (snapMode == QSGListView::SnapOneItem) { - if (FxViewItem *item = isRightToLeft() ? nextVisibleItem() : firstVisibleItem()) - maxDistance = qAbs(item->position() + dataValue); + if (snapMode == QSGListView::SnapOneItem && !hData.flicking && !vData.flicking) { + // if we've been dragged < averageSize/2 then bias towards the next item + qreal dist = data.move.value() - (data.pressPos - data.dragStartOffset); + qreal bias = dist < averageSize/2 ? averageSize/2 : 0; + if (isRightToLeft()) + bias = -bias; + data.flickTarget = -snapPosAt(-(dataValue - highlightStart) - bias) + highlightStart; + maxDistance = qAbs(data.flickTarget - data.move.value()); + velocity = maxVelocity; } else { maxDistance = qAbs(minExtent - data.move.value()); } @@ -1368,9 +1385,15 @@ void QSGListViewPrivate::flick(AxisData &data, qreal minExtent, qreal maxExtent, data.flickTarget = minExtent; } else { if (data.move.value() > maxExtent) { - if (snapMode == QSGListView::SnapOneItem) { - if (FxViewItem *item = isRightToLeft() ? firstVisibleItem() : nextVisibleItem()) - maxDistance = qAbs(item->position() + dataValue); + if (snapMode == QSGListView::SnapOneItem && !hData.flicking && !vData.flicking) { + // if we've been dragged < averageSize/2 then bias towards the next item + qreal dist = data.move.value() - (data.pressPos - data.dragStartOffset); + qreal bias = -dist < averageSize/2 ? averageSize/2 : 0; + if (isRightToLeft()) + bias = -bias; + data.flickTarget = -snapPosAt(-(dataValue - highlightStart) + bias) + highlightStart; + maxDistance = qAbs(data.flickTarget - data.move.value()); + velocity = -maxVelocity; } else { maxDistance = qAbs(maxExtent - data.move.value()); } @@ -1379,7 +1402,6 @@ void QSGListViewPrivate::flick(AxisData &data, qreal minExtent, qreal maxExtent, data.flickTarget = maxExtent; } bool overShoot = boundsBehavior == QSGFlickable::DragAndOvershootBounds; - qreal highlightStart = isRightToLeft() && highlightRangeStartValid ? size()-highlightRangeEnd : highlightRangeStart; if (maxDistance > 0 || overShoot) { // These modes require the list to stop exactly on an item boundary. // The initial flick will estimate the boundary to stop on. @@ -1392,7 +1414,7 @@ void QSGListViewPrivate::flick(AxisData &data, qreal minExtent, qreal maxExtent, else v = maxVelocity; } - if (!flickingHorizontally && !flickingVertically) { + if (!hData.flicking && !vData.flicking) { // the initial flick - estimate boundary qreal accel = deceleration; qreal v2 = v * v; @@ -1404,8 +1426,10 @@ void QSGListViewPrivate::flick(AxisData &data, qreal minExtent, qreal maxExtent, if (v > 0) dist = -dist; if ((maxDistance > 0.0 && v2 / (2.0f * maxDistance) < accel) || snapMode == QSGListView::SnapOneItem) { - qreal distTemp = isRightToLeft() ? -dist : dist; - data.flickTarget = -snapPosAt(-(dataValue - highlightStart) + distTemp) + highlightStart; + if (snapMode != QSGListView::SnapOneItem) { + qreal distTemp = isRightToLeft() ? -dist : dist; + data.flickTarget = -snapPosAt(-(dataValue - highlightStart) + distTemp) + highlightStart; + } data.flickTarget = isRightToLeft() ? -data.flickTarget+size() : data.flickTarget; if (overShoot) { if (data.flickTarget >= minExtent) { @@ -1442,14 +1466,14 @@ void QSGListViewPrivate::flick(AxisData &data, qreal minExtent, qreal maxExtent, timeline.reset(data.move); timeline.accel(data.move, v, accel, maxDistance + overshootDist); timeline.callback(QDeclarativeTimeLineCallback(&data.move, fixupCallback, this)); - if (!flickingHorizontally && q->xflick()) { - flickingHorizontally = true; + if (!hData.flicking && q->xflick()) { + hData.flicking = true; emit q->flickingChanged(); emit q->flickingHorizontallyChanged(); emit q->flickStarted(); } - if (!flickingVertically && q->yflick()) { - flickingVertically = true; + if (!vData.flicking && q->yflick()) { + vData.flicking = true; emit q->flickingChanged(); emit q->flickingVerticallyChanged(); emit q->flickStarted(); @@ -2137,7 +2161,7 @@ void QSGListView::viewportMoved() d->inViewportMoved = true; d->lazyRelease = true; d->refill(); - if (d->flickingHorizontally || d->flickingVertically || d->movingHorizontally || d->movingVertically) + if (d->hData.flicking || d->vData.flicking || d->hData.moving || d->vData.moving) d->moveReason = QSGListViewPrivate::Mouse; if (d->moveReason != QSGListViewPrivate::SetIndex) { if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange && d->highlight) { @@ -2175,7 +2199,7 @@ void QSGListView::viewportMoved() } } - if ((d->flickingHorizontally || d->flickingVertically) && d->correctFlick && !d->inFlickCorrection) { + if ((d->hData.flicking || d->vData.flicking) && d->correctFlick && !d->inFlickCorrection) { d->inFlickCorrection = true; // Near an end and it seems that the extent has changed? // Recalculate the flick so that we don't end up in an odd position. diff --git a/src/qtquick1/graphicsitems/qdeclarativeflickable.cpp b/src/qtquick1/graphicsitems/qdeclarativeflickable.cpp index 6fa92b3..6a7f6ae 100644 --- a/src/qtquick1/graphicsitems/qdeclarativeflickable.cpp +++ b/src/qtquick1/graphicsitems/qdeclarativeflickable.cpp @@ -170,9 +170,7 @@ QDeclarative1FlickablePrivate::QDeclarative1FlickablePrivate() : contentItem(new QDeclarativeItem) , hData(this, &QDeclarative1FlickablePrivate::setRoundedViewportX) , vData(this, &QDeclarative1FlickablePrivate::setRoundedViewportY) - , flickingHorizontally(false), flickingVertically(false) , hMoved(false), vMoved(false) - , movingHorizontally(false), movingVertically(false) , stealMouse(false), pressed(false), interactive(true), calcVelocity(false) , deceleration(QML_FLICK_DEFAULTDECELERATION) , maxVelocity(QML_FLICK_DEFAULTMAXVELOCITY), reportedVelocitySmoothing(100) @@ -296,18 +294,18 @@ void QDeclarative1FlickablePrivate::flick(AxisData &data, qreal minExtent, qreal else timeline.accel(data.move, v, deceleration, maxDistance); timeline.callback(QDeclarative1TimeLineCallback(&data.move, fixupCallback, this)); - if (!flickingHorizontally && q->xflick()) { - flickingHorizontally = true; + if (!hData.flicking && q->xflick()) { + hData.flicking = true; emit q->flickingChanged(); emit q->flickingHorizontallyChanged(); - if (!flickingVertically) + if (!vData.flicking) emit q->flickStarted(); } - if (!flickingVertically && q->yflick()) { - flickingVertically = true; + if (!vData.flicking && q->yflick()) { + vData.flicking = true; emit q->flickingChanged(); emit q->flickingVerticallyChanged(); - if (!flickingHorizontally) + if (!hData.flicking) emit q->flickStarted(); } } else { @@ -617,11 +615,11 @@ void QDeclarative1Flickable::setInteractive(bool interactive) Q_D(QDeclarative1Flickable); if (interactive != d->interactive) { d->interactive = interactive; - if (!interactive && (d->flickingHorizontally || d->flickingVertically)) { + if (!interactive && (d->hData.flicking || d->vData.flicking)) { d->timeline.clear(); d->vTime = d->timeline.time(); - d->flickingHorizontally = false; - d->flickingVertically = false; + d->hData.flicking = false; + d->vData.flicking = false; emit flickingChanged(); emit flickingHorizontallyChanged(); emit flickingVerticallyChanged(); @@ -774,8 +772,8 @@ void QDeclarative1FlickablePrivate::handleMousePressEvent(QGraphicsSceneMouseEve pressPos = event->pos(); hData.pressPos = hData.move.value(); vData.pressPos = vData.move.value(); - flickingHorizontally = false; - flickingVertically = false; + hData.flicking = false; + vData.flicking = false; QDeclarativeItemPrivate::start(pressTime); QDeclarativeItemPrivate::start(velocityTime); } @@ -900,17 +898,14 @@ void QDeclarative1FlickablePrivate::handleMouseReleaseEvent(QGraphicsSceneMouseE return; // if we drag then pause before release we should not cause a flick. - if (QDeclarativeItemPrivate::elapsed(lastPosTime) < 100) { - vData.updateVelocity(); - hData.updateVelocity(); - } else { - hData.velocity = 0.0; - vData.velocity = 0.0; - } + qint64 elapsed = QDeclarativeItemPrivate::elapsed(lastPosTime); + + vData.updateVelocity(); + hData.updateVelocity(); vTime = timeline.time(); - qreal velocity = vData.velocity; + qreal velocity = elapsed < 100 ? vData.velocity : 0; if (vData.atBeginning || vData.atEnd) velocity /= 2; if (q->yflick() && qAbs(velocity) > MinimumFlickVelocity && qAbs(event->pos().y() - pressPos.y()) > FlickThreshold) { @@ -921,7 +916,7 @@ void QDeclarative1FlickablePrivate::handleMouseReleaseEvent(QGraphicsSceneMouseE fixupY(); } - velocity = hData.velocity; + velocity = elapsed < 100 ? hData.velocity : 0; if (hData.atBeginning || hData.atEnd) velocity /= 2; if (q->xflick() && qAbs(velocity) > MinimumFlickVelocity && qAbs(event->pos().x() - pressPos.x()) > FlickThreshold) { @@ -987,9 +982,9 @@ void QDeclarative1Flickable::wheelEvent(QGraphicsSceneWheelEvent *event) valid = true; } if (valid) { - d->flickingVertically = false; + d->vData.flicking = false; d->flickY(d->vData.velocity); - if (d->flickingVertically) { + if (d->vData.flicking) { d->vMoved = true; movementStarting(); } @@ -1005,9 +1000,9 @@ void QDeclarative1Flickable::wheelEvent(QGraphicsSceneWheelEvent *event) valid = true; } if (valid) { - d->flickingHorizontally = false; + d->hData.flicking = false; d->flickX(d->hData.velocity); - if (d->flickingHorizontally) { + if (d->hData.flicking) { d->hMoved = true; movementStarting(); } @@ -1156,7 +1151,7 @@ void QDeclarative1Flickable::viewportMoved() } } - if (!d->vData.inOvershoot && !d->vData.fixingUp && d->flickingVertically + if (!d->vData.inOvershoot && !d->vData.fixingUp && d->vData.flicking && (d->vData.move.value() > minYExtent() || d->vData.move.value() < maxYExtent()) && qAbs(d->vData.smoothVelocity.value()) > 100) { // Increase deceleration if we've passed a bound @@ -1166,7 +1161,7 @@ void QDeclarative1Flickable::viewportMoved() d->timeline.accel(d->vData.move, -d->vData.smoothVelocity.value(), d->deceleration*QML_FLICK_OVERSHOOTFRICTION, maxDistance); d->timeline.callback(QDeclarative1TimeLineCallback(&d->vData.move, d->fixupY_callback, d)); } - if (!d->hData.inOvershoot && !d->hData.fixingUp && d->flickingHorizontally + if (!d->hData.inOvershoot && !d->hData.fixingUp && d->hData.flicking && (d->hData.move.value() > minXExtent() || d->hData.move.value() < maxXExtent()) && qAbs(d->hData.smoothVelocity.value()) > 100) { // Increase deceleration if we've passed a bound @@ -1198,7 +1193,7 @@ void QDeclarative1Flickable::geometryChanged(const QRectF &newGeometry, emit contentWidthChanged(); } // Make sure that we're entirely in view. - if (!d->pressed && !d->movingHorizontally && !d->movingVertically) { + if (!d->pressed && !d->hData.moving && !d->vData.moving) { d->fixupMode = QDeclarative1FlickablePrivate::Immediate; d->fixupX(); } @@ -1211,7 +1206,7 @@ void QDeclarative1Flickable::geometryChanged(const QRectF &newGeometry, emit contentHeightChanged(); } // Make sure that we're entirely in view. - if (!d->pressed && !d->movingHorizontally && !d->movingVertically) { + if (!d->pressed && !d->hData.moving && !d->vData.moving) { d->fixupMode = QDeclarative1FlickablePrivate::Immediate; d->fixupY(); } @@ -1366,7 +1361,7 @@ void QDeclarative1Flickable::setContentWidth(qreal w) else d->contentItem->setWidth(w); // Make sure that we're entirely in view. - if (!d->pressed && !d->movingHorizontally && !d->movingVertically) { + if (!d->pressed && !d->hData.moving && !d->vData.moving) { d->fixupMode = QDeclarative1FlickablePrivate::Immediate; d->fixupX(); } else if (!d->pressed && d->hData.fixingUp) { @@ -1394,7 +1389,7 @@ void QDeclarative1Flickable::setContentHeight(qreal h) else d->contentItem->setHeight(h); // Make sure that we're entirely in view. - if (!d->pressed && !d->movingHorizontally && !d->movingVertically) { + if (!d->pressed && !d->hData.moving && !d->vData.moving) { d->fixupMode = QDeclarative1FlickablePrivate::Immediate; d->fixupY(); } else if (!d->pressed && d->vData.fixingUp) { @@ -1651,7 +1646,7 @@ void QDeclarative1Flickable::setFlickDeceleration(qreal deceleration) bool QDeclarative1Flickable::isFlicking() const { Q_D(const QDeclarative1Flickable); - return d->flickingHorizontally || d->flickingVertically; + return d->hData.flicking || d->vData.flicking; } /*! @@ -1665,13 +1660,13 @@ bool QDeclarative1Flickable::isFlicking() const bool QDeclarative1Flickable::isFlickingHorizontally() const { Q_D(const QDeclarative1Flickable); - return d->flickingHorizontally; + return d->hData.flicking; } bool QDeclarative1Flickable::isFlickingVertically() const { Q_D(const QDeclarative1Flickable); - return d->flickingVertically; + return d->vData.flicking; } /*! @@ -1707,7 +1702,7 @@ void QDeclarative1Flickable::setPressDelay(int delay) bool QDeclarative1Flickable::isMoving() const { Q_D(const QDeclarative1Flickable); - return d->movingHorizontally || d->movingVertically; + return d->hData.moving || d->vData.moving; } /*! @@ -1722,30 +1717,30 @@ bool QDeclarative1Flickable::isMoving() const bool QDeclarative1Flickable::isMovingHorizontally() const { Q_D(const QDeclarative1Flickable); - return d->movingHorizontally; + return d->hData.moving; } bool QDeclarative1Flickable::isMovingVertically() const { Q_D(const QDeclarative1Flickable); - return d->movingVertically; + return d->vData.moving; } void QDeclarative1Flickable::movementStarting() { Q_D(QDeclarative1Flickable); - if (d->hMoved && !d->movingHorizontally) { - d->movingHorizontally = true; + if (d->hMoved && !d->hData.moving) { + d->hData.moving = true; emit movingChanged(); emit movingHorizontallyChanged(); - if (!d->movingVertically) + if (!d->vData.moving) emit movementStarted(); } - else if (d->vMoved && !d->movingVertically) { - d->movingVertically = true; + else if (d->vMoved && !d->vData.moving) { + d->vData.moving = true; emit movingChanged(); emit movingVerticallyChanged(); - if (!d->movingHorizontally) + if (!d->hData.moving) emit movementStarted(); } } @@ -1762,20 +1757,20 @@ void QDeclarative1Flickable::movementEnding() void QDeclarative1Flickable::movementXEnding() { Q_D(QDeclarative1Flickable); - if (d->flickingHorizontally) { - d->flickingHorizontally = false; + if (d->hData.flicking) { + d->hData.flicking = false; emit flickingChanged(); emit flickingHorizontallyChanged(); - if (!d->flickingVertically) + if (!d->vData.flicking) emit flickEnded(); } if (!d->pressed && !d->stealMouse) { - if (d->movingHorizontally) { - d->movingHorizontally = false; + if (d->hData.moving) { + d->hData.moving = false; d->hMoved = false; emit movingChanged(); emit movingHorizontallyChanged(); - if (!d->movingVertically) + if (!d->vData.moving) emit movementEnded(); } } @@ -1785,20 +1780,20 @@ void QDeclarative1Flickable::movementXEnding() void QDeclarative1Flickable::movementYEnding() { Q_D(QDeclarative1Flickable); - if (d->flickingVertically) { - d->flickingVertically = false; + if (d->vData.flicking) { + d->vData.flicking = false; emit flickingChanged(); emit flickingVerticallyChanged(); - if (!d->flickingHorizontally) + if (!d->hData.flicking) emit flickEnded(); } if (!d->pressed && !d->stealMouse) { - if (d->movingVertically) { - d->movingVertically = false; + if (d->vData.moving) { + d->vData.moving = false; d->vMoved = false; emit movingChanged(); emit movingVerticallyChanged(); - if (!d->movingHorizontally) + if (!d->hData.moving) emit movementEnded(); } } diff --git a/src/qtquick1/graphicsitems/qdeclarativeflickable_p_p.h b/src/qtquick1/graphicsitems/qdeclarativeflickable_p_p.h index 5bbeb27..c76da83 100644 --- a/src/qtquick1/graphicsitems/qdeclarativeflickable_p_p.h +++ b/src/qtquick1/graphicsitems/qdeclarativeflickable_p_p.h @@ -94,7 +94,7 @@ public: struct AxisData { AxisData(QDeclarative1FlickablePrivate *fp, void (QDeclarative1FlickablePrivate::*func)(qreal)) : move(fp, func), viewSize(-1), smoothVelocity(fp), atEnd(false), atBeginning(true) - , fixingUp(false), inOvershoot(false) + , fixingUp(false), inOvershoot(false), moving(false), flicking(false) {} void reset() { @@ -121,6 +121,8 @@ public: bool atBeginning : 1; bool fixingUp : 1; bool inOvershoot : 1; + bool moving : 1; + bool flicking : 1; }; void flickX(qreal velocity); @@ -152,12 +154,8 @@ public: AxisData vData; QDeclarative1TimeLine timeline; - bool flickingHorizontally : 1; - bool flickingVertically : 1; bool hMoved : 1; bool vMoved : 1; - bool movingHorizontally : 1; - bool movingVertically : 1; bool stealMouse : 1; bool pressed : 1; bool interactive : 1; diff --git a/src/qtquick1/graphicsitems/qdeclarativegridview.cpp b/src/qtquick1/graphicsitems/qdeclarativegridview.cpp index f2511a1..feabbf0 100644 --- a/src/qtquick1/graphicsitems/qdeclarativegridview.cpp +++ b/src/qtquick1/graphicsitems/qdeclarativegridview.cpp @@ -51,11 +51,13 @@ #include #include +#include "qplatformdefs.h" QT_BEGIN_NAMESPACE - - +#ifndef QML_FLICK_SNAPONETHRESHOLD +#define QML_FLICK_SNAPONETHRESHOLD 30 +#endif //---------------------------------------------------------------------------- @@ -346,9 +348,12 @@ public: Q_Q(const QDeclarative1GridView); qreal snapPos = 0; if (!visibleItems.isEmpty()) { + qreal highlightStart = isRightToLeftTopToBottom() && highlightRangeStartValid ? size()-highlightRangeEnd : highlightRangeStart; + pos += highlightStart; pos += rowSize()/2; snapPos = visibleItems.first()->rowPos() - visibleIndex / columns * rowSize(); snapPos = pos - fmodf(pos - snapPos, qreal(rowSize())); + snapPos -= highlightStart; qreal maxExtent; qreal minExtent; if (isRightToLeftTopToBottom()) { @@ -876,7 +881,7 @@ void QDeclarative1GridViewPrivate::updateHighlight() { if ((!currentItem && highlight) || (currentItem && !highlight)) createHighlight(); - if (currentItem && autoHighlight && highlight && !movingHorizontally && !movingVertically) { + if (currentItem && autoHighlight && highlight && !hData.moving && !vData.moving) { // auto-update highlight highlightXAnimator->to = currentItem->item->x(); highlightYAnimator->to = currentItem->item->y(); @@ -1061,12 +1066,36 @@ void QDeclarative1GridViewPrivate::fixup(AxisData &data, qreal minExtent, qreal highlightEnd = highlightRangeEnd; } + bool strictHighlightRange = haveHighlightRange && highlightRange == QDeclarative1GridView::StrictlyEnforceRange; + if (snapMode != QDeclarative1GridView::NoSnap) { qreal tempPosition = isRightToLeftTopToBottom() ? -position()-size() : position(); + if (snapMode == QDeclarative1GridView::SnapOneRow && moveReason == Mouse) { + // if we've been dragged < rowSize()/2 then bias towards the next row + qreal dist = data.move.value() - (data.pressPos - data.dragStartOffset); + qreal bias = 0; + if (data.velocity > 0 && dist > QML_FLICK_SNAPONETHRESHOLD && dist < rowSize()/2) + bias = rowSize()/2; + else if (data.velocity < 0 && dist < -QML_FLICK_SNAPONETHRESHOLD && dist > -rowSize()/2) + bias = -rowSize()/2; + if (isRightToLeftTopToBottom()) + bias = -bias; + tempPosition -= bias; + } FxGridItem1 *topItem = snapItemAt(tempPosition+highlightStart); + if (!topItem && strictHighlightRange && currentItem) { + // StrictlyEnforceRange always keeps an item in range + updateHighlight(); + topItem = currentItem; + } FxGridItem1 *bottomItem = snapItemAt(tempPosition+highlightEnd); + if (!bottomItem && strictHighlightRange && currentItem) { + // StrictlyEnforceRange always keeps an item in range + updateHighlight(); + bottomItem = currentItem; + } qreal pos; - if (topItem && bottomItem && haveHighlightRange && highlightRange == QDeclarative1GridView::StrictlyEnforceRange) { + 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; @@ -1074,7 +1103,7 @@ void QDeclarative1GridViewPrivate::fixup(AxisData &data, qreal minExtent, qreal qreal headerPos = 0; if (header) headerPos = isRightToLeftTopToBottom() ? header->rowPos() + cellWidth - headerSize() : header->rowPos(); - if (topItem->index == 0 && header && tempPosition+highlightStart < headerPos+headerSize()/2) { + if (topItem->index == 0 && header && tempPosition+highlightStart < headerPos+headerSize()/2 && !strictHighlightRange) { pos = isRightToLeftTopToBottom() ? - headerPos + highlightStart - size() : headerPos - highlightStart; } else { if (isRightToLeftTopToBottom()) @@ -1084,25 +1113,13 @@ void QDeclarative1GridViewPrivate::fixup(AxisData &data, qreal minExtent, qreal } } else if (bottomItem) { if (isRightToLeftTopToBottom()) - pos = qMax(qMin(-bottomItem->rowPos() + highlightStart - size(), -maxExtent), -minExtent); + pos = qMax(qMin(-bottomItem->rowPos() + highlightEnd - size(), -maxExtent), -minExtent); else - pos = qMax(qMin(bottomItem->rowPos() - highlightStart, -maxExtent), -minExtent); + pos = qMax(qMin(bottomItem->rowPos() - highlightEnd, -maxExtent), -minExtent); } else { QDeclarative1FlickablePrivate::fixup(data, minExtent, maxExtent); return; } - if (currentItem && haveHighlightRange && highlightRange == QDeclarative1GridView::StrictlyEnforceRange) { - updateHighlight(); - qreal currPos = currentItem->rowPos(); - if (isRightToLeftTopToBottom()) - pos = -pos-size(); // Transform Pos if required - if (pos < currPos + rowSize() - highlightEnd) - pos = currPos + rowSize() - highlightEnd; - if (pos > currPos - highlightStart) - pos = currPos - highlightStart; - if (isRightToLeftTopToBottom()) - pos = -pos-size(); // Untransform - } qreal dist = qAbs(data.move + pos); if (dist > 0) { timeline.reset(data.move); @@ -1159,9 +1176,14 @@ void QDeclarative1GridViewPrivate::flick(AxisData &data, qreal minExtent, qreal if (velocity > 0) { if (data.move.value() < minExtent) { if (snapMode == QDeclarative1GridView::SnapOneRow) { - if (FxGridItem1 *item = firstVisibleItem()) { - maxDistance = qAbs(item->rowPos() + dataValue); - } + // if we've been dragged < averageSize/2 then bias towards the next item + qreal dist = data.move.value() - (data.pressPos - data.dragStartOffset); + qreal bias = dist < rowSize()/2 ? rowSize()/2 : 0; + if (isRightToLeftTopToBottom()) + bias = -bias; + data.flickTarget = -snapPosAt(-dataValue - bias); + maxDistance = qAbs(data.flickTarget - data.move.value()); + velocity = maxVelocity; } else { maxDistance = qAbs(minExtent - data.move.value()); } @@ -1171,8 +1193,14 @@ void QDeclarative1GridViewPrivate::flick(AxisData &data, qreal minExtent, qreal } else { if (data.move.value() > maxExtent) { if (snapMode == QDeclarative1GridView::SnapOneRow) { - qreal pos = snapPosAt(-dataValue) + (isRightToLeftTopToBottom() ? 0 : rowSize()); - maxDistance = qAbs(pos + dataValue); + // if we've been dragged < averageSize/2 then bias towards the next item + qreal dist = data.move.value() - (data.pressPos - data.dragStartOffset); + qreal bias = -dist < rowSize()/2 ? rowSize()/2 : 0; + if (isRightToLeftTopToBottom()) + bias = -bias; + data.flickTarget = -snapPosAt(-dataValue + bias); + maxDistance = qAbs(data.flickTarget - data.move.value()); + velocity = -maxVelocity; } else { maxDistance = qAbs(maxExtent - data.move.value()); } @@ -1182,7 +1210,6 @@ void QDeclarative1GridViewPrivate::flick(AxisData &data, qreal minExtent, qreal } bool overShoot = boundsBehavior == QDeclarative1Flickable::DragAndOvershootBounds; - qreal highlightStart = isRightToLeftTopToBottom() && highlightRangeStartValid ? size()-highlightRangeEnd : highlightRangeStart; if (maxDistance > 0 || overShoot) { // This mode requires the grid to stop exactly on a row boundary. @@ -1202,9 +1229,20 @@ void QDeclarative1GridViewPrivate::flick(AxisData &data, qreal minExtent, qreal dist = qMin(dist, maxDistance); if (v > 0) dist = -dist; - qreal distTemp = isRightToLeftTopToBottom() ? -dist : dist; - data.flickTarget = -snapPosAt(-(dataValue - highlightStart) + distTemp) + highlightStart; + if (snapMode != QDeclarative1GridView::SnapOneRow) { + qreal distTemp = isRightToLeftTopToBottom() ? -dist : dist; + data.flickTarget = -snapPosAt(-dataValue + distTemp); + } data.flickTarget = isRightToLeftTopToBottom() ? -data.flickTarget+size() : data.flickTarget; + if (overShoot) { + if (data.flickTarget >= minExtent) { + overshootDist = overShootDistance(vSize); + data.flickTarget += overshootDist; + } else if (data.flickTarget <= maxExtent) { + overshootDist = overShootDistance(vSize); + data.flickTarget -= overshootDist; + } + } qreal adjDist = -data.flickTarget + data.move.value(); if (qAbs(adjDist) > qAbs(dist)) { // Prevent painfully slow flicking - adjust velocity to suit flickDeceleration @@ -1225,14 +1263,14 @@ void QDeclarative1GridViewPrivate::flick(AxisData &data, qreal minExtent, qreal timeline.reset(data.move); timeline.accel(data.move, v, accel, maxDistance + overshootDist); timeline.callback(QDeclarative1TimeLineCallback(&data.move, fixupCallback, this)); - if (!flickingHorizontally && q->xflick()) { - flickingHorizontally = true; + if (!hData.flicking && q->xflick()) { + hData.flicking = true; emit q->flickingChanged(); emit q->flickingHorizontallyChanged(); emit q->flickStarted(); } - if (!flickingVertically && q->yflick()) { - flickingVertically = true; + if (!vData.flicking && q->yflick()) { + vData.flicking = true; emit q->flickingChanged(); emit q->flickingVerticallyChanged(); emit q->flickStarted(); @@ -1557,6 +1595,8 @@ void QDeclarative1GridView::setCurrentIndex(int index) if (index == d->currentIndex) return; if (isComponentComplete() && d->isValid()) { + if (d->layoutScheduled) + d->layout(); d->moveReason = QDeclarative1GridViewPrivate::SetIndex; d->updateCurrent(index); } else { @@ -2110,7 +2150,8 @@ bool QDeclarative1GridView::event(QEvent *event) { Q_D(QDeclarative1GridView); if (event->type() == QEvent::User) { - d->layout(); + if (d->layoutScheduled) + d->layout(); return true; } @@ -2124,7 +2165,7 @@ void QDeclarative1GridView::viewportMoved() if (!d->itemCount) return; d->lazyRelease = true; - if (d->flickingHorizontally || d->flickingVertically) { + if (d->hData.flicking || d->vData.flicking) { if (yflick()) { if (d->vData.velocity > 0) d->bufferMode = QDeclarative1GridViewPrivate::BufferBefore; @@ -2140,7 +2181,7 @@ void QDeclarative1GridView::viewportMoved() } } refill(); - if (d->flickingHorizontally || d->flickingVertically || d->movingHorizontally || d->movingVertically) + if (d->hData.flicking || d->vData.flicking || d->hData.moving || d->vData.moving) d->moveReason = QDeclarative1GridViewPrivate::Mouse; if (d->moveReason != QDeclarative1GridViewPrivate::SetIndex) { if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange && d->highlight) { @@ -2928,6 +2969,11 @@ void QDeclarative1GridView::itemsRemoved(int modelIndex, int count) } } + // If we removed items before visible items a layout may be + // required to ensure item 0 is in the first column. + if (!removedVisible && modelIndex < d->visibleIndex) + d->scheduleLayout(); + // fix current if (d->currentIndex >= modelIndex + count) { d->currentIndex -= count; diff --git a/src/qtquick1/graphicsitems/qdeclarativelistview.cpp b/src/qtquick1/graphicsitems/qdeclarativelistview.cpp index 5119c0e..7b9cb12 100644 --- a/src/qtquick1/graphicsitems/qdeclarativelistview.cpp +++ b/src/qtquick1/graphicsitems/qdeclarativelistview.cpp @@ -52,10 +52,13 @@ #include #include +#include "qplatformdefs.h" QT_BEGIN_NAMESPACE - +#ifndef QML_FLICK_SNAPONETHRESHOLD +#define QML_FLICK_SNAPONETHRESHOLD 30 +#endif void QDeclarative1ViewSection::setProperty(const QString &property) { @@ -235,21 +238,6 @@ public: return visibleItems.count() ? visibleItems.first() : 0; } - FxListItem1 *nextVisibleItem() const { - const qreal pos = isRightToLeft() ? -position()-size() : position(); - bool foundFirst = false; - for (int i = 0; i < visibleItems.count(); ++i) { - FxListItem1 *item = visibleItems.at(i); - if (item->index != -1) { - if (foundFirst) - return item; - else if (item->position() < pos && item->endPosition() > pos) - foundFirst = true; - } - } - return 0; - } - // Returns the item before modelIndex, if created. // May return an item marked for removal. FxListItem1 *itemBefore(int modelIndex) const { @@ -1013,7 +1001,7 @@ void QDeclarative1ListViewPrivate::updateHighlight() { if ((!currentItem && highlight) || (currentItem && !highlight)) createHighlight(); - if (currentItem && autoHighlight && highlight && !movingHorizontally && !movingVertically) { + if (currentItem && autoHighlight && highlight && !hData.moving && !vData.moving) { // auto-update highlight highlightPosAnimator->to = isRightToLeft() ? -currentItem->itemPosition()-currentItem->itemSize() @@ -1308,6 +1296,7 @@ void QDeclarative1ListViewPrivate::fixup(AxisData &data, qreal minExtent, qreal correctFlick = false; fixupMode = moveReason == Mouse ? fixupMode : Immediate; + bool strictHighlightRange = haveHighlightRange && highlightRange == QDeclarative1ListView::StrictlyEnforceRange; qreal highlightStart; qreal highlightEnd; @@ -1323,35 +1312,36 @@ void QDeclarative1ListViewPrivate::fixup(AxisData &data, qreal minExtent, qreal highlightEnd = highlightRangeEnd; } - if (currentItem && haveHighlightRange && highlightRange == QDeclarative1ListView::StrictlyEnforceRange - && moveReason != QDeclarative1ListViewPrivate::SetIndex) { - updateHighlight(); - qreal pos = currentItem->itemPosition(); - if (viewPos < pos + currentItem->itemSize() - highlightEnd) - viewPos = pos + currentItem->itemSize() - highlightEnd; - if (viewPos > pos - highlightStart) - viewPos = pos - highlightStart; - if (isRightToLeft()) - viewPos = -viewPos-size(); - - timeline.reset(data.move); - if (viewPos != position()) { - if (fixupMode != Immediate) { - timeline.move(data.move, -viewPos, QEasingCurve(QEasingCurve::InOutQuad), fixupDuration/2); - data.fixingUp = true; - } else { - timeline.set(data.move, -viewPos); - } - } - vTime = timeline.time(); - } else if (snapMode != QDeclarative1ListView::NoSnap && moveReason != QDeclarative1ListViewPrivate::SetIndex) { + if (snapMode != QDeclarative1ListView::NoSnap && moveReason != QDeclarative1ListViewPrivate::SetIndex) { qreal tempPosition = isRightToLeft() ? -position()-size() : position(); + if (snapMode == QDeclarative1ListView::SnapOneItem && moveReason == Mouse) { + // if we've been dragged < averageSize/2 then bias towards the next item + qreal dist = data.move.value() - (data.pressPos - data.dragStartOffset); + qreal bias = 0; + if (data.velocity > 0 && dist > QML_FLICK_SNAPONETHRESHOLD && dist < averageSize/2) + bias = averageSize/2; + else if (data.velocity < 0 && dist < -QML_FLICK_SNAPONETHRESHOLD && dist > -averageSize/2) + bias = -averageSize/2; + if (isRightToLeft()) + bias = -bias; + tempPosition -= bias; + } FxListItem1 *topItem = snapItemAt(tempPosition+highlightStart); + if (!topItem && strictHighlightRange && currentItem) { + // StrictlyEnforceRange always keeps an item in range + updateHighlight(); + topItem = currentItem; + } FxListItem1 *bottomItem = snapItemAt(tempPosition+highlightEnd); + if (!bottomItem && strictHighlightRange && currentItem) { + // StrictlyEnforceRange always keeps an item in range + updateHighlight(); + bottomItem = currentItem; + } qreal pos; - bool isInBounds = -position() > maxExtent && -position() < minExtent; - if (topItem && isInBounds) { - if (topItem->index == 0 && header && tempPosition+highlightStart < header->position()+header->size()/2) { + 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; } else { if (isRightToLeft()) @@ -1361,9 +1351,9 @@ void QDeclarative1ListViewPrivate::fixup(AxisData &data, qreal minExtent, qreal } } else if (bottomItem && isInBounds) { if (isRightToLeft()) - pos = qMax(qMin(-bottomItem->position() + highlightStart - size(), -maxExtent), -minExtent); + pos = qMax(qMin(-bottomItem->position() + highlightEnd - size(), -maxExtent), -minExtent); else - pos = qMax(qMin(bottomItem->position() - highlightStart, -maxExtent), -minExtent); + pos = qMax(qMin(bottomItem->position() - highlightEnd, -maxExtent), -minExtent); } else { QDeclarative1FlickablePrivate::fixup(data, minExtent, maxExtent); return; @@ -1380,6 +1370,27 @@ void QDeclarative1ListViewPrivate::fixup(AxisData &data, qreal minExtent, qreal } vTime = timeline.time(); } + } else if (currentItem && strictHighlightRange + && moveReason != QDeclarative1ListViewPrivate::SetIndex) { + updateHighlight(); + qreal pos = currentItem->itemPosition(); + if (viewPos < pos + currentItem->itemSize() - highlightEnd) + viewPos = pos + currentItem->itemSize() - highlightEnd; + if (viewPos > pos - highlightStart) + viewPos = pos - highlightStart; + if (isRightToLeft()) + viewPos = -viewPos-size(); + + timeline.reset(data.move); + if (viewPos != position()) { + if (fixupMode != Immediate) { + timeline.move(data.move, -viewPos, QEasingCurve(QEasingCurve::InOutQuad), fixupDuration/2); + data.fixingUp = true; + } else { + timeline.set(data.move, -viewPos); + } + } + vTime = timeline.time(); } else { QDeclarative1FlickablePrivate::fixup(data, minExtent, maxExtent); } @@ -1401,12 +1412,19 @@ void QDeclarative1ListViewPrivate::flick(AxisData &data, qreal minExtent, qreal } 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) { - if (snapMode == QDeclarative1ListView::SnapOneItem) { - if (FxListItem1 *item = isRightToLeft() ? nextVisibleItem() : firstVisibleItem()) - maxDistance = qAbs(item->position() + dataValue); + if (snapMode == QDeclarative1ListView::SnapOneItem && !hData.flicking && !vData.flicking) { + // if we've been dragged < averageSize/2 then bias towards the next item + qreal dist = data.move.value() - (data.pressPos - data.dragStartOffset); + qreal bias = dist < averageSize/2 ? averageSize/2 : 0; + if (isRightToLeft()) + bias = -bias; + data.flickTarget = -snapPosAt(-(dataValue - highlightStart) - bias) + highlightStart; + maxDistance = qAbs(data.flickTarget - data.move.value()); + velocity = maxVelocity; } else { maxDistance = qAbs(minExtent - data.move.value()); } @@ -1415,9 +1433,15 @@ void QDeclarative1ListViewPrivate::flick(AxisData &data, qreal minExtent, qreal data.flickTarget = minExtent; } else { if (data.move.value() > maxExtent) { - if (snapMode == QDeclarative1ListView::SnapOneItem) { - if (FxListItem1 *item = isRightToLeft() ? firstVisibleItem() : nextVisibleItem()) - maxDistance = qAbs(item->position() + dataValue); + if (snapMode == QDeclarative1ListView::SnapOneItem && !hData.flicking && !vData.flicking) { + // if we've been dragged < averageSize/2 then bias towards the next item + qreal dist = data.move.value() - (data.pressPos - data.dragStartOffset); + qreal bias = -dist < averageSize/2 ? averageSize/2 : 0; + if (isRightToLeft()) + bias = -bias; + data.flickTarget = -snapPosAt(-(dataValue - highlightStart) + bias) + highlightStart; + maxDistance = qAbs(data.flickTarget - data.move.value()); + velocity = -maxVelocity; } else { maxDistance = qAbs(maxExtent - data.move.value()); } @@ -1427,7 +1451,6 @@ void QDeclarative1ListViewPrivate::flick(AxisData &data, qreal minExtent, qreal } bool overShoot = boundsBehavior == QDeclarative1Flickable::DragAndOvershootBounds; - qreal highlightStart = isRightToLeft() && highlightRangeStartValid ? size()-highlightRangeEnd : highlightRangeStart; if (maxDistance > 0 || overShoot) { // These modes require the list to stop exactly on an item boundary. @@ -1441,7 +1464,7 @@ void QDeclarative1ListViewPrivate::flick(AxisData &data, qreal minExtent, qreal else v = maxVelocity; } - if (!flickingHorizontally && !flickingVertically) { + if (!hData.flicking && !vData.flicking) { // the initial flick - estimate boundary qreal accel = deceleration; qreal v2 = v * v; @@ -1453,8 +1476,10 @@ void QDeclarative1ListViewPrivate::flick(AxisData &data, qreal minExtent, qreal if (v > 0) dist = -dist; if ((maxDistance > 0.0 && v2 / (2.0f * maxDistance) < accel) || snapMode == QDeclarative1ListView::SnapOneItem) { - qreal distTemp = isRightToLeft() ? -dist : dist; - data.flickTarget = -snapPosAt(-(dataValue - highlightStart) + distTemp) + highlightStart; + if (snapMode != QDeclarative1ListView::SnapOneItem) { + qreal distTemp = isRightToLeft() ? -dist : dist; + data.flickTarget = -snapPosAt(-(dataValue - highlightStart) + distTemp) + highlightStart; + } data.flickTarget = isRightToLeft() ? -data.flickTarget+size() : data.flickTarget; if (overShoot) { if (data.flickTarget >= minExtent) { @@ -1492,14 +1517,14 @@ void QDeclarative1ListViewPrivate::flick(AxisData &data, qreal minExtent, qreal timeline.reset(data.move); timeline.accel(data.move, v, accel, maxDistance + overshootDist); timeline.callback(QDeclarative1TimeLineCallback(&data.move, fixupCallback, this)); - if (!flickingHorizontally && q->xflick()) { - flickingHorizontally = true; + if (!hData.flicking && q->xflick()) { + hData.flicking = true; emit q->flickingChanged(); emit q->flickingHorizontallyChanged(); emit q->flickStarted(); } - if (!flickingVertically && q->yflick()) { - flickingVertically = true; + if (!vData.flicking && q->yflick()) { + vData.flicking = true; emit q->flickingChanged(); emit q->flickingVerticallyChanged(); emit q->flickStarted(); @@ -1876,6 +1901,8 @@ void QDeclarative1ListView::setCurrentIndex(int index) if (index == d->currentIndex) return; if (isComponentComplete() && d->isValid()) { + if (d->layoutScheduled) + d->layout(); d->moveReason = QDeclarative1ListViewPrivate::SetIndex; d->updateCurrent(index); } else if (d->currentIndex != index) { @@ -2568,7 +2595,8 @@ bool QDeclarative1ListView::event(QEvent *event) { Q_D(QDeclarative1ListView); if (event->type() == QEvent::User) { - d->layout(); + if (d->layoutScheduled) + d->layout(); return true; } @@ -2587,7 +2615,7 @@ void QDeclarative1ListView::viewportMoved() d->inViewportMoved = true; d->lazyRelease = true; refill(); - if (d->flickingHorizontally || d->flickingVertically || d->movingHorizontally || d->movingVertically) + if (d->hData.flicking || d->vData.flicking || d->hData.moving || d->vData.moving) d->moveReason = QDeclarative1ListViewPrivate::Mouse; if (d->moveReason != QDeclarative1ListViewPrivate::SetIndex) { if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange && d->highlight) { @@ -2621,7 +2649,7 @@ void QDeclarative1ListView::viewportMoved() } } - if ((d->flickingHorizontally || d->flickingVertically) && d->correctFlick && !d->inFlickCorrection) { + if ((d->hData.flicking || d->vData.flicking) && d->correctFlick && !d->inFlickCorrection) { d->inFlickCorrection = true; // Near an end and it seems that the extent has changed? // Recalculate the flick so that we don't end up in an odd position. diff --git a/tests/auto/qtquick1/qdeclarativegridview/tst_qdeclarativegridview.cpp b/tests/auto/qtquick1/qdeclarativegridview/tst_qdeclarativegridview.cpp index e96af51..c370a01 100644 --- a/tests/auto/qtquick1/qdeclarativegridview/tst_qdeclarativegridview.cpp +++ b/tests/auto/qtquick1/qdeclarativegridview/tst_qdeclarativegridview.cpp @@ -448,12 +448,12 @@ void tst_QDeclarative1GridView::removed() model.removeItem(1); // Confirm items positioned correctly - for (int i = 6; i < 18; ++i) { + for (int i = 3; i < 15; ++i) { QDeclarativeItem *item = findItem(contentItem, "wrapper", i); if (!item) qWarning() << "Item" << i << "not found"; QTRY_VERIFY(item); - QTRY_VERIFY(item->x() == (i%3)*80); - QTRY_VERIFY(item->y() == (i/3)*60); + QTRY_COMPARE(item->x(), (i%3)*80.0); + QTRY_COMPARE(item->y(), 60+(i/3)*60.0); } // Remove currentIndex @@ -474,7 +474,7 @@ void tst_QDeclarative1GridView::removed() if (!item) qWarning() << "Item" << i << "not found"; QTRY_VERIFY(item); QTRY_VERIFY(item->x() == (i%3)*80); - QTRY_VERIFY(item->y() == (i/3)*60); + QTRY_VERIFY(item->y() == 60+(i/3)*60); } // remove item outside current view.