Search
SailfishOS Open Build Service
>
Projects
>
home:kaltsi
:
tnhlbug
>
qt
> 0012-Backport-Flickable-margins.patch
Log In
Username
Password
Cancel
Overview
Repositories
Revisions
Requests
Users
Advanced
Attributes
Meta
File 0012-Backport-Flickable-margins.patch of Package qt
From 781e0e00edf439a34ba087fd5e460bb4640f31fb Mon Sep 17 00:00:00 2001 From: Martin Jones <martin.jones@qinetic.com.au> Date: Mon, 22 Oct 2012 16:06:10 +1000 Subject: [PATCH 12/29] Backport Flickable margins Backport topMargin, BottomMargin, etc. and originX, originY in QtQuick 1.2 --- .../graphicsitems/qdeclarativeflickable.cpp | 170 ++++++++++++++++++-- .../graphicsitems/qdeclarativeflickable_p.h | 30 ++++ .../graphicsitems/qdeclarativeflickable_p_p.h | 19 ++- .../graphicsitems/qdeclarativegridview.cpp | 81 +++++++++- .../graphicsitems/qdeclarativegridview_p.h | 1 + .../graphicsitems/qdeclarativelistview.cpp | 97 +++++++---- .../graphicsitems/qdeclarativelistview_p.h | 1 + 7 files changed, 351 insertions(+), 48 deletions(-) diff --git a/src/declarative/graphicsitems/qdeclarativeflickable.cpp b/src/declarative/graphicsitems/qdeclarativeflickable.cpp index 8982c6d..338c1fc 100644 --- a/src/declarative/graphicsitems/qdeclarativeflickable.cpp +++ b/src/declarative/graphicsitems/qdeclarativeflickable.cpp @@ -417,6 +417,16 @@ void QDeclarativeFlickablePrivate::updateBeginningEnd() atBoundaryChange = true; } + if (vData.extentsChanged) { + vData.extentsChanged = false; + emit q->originYChanged(); + } + + if (hData.extentsChanged) { + hData.extentsChanged = false; + emit q->originXChanged(); + } + if (atBoundaryChange) emit q->isAtBoundaryChanged(); @@ -577,6 +587,7 @@ qreal QDeclarativeFlickable::contentX() const void QDeclarativeFlickable::setContentX(qreal pos) { Q_D(QDeclarativeFlickable); + d->hData.explicitValue = true; d->timeline.reset(d->hData.move); d->vTime = d->timeline.time(); movementXEnding(); @@ -595,6 +606,7 @@ qreal QDeclarativeFlickable::contentY() const void QDeclarativeFlickable::setContentY(qreal pos) { Q_D(QDeclarativeFlickable); + d->hData.explicitValue = true; d->timeline.reset(d->vData.move); d->vTime = d->timeline.time(); movementYEnding(); @@ -775,10 +787,10 @@ void QDeclarativeFlickablePrivate::handleMousePressEvent(QGraphicsSceneMouseEven timeline.clear(); hData.reset(); vData.reset(); - hData.dragMinBound = q->minXExtent(); - vData.dragMinBound = q->minYExtent(); - hData.dragMaxBound = q->maxXExtent(); - vData.dragMaxBound = q->maxYExtent(); + hData.dragMinBound = q->minXExtent() - hData.startMargin; + vData.dragMinBound = q->minYExtent() - vData.startMargin; + hData.dragMaxBound = q->maxXExtent() + hData.endMargin; + vData.dragMaxBound = q->maxYExtent() + vData.endMargin; fixupMode = Normal; lastPos = QPoint(); QDeclarativeItemPrivate::start(lastPosTime); @@ -808,8 +820,11 @@ void QDeclarativeFlickablePrivate::handleMouseMoveEvent(QGraphicsSceneMouseEvent if (!vMoved) vData.dragStartOffset = dy; qreal newY = dy + vData.pressPos - vData.dragStartOffset; - const qreal minY = vData.dragMinBound; - const qreal maxY = vData.dragMaxBound; + // Recalculate bounds in case margins have changed, but use the content + // size estimate taken at the start of the drag in case the drag causes + // the estimate to be altered + const qreal minY = vData.dragMinBound + vData.startMargin; + const qreal maxY = vData.dragMaxBound - vData.endMargin; if (newY > minY) newY = minY + (newY - minY) / 2; if (newY < maxY && maxY - minY <= 0) @@ -840,8 +855,8 @@ void QDeclarativeFlickablePrivate::handleMouseMoveEvent(QGraphicsSceneMouseEvent if (!hMoved) hData.dragStartOffset = dx; qreal newX = dx + hData.pressPos - hData.dragStartOffset; - const qreal minX = hData.dragMinBound; - const qreal maxX = hData.dragMaxBound; + const qreal minX = hData.dragMinBound + hData.startMargin; + const qreal maxX = hData.dragMaxBound - hData.endMargin; if (newX > minX) newX = minX + (newX - minX) / 2; if (newX < maxX && maxX - minX <= 0) @@ -1117,23 +1132,37 @@ void QDeclarativeFlickable::timerEvent(QTimerEvent *event) qreal QDeclarativeFlickable::minYExtent() const { - return 0.0; + Q_D(const QDeclarativeFlickable); + return d->vData.startMargin; } qreal QDeclarativeFlickable::minXExtent() const { - return 0.0; + Q_D(const QDeclarativeFlickable); + return d->hData.startMargin; } /* returns -ve */ qreal QDeclarativeFlickable::maxXExtent() const { - return width() - vWidth(); + Q_D(const QDeclarativeFlickable); + return width() - vWidth() - d->hData.endMargin; } /* returns -ve */ qreal QDeclarativeFlickable::maxYExtent() const { - return height() - vHeight(); + Q_D(const QDeclarativeFlickable); + return height() - vHeight() - d->vData.endMargin; +} + +void QDeclarativeFlickable::componentComplete() +{ + Q_D(QDeclarativeFlickable); + QDeclarativeItem::componentComplete(); + if (!d->hData.explicitValue && d->hData.startMargin != 0.) + setContentX(-minXExtent()); + if (!d->vData.explicitValue && d->vData.startMargin != 0.) + setContentY(-minYExtent()); } void QDeclarativeFlickable::viewportMoved() @@ -1377,6 +1406,7 @@ void QDeclarativeFlickable::setContentWidth(qreal w) d->contentItem->setWidth(width()); else d->contentItem->setWidth(w); + d->hData.markExtentsDirty(); // Make sure that we're entirely in view. if (!d->pressed && !d->hData.moving && !d->vData.moving) { d->fixupMode = QDeclarativeFlickablePrivate::Immediate; @@ -1405,6 +1435,7 @@ void QDeclarativeFlickable::setContentHeight(qreal h) d->contentItem->setHeight(height()); else d->contentItem->setHeight(h); + d->vData.markExtentsDirty(); // Make sure that we're entirely in view. if (!d->pressed && !d->hData.moving && !d->vData.moving) { d->fixupMode = QDeclarativeFlickablePrivate::Immediate; @@ -1418,6 +1449,121 @@ void QDeclarativeFlickable::setContentHeight(qreal h) } /*! + \qmlproperty real Flickable::topMargin + \qmlproperty real Flickable::leftMargin + \qmlproperty real Flickable::bottomMargin + \qmlproperty real Flickable::rightMargin + + These properties hold the margins around the content. This space is reserved + in addition to the contentWidth and contentHeight. +*/ + +qreal QDeclarativeFlickable::topMargin() const +{ + Q_D(const QDeclarativeFlickable); + return d->vData.startMargin; +} + +void QDeclarativeFlickable::setTopMargin(qreal m) +{ + Q_D(QDeclarativeFlickable); + if (d->vData.startMargin == m) + return; + d->vData.startMargin = m; + d->vData.markExtentsDirty(); + if (!d->pressed && !d->hData.moving && !d->vData.moving) { + d->fixupMode = QDeclarativeFlickablePrivate::Immediate; + d->fixupY(); + } + emit topMarginChanged(); + d->updateBeginningEnd(); +} + +qreal QDeclarativeFlickable::bottomMargin() const +{ + Q_D(const QDeclarativeFlickable); + return d->vData.endMargin; +} + +void QDeclarativeFlickable::setBottomMargin(qreal m) +{ + Q_D(QDeclarativeFlickable); + if (d->vData.endMargin == m) + return; + d->vData.endMargin = m; + d->vData.markExtentsDirty(); + if (!d->pressed && !d->hData.moving && !d->vData.moving) { + d->fixupMode = QDeclarativeFlickablePrivate::Immediate; + d->fixupY(); + } + emit bottomMarginChanged(); + d->updateBeginningEnd(); +} + +qreal QDeclarativeFlickable::leftMargin() const +{ + Q_D(const QDeclarativeFlickable); + return d->hData.startMargin; +} + +void QDeclarativeFlickable::setLeftMargin(qreal m) +{ + Q_D(QDeclarativeFlickable); + if (d->hData.startMargin == m) + return; + d->hData.startMargin = m; + d->hData.markExtentsDirty(); + if (!d->pressed && !d->hData.moving && !d->vData.moving) { + d->fixupMode = QDeclarativeFlickablePrivate::Immediate; + d->fixupX(); + } + emit leftMarginChanged(); + d->updateBeginningEnd(); +} + +qreal QDeclarativeFlickable::rightMargin() const +{ + Q_D(const QDeclarativeFlickable); + return d->hData.endMargin; +} + +void QDeclarativeFlickable::setRightMargin(qreal m) +{ + Q_D(QDeclarativeFlickable); + if (d->hData.endMargin == m) + return; + d->hData.endMargin = m; + d->hData.markExtentsDirty(); + if (!d->pressed && !d->hData.moving && !d->vData.moving) { + d->fixupMode = QDeclarativeFlickablePrivate::Immediate; + d->fixupX(); + } + emit rightMarginChanged(); + d->updateBeginningEnd(); +} + +/*! + \qmlproperty real Flickable::originY + \qmlproperty real Flickable::originX + + These properties hold the origin of the content. This is usually (0,0), however + ListView and GridView may have an arbitrary origin due to delegate size variation, + or item insertion/removal outside the visible region. +*/ + +qreal QDeclarativeFlickable::originY() const +{ + Q_D(const QDeclarativeFlickable); + return -minYExtent() + d->vData.startMargin; +} + +qreal QDeclarativeFlickable::originX() const +{ + Q_D(const QDeclarativeFlickable); + return -minXExtent() + d->hData.startMargin; +} + +/*! \qmlmethod Flickable::resizeContent(real width, real height, QPointF center) \preliminary \since QtQuick 1.1 diff --git a/src/declarative/graphicsitems/qdeclarativeflickable_p.h b/src/declarative/graphicsitems/qdeclarativeflickable_p.h index c5561b3..3e46d08 100644 --- a/src/declarative/graphicsitems/qdeclarativeflickable_p.h +++ b/src/declarative/graphicsitems/qdeclarativeflickable_p.h @@ -62,6 +62,14 @@ class Q_AUTOTEST_EXPORT QDeclarativeFlickable : public QDeclarativeItem Q_PROPERTY(qreal contentY READ contentY WRITE setContentY NOTIFY contentYChanged) Q_PROPERTY(QDeclarativeItem *contentItem READ contentItem CONSTANT) + Q_PROPERTY(qreal topMargin READ topMargin WRITE setTopMargin NOTIFY topMarginChanged REVISION 2) + Q_PROPERTY(qreal bottomMargin READ bottomMargin WRITE setBottomMargin NOTIFY bottomMarginChanged REVISION 2) + Q_PROPERTY(qreal originY READ originY NOTIFY originYChanged REVISION 2) + + Q_PROPERTY(qreal leftMargin READ leftMargin WRITE setLeftMargin NOTIFY leftMarginChanged REVISION 2) + Q_PROPERTY(qreal rightMargin READ rightMargin WRITE setRightMargin NOTIFY rightMarginChanged REVISION 2) + Q_PROPERTY(qreal originX READ originX NOTIFY originXChanged REVISION 2) + Q_PROPERTY(qreal horizontalVelocity READ horizontalVelocity NOTIFY horizontalVelocityChanged) Q_PROPERTY(qreal verticalVelocity READ verticalVelocity NOTIFY verticalVelocityChanged) @@ -119,6 +127,21 @@ public: qreal contentY() const; virtual void setContentY(qreal pos); + qreal topMargin() const; + void setTopMargin(qreal m); + + qreal bottomMargin() const; + void setBottomMargin(qreal m); + + qreal leftMargin() const; + void setLeftMargin(qreal m); + + qreal rightMargin() const; + void setRightMargin(qreal m); + + virtual qreal originY() const; + virtual qreal originX() const; + bool isMoving() const; bool isMovingHorizontally() const; bool isMovingVertically() const; @@ -187,6 +210,12 @@ Q_SIGNALS: void flickEnded(); void dragStarted(); void dragEnded(); + Q_REVISION(2) void topMarginChanged(); + Q_REVISION(2) void bottomMarginChanged(); + Q_REVISION(2) void leftMarginChanged(); + Q_REVISION(2) void rightMarginChanged(); + Q_REVISION(2) void originYChanged(); + Q_REVISION(2) void originXChanged(); protected: virtual bool sceneEventFilter(QGraphicsItem *, QEvent *); @@ -212,6 +241,7 @@ protected: virtual qreal maxYExtent() const; qreal vWidth() const; qreal vHeight() const; + virtual void componentComplete(); virtual void viewportMoved(); virtual void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry); diff --git a/src/declarative/graphicsitems/qdeclarativeflickable_p_p.h b/src/declarative/graphicsitems/qdeclarativeflickable_p_p.h index 941ed3f..3e5890e 100644 --- a/src/declarative/graphicsitems/qdeclarativeflickable_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativeflickable_p_p.h @@ -98,8 +98,11 @@ public: struct AxisData { AxisData(QDeclarativeFlickablePrivate *fp, void (QDeclarativeFlickablePrivate::*func)(qreal)) - : move(fp, func), viewSize(-1), smoothVelocity(fp), atEnd(false), atBeginning(true) - , fixingUp(false), inOvershoot(false), moving(false), flicking(false), dragging(false) + : move(fp, func), viewSize(-1), startMargin(0), endMargin(0) + , smoothVelocity(fp), atEnd(false), atBeginning(true) + , fixingUp(false), inOvershoot(false), moving(false), flicking(false) + , dragging(false), extentsChanged(false) + , explicitValue(false), minExtentDirty(true), maxExtentDirty(true) {} void reset() { @@ -109,6 +112,12 @@ public: inOvershoot = false; } + void markExtentsDirty() { + minExtentDirty = true; + maxExtentDirty = true; + extentsChanged = true; + } + void addVelocitySample(qreal v, qreal maxVelocity); void updateVelocity(); @@ -120,6 +129,8 @@ public: qreal dragMaxBound; qreal velocity; qreal flickTarget; + qreal startMargin; + qreal endMargin; QDeclarativeFlickablePrivate::Velocity smoothVelocity; QPODVector<qreal,10> velocityBuffer; bool atEnd : 1; @@ -129,6 +140,10 @@ public: bool moving : 1; bool flicking : 1; bool dragging : 1; + bool extentsChanged : 1; + bool explicitValue : 1; + mutable bool minExtentDirty : 1; + mutable bool maxExtentDirty : 1; }; void flickX(qreal velocity); diff --git a/src/declarative/graphicsitems/qdeclarativegridview.cpp b/src/declarative/graphicsitems/qdeclarativegridview.cpp index 938a114..cc60883 100644 --- a/src/declarative/graphicsitems/qdeclarativegridview.cpp +++ b/src/declarative/graphicsitems/qdeclarativegridview.cpp @@ -202,7 +202,7 @@ public: if (q->isComponentComplete()) { clear(); updateGrid(); - setPosition(0); + setPosition(contentStartOffset()); q->refill(); updateCurrent(currentIndex); } @@ -248,11 +248,11 @@ public: } qreal startPosition() const { - return isRightToLeftTopToBottom() ? -lastPosition()+1 : originPosition(); + return isRightToLeftTopToBottom() ? -lastPosition() : originPosition(); } qreal endPosition() const { - return isRightToLeftTopToBottom() ? -originPosition()+1 : lastPosition(); + return isRightToLeftTopToBottom() ? -originPosition() : lastPosition(); } @@ -408,6 +408,25 @@ public: : header->item->width(); } + qreal footerSize() const { + if (!footer) + return 0.0; + + return flow == QDeclarativeGridView::LeftToRight + ? footer->item->height() + : footer->item->width(); + } + + void updateViewport() { + Q_Q(QDeclarativeGridView); + qreal extra = headerSize() + footerSize(); + qreal contentSize = isValid() ? (endPosition() - startPosition() + 1) : 0.0; + if (flow == QDeclarativeGridView::LeftToRight) { + q->setContentHeight(contentSize + extra); + } else { + q->setContentWidth(contentSize + extra); + } + } virtual void itemGeometryChanged(QDeclarativeItem *item, const QRectF &newGeometry, const QRectF &oldGeometry) { Q_Q(const QDeclarativeGridView); @@ -428,6 +447,28 @@ public: } } + void markExtentsDirty() { + if (flow == QDeclarativeGridView::LeftToRight) + vData.markExtentsDirty(); + else + hData.markExtentsDirty(); + } + + qreal contentStartOffset() const { + Q_Q(const QDeclarativeGridView); + qreal pos = 0; + if (flow == QDeclarativeGridView::LeftToRight) { + pos = -vData.startMargin; + } else { + if (q->effectiveLayoutDirection() == Qt::LeftToRight) + pos = -hData.startMargin; + else + pos = -hData.endMargin; + } + + return pos; + } + void positionViewAtIndex(int index, int mode); virtual void fixup(AxisData &data, qreal minExtent, qreal maxExtent); virtual void flick(AxisData &data, qreal minExtent, qreal maxExtent, qreal vSize, @@ -514,6 +555,7 @@ void QDeclarativeGridViewPrivate::clear() currentItem = 0; createHighlight(); trackedItem = 0; + markExtentsDirty(); itemCount = 0; } @@ -712,6 +754,7 @@ void QDeclarativeGridViewPrivate::refill(qreal from, qreal to, bool doBuffer) deferredRelease = true; } if (changed) { + markExtentsDirty(); if (header) updateHeader(); if (footer) @@ -754,6 +797,8 @@ void QDeclarativeGridViewPrivate::layout() layoutScheduled = false; if (!isValid() && !visibleItems.count()) { clear(); + fixupMode = QDeclarativeFlickablePrivate::Immediate; + fixupPosition(); return; } if (visibleItems.count()) { @@ -779,6 +824,7 @@ void QDeclarativeGridViewPrivate::layout() if (footer) updateFooter(); q->refill(); + markExtentsDirty(); updateHighlight(); moveReason = Other; if (flow == QDeclarativeGridView::LeftToRight) { @@ -1440,6 +1486,7 @@ void QDeclarativeGridView::setModel(const QVariant &model) disconnect(d->model, SIGNAL(destroyingItem(QDeclarativeItem*)), this, SLOT(destroyingItem(QDeclarativeItem*))); } d->clear(); + d->setPosition(d->contentStartOffset()); d->modelVariant = model; QObject *object = qvariant_cast<QObject*>(model); QDeclarativeVisualModel *vim = 0; @@ -1481,6 +1528,8 @@ void QDeclarativeGridView::setModel(const QVariant &model) connect(d->model, SIGNAL(createdItem(int,QDeclarativeItem*)), this, SLOT(createdItem(int,QDeclarativeItem*))); connect(d->model, SIGNAL(destroyingItem(QDeclarativeItem*)), this, SLOT(destroyingItem(QDeclarativeItem*))); emit countChanged(); + } else if (isComponentComplete()) { + d->updateViewport(); } emit modelChanged(); } @@ -2059,6 +2108,7 @@ void QDeclarativeGridView::setFooter(QDeclarativeComponent *footer) d->footer = 0; } d->footerComponent = footer; + d->markExtentsDirty(); if (isComponentComplete()) { d->updateFooter(); d->updateGrid(); @@ -2095,6 +2145,7 @@ void QDeclarativeGridView::setHeader(QDeclarativeComponent *header) d->header = 0; } d->headerComponent = header; + d->markExtentsDirty(); if (isComponentComplete()) { d->updateHeader(); d->updateFooter(); @@ -2121,6 +2172,15 @@ void QDeclarativeGridView::setContentY(qreal pos) QDeclarativeFlickable::setContentY(pos); } +qreal QDeclarativeGridView::originX() const +{ + Q_D(const QDeclarativeGridView); + if (d->isRightToLeftTopToBottom()) + return -maxXExtent() + d->size() - d->hData.endMargin; + else + return -minXExtent() + d->hData.startMargin; +} + bool QDeclarativeGridView::event(QEvent *event) { Q_D(QDeclarativeGridView); @@ -2201,13 +2261,14 @@ qreal QDeclarativeGridView::minYExtent() const Q_D(const QDeclarativeGridView); if (d->flow == QDeclarativeGridView::TopToBottom) return QDeclarativeFlickable::minYExtent(); - qreal extent = -d->startPosition(); + qreal extent = d->vData.startMargin - d->startPosition(); if (d->header && d->visibleItems.count()) extent += d->header->item->height(); if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) { extent += d->highlightRangeStart; extent = qMax(extent, -(d->rowPosAt(0) + d->rowSize() - d->highlightRangeEnd)); } + d->hData.minExtentDirty = false; return extent; } @@ -2228,9 +2289,11 @@ qreal QDeclarativeGridView::maxYExtent() const } if (d->footer) extent -= d->footer->item->height(); + extent -= d->vData.endMargin; const qreal minY = minYExtent(); if (extent > minY) extent = minY; + d->vData.maxExtentDirty = false; return extent; } @@ -2239,7 +2302,7 @@ qreal QDeclarativeGridView::minXExtent() const Q_D(const QDeclarativeGridView); if (d->flow == QDeclarativeGridView::LeftToRight) return QDeclarativeFlickable::minXExtent(); - qreal extent = -d->startPosition(); + qreal extent = -d->startPosition() + d->hData.startMargin; qreal highlightStart; qreal highlightEnd; qreal endPositionFirstItem = 0; @@ -2263,6 +2326,7 @@ qreal QDeclarativeGridView::minXExtent() const extent += d->isRightToLeftTopToBottom() ? -highlightStart : highlightStart; extent = qMax(extent, -(endPositionFirstItem - highlightEnd)); } + d->hData.minExtentDirty = false; return extent; } @@ -2300,14 +2364,17 @@ qreal QDeclarativeGridView::maxXExtent() const if (d->isRightToLeftTopToBottom()) { if (d->header) extent -= d->header->item->width(); + extent -= d->hData.endMargin; } else { if (d->footer) extent -= d->footer->item->width(); + extent -= d->hData.endMargin; } const qreal minX = minXExtent(); if (extent > minX) extent = minX; + d->hData.maxExtentDirty = false; return extent; } @@ -2680,6 +2747,7 @@ void QDeclarativeGridView::componentComplete() d->updateHeader(); d->updateFooter(); d->updateGrid(); + d->setPosition(d->contentStartOffset()); if (d->isValid()) { refill(); d->moveReason = QDeclarativeGridViewPrivate::SetIndex; @@ -2694,6 +2762,8 @@ void QDeclarativeGridView::componentComplete() } d->moveReason = QDeclarativeGridViewPrivate::Other; d->fixupPosition(); + } else { + d->updateViewport(); } } @@ -2978,6 +3048,7 @@ void QDeclarativeGridView::itemsRemoved(int modelIndex, int count) d->setPosition(0); d->updateHeader(); d->updateFooter(); + d->updateViewport(); update(); } } diff --git a/src/declarative/graphicsitems/qdeclarativegridview_p.h b/src/declarative/graphicsitems/qdeclarativegridview_p.h index 6ca2ea5..2371db4 100644 --- a/src/declarative/graphicsitems/qdeclarativegridview_p.h +++ b/src/declarative/graphicsitems/qdeclarativegridview_p.h @@ -162,6 +162,7 @@ public: virtual void setContentX(qreal pos); virtual void setContentY(qreal pos); + virtual qreal originX() const; enum PositionMode { Beginning, Center, End, Visible, Contain }; diff --git a/src/declarative/graphicsitems/qdeclarativelistview.cpp b/src/declarative/graphicsitems/qdeclarativelistview.cpp index 9d1238c..a1ccdfb 100644 --- a/src/declarative/graphicsitems/qdeclarativelistview.cpp +++ b/src/declarative/graphicsitems/qdeclarativelistview.cpp @@ -210,7 +210,6 @@ public: , correctFlick(false), inFlickCorrection(false), lazyRelease(false) , deferredRelease(false), layoutScheduled(false), currentIndexCleared(false) , inViewportMoved(false) - , minExtentDirty(true), maxExtentDirty(true) {} void init(); @@ -473,12 +472,32 @@ public: return -1; // Not in visibleList } + qreal headerSize() const { + if (!header) + return 0.0; + + return orient == QDeclarativeListView::Vertical + ? header->item->height() + : header->item->width(); + } + + qreal footerSize() const { + if (!footer) + return 0.0; + + return orient == QDeclarativeListView::Vertical + ? footer->item->height() + : footer->item->width(); + } + void updateViewport() { Q_Q(QDeclarativeListView); + qreal extra = headerSize() + footerSize(); + qreal contentSize = isValid() ? (endPosition() - startPosition() + 1) : 0.0; if (orient == QDeclarativeListView::Vertical) { - q->setContentHeight(endPosition() - startPosition() + 1); + q->setContentHeight(contentSize + extra); } else { - q->setContentWidth(endPosition() - startPosition() + 1); + q->setContentWidth(contentSize + extra); } } @@ -505,6 +524,13 @@ public: q->trackedPositionChanged(); } + void markExtentsDirty() { + if (orient == QDeclarativeListView::Vertical) + vData.markExtentsDirty(); + else + hData.markExtentsDirty(); + } + // for debugging only void checkVisible() const { int skip = 0; @@ -596,8 +622,6 @@ public: bool layoutScheduled : 1; bool currentIndexCleared : 1; bool inViewportMoved : 1; - mutable bool minExtentDirty : 1; - mutable bool maxExtentDirty : 1; }; void QDeclarativeListViewPrivate::init() @@ -626,8 +650,7 @@ void QDeclarativeListViewPrivate::clear() currentItem = 0; createHighlight(); trackedItem = 0; - minExtentDirty = true; - maxExtentDirty = true; + markExtentsDirty(); itemCount = 0; } @@ -730,8 +753,11 @@ void QDeclarativeListViewPrivate::releaseItem(FxListItem *item) void QDeclarativeListViewPrivate::refill(qreal from, qreal to, bool doBuffer) { Q_Q(QDeclarativeListView); - if (!isValid() || !q->isComponentComplete()) + if (!isValid() || !q->isComponentComplete()) { + if (q->isComponentComplete()) + updateViewport(); return; + } itemCount = model->count(); qreal bufferFrom = from - buffer; qreal bufferTo = to + buffer; @@ -830,8 +856,7 @@ void QDeclarativeListViewPrivate::refill(qreal from, qreal to, bool doBuffer) deferredRelease = true; } if (changed) { - minExtentDirty = true; - maxExtentDirty = true; + markExtentsDirty(); if (visibleItems.count()) visiblePos = (*visibleItems.constBegin())->position(); updateAverage(); @@ -869,7 +894,8 @@ void QDeclarativeListViewPrivate::layout() layoutScheduled = false; if (!isValid() && !visibleItems.count()) { clear(); - setPosition(0); + fixupMode = QDeclarativeFlickablePrivate::Immediate; + fixupPosition(); return; } if (!visibleItems.isEmpty()) { @@ -889,8 +915,7 @@ void QDeclarativeListViewPrivate::layout() currentItem->setPosition(positionAt(currentIndex)); } q->refill(); - minExtentDirty = true; - maxExtentDirty = true; + markExtentsDirty(); updateHighlight(); if (!q->isMoving() && !q->isFlicking()) { fixupPosition(); @@ -1789,6 +1814,8 @@ void QDeclarativeListView::setModel(const QVariant &model) connect(d->model, SIGNAL(createdItem(int,QDeclarativeItem*)), this, SLOT(createdItem(int,QDeclarativeItem*))); connect(d->model, SIGNAL(destroyingItem(QDeclarativeItem*)), this, SLOT(destroyingItem(QDeclarativeItem*))); emit countChanged(); + } else if (isComponentComplete()) { + d->updateViewport(); } emit modelChanged(); } @@ -2507,8 +2534,7 @@ void QDeclarativeListView::setFooter(QDeclarativeComponent *footer) d->footer = 0; } d->footerComponent = footer; - d->minExtentDirty = true; - d->maxExtentDirty = true; + d->markExtentsDirty(); if (isComponentComplete()) { d->updateFooter(); d->updateViewport(); @@ -2545,8 +2571,7 @@ void QDeclarativeListView::setHeader(QDeclarativeComponent *header) d->header = 0; } d->headerComponent = header; - d->minExtentDirty = true; - d->maxExtentDirty = true; + d->markExtentsDirty(); if (isComponentComplete()) { d->updateHeader(); d->updateFooter(); @@ -2573,6 +2598,15 @@ void QDeclarativeListView::setContentY(qreal pos) QDeclarativeFlickable::setContentY(pos); } +qreal QDeclarativeListView::originX() const +{ + Q_D(const QDeclarativeListView); + if (d->isRightToLeft()) + return -maxXExtent() + d->size() - d->hData.endMargin; + else + return -minXExtent() + d->hData.startMargin; +} + bool QDeclarativeListView::event(QEvent *event) { Q_D(QDeclarativeListView); @@ -2678,8 +2712,8 @@ qreal QDeclarativeListView::minYExtent() const Q_D(const QDeclarativeListView); if (d->orient == QDeclarativeListView::Horizontal) return QDeclarativeFlickable::minYExtent(); - if (d->minExtentDirty) { - d->minExtent = -d->startPosition(); + if (d->vData.minExtentDirty) { + d->minExtent = d->vData.startMargin-d->startPosition(); if (d->header && d->visibleItems.count()) d->minExtent += d->header->size(); if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) { @@ -2690,7 +2724,7 @@ qreal QDeclarativeListView::minYExtent() const } d->minExtent = qMax(d->minExtent, -(d->endPositionAt(0) - d->highlightRangeEnd + 1)); } - d->minExtentDirty = false; + d->vData.minExtentDirty = false; } return d->minExtent; @@ -2701,7 +2735,7 @@ qreal QDeclarativeListView::maxYExtent() const Q_D(const QDeclarativeListView); if (d->orient == QDeclarativeListView::Horizontal) return height(); - if (d->maxExtentDirty) { + if (d->vData.maxExtentDirty) { if (!d->model || !d->model->count()) { d->maxExtent = d->header ? -d->header->size() : 0; d->maxExtent += height(); @@ -2714,10 +2748,11 @@ qreal QDeclarativeListView::maxYExtent() const } if (d->footer) d->maxExtent -= d->footer->size(); + d->maxExtent -= d->vData.endMargin; qreal minY = minYExtent(); if (d->maxExtent > minY) d->maxExtent = minY; - d->maxExtentDirty = false; + d->vData.maxExtentDirty = false; } return d->maxExtent; } @@ -2727,8 +2762,8 @@ qreal QDeclarativeListView::minXExtent() const Q_D(const QDeclarativeListView); if (d->orient == QDeclarativeListView::Vertical) return QDeclarativeFlickable::minXExtent(); - if (d->minExtentDirty) { - d->minExtent = -d->startPosition(); + if (d->hData.minExtentDirty) { + d->minExtent = -d->startPosition() + d->hData.startMargin; qreal highlightStart; qreal highlightEnd; @@ -2758,7 +2793,7 @@ qreal QDeclarativeListView::minXExtent() const d->minExtent += d->isRightToLeft() ? -highlightStart : highlightStart; d->minExtent = qMax(d->minExtent, -(endPositionFirstItem - highlightEnd + 1)); } - d->minExtentDirty = false; + d->hData.minExtentDirty = false; } return d->minExtent; @@ -2769,7 +2804,7 @@ qreal QDeclarativeListView::maxXExtent() const Q_D(const QDeclarativeListView); if (d->orient == QDeclarativeListView::Vertical) return width(); - if (d->maxExtentDirty) { + if (d->hData.maxExtentDirty) { qreal highlightStart; qreal highlightEnd; qreal lastItemPosition = 0; @@ -2801,14 +2836,16 @@ qreal QDeclarativeListView::maxXExtent() const if (d->isRightToLeft()) { if (d->header && d->visibleItems.count()) d->maxExtent -= d->header->size(); + d->maxExtent -= d->hData.endMargin; } else { if (d->footer) d->maxExtent -= d->footer->size(); + d->maxExtent -= d->hData.endMargin; qreal minX = minXExtent(); if (d->maxExtent > minX) d->maxExtent = minX; } - d->maxExtentDirty = false; + d->hData.maxExtentDirty = false; } return d->maxExtent; } @@ -2853,8 +2890,7 @@ void QDeclarativeListView::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) { Q_D(QDeclarativeListView); - d->maxExtentDirty = true; - d->minExtentDirty = true; + d->markExtentsDirty(); if (d->isRightToLeft() && d->orient == QDeclarativeListView::Horizontal) { // maintain position relative to the right edge int dx = newGeometry.width() - oldGeometry.width(); @@ -3108,6 +3144,8 @@ void QDeclarativeListView::componentComplete() } d->moveReason = QDeclarativeListViewPrivate::Other; d->fixupPosition(); + } else { + d->updateViewport(); } } @@ -3442,6 +3480,7 @@ void QDeclarativeListView::itemsRemoved(int modelIndex, int count) d->setPosition(0); d->updateHeader(); d->updateFooter(); + d->updateViewport(); update(); } else { if (modelIndex < d->visibleIndex) diff --git a/src/declarative/graphicsitems/qdeclarativelistview_p.h b/src/declarative/graphicsitems/qdeclarativelistview_p.h index f16231f..f6a521a 100644 --- a/src/declarative/graphicsitems/qdeclarativelistview_p.h +++ b/src/declarative/graphicsitems/qdeclarativelistview_p.h @@ -209,6 +209,7 @@ public: virtual void setContentX(qreal pos); virtual void setContentY(qreal pos); + virtual qreal originX() const; static QDeclarativeListViewAttached *qmlAttachedProperties(QObject *); -- 1.7.10.3