src/hbwidgets/itemviews/hbabstractitemview_p.cpp
changeset 1 f7ac710697a9
parent 0 16d8024aca5e
child 2 06ff229162e9
equal deleted inserted replaced
0:16d8024aca5e 1:f7ac710697a9
    27 #include "hbabstractitemview.h"
    27 #include "hbabstractitemview.h"
    28 #include "hbabstractviewitem.h"
    28 #include "hbabstractviewitem.h"
    29 #include "hbabstractitemcontainer.h"
    29 #include "hbabstractitemcontainer.h"
    30 #include "hbmodeliterator.h"
    30 #include "hbmodeliterator.h"
    31 
    31 
    32 #include <hbgesturefilter.h>
       
    33 #include <hbinstance.h>
    32 #include <hbinstance.h>
    34 #include <hbscrollbar.h>
    33 #include <hbscrollbar.h>
    35 #include <hbapplication.h>
    34 #include <hbapplication.h>
    36 #include <hbeffect.h>
    35 #include <hbeffect.h>
       
    36 #include <hbpangesture.h>
    37 
    37 
    38 #include <QGraphicsSceneMouseEvent>
    38 #include <QGraphicsSceneMouseEvent>
    39 #include <QEvent>
    39 #include <QEvent>
    40 #include <QItemSelectionModel>
    40 #include <QItemSelectionModel>
    41 #include <QGraphicsScene>
    41 #include <QGraphicsScene>
    42 #include <QGraphicsLayout>
    42 #include <QGraphicsLayout>
    43 #include <QTimer>
    43 #include <QTimer>
       
    44 #include <QGestureEvent>
    44 #include <QDebug>
    45 #include <QDebug>
       
    46 
       
    47 static const qreal CONTIGUOUS_SELECTION_SCROLL_SPEED = 0.2;
       
    48 static const qreal CONTIGUOUS_SELECTION_AREA_THRESHOLD = 0.2;
    45 
    49 
    46 HbAbstractItemViewPrivate::HbAbstractItemViewPrivate() :
    50 HbAbstractItemViewPrivate::HbAbstractItemViewPrivate() :
    47     mSelectionMode(HbAbstractItemView::NoSelection),
    51     mSelectionMode(HbAbstractItemView::NoSelection),
    48     mOptions(NoOptions),
    52     mOptions(NoOptions),
    49     mSelectionSettings(None),
    53     mSelectionSettings(None),
    50     mHitItem(0),
       
    51     mContainer(0),
    54     mContainer(0),
    52     mSelectionModel(0),
    55     mSelectionModel(0),
    53     mContSelectionAction(QItemSelectionModel::NoUpdate),
    56     mContSelectionAction(QItemSelectionModel::NoUpdate),
    54     mWasScrolling(false),
       
    55     mFilterRemoved(false),
       
    56     mClearingSelection(false),
    57     mClearingSelection(false),
    57     mAnimateItems(false),
    58     mAnimateItems(false),
    58     mPostponedScrollHint(HbAbstractItemView::PositionAtTop),
    59     mPostponedScrollHint(HbAbstractItemView::PositionAtTop),
    59     mPreviousSelectedCommand(QItemSelectionModel::NoUpdate),
    60     mPreviousSelectedCommand(QItemSelectionModel::NoUpdate),
    60     mInstantClickedModifiers(0),
       
    61     mAnimationTimer(0),
    61     mAnimationTimer(0),
    62 	mModelIterator(0),
    62 	mModelIterator(0),
    63     mEnabledAnimations(HbAbstractItemView::All)
    63     mEnabledAnimations(HbAbstractItemView::All),
       
    64     mLongPressEnabled(true),
       
    65 	mDoingContiguousSelection(false)
    64 {
    66 {
    65 }
    67 }
    66 
    68 
    67 HbAbstractItemViewPrivate::~HbAbstractItemViewPrivate()
    69 HbAbstractItemViewPrivate::~HbAbstractItemViewPrivate()
    68 {
    70 {
    83     q->setFlag(QGraphicsItem::ItemIsFocusable, true);
    85     q->setFlag(QGraphicsItem::ItemIsFocusable, true);
    84     q->setFocusPolicy(Qt::StrongFocus);
    86     q->setFocusPolicy(Qt::StrongFocus);
    85     
    87     
    86     q->setContentWidget(container);
    88     q->setContentWidget(container);
    87 
    89 
       
    90     q->grabGesture(Qt::PanGesture);
       
    91 
       
    92     //mAlignment = 0; // no alignment - there is no sense with recycling
       
    93 
    88     mContainer = container;
    94     mContainer = container;
    89     mContainer->setItemView(q);
    95     mContainer->setItemView(q);
    90 
    96 
    91     mModelIterator = modelIterator;
    97     mModelIterator = modelIterator;
       
    98 
       
    99     q->connect(mContainer, SIGNAL(itemCreated(HbAbstractViewItem *)),
       
   100             q, SLOT(itemCreated(HbAbstractViewItem *)));
    92 
   101 
    93     HbMainWindow *window = q->mainWindow();
   102     HbMainWindow *window = q->mainWindow();
    94     if (window
   103     if (window
    95         && q->scene()) { // added to scene
   104         && q->scene()) { // added to scene
    96         q->connect(window, SIGNAL(aboutToChangeOrientation()),
   105         q->connect(window, SIGNAL(aboutToChangeOrientation()),
   164         q->disconnect(model, SIGNAL(columnsRemoved(QModelIndex,int,int)),
   173         q->disconnect(model, SIGNAL(columnsRemoved(QModelIndex,int,int)),
   165                         q, SLOT(columnsRemoved(QModelIndex,int,int)));
   174                         q, SLOT(columnsRemoved(QModelIndex,int,int)));
   166         q->disconnect(model, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)),
   175         q->disconnect(model, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)),
   167                         q, SLOT(columnsAboutToBeRemoved(QModelIndex,int,int)));
   176                         q, SLOT(columnsAboutToBeRemoved(QModelIndex,int,int)));
   168         q->disconnect(model, SIGNAL(modelReset()), q, SLOT(reset()));
   177         q->disconnect(model, SIGNAL(modelReset()), q, SLOT(reset()));
   169         q->disconnect(model, SIGNAL(layoutChanged()), q, SLOT(_q_layoutChanged()));
   178         q->disconnect(model, SIGNAL(layoutChanged()), q, SLOT(modelLayoutChanged()));
   170 
   179 
   171         mModelIterator->setModel(0);
   180         mModelIterator->setModel(0);
   172     }
   181     }
   173 
   182 
   174     setSelectionModel(0);
   183     setSelectionModel(0);
   250         q->connect(model, SIGNAL(columnsRemoved(QModelIndex,int,int)),
   259         q->connect(model, SIGNAL(columnsRemoved(QModelIndex,int,int)),
   251                       q, SLOT(columnsRemoved(QModelIndex,int,int)));
   260                       q, SLOT(columnsRemoved(QModelIndex,int,int)));
   252         q->connect(model, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)),
   261         q->connect(model, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)),
   253                    q, SLOT(columnsAboutToBeRemoved(QModelIndex,int,int)));
   262                    q, SLOT(columnsAboutToBeRemoved(QModelIndex,int,int)));
   254         q->connect(model, SIGNAL(modelReset()), q, SLOT(reset()));
   263         q->connect(model, SIGNAL(modelReset()), q, SLOT(reset()));
   255         q->connect(model, SIGNAL(layoutChanged()), q, SLOT(_q_layoutChanged()));
   264         q->connect(model, SIGNAL(layoutChanged()), q, SLOT(modelLayoutChanged()));
   256 
   265 
   257         setSelectionModel(new QItemSelectionModel(model, q));
   266         setSelectionModel(new QItemSelectionModel(model, q));
   258     }   
   267     }   
   259 }
   268 }
   260 
   269 
   272     mModelIterator->setModel(0);
   281     mModelIterator->setModel(0);
   273     setSelectionModel(0);
   282     setSelectionModel(0);
   274     q->reset();
   283     q->reset();
   275 }
   284 }
   276 
   285 
   277 /*!
       
   278     \private
       
   279 
       
   280     Slot is called whenever the model layout changes. This resets the container.
       
   281 */
       
   282 void HbAbstractItemViewPrivate::_q_layoutChanged()
       
   283 {
       
   284     mContainer->setModelIndexes(mModelIterator->nextIndex(QModelIndex()));
       
   285 }
       
   286 
       
   287 void HbAbstractItemViewPrivate::_q_animationEnabled()
   286 void HbAbstractItemViewPrivate::_q_animationEnabled()
   288 {
   287 {
   289     mAnimateItems = true;
   288     mAnimateItems = true;
   290 }
   289 }
   291 
   290 
   292 void HbAbstractItemViewPrivate::_q_animationFinished(const HbEffect::EffectStatus &status)
   291 void HbAbstractItemViewPrivate::_q_animationFinished(const HbEffect::EffectStatus &status)
   293 {
   292 {
   294     Q_UNUSED(status);
   293     Q_UNUSED(status);
   295     if ( status.effectEvent == "appear") {
   294     if (status.effectEvent == "appear") {
   296         if (mPostponedScrollIndex.isValid()) { 
   295         if (mPostponedScrollIndex.isValid()) { 
   297             int count = mAppearAnimationIndexes.count();
   296             int count = mAppearAnimationIndexes.count();
   298             for (int i=0; i<count; i++) {
   297             for (int i=0; i<count; i++) {
   299                 if (mPostponedScrollIndex == mAppearAnimationIndexes.at(i)) {
   298                 if (mPostponedScrollIndex == mAppearAnimationIndexes.at(i)) {
   300                     scrollTo(mPostponedScrollIndex, mPostponedScrollHint);
   299                     scrollTo(mPostponedScrollIndex, mPostponedScrollHint);
   301                     break;
   300                     break;
   302                 }
   301                 }
   303             }
   302             }
   304         } 
   303         } 
       
   304 
       
   305         status.item->setFlag(QGraphicsItem::ItemSendsGeometryChanges, false);
   305         mAppearAnimationIndexes.clear();
   306         mAppearAnimationIndexes.clear();
   306     }
   307     }
   307 }
   308 }
   308 
   309 
   309 /*!
   310 /*!
       
   311     \reimp
       
   312 */
       
   313 void HbAbstractItemViewPrivate::setContentPosition(qreal value, Qt::Orientation orientation, bool animate)
       
   314 {
       
   315     Q_Q(HbAbstractItemView);
       
   316 
       
   317     if (handleScrollBar(orientation)) {
       
   318         if (mContainer->layout() && !mContainer->layout()->isActivated()) {
       
   319             mContainer->layout()->activate();
       
   320         }
       
   321 
       
   322         HbAbstractViewItem *firstItem = mContainer->items().first();
       
   323         qreal itemHeight;
       
   324         if (mContainer->uniformItemSizes()) {
       
   325             itemHeight = firstItem->size().height();
       
   326         } else {
       
   327             // avarrage height based on container content
       
   328             itemHeight = mContainer->size().height() / mContainer->items().size();
       
   329         }
       
   330         qreal visiblePos = -mContainer->pos().y()
       
   331                            + mModelIterator->indexPosition(firstItem->modelIndex()) * itemHeight;
       
   332         qreal viewHeight = q->boundingRect().height();
       
   333         qreal modelHeight = itemHeight * mModelIterator->indexCount() - viewHeight;
       
   334         qreal thumbPos = visiblePos / modelHeight;
       
   335 
       
   336         qreal diff = (value - thumbPos) * modelHeight;
       
   337 
       
   338         q->scrollByAmount(QPointF(0, diff));
       
   339     } else {
       
   340         HbScrollAreaPrivate::setContentPosition(value, orientation, animate);
       
   341     }
       
   342 
       
   343     if (animate) {
       
   344         updateScrollBar(orientation);
       
   345     }
       
   346 }
       
   347 
       
   348 bool HbAbstractItemViewPrivate::panTriggered(QGestureEvent *event)
       
   349 {
       
   350     Q_Q(HbAbstractItemView);
       
   351 
       
   352     HbPanGesture *gesture = static_cast<HbPanGesture *>(event->gesture(Qt::PanGesture));
       
   353 
       
   354     switch (gesture->state()) {
       
   355         case Qt::GestureStarted:
       
   356             mOptions |= PanningActive;
       
   357             // Fallthrough
       
   358         case Qt::GestureUpdated: {
       
   359             QPointF scenePos = event->mapToGraphicsScene(gesture->hotSpot());
       
   360             if (mDoingContiguousSelection) {
       
   361                 int retVal = false;
       
   362 
       
   363                 // loop through the items in the scene
       
   364                 qreal scenePosY = scenePos.y();
       
   365                 QPointF lastScenePos = scenePos + gesture->lastOffset() - gesture->offset();
       
   366                 qreal lastScenePosY = lastScenePos.y();
       
   367                 QPolygonF polygon;
       
   368                 polygon << lastScenePos << scenePos;
       
   369                 QList<QGraphicsItem *> items = q->scene()->items(polygon);
       
   370                 int itemCount = items.count();
       
   371                 for (int current = 0; current < itemCount ; ++current) {
       
   372                     HbAbstractViewItem *item = viewItem(items.at(current));
       
   373                     if (item && item->itemView() == q) {
       
   374                         QModelIndex itemIndex(item->modelIndex());
       
   375                         QGraphicsSceneMouseEvent mouseMoveEvent(QEvent::GraphicsSceneMouseMove);
       
   376                         QPointF scenePosInItemCoordinates = item->mapFromScene(scenePos);
       
   377                         QPointF position(qBound((qreal)0.0, scenePosInItemCoordinates.x(), item->size().width()), 
       
   378                                          qBound((qreal)0.0, scenePosInItemCoordinates.y(), item->size().height()));
       
   379                         mouseMoveEvent.setPos(position);
       
   380                         QItemSelectionModel::SelectionFlags command = q->selectionCommand(item, &mouseMoveEvent);
       
   381 
       
   382 						// in contiguousselectionarea there shall be no panning from HbScrollArea, thus return true
       
   383                         if (command != QItemSelectionModel::NoUpdate) {
       
   384                             retVal = true;
       
   385                         }
       
   386 
       
   387                         if ( itemIndex != mPreviousSelectedIndex
       
   388                           || command != mPreviousSelectedCommand) {
       
   389                             mPreviousSelectedIndex = itemIndex;
       
   390                             mPreviousSelectedCommand = command;
       
   391                             mSelectionModel->select(itemIndex, command);
       
   392                         }
       
   393 
       
   394                         // check if we need to start or keep on scrolling
       
   395                         int scrollDirection = 0;
       
   396                         QPointF pos = q->mapFromScene(scenePos);
       
   397                         if (pos.y() < (q->size().height() * CONTIGUOUS_SELECTION_AREA_THRESHOLD)) {
       
   398                              if (q->isScrolling()
       
   399                                  || (!q->isScrolling()
       
   400                                      && lastScenePosY >= scenePosY)) {                                
       
   401                                  scrollDirection = 1;
       
   402                              }
       
   403                         } else if (pos.y() > (q->size().height() * (1 - CONTIGUOUS_SELECTION_AREA_THRESHOLD))) {
       
   404                              if (q->isScrolling()
       
   405                                  || (!q->isScrolling()
       
   406                                      && lastScenePosY <= scenePosY)) {
       
   407                                  scrollDirection = -1;
       
   408                              }                        
       
   409                         }
       
   410 
       
   411                         // Start scrolling if needed. 
       
   412                         if (scrollDirection != 0) {
       
   413                             if (!mIsAnimating) {
       
   414                                 mPositionInContiguousSelection = scenePos;
       
   415                                 QObject::connect(q, SIGNAL(scrollPositionChanged(QPointF)), q, SLOT(_q_scrolling(QPointF)));    
       
   416                                 QObject::connect(q, SIGNAL(scrollingEnded()), q, SLOT(_q_scrollingEnded()));    
       
   417                                 QObject::connect(q, SIGNAL(scrollingStarted()), q, SLOT(_q_scrollingStarted()));    
       
   418                                 animateScroll(QPointF (0.0f, scrollDirection * CONTIGUOUS_SELECTION_SCROLL_SPEED));
       
   419                                 retVal = true;
       
   420                             }
       
   421                         } else if (q->isScrolling()) {
       
   422                             stopAnimating();
       
   423                             retVal = true;
       
   424                         }
       
   425                         break;
       
   426                     }
       
   427                 }
       
   428                 return retVal;
       
   429             }
       
   430             break;
       
   431         }
       
   432         case Qt::GestureFinished: 
       
   433         case Qt::GestureCanceled: {
       
   434             mOptions &= ~PanningActive;
       
   435             if (mDoingContiguousSelection) {
       
   436                 stopAnimating();
       
   437                 mDoingContiguousSelection = false;
       
   438                 return true;
       
   439             }               
       
   440             break;
       
   441         }
       
   442         default:
       
   443             break;
       
   444     }
       
   445 
       
   446     return false;
       
   447 }
       
   448 
       
   449 /*!
       
   450     This slot is called when the view is scrolling doing countinuousselection. It does the item 
       
   451     selection/deselection 
       
   452 */
       
   453 void HbAbstractItemViewPrivate::_q_scrolling(QPointF newPosition)
       
   454 {
       
   455     Q_UNUSED(newPosition);
       
   456 
       
   457     HbAbstractViewItem* hitItem = itemAt(mPositionInContiguousSelection);
       
   458     if (hitItem) {
       
   459         QModelIndex itemIndex(hitItem->modelIndex());
       
   460         if ( itemIndex != mPreviousSelectedIndex) {
       
   461             mPreviousSelectedIndex = itemIndex;
       
   462             mSelectionModel->select(itemIndex, mPreviousSelectedCommand);
       
   463         }
       
   464     }
       
   465 }
       
   466 
       
   467 /*!
       
   468     This slot is called when scrolling during continuousselction ends. It restores the original scrolling parameters 
       
   469 */
       
   470 void HbAbstractItemViewPrivate::_q_scrollingEnded()
       
   471 {
       
   472     Q_Q(HbAbstractItemView);
       
   473 
       
   474     mFrictionEnabled = mOrigFriction;
       
   475 
       
   476     QObject::disconnect(q, SIGNAL(scrollPositionChanged(QPointF)), q, SLOT(_q_scrollingI(QPointF)));    
       
   477     QObject::disconnect(q, SIGNAL(scrollingEnded()), q, SLOT(_q_scrollingEnded()));    
       
   478     QObject::disconnect(q, SIGNAL(scrollingStarted()), q, SLOT(_q_scrollingStarted()));    
       
   479 }
       
   480 
       
   481 /*!
       
   482     This slot is called when scrolling during continuousselction starts. It saves the original scrolling parameters 
       
   483 */
       
   484 void HbAbstractItemViewPrivate::_q_scrollingStarted()
       
   485 {
       
   486     mOrigFriction = mFrictionEnabled;
       
   487     mFrictionEnabled = false;
       
   488 }
       
   489 
       
   490 /*!
   310     \private
   491     \private
   311 
   492 
   312     When orientation switch occurs, 1) or 2) is applied to view after layout switch:
   493     When orientation switch occurs, 1) or 2) is applied to view after layout switch:
   313           1) if current item is wholly visible, it will be visible
   494           1) if last item is wholly visible, it will be visible
   314           2) if current item is not wholly visible, first visible item before layout switch is made visible
   495           2) if last item is not fully visible, the first fully visible item before layout switch is made the 
   315           In either case the visible item is at top of the view or as near as possible
   496 		     first fully visible item
   316  */
   497  */
   317 void HbAbstractItemViewPrivate::saveIndexMadeVisibleAfterMetricsChange()
   498 void HbAbstractItemViewPrivate::saveIndexMadeVisibleAfterMetricsChange()
   318 {
   499 {
   319     QModelIndex firstVisibleModelIndex;
   500     QModelIndex firstVisibleModelIndex;
   320     QModelIndex lastVisibleModelIndex;
   501     QModelIndex lastVisibleModelIndex;
   321     mContainer->firstAndLastVisibleModelIndex(firstVisibleModelIndex, lastVisibleModelIndex);
   502     mContainer->firstAndLastVisibleModelIndex(firstVisibleModelIndex, lastVisibleModelIndex);
   322 
   503 
   323     int firstVisibleRow = firstVisibleModelIndex.isValid() ? firstVisibleModelIndex.row() : 0;
   504     if (mModelIterator->model()) {
   324     int lastVisibleRow = lastVisibleModelIndex.isValid() ? lastVisibleModelIndex.row() : 0;
   505         if (lastVisibleModelIndex == mModelIterator->index(mModelIterator->indexCount() - 1)) {
   325 
   506             mVisibleIndex = lastVisibleModelIndex;
   326     // save current, if it is visible
   507         } else {
   327     firstVisibleRow = qMax(0, firstVisibleRow);
   508             mVisibleIndex = firstVisibleModelIndex;
   328     lastVisibleRow = qMax(0, lastVisibleRow);
   509         }
   329 
       
   330     if (mCurrentIndex.row() >= firstVisibleRow 
       
   331         && mCurrentIndex.row() <= lastVisibleRow) {
       
   332         mVisibleIndex = mCurrentIndex;
       
   333     } else if (mModelIterator->model()) {
       
   334         mVisibleIndex = mModelIterator->index(firstVisibleRow);
       
   335     }
   510     }
   336 }
   511 }
   337 
   512 
   338 /*!
   513 /*!
   339     \private
   514     \private
   404                     result.setX(itemRect.left() - viewRect.left());
   579                     result.setX(itemRect.left() - viewRect.left());
   405                 } else {                
   580                 } else {                
   406                     result.setX(itemRect.right() - viewRect.right());
   581                     result.setX(itemRect.right() - viewRect.right());
   407                 }
   582                 }
   408             }
   583             }
   409         }
   584         } else if (mScrollDirections & Qt::Horizontal) {
   410         else if (mScrollDirections & Qt::Horizontal) {
       
   411             switch (hint) {
   585             switch (hint) {
   412                 case HbAbstractItemView::PositionAtTop: {    // left
   586                 case HbAbstractItemView::PositionAtTop: {    // left
   413                     result.setX(itemRect.right() - viewRect.left() - sizeOffset.width());
   587                     result.setX(itemRect.right() - viewRect.left() - sizeOffset.width());
   414                     break;
   588                     break;
   415                 }
   589                 }
   450 {
   624 {
   451     if (item) {
   625     if (item) {
   452         switch (event->type())  {
   626         switch (event->type())  {
   453         case QEvent::GraphicsSceneMousePress: 
   627         case QEvent::GraphicsSceneMousePress: 
   454         case QEvent::GraphicsSceneMouseDoubleClick:
   628         case QEvent::GraphicsSceneMouseDoubleClick:
   455             if (item->selectionAreaContains(static_cast<const QGraphicsSceneMouseEvent *>(event)->scenePos())) {
   629             if (item->selectionAreaContains(static_cast<const QGraphicsSceneMouseEvent *>(event)->pos(), HbAbstractViewItem::SingleSelection)) {
   456                 mSelectionSettings |= Selection;
   630                 mSelectionSettings |= Selection;
   457             }
   631             }
   458             break;
   632             break;
   459         case QEvent::GraphicsSceneMouseRelease:
   633         case QEvent::GraphicsSceneMouseRelease:
   460             if (    mHitItem
   634             if (mSelectionSettings.testFlag(Selection)) {
   461                 &&  item->modelIndex() == mHitItem->modelIndex()
       
   462                 &&  mSelectionSettings.testFlag(Selection)) {
       
   463                 mSelectionSettings &= ~Selection;
   635                 mSelectionSettings &= ~Selection;
   464                 return QItemSelectionModel::ClearAndSelect;
   636                 return QItemSelectionModel::ClearAndSelect;
   465             }
   637             }
   466             break;
   638             break;
   467         default:
   639         default:
   474 
   646 
   475 
   647 
   476 QItemSelectionModel::SelectionFlags HbAbstractItemViewPrivate::multiSelectionCommand(
   648 QItemSelectionModel::SelectionFlags HbAbstractItemViewPrivate::multiSelectionCommand(
   477         const HbAbstractViewItem *item,
   649         const HbAbstractViewItem *item,
   478         const QEvent *event)
   650         const QEvent *event)
   479 {
       
   480     if (item) {
       
   481         switch (event->type())  {
       
   482         case QEvent::GraphicsSceneMousePress: 
       
   483         case QEvent::GraphicsSceneMouseDoubleClick:
       
   484             if (item->selectionAreaContains(static_cast<const QGraphicsSceneMouseEvent *>(event)->scenePos())) {
       
   485                 mSelectionSettings |= Selection;
       
   486             }
       
   487             break;
       
   488         case QEvent::GraphicsSceneMouseRelease:
       
   489             if (mHitItem
       
   490                 && item->modelIndex() == mHitItem->modelIndex() 
       
   491                 && mSelectionSettings.testFlag(Selection)) {
       
   492                 mSelectionSettings &= ~Selection;
       
   493                 return QItemSelectionModel::Toggle;
       
   494             }
       
   495             break;
       
   496         default:
       
   497             break;
       
   498         }
       
   499     }
       
   500     return QItemSelectionModel::NoUpdate;
       
   501 }
       
   502 
       
   503 QItemSelectionModel::SelectionFlags HbAbstractItemViewPrivate::contiguousSelectionCommand(
       
   504         const HbAbstractViewItem *item,
       
   505         const QEvent *event )
       
   506 {
   651 {
   507     Q_Q(HbAbstractItemView);
   652     Q_Q(HbAbstractItemView);
   508     if (item) {
   653     if (item) {
   509         switch (event->type()) {
   654         switch (event->type()) {
   510         case QEvent::GraphicsSceneMousePress: 
   655         case QEvent::GraphicsSceneMousePress: 
   511         case QEvent::GraphicsSceneMouseDoubleClick: {
   656         case QEvent::GraphicsSceneMouseDoubleClick: {
   512             if (item->selectionAreaContains(static_cast<const QGraphicsSceneMouseEvent *>(event)->scenePos())) {
   657 
   513                 mSelectionSettings |= Selection;
   658             // check if the mouse click is in the multiselectionarea
   514 
   659 		    if (item->selectionAreaContains(static_cast<const QGraphicsSceneMouseEvent *>(event)->pos(), HbAbstractViewItem::MultiSelection)) {
       
   660 		        mSelectionSettings |= Selection;
   515                 if (mSelectionModel && mSelectionModel->isSelected(item->modelIndex())) {
   661                 if (mSelectionModel && mSelectionModel->isSelected(item->modelIndex())) {
   516                     mContSelectionAction = QItemSelectionModel::Deselect;
   662                     mContSelectionAction = QItemSelectionModel::Deselect;
   517                 } else {
   663                 } else {
   518                     mContSelectionAction = QItemSelectionModel::Select;
   664                     mContSelectionAction = QItemSelectionModel::Select;
   519                 }
   665                 }
   520 
   666             }
   521                 // TODO: This should be changed to changing the gesture area of effect when that is possible...
   667 
   522                 // Gesture filter does not reset all of its internals: workaround is to delete and create the filter
   668             // check if the mouse click is in the "contiguousselectionarea"
       
   669             if (item->selectionAreaContains(static_cast<const QGraphicsSceneMouseEvent *>(event)->pos(), 
       
   670                                             HbAbstractViewItem::ContiguousSelection)) {
       
   671                 // it is assumed that the "contiguousselectionarea" is in the multiselectionarea
   523                 q->setLongPressEnabled(false);
   672                 q->setLongPressEnabled(false);
   524                 q->removeSceneEventFilter(mGestureFilter);
   673                 mDoingContiguousSelection = true;
   525                 mFilterRemoved = true;
   674             } else {
   526             }
   675                 mDoingContiguousSelection = false;
       
   676             }
       
   677 
   527             break;
   678             break;
   528             }
   679             }
   529         case QEvent::GraphicsSceneMouseRelease: {
   680         case QEvent::GraphicsSceneMouseRelease: {
   530             QItemSelectionModel::SelectionFlag flags =  QItemSelectionModel::NoUpdate;
   681             QItemSelectionModel::SelectionFlag flags =  QItemSelectionModel::NoUpdate;
   531             if (mSelectionSettings.testFlag(Selection)){
   682             if (mSelectionSettings.testFlag(Selection)){
   532                 flags = mContSelectionAction;
   683                 flags = mContSelectionAction;
   533                 mSelectionSettings &= ~Selection;
   684                 mSelectionSettings &= ~Selection;
   534                 mContSelectionAction = QItemSelectionModel::NoUpdate;
   685                 mContSelectionAction = QItemSelectionModel::NoUpdate;
   535             } 
   686             } 
   536             
   687             
   537             if (mFilterRemoved) {
   688             q->setLongPressEnabled(true);
   538                 // setLongPressEnabled installs filter
       
   539                 q->setLongPressEnabled(true);
       
   540                 mFilterRemoved = false;
       
   541             }
       
   542             return flags;
   689             return flags;
   543             }
   690             }
   544         case QEvent::GraphicsSceneMouseMove:
   691         case QEvent::GraphicsSceneMouseMove:
   545             return mContSelectionAction;
   692             if (mDoingContiguousSelection) {
       
   693                 return mContSelectionAction;
       
   694             } else {
       
   695                 return QItemSelectionModel::NoUpdate;
       
   696             }
   546         default:
   697         default:
   547             break;
   698             break;
   548         }
   699         }
   549     }
   700     }
   550     return QItemSelectionModel::NoUpdate;
   701     return QItemSelectionModel::NoUpdate;
   551 }
   702 }
   552 
   703 
   553 /*!
       
   554     Overwrites the default scroll area scrollbar updating algorithm when
       
   555     recycling is used. On recycling the scrollbar position & size is calculated
       
   556     using rows and their pixel size is not used.
       
   557 */
       
   558 void HbAbstractItemViewPrivate::updateScrollBar(Qt::Orientation orientation)
       
   559 {
       
   560     if (!handleScrollBar(orientation)) {
       
   561         HbScrollAreaPrivate::updateScrollBar(orientation);
       
   562     } else {
       
   563         if (mContainer->layout() && !mContainer->layout()->isActivated()) {
       
   564             mContainer->layout()->activate();
       
   565         }
       
   566 
       
   567         if (mContainer->uniformItemSizes()) {
       
   568             updateScrollBarForUniformSizedItems();
       
   569         } else {
       
   570             updateScrollBarForVariableSizedItems();
       
   571         }
       
   572     } 
       
   573 }
       
   574 
   704 
   575 /*!
   705 /*!
   576     Returns the abstract view item from given scene position, if there is any.
   706     Returns the abstract view item from given scene position, if there is any.
   577 */
   707 */
   578 HbAbstractViewItem *HbAbstractItemViewPrivate::itemAt(const QPointF& position) const
   708 HbAbstractViewItem *HbAbstractItemViewPrivate::itemAt(const QPointF& position) const
   621     mContainer->resize( newSize );    
   751     mContainer->resize( newSize );    
   622 }
   752 }
   623 
   753 
   624 
   754 
   625 QRectF HbAbstractItemViewPrivate::itemBoundingRect(const QGraphicsItem *item) const
   755 QRectF HbAbstractItemViewPrivate::itemBoundingRect(const QGraphicsItem *item) const
   626     {
   756 {
   627         Q_Q(const HbAbstractItemView);
   757     Q_Q(const HbAbstractItemView);
   628 
   758 
   629         if (mContainer) {
   759     if (mContainer) {
   630             QGraphicsLayout *containerLayout = mContainer->layout();
   760         QGraphicsLayout *containerLayout = mContainer->layout();
   631             if (containerLayout) {
   761         if (containerLayout) {
   632                 containerLayout->activate();
   762             containerLayout->activate();
   633             }
   763         }
   634         }
   764     }
   635 
   765 
   636         return item->mapToItem(q, item->boundingRect()).boundingRect();
   766     return item->mapToItem(q, item->boundingRect()).boundingRect();
   637     }
   767 }
   638 
   768 
   639 /*!
   769 /*!
   640     Returns true if given item is located within viewport (i.e.  view), otherwise
   770     Returns true if given item is located within viewport (i.e.  view), otherwise
   641     returns false. If fullyVisible parameter is true method will return true only
   771     returns false. If fullyVisible parameter is true method will return true only
   642     for item that is shown fully. In this case for partially visible items false is returned.
   772     for item that is shown fully. In this case for partially visible items false is returned.
   718     Q_Q(HbAbstractItemView);
   848     Q_Q(HbAbstractItemView);
   719     QPointF delta = pixelsToScroll(item, hint);
   849     QPointF delta = pixelsToScroll(item, hint);
   720     if (delta != QPointF()) {
   850     if (delta != QPointF()) {
   721         QPointF newPos = -mContainer->pos() + delta;
   851         QPointF newPos = -mContainer->pos() + delta;
   722         checkBoundaries(newPos);
   852         checkBoundaries(newPos);
   723         // scroll area logic is oposite to real position
   853 
       
   854         // scroll area logic is opposite to real position.
   724         q->scrollContentsTo(newPos);
   855         q->scrollContentsTo(newPos);
   725     }
   856     }
   726 }
   857 }
   727 void HbAbstractItemViewPrivate::checkBoundaries(QPointF &newPos)
   858 void HbAbstractItemViewPrivate::checkBoundaries(QPointF &newPos)
   728 {
   859 {
   750             newPos.setX(rightBoundary()); 
   881             newPos.setX(rightBoundary()); 
   751         }
   882         }
   752     }
   883     }
   753 }
   884 }
   754 
   885 
   755 void HbAbstractItemViewPrivate::updateScrollBarForUniformSizedItems()
       
   756 {
       
   757     Q_Q(const HbAbstractItemView);
       
   758     
       
   759     HbAbstractViewItem *firstItem = mContainer->items().first();
       
   760     qreal uniformItemHeight = firstItem->size().height();
       
   761     qreal containerVirtualHeight = uniformItemHeight *  (mModelIterator->indexCount());
       
   762     qreal thumbPosition(0);
       
   763     int firstBufferItemRowNumber = mModelIterator->indexPosition(firstItem->modelIndex());
       
   764      
       
   765     QRectF itemRect = itemBoundingRect(firstItem);
       
   766     qreal realTopBoundary = itemRect.top();   
       
   767     qreal virtualTopBoundary = realTopBoundary - (firstBufferItemRowNumber*uniformItemHeight); 
       
   768    
       
   769     if ((containerVirtualHeight - q->boundingRect().height()) != 0) {
       
   770         thumbPosition = 
       
   771             (-virtualTopBoundary) / (containerVirtualHeight - q->boundingRect().height());
       
   772     }  
       
   773  
       
   774     thumbPosition = qBound((qreal)0.0, thumbPosition, (qreal)1.0);
       
   775  
       
   776     if (mVerticalScrollBar) {
       
   777         if (containerVirtualHeight!=0) {
       
   778             mVerticalScrollBar->setPageSize(qBound ( (qreal)0.0,
       
   779                                      q->boundingRect().height() / containerVirtualHeight,
       
   780                                       (qreal)1.0));
       
   781         }
       
   782         mVerticalScrollBar->setValue(thumbPosition); 
       
   783     }    
       
   784 }
       
   785 
       
   786 void HbAbstractItemViewPrivate::setScrollBarMetrics(Qt::Orientation orientation)
   886 void HbAbstractItemViewPrivate::setScrollBarMetrics(Qt::Orientation orientation)
   787 {   
   887 {
   788     if (!handleScrollBar(orientation) ) {
   888     if (!handleScrollBar(orientation) ) {
   789         HbScrollAreaPrivate::setScrollBarMetrics(orientation);
   889         HbScrollAreaPrivate::setScrollBarMetrics(orientation);
   790     } else {
   890     } else {
   791         //We just make sure that the base clas is not called
   891         Q_Q(HbAbstractItemView);
   792         //It set the page size wrongly
   892 
   793         updateScrollBar(orientation); 
   893         if (mContainer->layout() && !mContainer->layout()->isActivated()) {
       
   894             mContainer->layout()->activate();
       
   895         }
       
   896 
       
   897         qreal itemHeight;
       
   898         if (mContainer->uniformItemSizes()) {
       
   899             itemHeight = mContainer->items().first()->size().height();
       
   900         } else {
       
   901             // avarrage height based on container content
       
   902             itemHeight = mContainer->size().height() / mContainer->items().size();
       
   903         }
       
   904         qreal rowCount = q->boundingRect().height() / itemHeight;
       
   905         qreal modelRowCount = mModelIterator->indexCount();
       
   906         qreal thumbSize = rowCount / modelRowCount;
       
   907         mVerticalScrollBar->setPageSize(thumbSize);
   794     }
   908     }
   795 }
   909 }
   796 
   910 
   797 /*!
   911 /*!
   798     This function combines the conditions to solve whether the scroll bar calcultion should be handled in
   912     This function combines the conditions to solve whether the scroll bar calcultion should be handled in
   799     this class or is the base class calculation sufficient
   913     this class or is the base class calculation sufficient
   800 */
   914 */
   801 bool  HbAbstractItemViewPrivate::handleScrollBar(Qt::Orientation orientation)
   915 bool HbAbstractItemViewPrivate::handleScrollBar(Qt::Orientation orientation)
   802 {
   916 {
   803     if (!mContainer->itemRecycling()
   917     if (!mContainer->itemRecycling()
   804         || mContainer->itemPrototypes().count() != 1 
   918         || !(orientation & mScrollDirections)
   805         || orientation == Qt::Horizontal
   919         || mContainer->itemPrototypes().count() != 1
   806         || mContainer->items().count() == 0) {
   920         || mContainer->items().isEmpty()
   807             return false;
   921         || (!mVerticalScrollBar && orientation == Qt::Vertical)
       
   922         || (!mHorizontalScrollBar && orientation == Qt::Horizontal)) {
       
   923         return false;
   808     } else {
   924     } else {
   809         return true;
   925         return true;
   810     }
   926     }
   811 }
   927 }
   812 
   928 
   813 void HbAbstractItemViewPrivate::updateScrollBarForVariableSizedItems()
   929 /*!
   814 {
   930     Overwrites the default scroll area scrollbar updating algorithm when
   815     Q_Q(const HbAbstractItemView);
   931     recycling is used. While recycling is on scrollbar position & size 
   816     HbAbstractViewItem *firstItem = mContainer->items().first();
   932     are calculated using rows and their pixel sizes are not used (in fact only 
   817  
   933     container position is interesting to determine partially visible items
   818     // View position is the amount of hidden (fully or partially)
   934     - when container contain small amount of items it is important).
   819     // rows above the view area.
   935 */
   820     int position = mModelIterator->indexPosition(firstItem->modelIndex());
   936 void HbAbstractItemViewPrivate::updateScrollBar(Qt::Orientation orientation)
   821     if (position == -1) {
   937 {
   822         return; 
   938     if (!handleScrollBar(orientation)) {
   823     }
   939         HbScrollAreaPrivate::updateScrollBar(orientation);
   824     qreal viewY = (qreal)(position);
   940     } else {
   825 
   941         if (mContainer->layout() && !mContainer->layout()->isActivated()) {
   826     // View area height is the amount of rows within the view area.
   942             mContainer->layout()->activate();
   827     qreal viewH = 0;
   943         }
   828 
   944 
   829     //Index count calculation is time consuming with tree
   945         Q_Q(const HbAbstractItemView);
   830     int indexCount = mModelIterator->indexCount();
   946 
   831 
   947         qreal containerPos = mContainer->pos().y();
   832     // Total height is the amount of rows in the model.
   948         qreal itemHeight;
   833     qreal totalH = indexCount;
   949         if (mContainer->uniformItemSizes()) {
   834 
   950             itemHeight = mContainer->items().first()->size().height();
   835     qreal itemTop = firstItem->mapToItem(q, firstItem->pos()).y();
       
   836     qreal viewHeight = q->size().height();
       
   837     int itemCount = mContainer->items().count();
       
   838     
       
   839     for (int i=0; i < itemCount; ++i) {
       
   840         qreal itemHeight = mContainer->items().at(i)->size().height();
       
   841         qreal itemBottom = itemTop + itemHeight;
       
   842         if (itemTop < 0) {
       
   843             // Some part of the item is above the view area.
       
   844             if (itemBottom < 0) {
       
   845                 // Fully above the view area
       
   846                 viewY += 1;
       
   847             } else {
       
   848                 // Partially at the view area and partially above the view area.
       
   849                 viewY += (1.0 - itemBottom / itemHeight);
       
   850                 viewH += itemBottom / itemHeight;
       
   851             }
       
   852         } else if (itemTop < viewHeight) {
       
   853             // So part of the item is at the view area.
       
   854             if (itemBottom < viewHeight) {
       
   855                 // Fully at the view area
       
   856                 viewH += 1;
       
   857             } else {
       
   858                 // Partially at the view area and partially below the view area.
       
   859                 viewH += (viewHeight - itemTop) / itemHeight;
       
   860             }
       
   861         } else {
   951         } else {
   862             break;
   952             // avarrage height based on container content
   863         }
   953             itemHeight = mContainer->size().height() / mContainer->items().size();
   864 
   954         }
   865         itemTop += itemHeight;
   955         qreal rowCount = q->boundingRect().height() / itemHeight;
   866     }
   956         qreal modelRowCount = mModelIterator->indexCount() - rowCount;
   867 
   957         qreal firstVisibleRow = mModelIterator->indexPosition(mContainer->items().first()->modelIndex());
   868     // Shifting the values to scrollbar range that is from 0.0-1.0. 
   958         firstVisibleRow += -containerPos / itemHeight;
   869     qreal pos = viewY / (totalH - viewH);
   959         qreal thumbPos = firstVisibleRow / (qreal)modelRowCount;
   870     pos = qBound((qreal)0.0, pos, (qreal)1.0);
   960         mVerticalScrollBar->setValue(thumbPos);
   871 
   961     }
   872     if (mVerticalScrollBar) {
   962 }
   873         if (indexCount!=0) {
   963 
   874             mVerticalScrollBar->setPageSize(viewH / (qreal)(indexCount));
   964 void HbAbstractItemViewPrivate::rowsRemoved(const QModelIndex &parent, int start, int end)
   875         }
       
   876         mVerticalScrollBar->setValue(pos);
       
   877     }    
       
   878 }
       
   879 
       
   880 void HbAbstractItemViewPrivate::rowsRemoved(const QModelIndex &parent,int start,int end)
       
   881 {
   965 {
   882     if (mModelIterator->model()->columnCount(parent) == 0) {
   966     if (mModelIterator->model()->columnCount(parent) == 0) {
   883         return;
   967         return;
   884     }
   968     }
   885 
   969 
   898     }
   982     }
   899 
   983 
   900     for (int current = end; current >= start; --current) {
   984     for (int current = end; current >= start; --current) {
   901         //The items are already removed from the model. That's why their indexes are already invalid.
   985         //The items are already removed from the model. That's why their indexes are already invalid.
   902         //Here we loop the items in container and call removeItem() with QModelIndex().
   986         //Here we loop the items in container and call removeItem() with QModelIndex().
   903         bool animate = mEnabledAnimations & HbAbstractItemView::Disappear ? mAnimateItems : false;
   987         mContainer->removeItem(QModelIndex(), animationEnabled(false));
   904         mContainer->removeItem(QModelIndex(), animate);
       
   905     }
   988     }
   906 }
   989 }
   907 
   990 
   908 QItemSelectionModel::SelectionFlags HbAbstractItemViewPrivate::selectionFlags( 
   991 QItemSelectionModel::SelectionFlags HbAbstractItemViewPrivate::selectionFlags( 
   909                                                     const HbAbstractViewItem *item, 
   992                                                     const HbAbstractViewItem *item, 
   911 {
   994 {
   912     if (!item || !item->modelIndex().isValid() || !(item->flags() & QGraphicsItem::ItemIsSelectable))
   995     if (!item || !item->modelIndex().isValid() || !(item->flags() & QGraphicsItem::ItemIsSelectable))
   913         return QItemSelectionModel::NoUpdate;
   996         return QItemSelectionModel::NoUpdate;
   914 
   997 
   915     QItemSelectionModel::SelectionFlags flags = QItemSelectionModel::NoUpdate;
   998     QItemSelectionModel::SelectionFlags flags = QItemSelectionModel::NoUpdate;
   916     if (item && mHitItem && event){
   999     if (item && event){
   917         switch (mSelectionMode) {
  1000         switch (mSelectionMode) {
   918         case HbAbstractItemView::SingleSelection: 
  1001         case HbAbstractItemView::SingleSelection: 
   919             flags =  singleSelectionCommand(item, event);
  1002             flags =  singleSelectionCommand(item, event);
   920             break;
  1003             break;
   921         case HbAbstractItemView::MultiSelection:
  1004         case HbAbstractItemView::MultiSelection:
   922             flags =  multiSelectionCommand(item, event);
       
   923             break;
       
   924         case HbAbstractItemView::ContiguousSelection: {
  1005         case HbAbstractItemView::ContiguousSelection: {
   925             flags = contiguousSelectionCommand(item, event);
  1006             flags = multiSelectionCommand(item, event);
   926             break;
  1007             break;
   927         }
  1008         }
   928         case HbAbstractItemView::NoSelection: // Never update selection model
  1009         case HbAbstractItemView::NoSelection: // Never update selection model
   929             break;
  1010             break;
   930         }
  1011         }
   937 {
  1018 {
   938     mPostponedScrollIndex = QPersistentModelIndex();
  1019     mPostponedScrollIndex = QPersistentModelIndex();
   939     mContainer->reset();
  1020     mContainer->reset();
   940 }
  1021 }
   941 
  1022 
   942 void HbAbstractItemViewPrivate::startAppearEffect(const QModelIndex &parent, int start, int end)
  1023 void HbAbstractItemViewPrivate::startAppearEffect(const QString &itemType, const QString &effectEvent, const QModelIndex &parent, int start, int end)
   943 {
  1024 {
   944     Q_Q(HbAbstractItemView);
  1025     Q_Q(HbAbstractItemView);
   945     if( mAppearAnimationIndexes.count()) {
  1026     if( mAppearAnimationIndexes.count()) {
   946         mAppearAnimationIndexes.clear();
  1027         mAppearAnimationIndexes.clear();
   947     }
  1028     }
   949     for (int i = start; i <= end; i++) {
  1030     for (int i = start; i <= end; i++) {
   950         QPersistentModelIndex index = mModelIterator->index(i, parent);
  1031         QPersistentModelIndex index = mModelIterator->index(i, parent);
   951         HbAbstractViewItem *item = q->itemByIndex(index);
  1032         HbAbstractViewItem *item = q->itemByIndex(index);
   952         if (item) {
  1033         if (item) {
   953             items.append(item);
  1034             items.append(item);
       
  1035             item->setFlag(QGraphicsItem::ItemSendsGeometryChanges, true);
       
  1036 
   954             mAppearAnimationIndexes.append(index);
  1037             mAppearAnimationIndexes.append(index);
   955         }
  1038         }
   956     }
  1039     }
   957 
  1040 
   958     refreshContainerGeometry();
  1041     refreshContainerGeometry();
   959 
  1042 
   960     HbEffect::start(items, "viewitem", "appear", q, "_q_animationFinished");
  1043     HbEffect::start(items, itemType, effectEvent, q, "_q_animationFinished");
   961 }
  1044 }
   962 
  1045 
   963 void HbAbstractItemViewPrivate::ensureVisible(QPointF position, qreal xMargin, qreal yMargin)
  1046 void HbAbstractItemViewPrivate::ensureVisible(QPointF position, qreal xMargin, qreal yMargin)
   964 {
  1047 {
   965     mPostponedScrollIndex = QPersistentModelIndex();
  1048     mPostponedScrollIndex = QPersistentModelIndex();
   966     HbScrollAreaPrivate::ensureVisible(position, xMargin, yMargin);
  1049     HbScrollAreaPrivate::ensureVisible(position, xMargin, yMargin);
   967 }
  1050 }
   968 
  1051 
   969 
  1052 bool HbAbstractItemViewPrivate::animationEnabled(bool insertOperation)
       
  1053 {
       
  1054     if (insertOperation) {
       
  1055         return mEnabledAnimations & HbAbstractItemView::Appear ? mAnimateItems : false;
       
  1056     } else {
       
  1057         return mEnabledAnimations & HbAbstractItemView::Disappear ? mAnimateItems : false;
       
  1058     }
       
  1059 }