diff options
6 files changed, 121 insertions, 63 deletions
diff --git a/src/declarative/graphicsitems/qdeclarativeflickable.cpp b/src/declarative/graphicsitems/qdeclarativeflickable.cpp index 67068a0..9ccb3b6 100644 --- a/src/declarative/graphicsitems/qdeclarativeflickable.cpp +++ b/src/declarative/graphicsitems/qdeclarativeflickable.cpp @@ -264,6 +264,7 @@ void QDeclarativeFlickablePrivate::fixupY() void QDeclarativeFlickablePrivate::fixup(AxisData &data, qreal minExtent, qreal maxExtent) { + Q_Q(QDeclarativeFlickable); if (data.move.value() > minExtent || maxExtent > minExtent) { timeline.reset(data.move); if (data.move.value() != minExtent) { @@ -273,6 +274,7 @@ void QDeclarativeFlickablePrivate::fixup(AxisData &data, qreal minExtent, qreal timeline.move(data.move, minExtent, QEasingCurve(QEasingCurve::OutQuint), 3*fixupDuration/4); } else { data.move.setValue(minExtent); + q->viewportMoved(); } } //emit flickingChanged(); @@ -284,6 +286,7 @@ void QDeclarativeFlickablePrivate::fixup(AxisData &data, qreal minExtent, qreal timeline.move(data.move, maxExtent, QEasingCurve(QEasingCurve::OutQuint), 3*fixupDuration/4); } else { data.move.setValue(maxExtent); + q->viewportMoved(); } //emit flickingChanged(); } else { diff --git a/src/declarative/graphicsitems/qdeclarativegridview.cpp b/src/declarative/graphicsitems/qdeclarativegridview.cpp index f35b903..af22e08 100644 --- a/src/declarative/graphicsitems/qdeclarativegridview.cpp +++ b/src/declarative/graphicsitems/qdeclarativegridview.cpp @@ -97,7 +97,7 @@ class QDeclarativeGridViewPrivate : public QDeclarativeFlickablePrivate public: QDeclarativeGridViewPrivate() : currentItem(0), flow(QDeclarativeGridView::LeftToRight) - , visiblePos(0), visibleIndex(0) , currentIndex(-1) + , visibleIndex(0) , currentIndex(-1) , cellWidth(100), cellHeight(100), columns(1), requestedIndex(-1) , highlightRangeStart(0), highlightRangeEnd(0), highlightRange(QDeclarativeGridView::NoHighlightRange) , highlightComponent(0), highlight(0), trackedItem(0) @@ -305,7 +305,6 @@ public: QHash<QDeclarativeItem*,int> unrequestedItems; FxGridItem *currentItem; QDeclarativeGridView::Flow flow; - int visiblePos; int visibleIndex; int currentIndex; int cellWidth; @@ -350,7 +349,6 @@ void QDeclarativeGridViewPrivate::clear() for (int i = 0; i < visibleItems.count(); ++i) releaseItem(visibleItems.at(i)); visibleItems.clear(); - visiblePos = 0; visibleIndex = 0; releaseItem(currentItem); currentItem = 0; @@ -536,7 +534,7 @@ void QDeclarativeGridViewPrivate::scheduleLayout() Q_Q(QDeclarativeGridView); if (!layoutScheduled) { layoutScheduled = true; - QMetaObject::invokeMethod(q, "layout", Qt::QueuedConnection); + QCoreApplication::postEvent(q, new QEvent(QEvent::User), Qt::HighEventPriority); } } @@ -748,10 +746,12 @@ void QDeclarativeGridViewPrivate::fixup(AxisData &data, qreal minExtent, qreal m if (currentItem && currentItem->rowPos() - position() != highlightRangeStart) { qreal pos = currentItem->rowPos() - highlightRangeStart; timeline.reset(data.move); - if (fixupDuration) + if (fixupDuration) { timeline.move(data.move, -pos, QEasingCurve(QEasingCurve::InOutQuad), fixupDuration/2); - else + } else { data.move.setValue(-pos); + q->viewportMoved(); + } vTime = timeline.time(); } } else if (snapMode != QDeclarativeGridView::NoSnap) { @@ -760,10 +760,12 @@ void QDeclarativeGridViewPrivate::fixup(AxisData &data, qreal minExtent, qreal m qreal dist = qAbs(data.move.value() - pos); if (dist > 0) { timeline.reset(data.move); - if (fixupDuration) + if (fixupDuration) { timeline.move(data.move, pos, QEasingCurve(QEasingCurve::InOutQuad), fixupDuration/2); - else + } else { data.move.setValue(pos); + q->viewportMoved(); + } vTime = timeline.time(); } } else { @@ -1423,6 +1425,17 @@ void QDeclarativeGridView::setSnapMode(SnapMode mode) } } +bool QDeclarativeGridView::event(QEvent *event) +{ + Q_D(QDeclarativeGridView); + if (event->type() == QEvent::User) { + d->layout(); + return true; + } + + return QDeclarativeFlickable::event(event); +} + void QDeclarativeGridView::viewportMoved() { Q_D(QDeclarativeGridView); @@ -1765,7 +1778,7 @@ void QDeclarativeGridView::itemsInserted(int modelIndex, int count) { Q_D(QDeclarativeGridView); if (!d->visibleItems.count() || d->model->count() <= 1) { - refill(); + d->scheduleLayout(); d->updateCurrent(qMax(0, qMin(d->currentIndex, d->model->count()-1))); emit countChanged(); return; @@ -1795,7 +1808,7 @@ void QDeclarativeGridView::itemsInserted(int modelIndex, int count) if (d->currentItem) d->currentItem->index = d->currentIndex; } - d->layout(); + d->scheduleLayout(); emit countChanged(); return; } @@ -1825,9 +1838,21 @@ void QDeclarativeGridView::itemsInserted(int modelIndex, int count) } } + // Update the indexes of the following visible items. + for (int i = 0; i < d->visibleItems.count(); ++i) { + FxGridItem *listItem = d->visibleItems.at(i); + if (listItem->index != -1 && listItem->index >= modelIndex) + listItem->index += count; + } + + bool addedVisible = false; QList<FxGridItem*> added; int i = 0; while (i < insertCount && rowPos <= to + d->rowSize()*(d->columns - (colPos/d->colSize()))/qreal(d->columns)) { + if (!addedVisible) { + d->scheduleLayout(); + addedVisible = true; + } FxGridItem *item = d->createItem(modelIndex + i); d->visibleItems.insert(index, item); item->setPosition(colPos, rowPos); @@ -1848,6 +1873,15 @@ void QDeclarativeGridView::itemsInserted(int modelIndex, int count) } } + // update visibleIndex + d->visibleIndex = 0; + for (QList<FxGridItem*>::Iterator it = d->visibleItems.begin(); it != d->visibleItems.end(); ++it) { + if ((*it)->index != -1) { + d->visibleIndex = (*it)->index; + break; + } + } + if (d->currentIndex >= modelIndex) { // adjust current item index d->currentIndex += count; @@ -1856,17 +1890,11 @@ void QDeclarativeGridView::itemsInserted(int modelIndex, int count) d->currentItem->setPosition(d->colPosAt(d->currentIndex), d->rowPosAt(d->currentIndex)); } } - // Update the indexes of the following visible items. - for (; index < d->visibleItems.count(); ++index) { - FxGridItem *listItem = d->visibleItems.at(index); - if (listItem->index != -1) - listItem->index += count; - } // everything is in order now - emit add() signal for (int j = 0; j < added.count(); ++j) added.at(j)->attached->emitAdd(); - d->layout(); + emit countChanged(); } @@ -1882,8 +1910,10 @@ void QDeclarativeGridView::itemsRemoved(int modelIndex, int count) FxGridItem *item = *it; if (item->index == -1 || item->index < modelIndex) { // already removed, or before removed items - if (item->index < modelIndex) + if (item->index < modelIndex && !removedVisible) { + d->scheduleLayout(); removedVisible = true; + } ++it; } else if (item->index >= modelIndex + count) { // after removed items @@ -1891,7 +1921,10 @@ void QDeclarativeGridView::itemsRemoved(int modelIndex, int count) ++it; } else { // removed item - removedVisible = true; + if (!removedVisible) { + d->scheduleLayout(); + removedVisible = true; + } item->attached->emitRemove(); if (item->attached->delayRemove()) { item->index = -1; @@ -1909,6 +1942,7 @@ void QDeclarativeGridView::itemsRemoved(int modelIndex, int count) d->currentIndex -= count; if (d->currentItem) d->currentItem->index -= count; + emit currentIndexChanged(); } else if (currentRemoved) { // current item has been removed. d->releaseItem(d->currentItem); @@ -1918,6 +1952,7 @@ void QDeclarativeGridView::itemsRemoved(int modelIndex, int count) } // update visibleIndex + d->visibleIndex = 0; for (it = d->visibleItems.begin(); it != d->visibleItems.end(); ++it) { if ((*it)->index != -1) { d->visibleIndex = (*it)->index; @@ -1925,27 +1960,16 @@ void QDeclarativeGridView::itemsRemoved(int modelIndex, int count) } } - if (removedVisible) { - if (d->visibleItems.isEmpty()) { - d->visibleIndex = 0; - d->setPosition(0); - refill(); - } else { - // Correct the positioning of the items - d->scheduleLayout(); - } + if (removedVisible && d->visibleItems.isEmpty()) { + d->timeline.clear(); + d->setPosition(0); + if (d->model->count() == 0) + update(); } emit countChanged(); } -void QDeclarativeGridView::layout() -{ - Q_D(QDeclarativeGridView); - if (d->layoutScheduled) - d->layout(); -} - void QDeclarativeGridView::destroyRemoved() { Q_D(QDeclarativeGridView); diff --git a/src/declarative/graphicsitems/qdeclarativegridview_p.h b/src/declarative/graphicsitems/qdeclarativegridview_p.h index 183bb05..8e253e5 100644 --- a/src/declarative/graphicsitems/qdeclarativegridview_p.h +++ b/src/declarative/graphicsitems/qdeclarativegridview_p.h @@ -164,6 +164,7 @@ Q_SIGNALS: void snapModeChanged(); protected: + virtual bool event(QEvent *event); virtual void viewportMoved(); virtual qreal minYExtent() const; virtual qreal maxYExtent() const; @@ -181,7 +182,6 @@ private Q_SLOTS: void destroyRemoved(); void createdItem(int index, QDeclarativeItem *item); void destroyingItem(QDeclarativeItem *item); - void layout(); private: void refill(); diff --git a/src/declarative/graphicsitems/qdeclarativelistview.cpp b/src/declarative/graphicsitems/qdeclarativelistview.cpp index 6385ddd..007b31b 100644 --- a/src/declarative/graphicsitems/qdeclarativelistview.cpp +++ b/src/declarative/graphicsitems/qdeclarativelistview.cpp @@ -158,7 +158,7 @@ public: , bufferMode(NoBuffer) , ownModel(false), wrap(false), autoHighlight(true), haveHighlightRange(false) , correctFlick(true), inFlickCorrection(false), lazyRelease(false) - , deferredRelease(false), minExtentDirty(true), maxExtentDirty(true) + , deferredRelease(false), layoutScheduled(false), minExtentDirty(true), maxExtentDirty(true) {} void init(); @@ -414,6 +414,7 @@ public: } void refill(qreal from, qreal to, bool doBuffer = false); + void scheduleLayout(); void layout(); void updateUnrequestedIndexes(); void updateUnrequestedPositions(); @@ -480,6 +481,7 @@ public: bool inFlickCorrection : 1; bool lazyRelease : 1; bool deferredRelease : 1; + bool layoutScheduled : 1; mutable bool minExtentDirty : 1; mutable bool maxExtentDirty : 1; }; @@ -680,9 +682,19 @@ void QDeclarativeListViewPrivate::refill(qreal from, qreal to, bool doBuffer) lazyRelease = false; } +void QDeclarativeListViewPrivate::scheduleLayout() +{ + Q_Q(QDeclarativeListView); + if (!layoutScheduled) { + layoutScheduled = true; + QCoreApplication::postEvent(q, new QEvent(QEvent::User), Qt::HighEventPriority); + } +} + void QDeclarativeListViewPrivate::layout() { Q_Q(QDeclarativeListView); + layoutScheduled = false; updateSections(); if (!visibleItems.isEmpty()) { int oldEnd = visibleItems.last()->endPosition(); @@ -1082,10 +1094,12 @@ void QDeclarativeListViewPrivate::fixup(AxisData &data, qreal minExtent, qreal m if (currentItem && currentItem->position() - position() != highlightRangeStart) { qreal pos = currentItem->position() - highlightRangeStart; timeline.reset(data.move); - if (fixupDuration) + if (fixupDuration) { timeline.move(data.move, -pos, QEasingCurve(QEasingCurve::InOutQuad), fixupDuration/2); - else + } else { data.move.setValue(-pos); + q->viewportMoved(); + } vTime = timeline.time(); } } else if (snapMode != QDeclarativeListView::NoSnap) { @@ -1094,10 +1108,12 @@ void QDeclarativeListViewPrivate::fixup(AxisData &data, qreal minExtent, qreal m qreal dist = qAbs(data.move + pos); if (dist > 0) { timeline.reset(data.move); - if (fixupDuration) + if (fixupDuration) { timeline.move(data.move, -pos, QEasingCurve(QEasingCurve::InOutQuad), fixupDuration/2); - else + } else { data.move.setValue(-pos); + q->viewportMoved(); + } vTime = timeline.time(); } } @@ -1167,7 +1183,6 @@ void QDeclarativeListViewPrivate::flick(AxisData &data, qreal minExtent, qreal m } else { data.flickTarget = velocity > 0 ? minExtent : maxExtent; overshootDist = overShoot ? overShootDistance(v, vSize) : 0; - qDebug() << "boundary" << overshootDist; } timeline.reset(data.move); timeline.accel(data.move, v, accel, maxDistance + overshootDist); @@ -1946,6 +1961,17 @@ void QDeclarativeListView::setHeader(QDeclarativeComponent *header) } } +bool QDeclarativeListView::event(QEvent *event) +{ + Q_D(QDeclarativeListView); + if (event->type() == QEvent::User) { + d->layout(); + return true; + } + + return QDeclarativeFlickable::event(event); +} + void QDeclarativeListView::viewportMoved() { Q_D(QDeclarativeListView); @@ -2276,7 +2302,7 @@ void QDeclarativeListView::itemsInserted(int modelIndex, int count) d->updateUnrequestedIndexes(); d->moveReason = QDeclarativeListViewPrivate::Other; if (!d->visibleItems.count() || d->model->count() <= 1) { - d->layout(); + d->scheduleLayout(); d->updateCurrent(qMax(0, qMin(d->currentIndex, d->model->count()-1))); emit countChanged(); return; @@ -2307,7 +2333,7 @@ void QDeclarativeListView::itemsInserted(int modelIndex, int count) if (d->currentItem) d->currentItem->index = d->currentIndex; } - d->layout(); + d->scheduleLayout(); emit countChanged(); return; } @@ -2330,7 +2356,10 @@ void QDeclarativeListView::itemsInserted(int modelIndex, int count) int i = 0; int from = d->position() - d->buffer; for (i = count-1; i >= 0 && pos > from; --i) { - addedVisible = true; + if (!addedVisible) { + d->scheduleLayout(); + addedVisible = true; + } FxListItem *item = d->createItem(modelIndex + i); d->visibleItems.insert(insertionIdx, item); pos -= item->size() + d->spacing; @@ -2357,7 +2386,10 @@ void QDeclarativeListView::itemsInserted(int modelIndex, int count) int i = 0; int to = d->buffer+d->position()+d->size()-1; for (i = 0; i < count && pos <= to; ++i) { - addedVisible = true; + if (!addedVisible) { + d->scheduleLayout(); + addedVisible = true; + } FxListItem *item = d->createItem(modelIndex + i); d->visibleItems.insert(index, item); item->setPosition(pos); @@ -2393,8 +2425,6 @@ void QDeclarativeListView::itemsInserted(int modelIndex, int count) for (int j = 0; j < added.count(); ++j) added.at(j)->attached->emitAdd(); - if (addedVisible) - d->layout(); emit countChanged(); } @@ -2420,7 +2450,10 @@ void QDeclarativeListView::itemsRemoved(int modelIndex, int count) ++it; } else { // removed item - removedVisible = true; + if (!removedVisible) { + d->scheduleLayout(); + removedVisible = true; + } item->attached->emitRemove(); if (item->attached->delayRemove()) { item->index = -1; @@ -2445,6 +2478,7 @@ void QDeclarativeListView::itemsRemoved(int modelIndex, int count) d->currentIndex -= count; if (d->currentItem) d->currentItem->index -= count; + emit currentIndexChanged(); } else if (d->currentIndex >= modelIndex && d->currentIndex < modelIndex + count) { // current item has been removed. d->currentItem->attached->setIsCurrentItem(false); @@ -2462,20 +2496,13 @@ void QDeclarativeListView::itemsRemoved(int modelIndex, int count) } } - if (removedVisible) { - if (d->visibleItems.isEmpty()) { - d->visibleIndex = 0; - d->visiblePos = d->header ? d->header->size() : 0; - d->timeline.clear(); - d->setPosition(0); - if (d->model->count() == 0) - update(); - else - refill(); - } else { - // Correct the positioning of the items - d->layout(); - } + if (removedVisible && d->visibleItems.isEmpty()) { + d->visibleIndex = 0; + d->visiblePos = d->header ? d->header->size() : 0; + d->timeline.clear(); + d->setPosition(0); + if (d->model->count() == 0) + update(); } emit countChanged(); diff --git a/src/declarative/graphicsitems/qdeclarativelistview_p.h b/src/declarative/graphicsitems/qdeclarativelistview_p.h index d66ac2b..1bf9652 100644 --- a/src/declarative/graphicsitems/qdeclarativelistview_p.h +++ b/src/declarative/graphicsitems/qdeclarativelistview_p.h @@ -219,6 +219,7 @@ Q_SIGNALS: void footerChanged(); protected: + virtual bool event(QEvent *event); virtual void viewportMoved(); virtual qreal minYExtent() const; virtual qreal maxYExtent() const; diff --git a/tests/auto/declarative/qdeclarativelistview/tst_qdeclarativelistview.cpp b/tests/auto/declarative/qdeclarativelistview/tst_qdeclarativelistview.cpp index 75fbbf8..17257ae 100644 --- a/tests/auto/declarative/qdeclarativelistview/tst_qdeclarativelistview.cpp +++ b/tests/auto/declarative/qdeclarativelistview/tst_qdeclarativelistview.cpp @@ -925,6 +925,7 @@ void tst_QDeclarativeListView::sections() // Remove section boundary model.removeItem(5); + QTest::qWait(100); // New section header created QDeclarativeItem *item = findItem<QDeclarativeItem>(viewport, "wrapper", 5); @@ -932,6 +933,7 @@ void tst_QDeclarativeListView::sections() QCOMPARE(item->height(), 40.0); model.insertItem(3, "New Item", "0"); + QTest::qWait(100); // Section header moved item = findItem<QDeclarativeItem>(viewport, "wrapper", 5); @@ -944,6 +946,7 @@ void tst_QDeclarativeListView::sections() // insert item which will become a section header model.insertItem(6, "Replace header", "1"); + QTest::qWait(100); item = findItem<QDeclarativeItem>(viewport, "wrapper", 6); QVERIFY(item); |