src/hbwidgets/itemviews/hbgriditemcontainer_p.cpp
changeset 1 f7ac710697a9
parent 0 16d8024aca5e
child 2 06ff229162e9
equal deleted inserted replaced
0:16d8024aca5e 1:f7ac710697a9
    86 
    86 
    87     if (!index.isValid())
    87     if (!index.isValid())
    88         return;
    88         return;
    89 
    89 
    90     int bufferIndex = 0;
    90     int bufferIndex = 0;
    91     if (d->mItems.count() != 0) {
    91     QModelIndex firstInBuffer;
    92         bufferIndex = qMax(0, index.row() - d->mItems.first()->modelIndex().row());
    92     int firstInBufferPosition = -1;
       
    93     int indexPosition = d->mItemView->modelIterator()->indexPosition(index);
       
    94     if (!d->mItems.isEmpty()) {
       
    95         firstInBuffer = d->mItems.first()->modelIndex();
       
    96         firstInBufferPosition = d->mItemView->modelIterator()->indexPosition(firstInBuffer);
       
    97         bufferIndex = qMax(0, indexPosition - firstInBufferPosition);
    93     }
    98     }
    94     // inserting new item because of buffer size
    99     // inserting new item because of buffer size
    95     if (d->mItems.count() == 0
   100     if (d->mItems.isEmpty()
    96         || d->mItems.count() < maxItemCount()) {
   101         || d->mItems.count() < maxItemCount()) {
    97         insertItem(bufferIndex, index, animate);
   102         insertItem(bufferIndex, index, animate);
    98         viewLayout()->invalidate();
   103         viewLayout()->invalidate();
    99     }
   104     }
   100     // special case - only for grid, if added item is above the 
   105     // special case - only for grid, if added item is above the 
   101     // visible region we need to shift all visible items by one!
   106     // visible region we need to shift all visible items by one!
   102     else if (d->mItems.count() > 0
   107     else if (!d->mItems.isEmpty()
   103         && d->mItems.first()->modelIndex().row() > index.row()) {
   108         && firstInBufferPosition > indexPosition) {
   104         d->shiftUpItem(animate); // shift up in this case always return something
   109         d->shiftUpItem(animate); // shift up in this case always return something
   105         viewLayout()->invalidate();
   110         viewLayout()->invalidate();
   106     }
   111     }
   107     // new item is in visible range
   112     // new item is in visible range
   108     else if (bufferIndex < d->mItems.count()) {
   113     else if (bufferIndex < d->mItems.count()) {
       
   114         // new added item comes to buffer - it will be
       
   115         // recycled from last item in buffer (it is also ok
       
   116         // when that last item was invalid)
   109         HbAbstractViewItem *last = d->mItems.last();
   117         HbAbstractViewItem *last = d->mItems.last();
   110         if (animate) {
   118         if (animate) {
   111             last->setOpacity(0.0);
   119             last->setOpacity(0.0);
   112         }
   120         }
   113         setItemModelIndex(last, index);
   121         setItemModelIndex(last, index);
   158 
   166 
   159     if (!d->mItemView || !d->mItemView->model()) {
   167     if (!d->mItemView || !d->mItemView->model()) {
   160         return;
   168         return;
   161     }
   169     }
   162 
   170 
       
   171     HbModelIterator *modelIterator = d->mItemView->modelIterator();
   163     QModelIndex index = startIndex;
   172     QModelIndex index = startIndex;
   164     if (!index.isValid()) {
   173     if (!index.isValid()) {
   165         index = d->mItemView->model()->index(0, 0);
   174         index = modelIterator->nextIndex(QModelIndex());
   166         if (!index.isValid())
   175         if (!index.isValid()) {
       
   176             // this mean model is empty
   167             return;
   177             return;
   168     }
   178         }
   169     index = d->mItemView->model()->index(
   179     }
   170                 d->alignIndexToClosestFirstInRow(index.row()), 0);
   180 
   171 
   181     int indexPosition = modelIterator->indexPosition(index);
   172     int modelItemsCount = d->mItemView->model()->rowCount();
   182     indexPosition = d->alignIndexToClosestFirstInRow(indexPosition);
       
   183     index = modelIterator->index(indexPosition);
       
   184 
       
   185     int modelItemsCount = modelIterator->indexCount();
   173     int itemsCount = d->mItems.count();
   186     int itemsCount = d->mItems.count();
   174     int diff = index.row() + itemsCount - modelItemsCount;
   187     int diff = indexPosition + itemsCount - modelItemsCount;
   175     if (diff >= d->mItemsPerRow) {
   188     if (diff >= d->mItemsPerRow) {
   176         diff = modelItemsCount - itemsCount;
   189         // starting from index do not fill the buffer
   177         if (diff % d->mItemsPerRow) diff = diff + d->mItemsPerRow - diff % d->mItemsPerRow;
   190         // so new starting index need to be calculated
   178         index = d->mItemView->model()->index(diff, 0);
   191         // to fill the buffer with items
   179         if (!index.isValid())
   192         int newStartIndex = modelItemsCount - itemsCount;
   180             index = d->mItemView->model()->index(0, 0);
   193         int remainder = newStartIndex % d->mItemsPerRow;;
       
   194         if (remainder) {
       
   195             // move newStartIndex forward to contain
       
   196             // last row and empty items
       
   197             newStartIndex += d->mItemsPerRow - remainder;
       
   198         }
       
   199         index = modelIterator->index(newStartIndex);
       
   200         if (!index.isValid()) {
       
   201             // if invalid get first item from model
       
   202             index = modelIterator->nextIndex(QModelIndex());
       
   203         }
       
   204         indexPosition = modelIterator->indexPosition(index);
       
   205     }
       
   206 
       
   207     if (d->mItems.first()->modelIndex() == index) {
       
   208         // container already contain right items
       
   209         return;
   181     }
   210     }
   182 
   211 
   183     int i = 0;
   212     int i = 0;
   184     for (; i < itemsCount && index.isValid(); ++i) {
   213     for (; i < itemsCount && index.isValid(); ++i) {
   185         setItemModelIndex(d->mItems.at(i), index);
   214         setItemModelIndex(d->mItems.at(i), index);
   186         index = d->mItemView->modelIterator()->nextIndex(index);
   215         index = modelIterator->nextIndex(index);
   187     }
   216     }
   188 
   217 
   189     if (i < itemsCount) {
   218     if (i < itemsCount) {
   190         for (; i % d->mItemsPerRow != 0; i++) {
   219         for (; i % d->mItemsPerRow != 0; i++) {
   191             setItemModelIndex(d->mItems.at(i), index);
   220             setItemModelIndex(d->mItems.at(i), index);
   192         }
   221         }
   193         if (i < itemsCount) {
   222         if (i < itemsCount) {
       
   223             // somehow model size was change
       
   224             // this is almost impossible do get there -
       
   225             // means that items were removed but view 
       
   226             // was not noticed about that - or setModelIndexes
       
   227             // was call before model has noticed view
   194             while (i > d->mItems.count()) {
   228             while (i > d->mItems.count()) {
   195                 d->mItems.removeLast();
   229                 d->mItems.removeLast();
   196             }
   230             }
   197         }
   231         }
   198     }
   232     }
   208 }
   242 }
   209 
   243 
   210 /*!
   244 /*!
   211     \reimp
   245     \reimp
   212 */
   246 */
   213 void HbGridItemContainer::viewResized(const QSizeF &size)
   247 void HbGridItemContainer::viewResized(const QSizeF &)
   214 {
   248 {
   215     Q_D(HbGridItemContainer);
   249     Q_D(HbGridItemContainer);
   216     if (!(qFuzzyCompare(d->mViewSize.height(), size.height())
   250     d->resetBuffer();
   217             && qFuzzyCompare(d->mViewSize.width(), size.width()))) {
       
   218         QPointF p = pos();
       
   219         p.setY(p.y() *  size.height() / d->mViewSize.height());
       
   220         p.setX(p.x() * size.width() / d->mViewSize.width());
       
   221         setPos(p);
       
   222         d->mViewSize = size;
       
   223         d->resetBuffer();
       
   224     }
       
   225 }
   251 }
   226 
   252 
   227 /*!
   253 /*!
   228     \reimp
   254     \reimp
   229 */
   255 */
   248 }
   274 }
   249 
   275 
   250 /*!
   276 /*!
   251     \reimp
   277     \reimp
   252 */
   278 */
   253 
       
   254 QPointF HbGridItemContainer::recycleItems(const QPointF &delta)
   279 QPointF HbGridItemContainer::recycleItems(const QPointF &delta)
   255 {
   280 {
   256     Q_D(HbGridItemContainer);
   281     Q_D(HbGridItemContainer);
   257 
   282 
   258     if (!d->mItemRecycling || d->mItemsPerRow <=0) {
   283     if (d->mPrototypes.count() != 1) {
   259         return delta;
   284         return delta;
   260     }
   285     }
   261 
   286 
   262     QRectF viewRect(d->itemBoundingRect(d->mItemView));
   287     // current invisible space can be scrolled by base class
   263     QSizeF itemsCanvas(layout()->preferredSize());
   288     // recycling need only do the rest
   264     qreal invisibleArea = 0;
   289     const qreal diff = d->getDiffWithoutScrollareaCompensation(delta);
   265 
   290 
   266     qreal diff = 0.0;
   291     if (diff != 0.0) {
   267     if (Qt::Vertical == d->mScrollDirection) {
   292         HbModelIterator *modelIterator = d->mItemView->modelIterator();
   268         invisibleArea = itemsCanvas.height() - viewRect.height();
   293         qreal result = 0.0;
   269         diff = pos().y() - delta.y();
   294         qreal containerSize = (d->mScrollDirection == Qt::Vertical)
   270         if ((delta.y() < 0.0 && diff > 0) 
   295             ? size().height() : size().width();
   271             || (delta.y() > 0.0 && invisibleArea + diff < 0)) {
   296         bool doFarJump = false;
   272             diff = delta.y();
   297         if (qAbs(diff) > containerSize) {
       
   298             // if huge diff - current buffer does not containt any item that should
       
   299             // be there after jump - because of that use setModelIndexes instead of
       
   300             // recycling items - faster
       
   301             // but it is possible that even if far jump was requested (huge delta) 
       
   302             // it can't be done because of model size and current position (at the end)
       
   303             if (diff > 0) {
       
   304                 // scrolling down
       
   305                 int indexPos = modelIterator->indexPosition(d->lastValidItemIndex())
       
   306                                 + d->mItems.count();
       
   307                 doFarJump = (indexPos < modelIterator->indexCount());
       
   308             } else {
       
   309                 // scrolling up
       
   310                 int indexPos = modelIterator->indexPosition(d->mItems.first()->modelIndex())
       
   311                                 - d->mItems.count();
       
   312                 doFarJump = (indexPos >= 0);
       
   313             }
       
   314         }
       
   315         if (doFarJump) {
       
   316             // start calculations for far jump
       
   317             // take back into account real delta (do jump as far as possible
       
   318             // without leaving it for scroll area)
       
   319             result = d->farRecycling(delta);
   273         }
   320         }
   274         else {
   321         else {
   275             diff = 0.0;   
   322             result = d->recycling(diff);
   276         }
   323         }
   277     }
       
   278     else {
       
   279         invisibleArea = itemsCanvas.width() - viewRect.width();
       
   280         diff = pos().x() - delta.x();
       
   281         if ((delta.x() < 0.0 && diff > 0) 
       
   282             || (delta.x() > 0.0 && invisibleArea + diff < 0)) {
       
   283             diff = delta.x();
       
   284         }
       
   285         else {
       
   286             diff = 0.0;   
       
   287         }
       
   288     }
       
   289 
       
   290     if (diff != 0.0) {
       
   291         if (HbAbstractItemViewPrivate::d_ptr(d->mItemView)->mOptions & HbAbstractItemViewPrivate::PanningActive) {
       
   292             // jump is almost in the middle of fetched buffer - in most of cases
       
   293             // after scrolling was stopped panning should be done without fetching 
       
   294             // items
       
   295             // in case when buffer == 1 below lines do not change diff
       
   296             qreal extraDiff = invisibleArea/2 - d->mCachedItemHeight;
       
   297             if (extraDiff < 0.0) {
       
   298                 extraDiff = 0.0; // impossible because this mean that bufferSize == 0
       
   299             }
       
   300 
       
   301             if (diff < 0.0) {
       
   302                 diff -= extraDiff; 
       
   303             }
       
   304             else {
       
   305                 diff += extraDiff;
       
   306             }   
       
   307         }
       
   308 
       
   309         qreal result = (d->recycling(diff));
       
   310 
   324 
   311         QPointF newDelta(Qt::Vertical == d->mScrollDirection
   325         QPointF newDelta(Qt::Vertical == d->mScrollDirection
   312                 ?QPointF(0.0, delta.y() - result) 
   326                 ? QPointF(0.0, delta.y() - result) 
   313                 : QPointF(delta.x() - result, 0.0));
   327                 : QPointF(delta.x() - result, 0.0));
   314         
   328 
   315         return newDelta;
   329         return newDelta;
   316     }
   330     }
   317 
   331 
   318     return delta;
   332     return delta;
   319 }
   333 }
   458 */
   472 */
   459 void HbGridItemContainer::scrollTo(const QModelIndex &index, HbAbstractItemView::ScrollHint hint)
   473 void HbGridItemContainer::scrollTo(const QModelIndex &index, HbAbstractItemView::ScrollHint hint)
   460 {
   474 {
   461     Q_D(HbGridItemContainer);
   475     Q_D(HbGridItemContainer);
   462 
   476 
   463     if (!index.isValid() || d->mItems.count() <= 0)
   477     if (!index.isValid() || d->mItems.isEmpty())
   464         return;
   478         return;
   465     
   479     
   466     switch (hint) {
   480     switch (hint) {
   467         case HbAbstractItemView::EnsureVisible: d->scrollToEnsureVisible(index); break;
   481         case HbAbstractItemView::EnsureVisible: d->scrollToEnsureVisible(index); break;
   468         case HbAbstractItemView::PositionAtTop: d->scrollToPositionAtTop(index); break;
   482         case HbAbstractItemView::PositionAtTop: d->scrollToPositionAtTop(index); break;
   510         item->graphicsItem()->setOpacity(1.0);
   524         item->graphicsItem()->setOpacity(1.0);
   511         HbEffect::start(item->graphicsItem(), "gridviewitem", "appear", d->mItemView, "_q_animationFinished");
   525         HbEffect::start(item->graphicsItem(), "gridviewitem", "appear", d->mItemView, "_q_animationFinished");
   512     }
   526     }
   513 }
   527 }
   514 
   528 
       
   529 /*!
       
   530     \reimp
       
   531     In grid case items are allways same size
       
   532 */
       
   533 void HbGridItemContainer::setUniformItemSizes(bool enable)
       
   534 {
       
   535     Q_UNUSED(enable);
       
   536     // d->mUniformItemSizes - allways true
       
   537 }
   515 
   538 
   516 #include "moc_hbgriditemcontainer_p.cpp"
   539 #include "moc_hbgriditemcontainer_p.cpp"
   517 
   540