src/hbwidgets/itemviews/hbabstractitemview_p.cpp
changeset 1 f7ac710697a9
parent 0 16d8024aca5e
child 2 06ff229162e9
--- a/src/hbwidgets/itemviews/hbabstractitemview_p.cpp	Mon Apr 19 14:02:13 2010 +0300
+++ b/src/hbwidgets/itemviews/hbabstractitemview_p.cpp	Mon May 03 12:48:33 2010 +0300
@@ -29,11 +29,11 @@
 #include "hbabstractitemcontainer.h"
 #include "hbmodeliterator.h"
 
-#include <hbgesturefilter.h>
 #include <hbinstance.h>
 #include <hbscrollbar.h>
 #include <hbapplication.h>
 #include <hbeffect.h>
+#include <hbpangesture.h>
 
 #include <QGraphicsSceneMouseEvent>
 #include <QEvent>
@@ -41,26 +41,28 @@
 #include <QGraphicsScene>
 #include <QGraphicsLayout>
 #include <QTimer>
+#include <QGestureEvent>
 #include <QDebug>
 
+static const qreal CONTIGUOUS_SELECTION_SCROLL_SPEED = 0.2;
+static const qreal CONTIGUOUS_SELECTION_AREA_THRESHOLD = 0.2;
+
 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)
+    mEnabledAnimations(HbAbstractItemView::All),
+    mLongPressEnabled(true),
+	mDoingContiguousSelection(false)
 {
 }
 
@@ -85,11 +87,18 @@
     
     q->setContentWidget(container);
 
+    q->grabGesture(Qt::PanGesture);
+
+    //mAlignment = 0; // no alignment - there is no sense with recycling
+
     mContainer = container;
     mContainer->setItemView(q);
 
     mModelIterator = modelIterator;
 
+    q->connect(mContainer, SIGNAL(itemCreated(HbAbstractViewItem *)),
+            q, SLOT(itemCreated(HbAbstractViewItem *)));
+
     HbMainWindow *window = q->mainWindow();
     if (window
         && q->scene()) { // added to scene
@@ -166,7 +175,7 @@
         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()));
+        q->disconnect(model, SIGNAL(layoutChanged()), q, SLOT(modelLayoutChanged()));
 
         mModelIterator->setModel(0);
     }
@@ -252,7 +261,7 @@
         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()));
+        q->connect(model, SIGNAL(layoutChanged()), q, SLOT(modelLayoutChanged()));
 
         setSelectionModel(new QItemSelectionModel(model, q));
     }   
@@ -274,16 +283,6 @@
     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;
@@ -292,7 +291,7 @@
 void HbAbstractItemViewPrivate::_q_animationFinished(const HbEffect::EffectStatus &status)
 {
     Q_UNUSED(status);
-    if ( status.effectEvent == "appear") {
+    if (status.effectEvent == "appear") {
         if (mPostponedScrollIndex.isValid()) { 
             int count = mAppearAnimationIndexes.count();
             for (int i=0; i<count; i++) {
@@ -302,17 +301,199 @@
                 }
             }
         } 
+
+        status.item->setFlag(QGraphicsItem::ItemSendsGeometryChanges, false);
         mAppearAnimationIndexes.clear();
     }
 }
 
 /*!
+    \reimp
+*/
+void HbAbstractItemViewPrivate::setContentPosition(qreal value, Qt::Orientation orientation, bool animate)
+{
+    Q_Q(HbAbstractItemView);
+
+    if (handleScrollBar(orientation)) {
+        if (mContainer->layout() && !mContainer->layout()->isActivated()) {
+            mContainer->layout()->activate();
+        }
+
+        HbAbstractViewItem *firstItem = mContainer->items().first();
+        qreal itemHeight;
+        if (mContainer->uniformItemSizes()) {
+            itemHeight = firstItem->size().height();
+        } else {
+            // avarrage height based on container content
+            itemHeight = mContainer->size().height() / mContainer->items().size();
+        }
+        qreal visiblePos = -mContainer->pos().y()
+                           + mModelIterator->indexPosition(firstItem->modelIndex()) * itemHeight;
+        qreal viewHeight = q->boundingRect().height();
+        qreal modelHeight = itemHeight * mModelIterator->indexCount() - viewHeight;
+        qreal thumbPos = visiblePos / modelHeight;
+
+        qreal diff = (value - thumbPos) * modelHeight;
+
+        q->scrollByAmount(QPointF(0, diff));
+    } else {
+        HbScrollAreaPrivate::setContentPosition(value, orientation, animate);
+    }
+
+    if (animate) {
+        updateScrollBar(orientation);
+    }
+}
+
+bool HbAbstractItemViewPrivate::panTriggered(QGestureEvent *event)
+{
+    Q_Q(HbAbstractItemView);
+
+    HbPanGesture *gesture = static_cast<HbPanGesture *>(event->gesture(Qt::PanGesture));
+
+    switch (gesture->state()) {
+        case Qt::GestureStarted:
+            mOptions |= PanningActive;
+            // Fallthrough
+        case Qt::GestureUpdated: {
+            QPointF scenePos = event->mapToGraphicsScene(gesture->hotSpot());
+            if (mDoingContiguousSelection) {
+                int retVal = false;
+
+                // loop through the items in the scene
+                qreal scenePosY = scenePos.y();
+                QPointF lastScenePos = scenePos + gesture->lastOffset() - gesture->offset();
+                qreal lastScenePosY = lastScenePos.y();
+                QPolygonF polygon;
+                polygon << lastScenePos << scenePos;
+                QList<QGraphicsItem *> items = q->scene()->items(polygon);
+                int itemCount = items.count();
+                for (int current = 0; current < itemCount ; ++current) {
+                    HbAbstractViewItem *item = viewItem(items.at(current));
+                    if (item && item->itemView() == q) {
+                        QModelIndex itemIndex(item->modelIndex());
+                        QGraphicsSceneMouseEvent mouseMoveEvent(QEvent::GraphicsSceneMouseMove);
+                        QPointF scenePosInItemCoordinates = item->mapFromScene(scenePos);
+                        QPointF position(qBound((qreal)0.0, scenePosInItemCoordinates.x(), item->size().width()), 
+                                         qBound((qreal)0.0, scenePosInItemCoordinates.y(), item->size().height()));
+                        mouseMoveEvent.setPos(position);
+                        QItemSelectionModel::SelectionFlags command = q->selectionCommand(item, &mouseMoveEvent);
+
+						// in contiguousselectionarea there shall be no panning from HbScrollArea, thus return true
+                        if (command != QItemSelectionModel::NoUpdate) {
+                            retVal = true;
+                        }
+
+                        if ( itemIndex != mPreviousSelectedIndex
+                          || command != mPreviousSelectedCommand) {
+                            mPreviousSelectedIndex = itemIndex;
+                            mPreviousSelectedCommand = command;
+                            mSelectionModel->select(itemIndex, command);
+                        }
+
+                        // check if we need to start or keep on scrolling
+                        int scrollDirection = 0;
+                        QPointF pos = q->mapFromScene(scenePos);
+                        if (pos.y() < (q->size().height() * CONTIGUOUS_SELECTION_AREA_THRESHOLD)) {
+                             if (q->isScrolling()
+                                 || (!q->isScrolling()
+                                     && lastScenePosY >= scenePosY)) {                                
+                                 scrollDirection = 1;
+                             }
+                        } else if (pos.y() > (q->size().height() * (1 - CONTIGUOUS_SELECTION_AREA_THRESHOLD))) {
+                             if (q->isScrolling()
+                                 || (!q->isScrolling()
+                                     && lastScenePosY <= scenePosY)) {
+                                 scrollDirection = -1;
+                             }                        
+                        }
+
+                        // Start scrolling if needed. 
+                        if (scrollDirection != 0) {
+                            if (!mIsAnimating) {
+                                mPositionInContiguousSelection = scenePos;
+                                QObject::connect(q, SIGNAL(scrollPositionChanged(QPointF)), q, SLOT(_q_scrolling(QPointF)));    
+                                QObject::connect(q, SIGNAL(scrollingEnded()), q, SLOT(_q_scrollingEnded()));    
+                                QObject::connect(q, SIGNAL(scrollingStarted()), q, SLOT(_q_scrollingStarted()));    
+                                animateScroll(QPointF (0.0f, scrollDirection * CONTIGUOUS_SELECTION_SCROLL_SPEED));
+                                retVal = true;
+                            }
+                        } else if (q->isScrolling()) {
+                            stopAnimating();
+                            retVal = true;
+                        }
+                        break;
+                    }
+                }
+                return retVal;
+            }
+            break;
+        }
+        case Qt::GestureFinished: 
+        case Qt::GestureCanceled: {
+            mOptions &= ~PanningActive;
+            if (mDoingContiguousSelection) {
+                stopAnimating();
+                mDoingContiguousSelection = false;
+                return true;
+            }               
+            break;
+        }
+        default:
+            break;
+    }
+
+    return false;
+}
+
+/*!
+    This slot is called when the view is scrolling doing countinuousselection. It does the item 
+    selection/deselection 
+*/
+void HbAbstractItemViewPrivate::_q_scrolling(QPointF newPosition)
+{
+    Q_UNUSED(newPosition);
+
+    HbAbstractViewItem* hitItem = itemAt(mPositionInContiguousSelection);
+    if (hitItem) {
+        QModelIndex itemIndex(hitItem->modelIndex());
+        if ( itemIndex != mPreviousSelectedIndex) {
+            mPreviousSelectedIndex = itemIndex;
+            mSelectionModel->select(itemIndex, mPreviousSelectedCommand);
+        }
+    }
+}
+
+/*!
+    This slot is called when scrolling during continuousselction ends. It restores the original scrolling parameters 
+*/
+void HbAbstractItemViewPrivate::_q_scrollingEnded()
+{
+    Q_Q(HbAbstractItemView);
+
+    mFrictionEnabled = mOrigFriction;
+
+    QObject::disconnect(q, SIGNAL(scrollPositionChanged(QPointF)), q, SLOT(_q_scrollingI(QPointF)));    
+    QObject::disconnect(q, SIGNAL(scrollingEnded()), q, SLOT(_q_scrollingEnded()));    
+    QObject::disconnect(q, SIGNAL(scrollingStarted()), q, SLOT(_q_scrollingStarted()));    
+}
+
+/*!
+    This slot is called when scrolling during continuousselction starts. It saves the original scrolling parameters 
+*/
+void HbAbstractItemViewPrivate::_q_scrollingStarted()
+{
+    mOrigFriction = mFrictionEnabled;
+    mFrictionEnabled = false;
+}
+
+/*!
     \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
+          1) if last item is wholly visible, it will be visible
+          2) if last item is not fully visible, the first fully visible item before layout switch is made the 
+		     first fully visible item
  */
 void HbAbstractItemViewPrivate::saveIndexMadeVisibleAfterMetricsChange()
 {
@@ -320,18 +501,12 @@
     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);
+    if (mModelIterator->model()) {
+        if (lastVisibleModelIndex == mModelIterator->index(mModelIterator->indexCount() - 1)) {
+            mVisibleIndex = lastVisibleModelIndex;
+        } else {
+            mVisibleIndex = firstVisibleModelIndex;
+        }
     }
 }
 
@@ -406,8 +581,7 @@
                     result.setX(itemRect.right() - viewRect.right());
                 }
             }
-        }
-        else if (mScrollDirections & Qt::Horizontal) {
+        } else if (mScrollDirections & Qt::Horizontal) {
             switch (hint) {
                 case HbAbstractItemView::PositionAtTop: {    // left
                     result.setX(itemRect.right() - viewRect.left() - sizeOffset.width());
@@ -452,14 +626,12 @@
         switch (event->type())  {
         case QEvent::GraphicsSceneMousePress: 
         case QEvent::GraphicsSceneMouseDoubleClick:
-            if (item->selectionAreaContains(static_cast<const QGraphicsSceneMouseEvent *>(event)->scenePos())) {
+            if (item->selectionAreaContains(static_cast<const QGraphicsSceneMouseEvent *>(event)->pos(), HbAbstractViewItem::SingleSelection)) {
                 mSelectionSettings |= Selection;
             }
             break;
         case QEvent::GraphicsSceneMouseRelease:
-            if (    mHitItem
-                &&  item->modelIndex() == mHitItem->modelIndex()
-                &&  mSelectionSettings.testFlag(Selection)) {
+            if (mSelectionSettings.testFlag(Selection)) {
                 mSelectionSettings &= ~Selection;
                 return QItemSelectionModel::ClearAndSelect;
             }
@@ -477,53 +649,32 @@
         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;
 
+            // check if the mouse click is in the multiselectionarea
+		    if (item->selectionAreaContains(static_cast<const QGraphicsSceneMouseEvent *>(event)->pos(), HbAbstractViewItem::MultiSelection)) {
+		        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
+            // check if the mouse click is in the "contiguousselectionarea"
+            if (item->selectionAreaContains(static_cast<const QGraphicsSceneMouseEvent *>(event)->pos(), 
+                                            HbAbstractViewItem::ContiguousSelection)) {
+                // it is assumed that the "contiguousselectionarea" is in the multiselectionarea
                 q->setLongPressEnabled(false);
-                q->removeSceneEventFilter(mGestureFilter);
-                mFilterRemoved = true;
+                mDoingContiguousSelection = true;
+            } else {
+                mDoingContiguousSelection = false;
             }
+
             break;
             }
         case QEvent::GraphicsSceneMouseRelease: {
@@ -534,15 +685,15 @@
                 mContSelectionAction = QItemSelectionModel::NoUpdate;
             } 
             
-            if (mFilterRemoved) {
-                // setLongPressEnabled installs filter
-                q->setLongPressEnabled(true);
-                mFilterRemoved = false;
-            }
+            q->setLongPressEnabled(true);
             return flags;
             }
         case QEvent::GraphicsSceneMouseMove:
-            return mContSelectionAction;
+            if (mDoingContiguousSelection) {
+                return mContSelectionAction;
+            } else {
+                return QItemSelectionModel::NoUpdate;
+            }
         default:
             break;
         }
@@ -550,27 +701,6 @@
     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.
@@ -623,18 +753,18 @@
 
 
 QRectF HbAbstractItemViewPrivate::itemBoundingRect(const QGraphicsItem *item) const
-    {
-        Q_Q(const HbAbstractItemView);
+{
+    Q_Q(const HbAbstractItemView);
 
-        if (mContainer) {
-            QGraphicsLayout *containerLayout = mContainer->layout();
-            if (containerLayout) {
-                containerLayout->activate();
-            }
+    if (mContainer) {
+        QGraphicsLayout *containerLayout = mContainer->layout();
+        if (containerLayout) {
+            containerLayout->activate();
         }
+    }
 
-        return item->mapToItem(q, item->boundingRect()).boundingRect();
-    }
+    return item->mapToItem(q, item->boundingRect()).boundingRect();
+}
 
 /*!
     Returns true if given item is located within viewport (i.e.  view), otherwise
@@ -720,7 +850,8 @@
     if (delta != QPointF()) {
         QPointF newPos = -mContainer->pos() + delta;
         checkBoundaries(newPos);
-        // scroll area logic is oposite to real position
+
+        // scroll area logic is opposite to real position.
         q->scrollContentsTo(newPos);
     }
 }
@@ -752,45 +883,28 @@
     }
 }
 
-void HbAbstractItemViewPrivate::updateScrollBarForUniformSizedItems()
+void HbAbstractItemViewPrivate::setScrollBarMetrics(Qt::Orientation orientation)
 {
-    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); 
+        Q_Q(HbAbstractItemView);
+
+        if (mContainer->layout() && !mContainer->layout()->isActivated()) {
+            mContainer->layout()->activate();
+        }
+
+        qreal itemHeight;
+        if (mContainer->uniformItemSizes()) {
+            itemHeight = mContainer->items().first()->size().height();
+        } else {
+            // avarrage height based on container content
+            itemHeight = mContainer->size().height() / mContainer->items().size();
+        }
+        qreal rowCount = q->boundingRect().height() / itemHeight;
+        qreal modelRowCount = mModelIterator->indexCount();
+        qreal thumbSize = rowCount / modelRowCount;
+        mVerticalScrollBar->setPageSize(thumbSize);
     }
 }
 
@@ -798,86 +912,56 @@
     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)
+bool HbAbstractItemViewPrivate::handleScrollBar(Qt::Orientation orientation)
 {
     if (!mContainer->itemRecycling()
-        || mContainer->itemPrototypes().count() != 1 
-        || orientation == Qt::Horizontal
-        || mContainer->items().count() == 0) {
-            return false;
+        || !(orientation & mScrollDirections)
+        || mContainer->itemPrototypes().count() != 1
+        || mContainer->items().isEmpty()
+        || (!mVerticalScrollBar && orientation == Qt::Vertical)
+        || (!mHorizontalScrollBar && orientation == Qt::Horizontal)) {
+        return false;
     } else {
         return true;
     }
 }
 
-void HbAbstractItemViewPrivate::updateScrollBarForVariableSizedItems()
+/*!
+    Overwrites the default scroll area scrollbar updating algorithm when
+    recycling is used. While recycling is on scrollbar position & size 
+    are calculated using rows and their pixel sizes are not used (in fact only 
+    container position is interesting to determine partially visible items
+    - when container contain small amount of items it is important).
+*/
+void HbAbstractItemViewPrivate::updateScrollBar(Qt::Orientation orientation)
 {
-    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;
+    if (!handleScrollBar(orientation)) {
+        HbScrollAreaPrivate::updateScrollBar(orientation);
+    } else {
+        if (mContainer->layout() && !mContainer->layout()->isActivated()) {
+            mContainer->layout()->activate();
         }
 
-        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);
+        Q_Q(const HbAbstractItemView);
 
-    if (mVerticalScrollBar) {
-        if (indexCount!=0) {
-            mVerticalScrollBar->setPageSize(viewH / (qreal)(indexCount));
+        qreal containerPos = mContainer->pos().y();
+        qreal itemHeight;
+        if (mContainer->uniformItemSizes()) {
+            itemHeight = mContainer->items().first()->size().height();
+        } else {
+            // avarrage height based on container content
+            itemHeight = mContainer->size().height() / mContainer->items().size();
         }
-        mVerticalScrollBar->setValue(pos);
-    }    
+        qreal rowCount = q->boundingRect().height() / itemHeight;
+        qreal modelRowCount = mModelIterator->indexCount() - rowCount;
+        qreal firstVisibleRow = mModelIterator->indexPosition(mContainer->items().first()->modelIndex());
+        firstVisibleRow += -containerPos / itemHeight;
+        qreal thumbPos = firstVisibleRow / (qreal)modelRowCount;
+        mVerticalScrollBar->setValue(thumbPos);
+    }
 }
 
-void HbAbstractItemViewPrivate::rowsRemoved(const QModelIndex &parent,int start,int end)
+void HbAbstractItemViewPrivate::rowsRemoved(const QModelIndex &parent, int start, int end)
 {
     if (mModelIterator->model()->columnCount(parent) == 0) {
         return;
@@ -900,8 +984,7 @@
     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);
+        mContainer->removeItem(QModelIndex(), animationEnabled(false));
     }
 }
 
@@ -913,16 +996,14 @@
         return QItemSelectionModel::NoUpdate;
 
     QItemSelectionModel::SelectionFlags flags = QItemSelectionModel::NoUpdate;
-    if (item && mHitItem && event){
+    if (item && 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);
+            flags = multiSelectionCommand(item, event);
             break;
         }
         case HbAbstractItemView::NoSelection: // Never update selection model
@@ -939,7 +1020,7 @@
     mContainer->reset();
 }
 
-void HbAbstractItemViewPrivate::startAppearEffect(const QModelIndex &parent, int start, int end)
+void HbAbstractItemViewPrivate::startAppearEffect(const QString &itemType, const QString &effectEvent, const QModelIndex &parent, int start, int end)
 {
     Q_Q(HbAbstractItemView);
     if( mAppearAnimationIndexes.count()) {
@@ -951,13 +1032,15 @@
         HbAbstractViewItem *item = q->itemByIndex(index);
         if (item) {
             items.append(item);
+            item->setFlag(QGraphicsItem::ItemSendsGeometryChanges, true);
+
             mAppearAnimationIndexes.append(index);
         }
     }
 
     refreshContainerGeometry();
 
-    HbEffect::start(items, "viewitem", "appear", q, "_q_animationFinished");
+    HbEffect::start(items, itemType, effectEvent, q, "_q_animationFinished");
 }
 
 void HbAbstractItemViewPrivate::ensureVisible(QPointF position, qreal xMargin, qreal yMargin)
@@ -966,4 +1049,11 @@
     HbScrollAreaPrivate::ensureVisible(position, xMargin, yMargin);
 }
 
-
+bool HbAbstractItemViewPrivate::animationEnabled(bool insertOperation)
+{
+    if (insertOperation) {
+        return mEnabledAnimations & HbAbstractItemView::Appear ? mAnimateItems : false;
+    } else {
+        return mEnabledAnimations & HbAbstractItemView::Disappear ? mAnimateItems : false;
+    }
+}