src/hbwidgets/itemviews/hbabstractitemview_p.cpp
changeset 0 16d8024aca5e
child 1 f7ac710697a9
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hbwidgets/itemviews/hbabstractitemview_p.cpp	Mon Apr 19 14:02:13 2010 +0300
@@ -0,0 +1,969 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (developer.feedback@nokia.com)
+**
+** This file is part of the HbWidgets module of the UI Extensions for Mobile.
+**
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this file.
+** Please review the following information to ensure the GNU Lesser General
+** Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at developer.feedback@nokia.com.
+**
+****************************************************************************/
+
+#include "hbabstractitemview_p.h"
+#include "hbabstractitemview.h"
+#include "hbabstractviewitem.h"
+#include "hbabstractitemcontainer.h"
+#include "hbmodeliterator.h"
+
+#include <hbgesturefilter.h>
+#include <hbinstance.h>
+#include <hbscrollbar.h>
+#include <hbapplication.h>
+#include <hbeffect.h>
+
+#include <QGraphicsSceneMouseEvent>
+#include <QEvent>
+#include <QItemSelectionModel>
+#include <QGraphicsScene>
+#include <QGraphicsLayout>
+#include <QTimer>
+#include <QDebug>
+
+HbAbstractItemViewPrivate::HbAbstractItemViewPrivate() :
+    mSelectionMode(HbAbstractItemView::NoSelection),
+    mOptions(NoOptions),
+    mSelectionSettings(None),
+    mHitItem(0),
+    mContainer(0),
+    mSelectionModel(0),
+    mContSelectionAction(QItemSelectionModel::NoUpdate),
+    mWasScrolling(false),
+    mFilterRemoved(false),
+    mClearingSelection(false),
+    mAnimateItems(false),
+    mPostponedScrollHint(HbAbstractItemView::PositionAtTop),
+    mPreviousSelectedCommand(QItemSelectionModel::NoUpdate),
+    mInstantClickedModifiers(0),
+    mAnimationTimer(0),
+	mModelIterator(0),
+    mEnabledAnimations(HbAbstractItemView::All)
+{
+}
+
+HbAbstractItemViewPrivate::~HbAbstractItemViewPrivate()
+{
+    if (mModelIterator) {
+        delete mModelIterator;
+        mModelIterator = 0;
+    }
+}
+
+/*!
+
+*/
+void HbAbstractItemViewPrivate::init(HbAbstractItemContainer *container, HbModelIterator *modelIterator)
+{
+    Q_Q(HbAbstractItemView);
+
+    q->setLongPressEnabled(true);
+    q->setFlag(QGraphicsItem::ItemIsFocusable, true);
+    q->setFocusPolicy(Qt::StrongFocus);
+    
+    q->setContentWidget(container);
+
+    mContainer = container;
+    mContainer->setItemView(q);
+
+    mModelIterator = modelIterator;
+
+    HbMainWindow *window = q->mainWindow();
+    if (window
+        && q->scene()) { // added to scene
+        q->connect(window, SIGNAL(aboutToChangeOrientation()),
+                   q, SLOT(orientationAboutToBeChanged()));
+
+        q->connect(window, SIGNAL(orientationChanged(Qt::Orientation)),
+                   q, SLOT(orientationChanged(Qt::Orientation)));
+
+        if (q->verticalScrollBar()) {
+            q->verticalScrollBar()->installSceneEventFilter(q);
+        }
+        if (q->horizontalScrollBar()) {
+            q->horizontalScrollBar()->installSceneEventFilter(q);
+        }
+    }
+}
+
+/*!
+    Replaces current model with the given one. This deletes the existing
+    view items and calls reset() to update the view to correspond to 
+    current model. 
+*/
+void HbAbstractItemViewPrivate::setModel(QAbstractItemModel *model)
+{
+    Q_Q(HbAbstractItemView);
+
+    if (model != mModelIterator->model()) {
+        mAnimateItems = false;
+        clearCurrentModel();
+        mModelIterator->setModel(model);
+        initializeNewModel();
+
+        q->reset();
+
+        if (!mAnimationTimer) {
+            mAnimationTimer = new QTimer(q);
+            mAnimationTimer->setObjectName(QString("animationTimer"));
+            mAnimationTimer->setSingleShot(true);
+
+            QObject::connect(mAnimationTimer, SIGNAL(timeout()), q, SLOT(_q_animationEnabled()));
+        }
+
+        mAnimationTimer->start(3000);
+    }
+}
+
+/*!
+    Resets current model,selection Model,mRootIndex and mCurrentIndex to null. 
+*/
+void HbAbstractItemViewPrivate::clearCurrentModel()
+{
+    Q_Q(HbAbstractItemView);
+    if (mModelIterator->model()) {
+        QAbstractItemModel *model = mModelIterator->model();
+        q->disconnect(model, SIGNAL(destroyed()),
+                      q, SLOT(_q_modelDestroyed()));
+        q->disconnect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
+                      q, SLOT( dataChanged(QModelIndex,QModelIndex)));
+        q->disconnect(model, SIGNAL(rowsInserted(QModelIndex,int,int)),
+                      q, SLOT(rowsInserted(QModelIndex,int,int)));
+        q->disconnect(model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
+                      q, SLOT(rowsRemoved(QModelIndex,int,int)));
+        q->disconnect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
+                      q, SLOT(rowsAboutToBeRemoved(QModelIndex,int,int)));
+        q->disconnect(model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)),
+                      q, SLOT(rowsAboutToBeInserted(QModelIndex,int,int)));
+        q->disconnect(model, SIGNAL(columnsInserted(QModelIndex,int,int)),
+                        q, SLOT(columnsInserted(QModelIndex,int,int)));
+        q->disconnect(model, SIGNAL(columnsAboutToBeInserted(QModelIndex,int,int)),
+                        q, SLOT(columnsAboutToBeInserted(QModelIndex,int,int)));
+        q->disconnect(model, SIGNAL(columnsRemoved(QModelIndex,int,int)),
+                        q, SLOT(columnsRemoved(QModelIndex,int,int)));
+        q->disconnect(model, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)),
+                        q, SLOT(columnsAboutToBeRemoved(QModelIndex,int,int)));
+        q->disconnect(model, SIGNAL(modelReset()), q, SLOT(reset()));
+        q->disconnect(model, SIGNAL(layoutChanged()), q, SLOT(_q_layoutChanged()));
+
+        mModelIterator->setModel(0);
+    }
+
+    setSelectionModel(0);
+
+    mCurrentIndex = QModelIndex();
+    mModelIterator->setRootIndex(QPersistentModelIndex());
+}
+
+/*!
+    Updates current selectionModel to selectionModel.If selectionModel is invalid, current
+    selectionModel is not updated.
+*/
+void HbAbstractItemViewPrivate::setSelectionModel(QItemSelectionModel *selectionModel)
+{
+    Q_Q( HbAbstractItemView );
+    if (selectionModel
+        && selectionModel->model() != mModelIterator->model()) {
+        qWarning("QAbstractItemView::setSelectionModel() failed: "
+                 "Trying to set a selection model, which works on "
+                 "a different model than the view.");
+        return;
+    }
+
+    if (mSelectionModel) {
+        q->disconnect(mSelectionModel, SIGNAL(selectionChanged(QItemSelection, QItemSelection)),
+                       q, SLOT(currentSelectionChanged(QItemSelection, QItemSelection)));
+
+        q->disconnect(mSelectionModel, SIGNAL(currentChanged(QModelIndex, QModelIndex)),
+                       q, SLOT(currentIndexChanged(QModelIndex, QModelIndex)));
+
+        delete mSelectionModel;
+        mSelectionModel = 0;
+    }
+
+    mSelectionModel = selectionModel;
+
+    if (mSelectionModel) {
+        q->connect(mSelectionModel, SIGNAL(selectionChanged(QItemSelection, QItemSelection)),
+                   q, SLOT(currentSelectionChanged(QItemSelection, QItemSelection)));
+        q->connect(mSelectionModel, SIGNAL(currentChanged(QModelIndex, QModelIndex)),
+                    q, SLOT(currentIndexChanged(QModelIndex, QModelIndex)));
+    }
+}
+
+/*!
+    Initializes newModel
+*/
+void HbAbstractItemViewPrivate::initializeNewModel()
+{
+    Q_Q(HbAbstractItemView);
+
+    if (mModelIterator->model()) {
+        QAbstractItemModel *model = mModelIterator->model();
+        // These asserts do basic sanity checking of the model
+        Q_ASSERT_X(model->index(0,0) == model->index(0,0),
+                   "HbAbstractItemView::setModel",
+                   "A model should return the exact same index "
+                   "(including its internal id/pointer) when asked for it twice in a row.");
+        Q_ASSERT_X(model->index(0,0).parent() == QModelIndex(),
+                   "HbAbstractItemView::setModel",
+                   "The parent of a top level index should be invalid");
+
+        q->connect(model, SIGNAL(destroyed()),
+                   q, SLOT(_q_modelDestroyed()));
+        q->connect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
+                   q, SLOT( dataChanged(QModelIndex,QModelIndex)));
+        q->connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)),
+                   q, SLOT(rowsInserted(QModelIndex,int,int)));
+        q->connect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
+                   q, SLOT(rowsAboutToBeRemoved(QModelIndex,int,int)));
+        q->connect(model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
+                   q, SLOT(rowsRemoved(QModelIndex,int,int)));
+        q->connect(model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)),
+                   q, SLOT(rowsAboutToBeInserted(QModelIndex,int,int)));
+        q->connect(model, SIGNAL(columnsInserted(QModelIndex,int,int)),
+                      q, SLOT(columnsInserted(QModelIndex,int,int)));
+        q->connect(model, SIGNAL(columnsAboutToBeInserted(QModelIndex,int,int)),
+                   q, SLOT(columnsAboutToBeInserted(QModelIndex,int,int)));
+        q->connect(model, SIGNAL(columnsRemoved(QModelIndex,int,int)),
+                      q, SLOT(columnsRemoved(QModelIndex,int,int)));
+        q->connect(model, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)),
+                   q, SLOT(columnsAboutToBeRemoved(QModelIndex,int,int)));
+        q->connect(model, SIGNAL(modelReset()), q, SLOT(reset()));
+        q->connect(model, SIGNAL(layoutChanged()), q, SLOT(_q_layoutChanged()));
+
+        setSelectionModel(new QItemSelectionModel(model, q));
+    }   
+}
+
+/*!
+    \private
+
+    Slot is called whenever the model is destroyed.
+    deletes all children and disconnects all signal- slot connections
+    with model and selectionmodel
+*/
+void HbAbstractItemViewPrivate::_q_modelDestroyed()
+{
+    Q_Q(HbAbstractItemView);
+
+    mModelIterator->setModel(0);
+    setSelectionModel(0);
+    q->reset();
+}
+
+/*!
+    \private
+
+    Slot is called whenever the model layout changes. This resets the container.
+*/
+void HbAbstractItemViewPrivate::_q_layoutChanged()
+{
+    mContainer->setModelIndexes(mModelIterator->nextIndex(QModelIndex()));
+}
+
+void HbAbstractItemViewPrivate::_q_animationEnabled()
+{
+    mAnimateItems = true;
+}
+
+void HbAbstractItemViewPrivate::_q_animationFinished(const HbEffect::EffectStatus &status)
+{
+    Q_UNUSED(status);
+    if ( status.effectEvent == "appear") {
+        if (mPostponedScrollIndex.isValid()) { 
+            int count = mAppearAnimationIndexes.count();
+            for (int i=0; i<count; i++) {
+                if (mPostponedScrollIndex == mAppearAnimationIndexes.at(i)) {
+                    scrollTo(mPostponedScrollIndex, mPostponedScrollHint);
+                    break;
+                }
+            }
+        } 
+        mAppearAnimationIndexes.clear();
+    }
+}
+
+/*!
+    \private
+
+    When orientation switch occurs, 1) or 2) is applied to view after layout switch:
+          1) if current item is wholly visible, it will be visible
+          2) if current item is not wholly visible, first visible item before layout switch is made visible
+          In either case the visible item is at top of the view or as near as possible
+ */
+void HbAbstractItemViewPrivate::saveIndexMadeVisibleAfterMetricsChange()
+{
+    QModelIndex firstVisibleModelIndex;
+    QModelIndex lastVisibleModelIndex;
+    mContainer->firstAndLastVisibleModelIndex(firstVisibleModelIndex, lastVisibleModelIndex);
+
+    int firstVisibleRow = firstVisibleModelIndex.isValid() ? firstVisibleModelIndex.row() : 0;
+    int lastVisibleRow = lastVisibleModelIndex.isValid() ? lastVisibleModelIndex.row() : 0;
+
+    // save current, if it is visible
+    firstVisibleRow = qMax(0, firstVisibleRow);
+    lastVisibleRow = qMax(0, lastVisibleRow);
+
+    if (mCurrentIndex.row() >= firstVisibleRow 
+        && mCurrentIndex.row() <= lastVisibleRow) {
+        mVisibleIndex = mCurrentIndex;
+    } else if (mModelIterator->model()) {
+        mVisibleIndex = mModelIterator->index(firstVisibleRow);
+    }
+}
+
+/*!
+    \private
+
+    Minimum amount of pixels to scroll to make \a item visible.
+    Negative value scrolls view up, and positive value vice versa.
+    Returns 0, if no scrolling is needed.
+
+    Horizontally ensures that item is visible. 
+ */
+QPointF HbAbstractItemViewPrivate::pixelsToScroll(const HbAbstractViewItem *item,
+                                                  HbAbstractItemView::ScrollHint hint)
+{
+    Q_Q(HbAbstractItemView);
+
+    QPointF result(0,0);
+
+    if (item) {
+        refreshContainerGeometry();
+
+        QRectF itemRect = itemBoundingRect(item);
+        QRectF viewRect = q->boundingRect();
+
+        if (!viewRect.isValid()) {
+            return result;
+        }
+
+        QSizeF sizeOffset;
+        sizeOffset.setHeight(qMin(itemRect.height(), viewRect.height()));
+        sizeOffset.setWidth(qMin(itemRect.width(), viewRect.width()));
+
+        if (mScrollDirections & Qt::Vertical) {
+            switch (hint) {
+                case HbAbstractItemView::PositionAtTop: {
+                    result.setY(itemRect.bottom() - viewRect.top() - sizeOffset.height());
+                    break;
+                }
+                case HbAbstractItemView::PositionAtBottom: {
+                    result.setY(itemRect.top() + sizeOffset.height() - viewRect.bottom());
+                    break;
+                }
+                case HbAbstractItemView::PositionAtCenter: {
+                    qreal yCentre = viewRect.top() + (viewRect.height()) / 2 ;
+                    result.setY(itemRect.top() - yCentre + sizeOffset.height()/2);
+                    break;
+                }
+                case HbAbstractItemView::EnsureVisible:
+                default: {
+                    if (itemRect.top() < viewRect.top()) { 
+                        result.setY(itemRect.bottom() - viewRect.top() - sizeOffset.height());
+                    } else if (itemRect.bottom() > viewRect.bottom()) {
+                        result.setY(itemRect.top() + sizeOffset.height() - viewRect.bottom());
+                    }
+                    break;
+                }
+            }
+
+            if (itemRect.width() < viewRect.width()) {
+                if (itemRect.left() < viewRect.left()) {
+                    result.setX(itemRect.left() - viewRect.left());
+                } else if (itemRect.right() > viewRect.right()) {
+                    result.setX(itemRect.right() - viewRect.right());
+                }
+            } else {
+                // item does not fit in the screen, always align according to 
+                // mirroring 
+                if (HbApplication::layoutDirection() == Qt::LeftToRight) {
+                    result.setX(itemRect.left() - viewRect.left());
+                } else {                
+                    result.setX(itemRect.right() - viewRect.right());
+                }
+            }
+        }
+        else if (mScrollDirections & Qt::Horizontal) {
+            switch (hint) {
+                case HbAbstractItemView::PositionAtTop: {    // left
+                    result.setX(itemRect.right() - viewRect.left() - sizeOffset.width());
+                    break;
+                }
+                case HbAbstractItemView::PositionAtBottom: { // right
+                    result.setX(itemRect.left() + sizeOffset.width() - viewRect.right());
+                    break;
+                }
+                case HbAbstractItemView::PositionAtCenter: {
+                    qreal xCentre = viewRect.left() + (viewRect.width()) / 2 ;
+                    result.setX(itemRect.left() - xCentre + sizeOffset.width()/2);
+                    break;
+                }
+                case HbAbstractItemView::EnsureVisible:
+                default: {
+                    if (itemRect.left() < viewRect.left()) { 
+                        result.setX(itemRect.right() - viewRect.left() - sizeOffset.width());
+                    } else if (itemRect.right() > viewRect.right()) {
+                        result.setX(itemRect.left() + sizeOffset.width() - viewRect.right());
+                    }
+                    break;
+                }
+            }
+
+            if (itemRect.top() < viewRect.top()) {
+                result.setY(itemRect.top() - viewRect.top());
+            } else if (itemRect.bottom() > viewRect.bottom()) {
+                result.setY(itemRect.bottom() - viewRect.bottom());
+            }
+        }
+    }
+
+    return result;
+}
+
+QItemSelectionModel::SelectionFlags HbAbstractItemViewPrivate::singleSelectionCommand(
+        const HbAbstractViewItem *item,
+        const QEvent *event)
+{
+    if (item) {
+        switch (event->type())  {
+        case QEvent::GraphicsSceneMousePress: 
+        case QEvent::GraphicsSceneMouseDoubleClick:
+            if (item->selectionAreaContains(static_cast<const QGraphicsSceneMouseEvent *>(event)->scenePos())) {
+                mSelectionSettings |= Selection;
+            }
+            break;
+        case QEvent::GraphicsSceneMouseRelease:
+            if (    mHitItem
+                &&  item->modelIndex() == mHitItem->modelIndex()
+                &&  mSelectionSettings.testFlag(Selection)) {
+                mSelectionSettings &= ~Selection;
+                return QItemSelectionModel::ClearAndSelect;
+            }
+            break;
+        default:
+            break;
+        }
+    }
+
+    return QItemSelectionModel::NoUpdate;
+}
+
+
+QItemSelectionModel::SelectionFlags HbAbstractItemViewPrivate::multiSelectionCommand(
+        const HbAbstractViewItem *item,
+        const QEvent *event)
+{
+    if (item) {
+        switch (event->type())  {
+        case QEvent::GraphicsSceneMousePress: 
+        case QEvent::GraphicsSceneMouseDoubleClick:
+            if (item->selectionAreaContains(static_cast<const QGraphicsSceneMouseEvent *>(event)->scenePos())) {
+                mSelectionSettings |= Selection;
+            }
+            break;
+        case QEvent::GraphicsSceneMouseRelease:
+            if (mHitItem
+                && item->modelIndex() == mHitItem->modelIndex() 
+                && mSelectionSettings.testFlag(Selection)) {
+                mSelectionSettings &= ~Selection;
+                return QItemSelectionModel::Toggle;
+            }
+            break;
+        default:
+            break;
+        }
+    }
+    return QItemSelectionModel::NoUpdate;
+}
+
+QItemSelectionModel::SelectionFlags HbAbstractItemViewPrivate::contiguousSelectionCommand(
+        const HbAbstractViewItem *item,
+        const QEvent *event )
+{
+    Q_Q(HbAbstractItemView);
+    if (item) {
+        switch (event->type()) {
+        case QEvent::GraphicsSceneMousePress: 
+        case QEvent::GraphicsSceneMouseDoubleClick: {
+            if (item->selectionAreaContains(static_cast<const QGraphicsSceneMouseEvent *>(event)->scenePos())) {
+                mSelectionSettings |= Selection;
+
+                if (mSelectionModel && mSelectionModel->isSelected(item->modelIndex())) {
+                    mContSelectionAction = QItemSelectionModel::Deselect;
+                } else {
+                    mContSelectionAction = QItemSelectionModel::Select;
+                }
+
+                // TODO: This should be changed to changing the gesture area of effect when that is possible...
+                // Gesture filter does not reset all of its internals: workaround is to delete and create the filter
+                q->setLongPressEnabled(false);
+                q->removeSceneEventFilter(mGestureFilter);
+                mFilterRemoved = true;
+            }
+            break;
+            }
+        case QEvent::GraphicsSceneMouseRelease: {
+            QItemSelectionModel::SelectionFlag flags =  QItemSelectionModel::NoUpdate;
+            if (mSelectionSettings.testFlag(Selection)){
+                flags = mContSelectionAction;
+                mSelectionSettings &= ~Selection;
+                mContSelectionAction = QItemSelectionModel::NoUpdate;
+            } 
+            
+            if (mFilterRemoved) {
+                // setLongPressEnabled installs filter
+                q->setLongPressEnabled(true);
+                mFilterRemoved = false;
+            }
+            return flags;
+            }
+        case QEvent::GraphicsSceneMouseMove:
+            return mContSelectionAction;
+        default:
+            break;
+        }
+    }
+    return QItemSelectionModel::NoUpdate;
+}
+
+/*!
+    Overwrites the default scroll area scrollbar updating algorithm when
+    recycling is used. On recycling the scrollbar position & size is calculated
+    using rows and their pixel size is not used.
+*/
+void HbAbstractItemViewPrivate::updateScrollBar(Qt::Orientation orientation)
+{
+    if (!handleScrollBar(orientation)) {
+        HbScrollAreaPrivate::updateScrollBar(orientation);
+    } else {
+        if (mContainer->layout() && !mContainer->layout()->isActivated()) {
+            mContainer->layout()->activate();
+        }
+
+        if (mContainer->uniformItemSizes()) {
+            updateScrollBarForUniformSizedItems();
+        } else {
+            updateScrollBarForVariableSizedItems();
+        }
+    } 
+}
+
+/*!
+    Returns the abstract view item from given scene position, if there is any.
+*/
+HbAbstractViewItem *HbAbstractItemViewPrivate::itemAt(const QPointF& position) const
+{
+    Q_Q(const HbAbstractItemView);
+
+    HbAbstractViewItem *hitItem = 0;
+    QList<QGraphicsItem *> items = q->scene()->items(position);
+    
+    int count = items.count();
+    for (int current = 0; current < count; ++current) {
+        QGraphicsItem *item = items.at(current);
+        hitItem = viewItem(item);
+        // second condition needed, because in form there can be radio button list 
+        // and list of the form itself on top of each other
+        if (hitItem && mContainer->items().indexOf(hitItem) != -1)
+            return hitItem;
+    }
+    return hitItem;
+}
+
+/*!
+    
+*/
+void HbAbstractItemViewPrivate::refreshContainerGeometry()
+{
+    Q_Q(const HbAbstractItemView);
+
+    if (mContainer->layout())  {
+        if (!mContainer->layout()->isActivated()) {
+            // Make sure that the layout process has stopped.
+            mContainer->layout()->activate();
+        }
+    } 
+
+    QSizeF newSize = mContainer->effectiveSizeHint(Qt::PreferredSize);
+
+    if (!mScrollDirections.testFlag(Qt::Vertical)) {
+        newSize.setHeight(q->size().height());
+    } 
+    
+    if (!mScrollDirections.testFlag(Qt::Horizontal)) {
+        newSize.setWidth(q->size().width());
+    }
+       
+    mContainer->resize( newSize );    
+}
+
+
+QRectF HbAbstractItemViewPrivate::itemBoundingRect(const QGraphicsItem *item) const
+    {
+        Q_Q(const HbAbstractItemView);
+
+        if (mContainer) {
+            QGraphicsLayout *containerLayout = mContainer->layout();
+            if (containerLayout) {
+                containerLayout->activate();
+            }
+        }
+
+        return item->mapToItem(q, item->boundingRect()).boundingRect();
+    }
+
+/*!
+    Returns true if given item is located within viewport (i.e.  view), otherwise
+    returns false. If fullyVisible parameter is true method will return true only
+    for item that is shown fully. In this case for partially visible items false is returned.
+*/
+bool HbAbstractItemViewPrivate::visible(HbAbstractViewItem* item, bool fullyVisible) const
+{
+    Q_Q(const HbAbstractItemView);
+    bool visible = false;
+    if (item) {
+        QRectF itemRect(itemBoundingRect(item));
+        QRectF abstractViewRect(itemBoundingRect(q));
+        if (fullyVisible) {
+            if (abstractViewRect.contains(itemRect)) {
+                visible = true;
+            }
+        } else {
+            if (abstractViewRect.intersects(itemRect)) {
+                visible = true;
+            }
+        }
+    }
+    return visible;
+}
+
+/*!
+    Returns current Item.
+*/
+HbAbstractViewItem* HbAbstractItemViewPrivate::currentItem() const
+{
+    return mContainer->itemByIndex(mCurrentIndex);
+}
+
+/*!
+        Tries to convert given graphics item to HbLIstViewItem.
+        qgraphicsitem_cast cannot be used here as it does not support subclassing.
+        Also qobject_cast cannot be used directly as QGraphicsItem is not derived from 
+        QObject. But you can ask qgraphicsitem whether it is a widget or not
+        and cast the item to widget based on this information. After the item is
+        casted to widget then qobject_cast can be used.
+*/
+HbAbstractViewItem* HbAbstractItemViewPrivate::viewItem(QGraphicsItem *item) const
+    {
+        HbAbstractViewItem *result = 0;
+        if (item && item->isWidget()) {
+            result = qobject_cast<HbAbstractViewItem *>(static_cast<QGraphicsWidget *>(item));
+        }
+        return result;
+    }
+
+void HbAbstractItemViewPrivate::updateItems()
+{
+    QList<HbAbstractViewItem *> items = mContainer->items();
+    foreach (HbAbstractViewItem *item, items) {
+        item->updateChildItems();
+    }
+}
+
+void HbAbstractItemViewPrivate::scrollTo(const QModelIndex &index, HbAbstractItemView::ScrollHint hint)
+{
+    Q_Q(HbAbstractItemView);
+    // when called from HbAbstractItemView::scrollTo(), mPostponedScrollIndex is invalid
+    HbAbstractViewItem *viewItem = q->itemByIndex(index);
+    if (viewItem) {
+        HbScrollArea::ClampingStyle clampingStyle = mClampingStyle;
+        if (clampingStyle == HbScrollArea::BounceBackClamping) {
+            mClampingStyle = HbScrollArea::StrictClamping;
+        }
+        revealItem(viewItem, hint);
+        mClampingStyle = clampingStyle;
+    } else if (     index.isValid()
+                &&  index == mPostponedScrollIndex) {
+        q->scrollTo(index, hint);
+    }
+}
+
+void HbAbstractItemViewPrivate::revealItem(const HbAbstractViewItem *item, 
+                                            HbAbstractItemView::ScrollHint hint )
+{
+    Q_Q(HbAbstractItemView);
+    QPointF delta = pixelsToScroll(item, hint);
+    if (delta != QPointF()) {
+        QPointF newPos = -mContainer->pos() + delta;
+        checkBoundaries(newPos);
+        // scroll area logic is oposite to real position
+        q->scrollContentsTo(newPos);
+    }
+}
+void HbAbstractItemViewPrivate::checkBoundaries(QPointF &newPos)
+{
+    Q_Q(HbAbstractItemView);
+
+    if (mClampingStyle != HbScrollArea::NoClamping) {
+        QRectF viewRect = q->boundingRect();
+        QSizeF containerSize = mContainer->layout()->preferredSize();
+        
+        if (newPos.y() < topBoundary() ) {
+            newPos.setY(topBoundary());
+        }
+
+        // it is possible that above checking set newPos.y > 0
+        if (newPos.y() > bottomBoundary()) {
+            newPos.setY(bottomBoundary()); 
+        }
+            
+        if (newPos.x() < leftBoundary() ) {
+            newPos.setX(leftBoundary());
+        }
+
+        // it is possible that above checking set newPos.x > 0
+        if (newPos.x() > rightBoundary()) {
+            newPos.setX(rightBoundary()); 
+        }
+    }
+}
+
+void HbAbstractItemViewPrivate::updateScrollBarForUniformSizedItems()
+{
+    Q_Q(const HbAbstractItemView);
+    
+    HbAbstractViewItem *firstItem = mContainer->items().first();
+    qreal uniformItemHeight = firstItem->size().height();
+    qreal containerVirtualHeight = uniformItemHeight *  (mModelIterator->indexCount());
+    qreal thumbPosition(0);
+    int firstBufferItemRowNumber = mModelIterator->indexPosition(firstItem->modelIndex());
+     
+    QRectF itemRect = itemBoundingRect(firstItem);
+    qreal realTopBoundary = itemRect.top();   
+    qreal virtualTopBoundary = realTopBoundary - (firstBufferItemRowNumber*uniformItemHeight); 
+   
+    if ((containerVirtualHeight - q->boundingRect().height()) != 0) {
+        thumbPosition = 
+            (-virtualTopBoundary) / (containerVirtualHeight - q->boundingRect().height());
+    }  
+ 
+    thumbPosition = qBound((qreal)0.0, thumbPosition, (qreal)1.0);
+ 
+    if (mVerticalScrollBar) {
+        if (containerVirtualHeight!=0) {
+            mVerticalScrollBar->setPageSize(qBound ( (qreal)0.0,
+                                     q->boundingRect().height() / containerVirtualHeight,
+                                      (qreal)1.0));
+        }
+        mVerticalScrollBar->setValue(thumbPosition); 
+    }    
+}
+
+void HbAbstractItemViewPrivate::setScrollBarMetrics(Qt::Orientation orientation)
+{   
+    if (!handleScrollBar(orientation) ) {
+        HbScrollAreaPrivate::setScrollBarMetrics(orientation);
+    } else {
+        //We just make sure that the base clas is not called
+        //It set the page size wrongly
+        updateScrollBar(orientation); 
+    }
+}
+
+/*!
+    This function combines the conditions to solve whether the scroll bar calcultion should be handled in
+    this class or is the base class calculation sufficient
+*/
+bool  HbAbstractItemViewPrivate::handleScrollBar(Qt::Orientation orientation)
+{
+    if (!mContainer->itemRecycling()
+        || mContainer->itemPrototypes().count() != 1 
+        || orientation == Qt::Horizontal
+        || mContainer->items().count() == 0) {
+            return false;
+    } else {
+        return true;
+    }
+}
+
+void HbAbstractItemViewPrivate::updateScrollBarForVariableSizedItems()
+{
+    Q_Q(const HbAbstractItemView);
+    HbAbstractViewItem *firstItem = mContainer->items().first();
+ 
+    // View position is the amount of hidden (fully or partially)
+    // rows above the view area.
+    int position = mModelIterator->indexPosition(firstItem->modelIndex());
+    if (position == -1) {
+        return; 
+    }
+    qreal viewY = (qreal)(position);
+
+    // View area height is the amount of rows within the view area.
+    qreal viewH = 0;
+
+    //Index count calculation is time consuming with tree
+    int indexCount = mModelIterator->indexCount();
+
+    // Total height is the amount of rows in the model.
+    qreal totalH = indexCount;
+
+    qreal itemTop = firstItem->mapToItem(q, firstItem->pos()).y();
+    qreal viewHeight = q->size().height();
+    int itemCount = mContainer->items().count();
+    
+    for (int i=0; i < itemCount; ++i) {
+        qreal itemHeight = mContainer->items().at(i)->size().height();
+        qreal itemBottom = itemTop + itemHeight;
+        if (itemTop < 0) {
+            // Some part of the item is above the view area.
+            if (itemBottom < 0) {
+                // Fully above the view area
+                viewY += 1;
+            } else {
+                // Partially at the view area and partially above the view area.
+                viewY += (1.0 - itemBottom / itemHeight);
+                viewH += itemBottom / itemHeight;
+            }
+        } else if (itemTop < viewHeight) {
+            // So part of the item is at the view area.
+            if (itemBottom < viewHeight) {
+                // Fully at the view area
+                viewH += 1;
+            } else {
+                // Partially at the view area and partially below the view area.
+                viewH += (viewHeight - itemTop) / itemHeight;
+            }
+        } else {
+            break;
+        }
+
+        itemTop += itemHeight;
+    }
+
+    // Shifting the values to scrollbar range that is from 0.0-1.0. 
+    qreal pos = viewY / (totalH - viewH);
+    pos = qBound((qreal)0.0, pos, (qreal)1.0);
+
+    if (mVerticalScrollBar) {
+        if (indexCount!=0) {
+            mVerticalScrollBar->setPageSize(viewH / (qreal)(indexCount));
+        }
+        mVerticalScrollBar->setValue(pos);
+    }    
+}
+
+void HbAbstractItemViewPrivate::rowsRemoved(const QModelIndex &parent,int start,int end)
+{
+    if (mModelIterator->model()->columnCount(parent) == 0) {
+        return;
+    }
+
+    if (start <= mCurrentIndex.row() && mCurrentIndex.row() <= end) {
+        // new current: 1) next after last deleted (note that
+        // start and end index in model prior to deleting)
+        // 2) just before first deleted
+        QModelIndex newCurrentIndex = mModelIterator->model()->index(start, 0, parent);
+        if (!newCurrentIndex.isValid()) {
+            newCurrentIndex = mModelIterator->model()->index(qMax(0,start-1), 0, parent);
+        }
+
+        if (mSelectionModel) {
+            mSelectionModel->setCurrentIndex(newCurrentIndex, QItemSelectionModel::NoUpdate);
+        } 
+    }
+
+    for (int current = end; current >= start; --current) {
+        //The items are already removed from the model. That's why their indexes are already invalid.
+        //Here we loop the items in container and call removeItem() with QModelIndex().
+        bool animate = mEnabledAnimations & HbAbstractItemView::Disappear ? mAnimateItems : false;
+        mContainer->removeItem(QModelIndex(), animate);
+    }
+}
+
+QItemSelectionModel::SelectionFlags HbAbstractItemViewPrivate::selectionFlags( 
+                                                    const HbAbstractViewItem *item, 
+                                                    const QEvent *event)
+{
+    if (!item || !item->modelIndex().isValid() || !(item->flags() & QGraphicsItem::ItemIsSelectable))
+        return QItemSelectionModel::NoUpdate;
+
+    QItemSelectionModel::SelectionFlags flags = QItemSelectionModel::NoUpdate;
+    if (item && mHitItem && event){
+        switch (mSelectionMode) {
+        case HbAbstractItemView::SingleSelection: 
+            flags =  singleSelectionCommand(item, event);
+            break;
+        case HbAbstractItemView::MultiSelection:
+            flags =  multiSelectionCommand(item, event);
+            break;
+        case HbAbstractItemView::ContiguousSelection: {
+            flags = contiguousSelectionCommand(item, event);
+            break;
+        }
+        case HbAbstractItemView::NoSelection: // Never update selection model
+            break;
+        }
+    }
+
+    return flags;
+}
+
+void HbAbstractItemViewPrivate::resetContainer()
+{
+    mPostponedScrollIndex = QPersistentModelIndex();
+    mContainer->reset();
+}
+
+void HbAbstractItemViewPrivate::startAppearEffect(const QModelIndex &parent, int start, int end)
+{
+    Q_Q(HbAbstractItemView);
+    if( mAppearAnimationIndexes.count()) {
+        mAppearAnimationIndexes.clear();
+    }
+    QList< QGraphicsItem * >items;
+    for (int i = start; i <= end; i++) {
+        QPersistentModelIndex index = mModelIterator->index(i, parent);
+        HbAbstractViewItem *item = q->itemByIndex(index);
+        if (item) {
+            items.append(item);
+            mAppearAnimationIndexes.append(index);
+        }
+    }
+
+    refreshContainerGeometry();
+
+    HbEffect::start(items, "viewitem", "appear", q, "_q_animationFinished");
+}
+
+void HbAbstractItemViewPrivate::ensureVisible(QPointF position, qreal xMargin, qreal yMargin)
+{
+    mPostponedScrollIndex = QPersistentModelIndex();
+    HbScrollAreaPrivate::ensureVisible(position, xMargin, yMargin);
+}
+
+