src/hbwidgets/itemviews/hblistitemcontainer_p.cpp
changeset 0 16d8024aca5e
child 1 f7ac710697a9
equal deleted inserted replaced
-1:000000000000 0:16d8024aca5e
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2008-2010 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (developer.feedback@nokia.com)
       
     6 **
       
     7 ** This file is part of the HbWidgets module of the UI Extensions for Mobile.
       
     8 **
       
     9 ** GNU Lesser General Public License Usage
       
    10 ** This file may be used under the terms of the GNU Lesser General Public
       
    11 ** License version 2.1 as published by the Free Software Foundation and
       
    12 ** appearing in the file LICENSE.LGPL included in the packaging of this file.
       
    13 ** Please review the following information to ensure the GNU Lesser General
       
    14 ** Public License version 2.1 requirements will be met:
       
    15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    16 **
       
    17 ** In addition, as a special exception, Nokia gives you certain additional
       
    18 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    20 **
       
    21 ** If you have questions regarding the use of this file, please contact
       
    22 ** Nokia at developer.feedback@nokia.com.
       
    23 **
       
    24 ****************************************************************************/
       
    25 
       
    26 #include "hblistitemcontainer_p.h"
       
    27 #include "hblistitemcontainer_p_p.h"
       
    28 #include "hblistlayout_p.h"
       
    29 
       
    30 #include "hbabstractitemcontainer.h"
       
    31 #include "hbabstractitemview.h"
       
    32 #include "hblistviewitem.h"
       
    33 #include "hblistview.h"
       
    34 #include "hbmodeliterator.h"
       
    35 
       
    36 #include <qmath.h>
       
    37 #include <QDebug>
       
    38 
       
    39 const int Hb_Recycle_Buffer_Shrink_Threshold = 2; // Rather arbitrary
       
    40 
       
    41 HbListItemContainerPrivate::HbListItemContainerPrivate() :
       
    42     HbAbstractItemContainerPrivate(),
       
    43     mLayout(0)
       
    44 { 
       
    45 }
       
    46 
       
    47 HbListItemContainerPrivate::~HbListItemContainerPrivate()
       
    48 {
       
    49 }
       
    50 
       
    51 void HbListItemContainerPrivate::init()
       
    52 {   
       
    53     Q_Q(HbListItemContainer);
       
    54  
       
    55     mLayout = new HbListLayout();
       
    56     mLayout->setContentsMargins(0, 0, 0, 0);
       
    57     //mLayout->setPreferredWidth(q->size().width());
       
    58 
       
    59     q->setLayout(mLayout);
       
    60 }
       
    61 
       
    62 /*!
       
    63     \private
       
    64 
       
    65     Changes first abstract view item from item buffer to be the last one.
       
    66 */
       
    67 HbAbstractViewItem *HbListItemContainerPrivate::shiftDownItem(QPointF& delta)
       
    68 {
       
    69     Q_Q(HbListItemContainer);
       
    70 
       
    71     HbAbstractViewItem *item = 0;
       
    72     HbAbstractViewItem *lastItem = mItems.last();
       
    73 
       
    74     QModelIndex nextIndex = mItemView->modelIterator()->nextIndex(lastItem->modelIndex());
       
    75     if (nextIndex.isValid()) {
       
    76         item = mItems.takeFirst();
       
    77 
       
    78         q->itemRemoved(item);
       
    79 
       
    80         delta.setY(delta.y() - item->size().height());
       
    81 
       
    82         mItems.append(item);
       
    83 
       
    84         q->setItemModelIndex(item, nextIndex);
       
    85 
       
    86         q->itemAdded(mItems.count() - 1, item);
       
    87     }
       
    88 
       
    89     return item;
       
    90 }
       
    91 
       
    92 /*!
       
    93     \private
       
    94 
       
    95     Changes last view item from item buffer to be the first one.
       
    96 */
       
    97 HbAbstractViewItem *HbListItemContainerPrivate::shiftUpItem(QPointF& delta)
       
    98 {
       
    99     Q_Q(HbListItemContainer);
       
   100 
       
   101     HbAbstractViewItem *item = 0;
       
   102     HbAbstractViewItem *firstItem = mItems.first();
       
   103 
       
   104     QModelIndex previousIndex = mItemView->modelIterator()->previousIndex(firstItem->modelIndex());
       
   105     if (previousIndex.isValid()) {
       
   106         item = mItems.takeLast();
       
   107 
       
   108         q->itemRemoved(item);
       
   109 
       
   110         mItems.insert(0, item);
       
   111 
       
   112         q->setItemModelIndex(item, previousIndex);
       
   113         
       
   114         qreal itemHeight=0;
       
   115         if (q->uniformItemSizes()) {
       
   116             itemHeight = mItems.last()->preferredHeight();
       
   117         } else {
       
   118             //This is time consuming and causes backwards srolling to be slower than forwards.
       
   119             //The sizehint of the item is dirty.
       
   120             itemHeight = item->preferredHeight();
       
   121         }
       
   122         
       
   123         delta.setY(delta.y() + itemHeight);
       
   124 
       
   125         q->itemAdded(0, item);
       
   126     }
       
   127     return item;
       
   128 }
       
   129 
       
   130 bool HbListItemContainerPrivate::intoContainerBuffer(const QModelIndex &index) const
       
   131 {   
       
   132     if (mItems.first()->modelIndex().row() <= index.row()   
       
   133         && mItems.last()->modelIndex().row() >= index.row()){
       
   134         return true;
       
   135     } else {
       
   136         return false;
       
   137     }
       
   138 }
       
   139 
       
   140 int HbListItemContainerPrivate::containerBufferIndexForModelIndex(const QModelIndex &index) const 
       
   141 {   
       
   142     return qMax(0, index.row() - mItems.first()->modelIndex().row());
       
   143 }
       
   144 
       
   145 qreal HbListItemContainerPrivate::getSmallestItemHeight() const
       
   146 {
       
   147     Q_Q(const HbListItemContainer);
       
   148 
       
   149     qreal minHeight = 0;
       
   150     if (mItems.count() > 0) {
       
   151         minHeight = mLayout->smallestItemHeight();
       
   152     }
       
   153 
       
   154     if (minHeight == 0) {
       
   155         QModelIndex index;
       
   156         while (mItems.isEmpty()) {
       
   157             // in practise following conditions must apply: itemview is empty and scrollTo() has been called.
       
   158             // Starts populating items from given mFirstItemIndex
       
   159             if ( mFirstItemIndex.isValid()) {
       
   160                 index = mFirstItemIndex;
       
   161                 const_cast<QPersistentModelIndex&>(mFirstItemIndex) = QModelIndex();
       
   162             } else {
       
   163                 index = mItemView->modelIterator()->nextIndex(index);
       
   164             }
       
   165             if (!index.isValid()) {
       
   166                 break;
       
   167             }
       
   168             const_cast<HbListItemContainer *>(q)->insertItem(0, index);
       
   169         }
       
   170 
       
   171         if (!mItems.isEmpty()) {
       
   172             minHeight = mItems.first()->preferredHeight();
       
   173         }
       
   174     }
       
   175     return minHeight;
       
   176 }
       
   177 
       
   178 HbListItemContainer::HbListItemContainer(QGraphicsItem *parent) :
       
   179     HbAbstractItemContainer(*new HbListItemContainerPrivate, parent)
       
   180 {
       
   181     Q_D(HbListItemContainer);
       
   182 
       
   183     d->q_ptr = this;
       
   184     d->init();
       
   185 }
       
   186 
       
   187 HbListItemContainer::HbListItemContainer(HbListItemContainerPrivate &dd, QGraphicsItem *parent) :
       
   188     HbAbstractItemContainer(dd, parent)
       
   189 {
       
   190     Q_D(HbListItemContainer);
       
   191 
       
   192     d->q_ptr = this;
       
   193     d->init();
       
   194 }
       
   195 
       
   196 /*!
       
   197     Destructor.
       
   198  */
       
   199 HbListItemContainer::~HbListItemContainer()
       
   200 {
       
   201 }
       
   202 
       
   203 /*!
       
   204     \reimp
       
   205 */
       
   206 void HbListItemContainer::itemRemoved( HbAbstractViewItem *item, bool animate )
       
   207 {
       
   208     Q_D(HbListItemContainer);
       
   209 
       
   210     if (static_cast<HbListView *>(d->mItemView)->arrangeMode()) {
       
   211         d->mLayout->removeItem(item, false);
       
   212     } else {
       
   213         d->mLayout->removeItem(item, animate);
       
   214     }
       
   215 }
       
   216 
       
   217 /*!
       
   218     \reimp
       
   219 */
       
   220 void HbListItemContainer::itemAdded(int index, HbAbstractViewItem *item, bool animate)
       
   221 {
       
   222     Q_D(HbListItemContainer);
       
   223 
       
   224     if (static_cast<HbListView *>(d->mItemView)->arrangeMode()) {
       
   225         d->mLayout->insertItem(index,item, false);
       
   226     } else {
       
   227         d->mLayout->insertItem(index,item, animate);
       
   228     }
       
   229 
       
   230 }
       
   231 
       
   232 /*!
       
   233     \reimp
       
   234 */
       
   235 void HbListItemContainer::viewResized(const QSizeF &viewSize)
       
   236 {
       
   237 //    Q_D(HbListItemContainer);
       
   238     //d->mLayout->setPreferredWidth(size.width());
       
   239     QSizeF newSize = size();
       
   240     newSize.setWidth( viewSize.width() );
       
   241     resize( newSize );
       
   242 }
       
   243 
       
   244 /*!
       
   245     \reimp
       
   246 */
       
   247 QPointF HbListItemContainer::recycleItems(const QPointF &delta)
       
   248 {
       
   249     Q_D(HbListItemContainer);
       
   250 
       
   251     if (d->mPrototypes.count() != 1) {
       
   252         return delta;
       
   253     }
       
   254 
       
   255     QRectF viewRect(d->itemBoundingRect(d->mItemView));
       
   256     viewRect.moveTopLeft(viewRect.topLeft() + delta);
       
   257 
       
   258     int firstVisibleBufferIndex = -1;
       
   259     int lastVisibleBufferIndex = -1;
       
   260     d->firstAndLastVisibleBufferIndex(firstVisibleBufferIndex, lastVisibleBufferIndex, viewRect, false);
       
   261 
       
   262     int hiddenAbove = firstVisibleBufferIndex;
       
   263     int hiddenBelow = d->mItems.count() - lastVisibleBufferIndex - 1;
       
   264 
       
   265     if (d->mItems.count()
       
   266         && (firstVisibleBufferIndex == -1 || lastVisibleBufferIndex == -1)) {
       
   267         // All items out of sight.
       
   268         if (d->itemBoundingRect(d->mItems.first()).top() < 0) {
       
   269             // All items above view.
       
   270             hiddenAbove = d->mItems.count();
       
   271             hiddenBelow = 0;
       
   272         } else {
       
   273             // All items below view.
       
   274             hiddenAbove = 0;
       
   275             hiddenBelow = d->mItems.count();
       
   276         }
       
   277     }
       
   278 
       
   279     QPointF newDelta(delta);
       
   280 
       
   281     while (hiddenAbove > hiddenBelow + 1) {
       
   282         HbAbstractViewItem *item = d->shiftDownItem(newDelta);
       
   283         if (!item){
       
   284             break;
       
   285         }
       
   286 
       
   287         if (!d->visible(item, viewRect)) {
       
   288             hiddenBelow++;
       
   289         }
       
   290         hiddenAbove--;
       
   291     }
       
   292 
       
   293     while (hiddenBelow > hiddenAbove + 1) {
       
   294         HbAbstractViewItem *item = d->shiftUpItem(newDelta);
       
   295         if (!item) {
       
   296             break;
       
   297         }
       
   298 
       
   299         if (!d->visible( item, viewRect)) {
       
   300             hiddenAbove++;
       
   301         }
       
   302         hiddenBelow--;
       
   303     }
       
   304 
       
   305     return newDelta;
       
   306 }
       
   307 
       
   308 
       
   309 /*!
       
   310     Calculates the optimal view item buffer size. When recycling is turned off
       
   311     returned buffer same is same as the amount of rows within the model. When 
       
   312     recycling is enabled the amount is calculated by dividing the view area with
       
   313     average item height. Average item height is taken from the average of existing
       
   314     view item's heights or by creating item using prototype for the first row.
       
   315 */
       
   316 int HbListItemContainer::maxItemCount() const
       
   317 {
       
   318     Q_D(const HbListItemContainer);
       
   319 
       
   320     int targetCount = HbAbstractItemContainer::maxItemCount();
       
   321     if (targetCount > 0
       
   322         && d->mItemRecycling
       
   323         && d->mPrototypes.count() <= 1) {
       
   324     
       
   325         qreal minHeight = d->getSmallestItemHeight();
       
   326 
       
   327         if (minHeight > 0) {
       
   328             int countEstimate = qCeil(d->mItemView->boundingRect().height() / minHeight)
       
   329                 + d->mBufferSize;
       
   330 
       
   331             int currentCount = d->mItems.count();
       
   332             if (countEstimate < currentCount) {
       
   333                 // Shrink the recycle buffer only if change is more than
       
   334                 // buffer shrink threshold. 
       
   335                 if (countEstimate > (currentCount - Hb_Recycle_Buffer_Shrink_Threshold)) {
       
   336                     countEstimate = currentCount;
       
   337                 }
       
   338             }
       
   339 
       
   340             // This limits the targetCount not to be larger
       
   341             // than row count inside model.
       
   342             targetCount = qMin(targetCount, countEstimate);
       
   343         } else {
       
   344             targetCount = 0;
       
   345         }
       
   346     } 
       
   347     return targetCount;
       
   348 }
       
   349 
       
   350 HbAbstractViewItem *HbListItemContainer::createDefaultPrototype() const
       
   351 {
       
   352     return new HbListViewItem();
       
   353 }
       
   354 
       
   355 void HbListItemContainer::animationFinished(const HbEffect::EffectStatus &status)
       
   356 {
       
   357     Q_D(HbListItemContainer);
       
   358 
       
   359     HbAbstractViewItem *item = static_cast<HbAbstractViewItem *>(status.item);
       
   360     d->mLayout->removeAt(d->mLayout->indexOf(item));
       
   361     item->deleteLater();
       
   362 }
       
   363 
       
   364 #include "moc_hblistitemcontainer_p.cpp"
       
   365 
       
   366