diff options
Diffstat (limited to 'src/declarative/graphicsitems/qdeclarativelistview.cpp')
-rw-r--r-- | src/declarative/graphicsitems/qdeclarativelistview.cpp | 133 |
1 files changed, 76 insertions, 57 deletions
diff --git a/src/declarative/graphicsitems/qdeclarativelistview.cpp b/src/declarative/graphicsitems/qdeclarativelistview.cpp index 8695bc6..57b7dea 100644 --- a/src/declarative/graphicsitems/qdeclarativelistview.cpp +++ b/src/declarative/graphicsitems/qdeclarativelistview.cpp @@ -53,9 +53,14 @@ #include <qlistmodelinterface_p.h> #include <qmath.h> #include <QKeyEvent> +#include "qplatformdefs.h" QT_BEGIN_NAMESPACE +#ifndef QML_FLICK_SNAPONETHRESHOLD +#define QML_FLICK_SNAPONETHRESHOLD 30 +#endif + void QDeclarativeViewSection::setProperty(const QString &property) { if (property != m_property) { @@ -234,21 +239,6 @@ public: return visibleItems.count() ? visibleItems.first() : 0; } - FxListItem *nextVisibleItem() const { - const qreal pos = isRightToLeft() ? -position()-size() : position(); - bool foundFirst = false; - for (int i = 0; i < visibleItems.count(); ++i) { - FxListItem *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. FxListItem *itemBefore(int modelIndex) const { @@ -1007,7 +997,7 @@ void QDeclarativeListViewPrivate::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() @@ -1318,29 +1308,20 @@ void QDeclarativeListViewPrivate::fixup(AxisData &data, qreal minExtent, qreal m highlightEnd = highlightRangeEnd; } - if (currentItem && haveHighlightRange && highlightRange == QDeclarativeListView::StrictlyEnforceRange - && moveReason != QDeclarativeListViewPrivate::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 != QDeclarativeListView::NoSnap && moveReason != QDeclarativeListViewPrivate::SetIndex) { + if (snapMode != QDeclarativeListView::NoSnap && moveReason != QDeclarativeListViewPrivate::SetIndex) { qreal tempPosition = isRightToLeft() ? -position()-size() : position(); + if (snapMode == QDeclarativeListView::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; + } FxListItem *topItem = snapItemAt(tempPosition+highlightStart); FxListItem *bottomItem = snapItemAt(tempPosition+highlightEnd); qreal pos; @@ -1356,9 +1337,9 @@ void QDeclarativeListViewPrivate::fixup(AxisData &data, qreal minExtent, qreal m } } 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 { QDeclarativeFlickablePrivate::fixup(data, minExtent, maxExtent); return; @@ -1375,6 +1356,27 @@ void QDeclarativeListViewPrivate::fixup(AxisData &data, qreal minExtent, qreal m } vTime = timeline.time(); } + } else if (currentItem && haveHighlightRange && highlightRange == QDeclarativeListView::StrictlyEnforceRange + && moveReason != QDeclarativeListViewPrivate::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 { QDeclarativeFlickablePrivate::fixup(data, minExtent, maxExtent); } @@ -1396,12 +1398,19 @@ void QDeclarativeListViewPrivate::flick(AxisData &data, qreal minExtent, qreal m } 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 == QDeclarativeListView::SnapOneItem) { - if (FxListItem *item = isRightToLeft() ? nextVisibleItem() : firstVisibleItem()) - maxDistance = qAbs(item->position() + dataValue); + if (snapMode == QDeclarativeListView::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()); } @@ -1410,9 +1419,15 @@ void QDeclarativeListViewPrivate::flick(AxisData &data, qreal minExtent, qreal m data.flickTarget = minExtent; } else { if (data.move.value() > maxExtent) { - if (snapMode == QDeclarativeListView::SnapOneItem) { - if (FxListItem *item = isRightToLeft() ? firstVisibleItem() : nextVisibleItem()) - maxDistance = qAbs(item->position() + dataValue); + if (snapMode == QDeclarativeListView::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()); } @@ -1422,7 +1437,6 @@ void QDeclarativeListViewPrivate::flick(AxisData &data, qreal minExtent, qreal m } bool overShoot = boundsBehavior == QDeclarativeFlickable::DragAndOvershootBounds; - qreal highlightStart = isRightToLeft() && highlightRangeStartValid ? size()-highlightRangeEnd : highlightRangeStart; if (maxDistance > 0 || overShoot) { // These modes require the list to stop exactly on an item boundary. @@ -1436,7 +1450,7 @@ void QDeclarativeListViewPrivate::flick(AxisData &data, qreal minExtent, qreal m else v = maxVelocity; } - if (!flickingHorizontally && !flickingVertically) { + if (!hData.flicking && !vData.flicking) { // the initial flick - estimate boundary qreal accel = deceleration; qreal v2 = v * v; @@ -1448,8 +1462,10 @@ void QDeclarativeListViewPrivate::flick(AxisData &data, qreal minExtent, qreal m if (v > 0) dist = -dist; if ((maxDistance > 0.0 && v2 / (2.0f * maxDistance) < accel) || snapMode == QDeclarativeListView::SnapOneItem) { - qreal distTemp = isRightToLeft() ? -dist : dist; - data.flickTarget = -snapPosAt(-(dataValue - highlightStart) + distTemp) + highlightStart; + if (snapMode != QDeclarativeListView::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) { @@ -1487,14 +1503,14 @@ void QDeclarativeListViewPrivate::flick(AxisData &data, qreal minExtent, qreal m 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(); @@ -1870,6 +1886,8 @@ void QDeclarativeListView::setCurrentIndex(int index) if (index == d->currentIndex) return; if (isComponentComplete() && d->isValid()) { + if (d->layoutScheduled) + d->layout(); d->moveReason = QDeclarativeListViewPrivate::SetIndex; d->updateCurrent(index); } else if (d->currentIndex != index) { @@ -2555,7 +2573,8 @@ bool QDeclarativeListView::event(QEvent *event) { Q_D(QDeclarativeListView); if (event->type() == QEvent::User) { - d->layout(); + if (d->layoutScheduled) + d->layout(); return true; } @@ -2574,7 +2593,7 @@ void QDeclarativeListView::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 = QDeclarativeListViewPrivate::Mouse; if (d->moveReason != QDeclarativeListViewPrivate::SetIndex) { if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange && d->highlight) { @@ -2608,7 +2627,7 @@ void QDeclarativeListView::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. |