From d216acf40978fb4ad161bd25a4f4f1a0ceb7d0f3 Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Fri, 18 Dec 2009 17:31:52 +1000 Subject: ListView housekeeping optimizations. --- .../graphicsitems/qmlgraphicslistview.cpp | 132 +++++++++++++-------- 1 file changed, 80 insertions(+), 52 deletions(-) diff --git a/src/declarative/graphicsitems/qmlgraphicslistview.cpp b/src/declarative/graphicsitems/qmlgraphicslistview.cpp index cddf33c..e2eff2b 100644 --- a/src/declarative/graphicsitems/qmlgraphicslistview.cpp +++ b/src/declarative/graphicsitems/qmlgraphicslistview.cpp @@ -223,6 +223,7 @@ public: , bufferMode(NoBuffer) , ownModel(false), wrap(false), autoHighlight(true), haveHighlightRange(false) , correctFlick(true), inFlickCorrection(false), lazyRelease(false) + , minExtentDirty(true), maxExtentDirty(true) {} void init(); @@ -285,7 +286,7 @@ public: qreal startPosition() const { qreal pos = 0; if (!visibleItems.isEmpty()) { - pos = visibleItems.first()->position(); + pos = (*visibleItems.constBegin())->position(); if (visibleIndex > 0) pos -= visibleIndex * (averageSize + spacing) - spacing; } @@ -302,7 +303,7 @@ public: break; } } - pos = visibleItems.last()->endPosition() + invisibleCount * (averageSize + spacing); + pos = (*(--visibleItems.constEnd()))->endPosition() + invisibleCount * (averageSize + spacing); } return pos; } @@ -313,7 +314,7 @@ public: if (!visibleItems.isEmpty()) { if (modelIndex < visibleIndex) { int count = visibleIndex - modelIndex; - return visibleItems.first()->position() - count * (averageSize + spacing); + return (*visibleItems.constBegin())->position() - count * (averageSize + spacing); } else { int idx = visibleItems.count() - 1; while (idx >= 0 && visibleItems.at(idx)->index == -1) @@ -323,7 +324,7 @@ public: else idx = visibleItems.at(idx)->index; int count = modelIndex - idx - 1; - return visibleItems.last()->endPosition() + spacing + count * (averageSize + spacing) + 1; + return (*(--visibleItems.constEnd()))->endPosition() + spacing + count * (averageSize + spacing) + 1; } } return 0; @@ -446,10 +447,13 @@ public: void updateViewport() { Q_Q(QmlGraphicsListView); - if (orient == QmlGraphicsListView::Vertical) + minExtentDirty = true; + maxExtentDirty = true; + if (orient == QmlGraphicsListView::Vertical) { q->setViewportHeight(q->minYExtent() - q->maxYExtent()); - else + } else { q->setViewportWidth(q->minXExtent() - q->maxXExtent()); + } } void itemGeometryChanged(QmlGraphicsItem *, const QRectF &newGeometry, const QRectF &oldGeometry) { @@ -530,6 +534,8 @@ public: FxListItem *header; enum BufferMode { NoBuffer = 0x00, BufferBefore = 0x01, BufferAfter = 0x02 }; BufferMode bufferMode; + mutable qreal minExtent; + mutable qreal maxExtent; bool ownModel : 1; bool wrap : 1; @@ -538,6 +544,8 @@ public: bool correctFlick : 1; bool inFlickCorrection : 1; bool lazyRelease : 1; + mutable bool minExtentDirty : 1; + mutable bool maxExtentDirty : 1; }; void QmlGraphicsListViewPrivate::init() @@ -566,6 +574,8 @@ void QmlGraphicsListViewPrivate::clear() currentItem = 0; createHighlight(); trackedItem = 0; + minExtentDirty = true; + maxExtentDirty = true; } FxListItem *QmlGraphicsListViewPrivate::createItem(int modelIndex) @@ -655,8 +665,8 @@ void QmlGraphicsListViewPrivate::refill(qreal from, qreal to, bool doBuffer) int modelIndex = visibleIndex; qreal itemEnd = visiblePos-1; if (!visibleItems.isEmpty()) { - visiblePos = visibleItems.first()->position(); - itemEnd = visibleItems.last()->endPosition() + spacing; + visiblePos = (*visibleItems.constBegin())->position(); + itemEnd = (*(--visibleItems.constEnd()))->endPosition() + spacing; int i = visibleItems.count() - 1; while (i > 0 && visibleItems.at(i)->index == -1) --i; @@ -713,7 +723,7 @@ void QmlGraphicsListViewPrivate::refill(qreal from, qreal to, bool doBuffer) } if (changed) { if (visibleItems.count()) - visiblePos = visibleItems.first()->position(); + visiblePos = (*visibleItems.constBegin())->position(); updateAverage(); if (sectionCriteria) updateCurrentSection(); @@ -895,7 +905,7 @@ void QmlGraphicsListViewPrivate::createSection(FxListItem *listItem) listItem->section = sectionCache[i]; sectionCache[i] = 0; listItem->section->setVisible(true); - QmlContext *context = QmlEngine::contextForObject(listItem->section); + QmlContext *context = QmlEngine::contextForObject(listItem->section)->parentContext(); context->setContextProperty(QLatin1String("section"), listItem->attached->m_section); } else { QmlContext *context = new QmlContext(qmlContext(q)); @@ -1038,10 +1048,14 @@ void QmlGraphicsListViewPrivate::updateFooter() } } if (footer) { - if (visibleItems.count()) - footer->setPosition(endPosition()); - else + if (visibleItems.count()) { + qreal endPos = endPosition(); + qreal visiblePos = position() + q->height(); + if (endPos <= visiblePos || footer->position() < endPos) + footer->setPosition(endPos); + } else { footer->setPosition(visiblePos); + } } } @@ -1069,10 +1083,13 @@ void QmlGraphicsListViewPrivate::updateHeader() } } if (header) { - if (visibleItems.count()) - header->setPosition(startPosition() - header->size()); - else + if (visibleItems.count()) { + qreal startPos = startPosition(); + if (position() <= startPos || header->position() > startPos - header->size()) + header->setPosition(startPos - header->size()); + } else { header->setPosition(0); + } } } @@ -2088,31 +2105,36 @@ qreal QmlGraphicsListView::minYExtent() const Q_D(const QmlGraphicsListView); if (d->orient == QmlGraphicsListView::Horizontal) return QmlGraphicsFlickable::minYExtent(); - qreal extent = -d->startPosition(); - if (d->header && d->visibleItems.count()) - extent += d->header->size(); - if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) - extent += d->highlightRangeStart; + if (d->minExtentDirty) { + d->minExtent = -d->startPosition(); + if (d->header && d->visibleItems.count()) + d->minExtent += d->header->size(); + if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) + d->minExtent += d->highlightRangeStart; + d->minExtentDirty = false; + } - return extent; + return d->minExtent; } qreal QmlGraphicsListView::maxYExtent() const { Q_D(const QmlGraphicsListView); if (d->orient == QmlGraphicsListView::Horizontal) - return QmlGraphicsFlickable::maxYExtent(); - qreal extent; - if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) - extent = -(d->positionAt(count()-1) - d->highlightRangeEnd); - else - extent = -(d->endPosition() - height() + 1); - if (d->footer) - extent -= d->footer->size(); - qreal minY = minYExtent(); - if (extent > minY) - extent = minY; - return extent; + return height(); + if (d->maxExtentDirty) { + if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) + d->maxExtent = -(d->positionAt(count()-1) - d->highlightRangeEnd); + else + d->maxExtent = -(d->endPosition() - height() + 1); + if (d->footer) + d->maxExtent -= d->footer->size(); + qreal minY = minYExtent(); + if (d->maxExtent > minY) + d->maxExtent = minY; + d->maxExtentDirty = false; + } + return d->maxExtent; } qreal QmlGraphicsListView::minXExtent() const @@ -2120,31 +2142,37 @@ qreal QmlGraphicsListView::minXExtent() const Q_D(const QmlGraphicsListView); if (d->orient == QmlGraphicsListView::Vertical) return QmlGraphicsFlickable::minXExtent(); - qreal extent = -d->startPosition(); - if (d->header) - extent += d->header->size(); - if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) - extent += d->highlightRangeStart; + if (d->minExtentDirty) { + d->minExtent = -d->startPosition(); + if (d->header) + d->minExtent += d->header->size(); + if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) + d->minExtent += d->highlightRangeStart; + d->minExtentDirty = false; + } - return extent; + return d->minExtent; } qreal QmlGraphicsListView::maxXExtent() const { Q_D(const QmlGraphicsListView); if (d->orient == QmlGraphicsListView::Vertical) - return QmlGraphicsFlickable::maxXExtent(); - qreal extent; - if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) - extent = -(d->positionAt(count()-1) - d->highlightRangeEnd); - else - extent = -(d->endPosition() - width() + 1); - if (d->footer) - extent -= d->footer->size(); - qreal minX = minXExtent(); - if (extent > minX) - extent = minX; - return extent; + return width(); + if (d->maxExtentDirty) { + if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) + d->maxExtent = -(d->positionAt(count()-1) - d->highlightRangeEnd); + else + d->maxExtent = -(d->endPosition() - width() + 1); + if (d->footer) + d->maxExtent -= d->footer->size(); + qreal minX = minXExtent(); + if (d->maxExtent > minX) + d->maxExtent = minX; + d->maxExtentDirty = false; + } + + return d->maxExtent; } void QmlGraphicsListView::keyPressEvent(QKeyEvent *event) -- cgit v0.12 From c0dfcf9a230d0bcb6783777e3ee0b2f756980f93 Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Fri, 18 Dec 2009 17:42:20 +1000 Subject: Make sure header/footer are correctly positioned. --- src/declarative/graphicsitems/qmlgraphicslistview.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/declarative/graphicsitems/qmlgraphicslistview.cpp b/src/declarative/graphicsitems/qmlgraphicslistview.cpp index e2eff2b..351364e 100644 --- a/src/declarative/graphicsitems/qmlgraphicslistview.cpp +++ b/src/declarative/graphicsitems/qmlgraphicslistview.cpp @@ -1050,9 +1050,13 @@ void QmlGraphicsListViewPrivate::updateFooter() if (footer) { if (visibleItems.count()) { qreal endPos = endPosition(); - qreal visiblePos = position() + q->height(); - if (endPos <= visiblePos || footer->position() < endPos) + if (lastVisibleIndex() == model->count()-1) { footer->setPosition(endPos); + } else { + qreal visiblePos = position() + q->height(); + if (endPos <= visiblePos || footer->position() < endPos) + footer->setPosition(endPos); + } } else { footer->setPosition(visiblePos); } @@ -1085,8 +1089,12 @@ void QmlGraphicsListViewPrivate::updateHeader() if (header) { if (visibleItems.count()) { qreal startPos = startPosition(); - if (position() <= startPos || header->position() > startPos - header->size()) + if (visibleIndex == 0) { header->setPosition(startPos - header->size()); + } else { + if (position() <= startPos || header->position() > startPos - header->size()) + header->setPosition(startPos - header->size()); + } } else { header->setPosition(0); } -- cgit v0.12 From 45ca79610e1609f27c852afe7f8ae157f5ef7fbb Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Fri, 18 Dec 2009 18:50:14 +1000 Subject: Avoid excessive calls to QTime::currentTime() --- src/declarative/graphicsitems/qmlgraphicsflickable.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/declarative/graphicsitems/qmlgraphicsflickable.cpp b/src/declarative/graphicsitems/qmlgraphicsflickable.cpp index 79c7659..393edb6 100644 --- a/src/declarative/graphicsitems/qmlgraphicsflickable.cpp +++ b/src/declarative/graphicsitems/qmlgraphicsflickable.cpp @@ -865,7 +865,7 @@ void QmlGraphicsFlickable::viewportMoved() { Q_D(QmlGraphicsFlickable); - int elapsed = QmlGraphicsItemPrivate::elapsed(d->velocityTime); + int elapsed = QmlGraphicsItemPrivate::restart(d->velocityTime); if (!elapsed) return; @@ -888,7 +888,6 @@ void QmlGraphicsFlickable::viewportMoved() } } - QmlGraphicsItemPrivate::restart(d->velocityTime); d->lastFlickablePosition = QPointF(d->_moveY.value(), d->_moveX.value()); d->vTime = d->timeline.time(); -- cgit v0.12 From d49648884774f320473427fcea52a51ac2a4cca5 Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Mon, 21 Dec 2009 09:43:33 +1000 Subject: Fix Flickable within Flickable, with parent flickable !interactive. --- .../graphicsitems/qmlgraphicsflickable.cpp | 20 ++++++++++++-------- .../graphicsitems/qmlgraphicsflickable_p.h | 3 ++- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/declarative/graphicsitems/qmlgraphicsflickable.cpp b/src/declarative/graphicsitems/qmlgraphicsflickable.cpp index 393edb6..ed70b14 100644 --- a/src/declarative/graphicsitems/qmlgraphicsflickable.cpp +++ b/src/declarative/graphicsitems/qmlgraphicsflickable.cpp @@ -498,13 +498,16 @@ bool QmlGraphicsFlickable::isInteractive() const void QmlGraphicsFlickable::setInteractive(bool interactive) { Q_D(QmlGraphicsFlickable); - d->interactive = interactive; - if (!interactive && d->flicked) { - d->timeline.clear(); - d->vTime = d->timeline.time(); - d->flicked = false; - emit flickingChanged(); - emit flickEnded(); + if (interactive != d->interactive) { + d->interactive = interactive; + if (!interactive && d->flicked) { + d->timeline.clear(); + d->vTime = d->timeline.time(); + d->flicked = false; + emit flickingChanged(); + emit flickEnded(); + } + emit interactiveChanged(); } } @@ -1147,7 +1150,8 @@ bool QmlGraphicsFlickable::sendMouseEvent(QGraphicsSceneMouseEvent *event) bool QmlGraphicsFlickable::sceneEventFilter(QGraphicsItem *i, QEvent *e) { - if (!isVisible()) + Q_D(QmlGraphicsFlickable); + if (!isVisible() || !d->interactive) return QmlGraphicsItem::sceneEventFilter(i, e); switch (e->type()) { case QEvent::GraphicsSceneMousePress: diff --git a/src/declarative/graphicsitems/qmlgraphicsflickable_p.h b/src/declarative/graphicsitems/qmlgraphicsflickable_p.h index aa29f3e..df6f6b1 100644 --- a/src/declarative/graphicsitems/qmlgraphicsflickable_p.h +++ b/src/declarative/graphicsitems/qmlgraphicsflickable_p.h @@ -72,7 +72,7 @@ class Q_DECLARATIVE_EXPORT QmlGraphicsFlickable : public QmlGraphicsItem Q_PROPERTY(bool flicking READ isFlicking NOTIFY flickingChanged) Q_PROPERTY(FlickDirection flickDirection READ flickDirection WRITE setFlickDirection NOTIFY flickDirectionChanged) - Q_PROPERTY(bool interactive READ isInteractive WRITE setInteractive) + Q_PROPERTY(bool interactive READ isInteractive WRITE setInteractive NOTIFY interactiveChanged) Q_PROPERTY(int pressDelay READ pressDelay WRITE setPressDelay) Q_PROPERTY(bool atXEnd READ isAtXEnd NOTIFY isAtBoundaryChanged) @@ -159,6 +159,7 @@ Q_SIGNALS: void isAtBoundaryChanged(); void pageChanged(); void flickDirectionChanged(); + void interactiveChanged(); protected: virtual bool sceneEventFilter(QGraphicsItem *, QEvent *); -- cgit v0.12 From 944f41b814d826191a713de34cb9fdda439d14c5 Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Mon, 21 Dec 2009 10:11:54 +1000 Subject: Remove unnecessary locking. --- src/declarative/util/qmlpixmapcache.cpp | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/src/declarative/util/qmlpixmapcache.cpp b/src/declarative/util/qmlpixmapcache.cpp index 99bcb7b..475a21e 100644 --- a/src/declarative/util/qmlpixmapcache.cpp +++ b/src/declarative/util/qmlpixmapcache.cpp @@ -84,7 +84,6 @@ private: void loadImage(Job &job); QList jobs; - Job runningJob; QMutex mutex; QWaitCondition haveJob; bool quit; @@ -119,22 +118,21 @@ void QmlImageReader::read(QmlPixmapReply *reply) Job job; job.reply = reply; jobs.append(job); - haveJob.wakeOne(); + if (jobs.count() == 1) + haveJob.wakeOne(); mutex.unlock(); } void QmlImageReader::cancel(QmlPixmapReply *reply) { mutex.lock(); - if (runningJob.reply != reply) { - QList::iterator it = jobs.begin(); - while (it != jobs.end()) { - if ((*it).reply == reply) { - jobs.erase(it); - break; - } - ++it; + QList::iterator it = jobs.begin(); + while (it != jobs.end()) { + if ((*it).reply == reply) { + jobs.erase(it); + break; } + ++it; } mutex.unlock(); } @@ -158,14 +156,12 @@ void QmlImageReader::run() haveJob.wait(&mutex); if (quit) break; - runningJob = jobs.takeFirst(); + Job runningJob = jobs.takeFirst(); runningJob.reply->addRef(); mutex.unlock(); + loadImage(runningJob); - mutex.lock(); QCoreApplication::postEvent(runningJob.reply, new QmlImageDecodeEvent(runningJob.error, runningJob.img)); - runningJob.reply = 0; - mutex.unlock(); } } -- cgit v0.12