summaryrefslogtreecommitdiffstats
path: root/src/declarative/graphicsitems/qdeclarativelistview.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/declarative/graphicsitems/qdeclarativelistview.cpp')
-rw-r--r--src/declarative/graphicsitems/qdeclarativelistview.cpp130
1 files changed, 81 insertions, 49 deletions
diff --git a/src/declarative/graphicsitems/qdeclarativelistview.cpp b/src/declarative/graphicsitems/qdeclarativelistview.cpp
index 307c0a7..60e8f6c 100644
--- a/src/declarative/graphicsitems/qdeclarativelistview.cpp
+++ b/src/declarative/graphicsitems/qdeclarativelistview.cpp
@@ -50,6 +50,7 @@
#include <qdeclarativeguard_p.h>
#include <qlistmodelinterface_p.h>
+#include <qmath.h>
#include <QKeyEvent>
QT_BEGIN_NAMESPACE
@@ -270,6 +271,28 @@ public:
return 0;
}
+ qreal endPositionAt(int modelIndex) const {
+ if (FxListItem *item = visibleItem(modelIndex))
+ return item->endPosition();
+ if (!visibleItems.isEmpty()) {
+ if (modelIndex < visibleIndex) {
+ int count = visibleIndex - modelIndex;
+ return (*visibleItems.constBegin())->position() - (count - 1) * (averageSize + spacing) - spacing - 1;
+ } else {
+ int idx = visibleItems.count() - 1;
+ while (idx >= 0 && visibleItems.at(idx)->index == -1)
+ --idx;
+ if (idx < 0)
+ idx = visibleIndex;
+ else
+ idx = visibleItems.at(idx)->index;
+ int count = modelIndex - idx - 1;
+ return (*(--visibleItems.constEnd()))->endPosition() + count * (averageSize + spacing);
+ }
+ }
+ return 0;
+ }
+
QString sectionAt(int modelIndex) {
if (FxListItem *item = visibleItem(modelIndex))
return item->attached->section();
@@ -395,13 +418,16 @@ public:
}
void itemGeometryChanged(QDeclarativeItem *item, const QRectF &newGeometry, const QRectF &oldGeometry) {
+ Q_Q(QDeclarativeListView);
QDeclarativeFlickablePrivate::itemGeometryChanged(item, newGeometry, oldGeometry);
- if (item != viewport) {
+ if (item != viewport && (!highlight || item != highlight->item)) {
if ((orient == QDeclarativeListView::Vertical && newGeometry.height() != oldGeometry.height())
|| (orient == QDeclarativeListView::Horizontal && newGeometry.width() != oldGeometry.width())) {
scheduleLayout();
}
}
+ if (trackedItem && trackedItem->item == item)
+ q->trackedPositionChanged();
}
// for debugging only
@@ -566,13 +592,8 @@ void QDeclarativeListViewPrivate::releaseItem(FxListItem *item)
Q_Q(QDeclarativeListView);
if (!item || !model)
return;
- if (trackedItem == item) {
- const char *notifier1 = orient == QDeclarativeListView::Vertical ? SIGNAL(yChanged()) : SIGNAL(xChanged());
- const char *notifier2 = orient == QDeclarativeListView::Vertical ? SIGNAL(heightChanged()) : SIGNAL(widthChanged());
- QObject::disconnect(trackedItem->item, notifier1, q, SLOT(trackedPositionChanged()));
- QObject::disconnect(trackedItem->item, notifier2, q, SLOT(trackedPositionChanged()));
+ if (trackedItem == item)
trackedItem = 0;
- }
QDeclarativeItemPrivate *itemPrivate = static_cast<QDeclarativeItemPrivate*>(QGraphicsItemPrivate::get(item->item));
itemPrivate->removeItemChangeListener(this, QDeclarativeItemPrivate::Geometry);
if (model->release(item->item) == 0) {
@@ -769,21 +790,7 @@ void QDeclarativeListViewPrivate::updateTrackedItem()
FxListItem *item = currentItem;
if (highlight)
item = highlight;
-
- const char *notifier1 = orient == QDeclarativeListView::Vertical ? SIGNAL(yChanged()) : SIGNAL(xChanged());
- const char *notifier2 = orient == QDeclarativeListView::Vertical ? SIGNAL(heightChanged()) : SIGNAL(widthChanged());
-
- if (trackedItem && item != trackedItem) {
- QObject::disconnect(trackedItem->item, notifier1, q, SLOT(trackedPositionChanged()));
- QObject::disconnect(trackedItem->item, notifier2, q, SLOT(trackedPositionChanged()));
- trackedItem = 0;
- }
-
- if (!trackedItem && item) {
- trackedItem = item;
- QObject::connect(trackedItem->item, notifier1, q, SLOT(trackedPositionChanged()));
- QObject::connect(trackedItem->item, notifier2, q, SLOT(trackedPositionChanged()));
- }
+ trackedItem = item;
if (trackedItem)
q->trackedPositionChanged();
}
@@ -832,6 +839,8 @@ void QDeclarativeListViewPrivate::createHighlight()
highlight->item->setWidth(currentItem->item->width());
}
}
+ QDeclarativeItemPrivate *itemPrivate = static_cast<QDeclarativeItemPrivate*>(QGraphicsItemPrivate::get(item));
+ itemPrivate->addItemChangeListener(this, QDeclarativeItemPrivate::Geometry);
const QLatin1String posProp(orient == QDeclarativeListView::Vertical ? "y" : "x");
highlightPosAnimator = new QSmoothedAnimation(q);
highlightPosAnimator->target = QDeclarativeProperty(highlight->item, posProp);
@@ -1101,23 +1110,27 @@ void QDeclarativeListViewPrivate::fixup(AxisData &data, qreal minExtent, qreal m
|| (orient == QDeclarativeListView::Vertical && &data == &hData))
return;
- if ((&data == &vData && !q->yflick())
- || (&data == &hData && !q->xflick())
- || data.move.timeLine())
- return;
-
int oldDuration = fixupDuration;
fixupDuration = moveReason == Mouse ? fixupDuration : 0;
if (haveHighlightRange && highlightRange == QDeclarativeListView::StrictlyEnforceRange) {
- if (currentItem && currentItem->position() - position() != highlightRangeStart) {
- qreal pos = currentItem->position() - highlightRangeStart;
+ if (currentItem) {
+ updateHighlight();
+ qreal pos = currentItem->position();
+ qreal viewPos = position();
+ if (viewPos < pos + currentItem->size() - highlightRangeEnd)
+ viewPos = pos + currentItem->size() - highlightRangeEnd;
+ if (viewPos > pos - highlightRangeStart)
+ viewPos = pos - highlightRangeStart;
+
timeline.reset(data.move);
- if (fixupDuration) {
- timeline.move(data.move, -pos, QEasingCurve(QEasingCurve::InOutQuad), fixupDuration/2);
- } else {
- data.move.setValue(-pos);
- q->viewportMoved();
+ if (viewPos != position()) {
+ if (fixupDuration) {
+ timeline.move(data.move, -viewPos, QEasingCurve(QEasingCurve::InOutQuad), fixupDuration/2);
+ } else {
+ data.move.setValue(-viewPos);
+ q->viewportMoved();
+ }
}
vTime = timeline.time();
}
@@ -1177,6 +1190,7 @@ void QDeclarativeListViewPrivate::flick(AxisData &data, qreal minExtent, qreal m
if (snapMode == QDeclarativeListView::NoSnap && highlightRange != QDeclarativeListView::StrictlyEnforceRange)
data.flickTarget = maxExtent;
}
+ bool overShoot = boundsBehavior == QDeclarativeFlickable::DragAndOvershootBounds;
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.
@@ -1211,7 +1225,15 @@ void QDeclarativeListViewPrivate::flick(AxisData &data, qreal minExtent, qreal m
data.flickTarget -= overshootDist;
}
}
- dist = -data.flickTarget + data.move.value();
+ qreal adjDist = -data.flickTarget + data.move.value();
+ if (qAbs(adjDist) > qAbs(dist)) {
+ // Prevent painfully slow flicking - adjust velocity to suit flickDeceleration
+ v2 = accel * 2.0f * qAbs(dist);
+ v = qSqrt(v2);
+ if (dist > 0)
+ v = -v;
+ }
+ dist = adjDist;
accel = v2 / (2.0f * qAbs(dist));
} else if (overShoot) {
data.flickTarget = data.move.value() - dist;
@@ -1286,7 +1308,7 @@ void QDeclarativeListViewPrivate::flick(AxisData &data, qreal minExtent, qreal m
In this case ListModel is a handy way for us to test our UI. In practice
the model would be implemented in C++, or perhaps via a SQL data source.
- Note that views do not enable \e clip automatically. If the view
+ \bold Note that views do not enable \e clip automatically. If the view
is not clipped by another item or the screen, it will be necessary
to set \e {clip: true} in order to have the out of view items clipped
nicely.
@@ -2062,12 +2084,12 @@ void QDeclarativeListView::viewportMoved()
if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange && d->highlight) {
// reposition highlight
qreal pos = d->highlight->position();
- qreal viewPos = qRound(d->position());
- if (pos > viewPos + d->highlightRangeEnd - 1 - d->highlight->size())
- pos = viewPos + d->highlightRangeEnd - 1 - d->highlight->size();
+ qreal viewPos = d->position();
+ if (pos > viewPos + d->highlightRangeEnd - d->highlight->size())
+ pos = viewPos + d->highlightRangeEnd - d->highlight->size();
if (pos < viewPos + d->highlightRangeStart)
pos = viewPos + d->highlightRangeStart;
- d->highlight->setPosition(pos);
+ d->highlight->setPosition(qRound(pos));
// update current index
int idx = d->snapIndex();
@@ -2124,8 +2146,10 @@ qreal QDeclarativeListView::minYExtent() const
d->minExtent = -d->startPosition();
if (d->header && d->visibleItems.count())
d->minExtent += d->header->size();
- if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange)
+ if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
d->minExtent += d->highlightRangeStart;
+ d->minExtent = qMax(d->minExtent, -(d->endPositionAt(0) - d->highlightRangeEnd + 1));
+ }
d->minExtentDirty = false;
}
@@ -2139,10 +2163,12 @@ qreal QDeclarativeListView::maxYExtent() const
return height();
if (d->maxExtentDirty) {
if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
- d->maxExtent = -(d->endPosition() - d->highlightRangeEnd);
- d->maxExtent = qMax(d->maxExtent, -(d->positionAt(d->model->count()-1) - d->highlightRangeStart));
- } else
+ d->maxExtent = -(d->positionAt(d->model->count()-1) - d->highlightRangeStart);
+ if (d->highlightRangeEnd != d->highlightRangeStart)
+ d->maxExtent = qMin(d->maxExtent, -(d->endPosition() - d->highlightRangeEnd + 1));
+ } else {
d->maxExtent = -(d->endPosition() - height() + 1);
+ }
if (d->footer)
d->maxExtent -= d->footer->size();
qreal minY = minYExtent();
@@ -2162,8 +2188,10 @@ qreal QDeclarativeListView::minXExtent() const
d->minExtent = -d->startPosition();
if (d->header)
d->minExtent += d->header->size();
- if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange)
+ if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
d->minExtent += d->highlightRangeStart;
+ d->minExtent = qMax(d->minExtent, -(d->endPositionAt(0) - d->highlightRangeEnd + 1));
+ }
d->minExtentDirty = false;
}
@@ -2177,10 +2205,12 @@ qreal QDeclarativeListView::maxXExtent() const
return width();
if (d->maxExtentDirty) {
if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
- d->maxExtent = -(d->endPosition() - d->highlightRangeEnd);
- d->maxExtent = qMax(d->maxExtent, -(d->positionAt(d->model->count()-1) - d->highlightRangeStart));
- } else
+ d->maxExtent = -(d->positionAt(d->model->count()-1) - d->highlightRangeStart);
+ if (d->highlightRangeEnd != d->highlightRangeStart)
+ d->maxExtent = qMin(d->maxExtent, -(d->endPosition() - d->highlightRangeEnd + 1));
+ } else {
d->maxExtent = -(d->endPosition() - width() + 1);
+ }
if (d->footer)
d->maxExtent -= d->footer->size();
qreal minX = minXExtent();
@@ -2389,7 +2419,7 @@ void QDeclarativeListView::trackedPositionChanged()
if (!d->trackedItem || !d->currentItem)
return;
if (!isFlicking() && !d->moving && d->moveReason == QDeclarativeListViewPrivate::SetIndex) {
- const qreal trackedPos = d->trackedItem->position();
+ const qreal trackedPos = qCeil(d->trackedItem->position());
const qreal viewPos = d->position();
if (d->haveHighlightRange) {
if (d->highlightRange == StrictlyEnforceRange) {
@@ -2823,6 +2853,8 @@ void QDeclarativeListView::animStopped()
{
Q_D(QDeclarativeListView);
d->bufferMode = QDeclarativeListViewPrivate::NoBuffer;
+ if (d->haveHighlightRange && d->highlightRange == QDeclarativeListView::StrictlyEnforceRange)
+ d->updateHighlight();
}
QDeclarativeListViewAttached *QDeclarativeListView::qmlAttachedProperties(QObject *obj)