diff -r 16d8024aca5e -r f7ac710697a9 src/hbwidgets/itemviews/hbgriditemcontainer_p.cpp --- a/src/hbwidgets/itemviews/hbgriditemcontainer_p.cpp Mon Apr 19 14:02:13 2010 +0300 +++ b/src/hbwidgets/itemviews/hbgriditemcontainer_p.cpp Mon May 03 12:48:33 2010 +0300 @@ -88,24 +88,32 @@ return; int bufferIndex = 0; - if (d->mItems.count() != 0) { - bufferIndex = qMax(0, index.row() - d->mItems.first()->modelIndex().row()); + QModelIndex firstInBuffer; + int firstInBufferPosition = -1; + int indexPosition = d->mItemView->modelIterator()->indexPosition(index); + if (!d->mItems.isEmpty()) { + firstInBuffer = d->mItems.first()->modelIndex(); + firstInBufferPosition = d->mItemView->modelIterator()->indexPosition(firstInBuffer); + bufferIndex = qMax(0, indexPosition - firstInBufferPosition); } // inserting new item because of buffer size - if (d->mItems.count() == 0 + if (d->mItems.isEmpty() || d->mItems.count() < maxItemCount()) { insertItem(bufferIndex, index, animate); viewLayout()->invalidate(); } // special case - only for grid, if added item is above the // visible region we need to shift all visible items by one! - else if (d->mItems.count() > 0 - && d->mItems.first()->modelIndex().row() > index.row()) { + else if (!d->mItems.isEmpty() + && firstInBufferPosition > indexPosition) { d->shiftUpItem(animate); // shift up in this case always return something viewLayout()->invalidate(); } // new item is in visible range else if (bufferIndex < d->mItems.count()) { + // new added item comes to buffer - it will be + // recycled from last item in buffer (it is also ok + // when that last item was invalid) HbAbstractViewItem *last = d->mItems.last(); if (animate) { last->setOpacity(0.0); @@ -160,30 +168,51 @@ return; } + HbModelIterator *modelIterator = d->mItemView->modelIterator(); QModelIndex index = startIndex; if (!index.isValid()) { - index = d->mItemView->model()->index(0, 0); - if (!index.isValid()) + index = modelIterator->nextIndex(QModelIndex()); + if (!index.isValid()) { + // this mean model is empty return; + } } - index = d->mItemView->model()->index( - d->alignIndexToClosestFirstInRow(index.row()), 0); + + int indexPosition = modelIterator->indexPosition(index); + indexPosition = d->alignIndexToClosestFirstInRow(indexPosition); + index = modelIterator->index(indexPosition); - int modelItemsCount = d->mItemView->model()->rowCount(); + int modelItemsCount = modelIterator->indexCount(); int itemsCount = d->mItems.count(); - int diff = index.row() + itemsCount - modelItemsCount; + int diff = indexPosition + itemsCount - modelItemsCount; if (diff >= d->mItemsPerRow) { - diff = modelItemsCount - itemsCount; - if (diff % d->mItemsPerRow) diff = diff + d->mItemsPerRow - diff % d->mItemsPerRow; - index = d->mItemView->model()->index(diff, 0); - if (!index.isValid()) - index = d->mItemView->model()->index(0, 0); + // starting from index do not fill the buffer + // so new starting index need to be calculated + // to fill the buffer with items + int newStartIndex = modelItemsCount - itemsCount; + int remainder = newStartIndex % d->mItemsPerRow;; + if (remainder) { + // move newStartIndex forward to contain + // last row and empty items + newStartIndex += d->mItemsPerRow - remainder; + } + index = modelIterator->index(newStartIndex); + if (!index.isValid()) { + // if invalid get first item from model + index = modelIterator->nextIndex(QModelIndex()); + } + indexPosition = modelIterator->indexPosition(index); + } + + if (d->mItems.first()->modelIndex() == index) { + // container already contain right items + return; } int i = 0; for (; i < itemsCount && index.isValid(); ++i) { setItemModelIndex(d->mItems.at(i), index); - index = d->mItemView->modelIterator()->nextIndex(index); + index = modelIterator->nextIndex(index); } if (i < itemsCount) { @@ -191,6 +220,11 @@ setItemModelIndex(d->mItems.at(i), index); } if (i < itemsCount) { + // somehow model size was change + // this is almost impossible do get there - + // means that items were removed but view + // was not noticed about that - or setModelIndexes + // was call before model has noticed view while (i > d->mItems.count()) { d->mItems.removeLast(); } @@ -210,18 +244,10 @@ /*! \reimp */ -void HbGridItemContainer::viewResized(const QSizeF &size) +void HbGridItemContainer::viewResized(const QSizeF &) { Q_D(HbGridItemContainer); - if (!(qFuzzyCompare(d->mViewSize.height(), size.height()) - && qFuzzyCompare(d->mViewSize.width(), size.width()))) { - QPointF p = pos(); - p.setY(p.y() * size.height() / d->mViewSize.height()); - p.setX(p.x() * size.width() / d->mViewSize.width()); - setPos(p); - d->mViewSize = size; - d->resetBuffer(); - } + d->resetBuffer(); } /*! @@ -250,68 +276,56 @@ /*! \reimp */ - QPointF HbGridItemContainer::recycleItems(const QPointF &delta) { Q_D(HbGridItemContainer); - if (!d->mItemRecycling || d->mItemsPerRow <=0) { + if (d->mPrototypes.count() != 1) { return delta; } - QRectF viewRect(d->itemBoundingRect(d->mItemView)); - QSizeF itemsCanvas(layout()->preferredSize()); - qreal invisibleArea = 0; + // current invisible space can be scrolled by base class + // recycling need only do the rest + const qreal diff = d->getDiffWithoutScrollareaCompensation(delta); - qreal diff = 0.0; - if (Qt::Vertical == d->mScrollDirection) { - invisibleArea = itemsCanvas.height() - viewRect.height(); - diff = pos().y() - delta.y(); - if ((delta.y() < 0.0 && diff > 0) - || (delta.y() > 0.0 && invisibleArea + diff < 0)) { - diff = delta.y(); + if (diff != 0.0) { + HbModelIterator *modelIterator = d->mItemView->modelIterator(); + qreal result = 0.0; + qreal containerSize = (d->mScrollDirection == Qt::Vertical) + ? size().height() : size().width(); + bool doFarJump = false; + if (qAbs(diff) > containerSize) { + // if huge diff - current buffer does not containt any item that should + // be there after jump - because of that use setModelIndexes instead of + // recycling items - faster + // but it is possible that even if far jump was requested (huge delta) + // it can't be done because of model size and current position (at the end) + if (diff > 0) { + // scrolling down + int indexPos = modelIterator->indexPosition(d->lastValidItemIndex()) + + d->mItems.count(); + doFarJump = (indexPos < modelIterator->indexCount()); + } else { + // scrolling up + int indexPos = modelIterator->indexPosition(d->mItems.first()->modelIndex()) + - d->mItems.count(); + doFarJump = (indexPos >= 0); + } } - else { - diff = 0.0; - } - } - else { - invisibleArea = itemsCanvas.width() - viewRect.width(); - diff = pos().x() - delta.x(); - if ((delta.x() < 0.0 && diff > 0) - || (delta.x() > 0.0 && invisibleArea + diff < 0)) { - diff = delta.x(); + if (doFarJump) { + // start calculations for far jump + // take back into account real delta (do jump as far as possible + // without leaving it for scroll area) + result = d->farRecycling(delta); } else { - diff = 0.0; - } - } - - if (diff != 0.0) { - if (HbAbstractItemViewPrivate::d_ptr(d->mItemView)->mOptions & HbAbstractItemViewPrivate::PanningActive) { - // jump is almost in the middle of fetched buffer - in most of cases - // after scrolling was stopped panning should be done without fetching - // items - // in case when buffer == 1 below lines do not change diff - qreal extraDiff = invisibleArea/2 - d->mCachedItemHeight; - if (extraDiff < 0.0) { - extraDiff = 0.0; // impossible because this mean that bufferSize == 0 - } - - if (diff < 0.0) { - diff -= extraDiff; - } - else { - diff += extraDiff; - } + result = d->recycling(diff); } - qreal result = (d->recycling(diff)); + QPointF newDelta(Qt::Vertical == d->mScrollDirection + ? QPointF(0.0, delta.y() - result) + : QPointF(delta.x() - result, 0.0)); - QPointF newDelta(Qt::Vertical == d->mScrollDirection - ?QPointF(0.0, delta.y() - result) - : QPointF(delta.x() - result, 0.0)); - return newDelta; } @@ -460,7 +474,7 @@ { Q_D(HbGridItemContainer); - if (!index.isValid() || d->mItems.count() <= 0) + if (!index.isValid() || d->mItems.isEmpty()) return; switch (hint) { @@ -512,6 +526,15 @@ } } +/*! + \reimp + In grid case items are allways same size +*/ +void HbGridItemContainer::setUniformItemSizes(bool enable) +{ + Q_UNUSED(enable); + // d->mUniformItemSizes - allways true +} #include "moc_hbgriditemcontainer_p.cpp"