src/hbwidgets/itemviews/hblistview.cpp
changeset 1 f7ac710697a9
parent 0 16d8024aca5e
child 2 06ff229162e9
equal deleted inserted replaced
0:16d8024aca5e 1:f7ac710697a9
    28 
    28 
    29 #include "hblistlayout_p.h"
    29 #include "hblistlayout_p.h"
    30 #include "hblistviewitem.h"
    30 #include "hblistviewitem.h"
    31 #include "hblistitemcontainer_p.h"
    31 #include "hblistitemcontainer_p.h"
    32 #include "hblistitemcontainer_p.h"
    32 #include "hblistitemcontainer_p.h"
    33 #include "hbgesturefilter.h"
       
    34 #include "hbscrollbar.h"
    33 #include "hbscrollbar.h"
    35 #include <hbwidgetfeedback.h>
    34 #include <hbwidgetfeedback.h>
    36 #include "hbmodeliterator.h"
    35 #include "hbmodeliterator.h"
    37 
    36 
    38 #include <QGraphicsSceneMouseEvent>
    37 #include <QGraphicsSceneMouseEvent>
    39 #include <QGraphicsScene>
    38 #include <QGraphicsScene>
    40 #include <QAbstractItemModel>
    39 #include <QAbstractItemModel>
       
    40 
       
    41 #include <QPanGesture>
    41 
    42 
    42 #include <qdebug.h>
    43 #include <qdebug.h>
    43 /*!
    44 /*!
    44     @beta
    45     @beta
    45     @hbwidgets
    46     @hbwidgets
    70 
    71 
    71     View item layout configuration happens from HbListViewItem prototype that can be accesses with HbListViewItem::listItemPrototype function.
    72     View item layout configuration happens from HbListViewItem prototype that can be accesses with HbListViewItem::listItemPrototype function.
    72     
    73     
    73     More information about this can be found from HbListViewItem documentation.
    74     More information about this can be found from HbListViewItem documentation.
    74 */
    75 */
    75 
       
    76 static const qreal DRAGGED_ITEM_SCROLL_SPEED = 0.2;
       
    77 static const int FLICKMINDISTANCE = 50;
       
    78 static const qreal FLICK_TIMEOUT = 200;
       
    79 static const qreal SCROLLSPEED_FACTOR = 0.0004;
       
    80 
    76 
    81 /*!
    77 /*!
    82     Constructs a list view with \a parent.
    78     Constructs a list view with \a parent.
    83  */
    79  */
    84 HbListView::HbListView(QGraphicsItem *parent)
    80 HbListView::HbListView(QGraphicsItem *parent)
   138 
   134 
   139     //If item is in the buffer, just reveal it.
   135     //If item is in the buffer, just reveal it.
   140     //This is always the case if recycling is off 
   136     //This is always the case if recycling is off 
   141     //and sometimes the case when recycling is on
   137     //and sometimes the case when recycling is on
   142     if (itemRecycling()) {
   138     if (itemRecycling()) {
   143         if (!   (    d->mContainer->itemByIndex(index)
   139         if (    !d->mContainer->itemByIndex(index)
   144                 &&  (   hint == PositionAtTop
   140             ||  hint != EnsureVisible) {
   145                     ||  hint == EnsureVisible))) {
       
   146             //Now the item is not in the buffer.
   141             //Now the item is not in the buffer.
   147             //We must first set the item to be in the buffer
   142             //We must first set the item to be in the buffer
   148             //If the item is above let's put it first and if it is below put it last
   143             //If the item is above let's put it first and if it is below put it last
   149             int newIndex = -1;
   144             int newIndex = -1;
   150             switch (hint) {
   145             switch (hint) {
   242             if (d->mSelectionMode != HbAbstractItemView::NoSelection
   237             if (d->mSelectionMode != HbAbstractItemView::NoSelection
   243                 || !d->mModelIterator->model()
   238                 || !d->mModelIterator->model()
   244                 || !(d->mModelIterator->model()->supportedDropActions().testFlag(Qt::MoveAction))) {
   239                 || !(d->mModelIterator->model()->supportedDropActions().testFlag(Qt::MoveAction))) {
   245                 return false;
   240                 return false;
   246             }
   241             }
   247             if (d->mGestureFilter) {
       
   248                 removeSceneEventFilter(d->mGestureFilter);
       
   249                 d->mFilterRemoved = true;
       
   250             }
       
   251             verticalScrollBar()->setInteractive(true);
   242             verticalScrollBar()->setInteractive(true);
   252 
       
   253         } else {
   243         } else {
   254             if (d->mFilterRemoved) {
       
   255                 installSceneEventFilter(d->mGestureFilter);
       
   256                 d->mFilterRemoved = false;
       
   257             }
       
   258             verticalScrollBar()->setInteractive(false);
   244             verticalScrollBar()->setInteractive(false);
   259         }
   245         }
   260         d->mArrangeMode = arrangeMode;
   246         d->mArrangeMode = arrangeMode;
   261         d->mAnimateItems = !d->mArrangeMode;
   247         d->mAnimateItems = !d->mArrangeMode;
       
   248 
       
   249         if (d->mArrangeMode == true) {
       
   250             d->mOriginalFriction = d->mFrictionEnabled;
       
   251             setFrictionEnabled(false);
       
   252         } else {
       
   253             setFrictionEnabled(d->mOriginalFriction);
       
   254         }
   262     }
   255     }
   263     return true;
   256     return true;
   264 }
   257 }
   265 
       
   266 /*!
       
   267     \reimp
       
   268 */
       
   269 void HbListView::mousePressEvent(QGraphicsSceneMouseEvent *event)
       
   270 {
       
   271     Q_D(HbListView);
       
   272     if (d->mArrangeMode 
       
   273         && d->mSelectionMode == HbAbstractItemView::NoSelection
       
   274         && !d->mDraggedItem) {
       
   275 
       
   276         if (d->mFilterRemoved == false && d->mGestureFilter) {
       
   277             removeSceneEventFilter(d->mGestureFilter);
       
   278             d->mFilterRemoved = true;
       
   279         }
       
   280 
       
   281         d->mDraggedItem = d->itemAt(event->scenePos());
       
   282         if(d->mDraggedItem) {
       
   283             d->mDraggedItemIndex = d->mDraggedItem->modelIndex();
       
   284 
       
   285             if (d->mDraggedItemIndex.isValid()) {
       
   286                 setCurrentIndex(d->mDraggedItemIndex);
       
   287                 d->mMousePressTimer.restart();
       
   288                 d->mMousePressPos = event->scenePos();
       
   289                 d->mOriginalTransform = d->mDraggedItem->transform();
       
   290                 d->mDraggedItem->setZValue(d->mDraggedItem->zValue() + 1);
       
   291                 d->mDraggedItem->setPressed(true);
       
   292 
       
   293                 connect(this, SIGNAL(scrollPositionChanged(QPointF)), this, SLOT(scrolling(QPointF)));    
       
   294                 Hb::InteractionModifiers modifiers = 0;
       
   295                 if (d->mWasScrolling) {
       
   296                     modifiers |= Hb::ModifierScrolling;
       
   297                 }
       
   298                 HbWidgetFeedback::triggered(d->mDraggedItem,Hb::InstantPressed,modifiers);
       
   299             } else {
       
   300                 d->mDraggedItem = 0;
       
   301             }
       
   302         }
       
   303     } else {
       
   304         if (!d->mDraggedItem) {
       
   305             HbAbstractItemView::mousePressEvent(event);
       
   306         }
       
   307     }
       
   308 }
       
   309 
       
   310 /*!
       
   311     \reimp
       
   312 */
       
   313 void HbListView::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
       
   314 {
       
   315     Q_D(HbListView);
       
   316 
       
   317     if (d->mArrangeMode
       
   318         && d->mSelectionMode == HbAbstractItemView::NoSelection
       
   319         && d->mDraggedItem) {
       
   320 
       
   321         if (!isScrolling()) {
       
   322             // move the item with the cursor to indicate the move
       
   323             d->mDraggedItem->translate(0, event->scenePos().y() - event->lastScenePos().y());
       
   324 
       
   325             if (d->mMousePressTimer.elapsed() >= FLICK_TIMEOUT) {
       
   326                 d->moveDraggedItemTo(event->scenePos());
       
   327             }
       
   328         }
       
   329 
       
   330         // in case we are "dragging" an item and at the top/bottom of
       
   331         // the view the view is scrolled to reveal more items in
       
   332         // that direction
       
   333         QModelIndex firstVisible;
       
   334         QModelIndex lastVisible;        
       
   335         d->mContainer->firstAndLastVisibleModelIndex(firstVisible, lastVisible);
       
   336         if (firstVisible.isValid() && lastVisible.isValid()) {
       
   337             // above indexes are valid so container contain at least one item - so it is
       
   338             // safe to call first and last
       
   339             QModelIndex firstItemIndex = d->mContainer->items().first()->modelIndex();
       
   340             QModelIndex lastItemIndex = d->mContainer->items().last()->modelIndex();
       
   341             // If the item is dragged up in the list (and there are more items to show), scroll up
       
   342             if (!isScrolling()
       
   343                 && !isVisible(firstItemIndex)
       
   344                 && event->scenePos().y() < d->mMousePressPos.y()
       
   345                 && event->pos().y() < itemByIndex(firstVisible)->size().height()) {
       
   346                 d->mScrollStartMousePos = event->scenePos();
       
   347                 d->mLastScrollPos = QPointF(0,0);
       
   348                 d->animateScroll(QPointF(0.0f , DRAGGED_ITEM_SCROLL_SPEED));
       
   349             }
       
   350             // If the item is dragged down in the list (and there are more items to show), scroll down
       
   351             else if (!isScrolling()
       
   352                        && !isVisible(lastItemIndex)
       
   353                        && event->scenePos().y() > d->mMousePressPos.y()
       
   354                        && event->pos().y() > (size().height() - itemByIndex(lastVisible)->size().height())) {
       
   355                 d->mScrollStartMousePos = event->scenePos();
       
   356                 d->mLastScrollPos = QPointF(0,0);
       
   357                 d->animateScroll(QPointF(0.0f , (-1 * DRAGGED_ITEM_SCROLL_SPEED)));
       
   358             }
       
   359             // If the view is scrolling and the drag event is inside the view, we need to stop the scrolling
       
   360             else if (event->pos().y() < (size().height() - itemByIndex(lastVisible)->size().height())
       
   361                        && event->pos().y() > itemByIndex(firstVisible)->size().height()
       
   362                        && isScrolling()) {
       
   363                 d->stopAnimating();
       
   364             }
       
   365         }
       
   366     } else {
       
   367         HbAbstractItemView::mouseMoveEvent(event);
       
   368     }
       
   369 }
       
   370 
       
   371 
   258 
   372 /*!
   259 /*!
   373     This slot is called when the arrangeMode is true, user is dragging an item 
   260     This slot is called when the arrangeMode is true, user is dragging an item 
   374     and the underlying scrollarea is moving. 
   261     and the underlying scrollarea is moving. 
   375 */void HbListView::scrolling(QPointF newPosition)
   262 */
       
   263 void HbListView::scrolling(QPointF newPosition)
   376 {
   264 {
   377     Q_UNUSED(newPosition);
   265     Q_UNUSED(newPosition);
   378 
   266 
   379     Q_D(HbListView);
   267     Q_D(HbListView);
   380     if (d->mArrangeMode
   268     if (d->mArrangeMode
   392         d->moveDraggedItemTo(d->mScrollStartMousePos);
   280         d->moveDraggedItemTo(d->mScrollStartMousePos);
   393 
   281 
   394         if (d->mDraggedItem) {
   282         if (d->mDraggedItem) {
   395             d->mDraggedItem->translate(delta.x(), delta.y());
   283             d->mDraggedItem->translate(delta.x(), delta.y());
   396         }
   284         }
   397     }
       
   398 }
       
   399 
       
   400 
       
   401 
       
   402 /*!
       
   403     \reimp
       
   404 */
       
   405 void HbListView::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
       
   406 {
       
   407     Q_D(HbListView);
       
   408 
       
   409     if (d->mArrangeMode 
       
   410         && d->mSelectionMode == HbAbstractItemView::NoSelection
       
   411         && d->mDraggedItem) {
       
   412 
       
   413         disconnect(this, SIGNAL(scrollPositionChanged(QPointF)), this, SLOT(scrolling(QPointF)));
       
   414 
       
   415         if (isScrolling()) {
       
   416             d->stopAnimating();
       
   417         }
       
   418 
       
   419         // remove item's drag indications
       
   420         d->mDraggedItem->setOpacity(1.0);
       
   421         d->mDraggedItem->setTransform(d->mOriginalTransform);
       
   422         d->mDraggedItem->setZValue(d->mDraggedItem->zValue() - 1);
       
   423         d->mDraggedItem->setPressed(false);
       
   424 
       
   425         if (d->itemAt(event->scenePos())) {
       
   426             int downTime = d->mMousePressTimer.elapsed();
       
   427             // this seems to be a flick rather than item move, so start 
       
   428             // scrolling
       
   429             qreal distance = event->scenePos().y() - d->mMousePressPos.y();
       
   430             if (downTime > 0 && downTime < FLICK_TIMEOUT 
       
   431                 && qAbs(distance) > FLICKMINDISTANCE ) {
       
   432                 d->animateScroll(QPointF (0.0f, (distance * 1000 / downTime) * SCROLLSPEED_FACTOR));
       
   433             }
       
   434         }
       
   435 
       
   436         Hb::InteractionModifiers modifiers = 0;
       
   437         if (d->mWasScrolling) {
       
   438             modifiers |= Hb::ModifierScrolling;
       
   439         }
       
   440         HbWidgetFeedback::triggered(d->mDraggedItem,Hb::InstantReleased,modifiers);
       
   441         d->mDraggedItem = 0;
       
   442 
       
   443     } else {
       
   444         HbAbstractItemView::mouseReleaseEvent(event);
       
   445     }
   285     }
   446 }
   286 }
   447 
   287 
   448 /*!
   288 /*!
   449     Moves the item in row \a from to row \a to. 
   289     Moves the item in row \a from to row \a to. 
   482 {
   322 {
   483     Q_D(HbListView);
   323     Q_D(HbListView);
   484 
   324 
   485     if (parent == d->mModelIterator->rootIndex()) {
   325     if (parent == d->mModelIterator->rootIndex()) {
   486         HbAbstractItemView::rowsInserted(parent, start, end);
   326         HbAbstractItemView::rowsInserted(parent, start, end);
   487         bool animate = d->mEnabledAnimations & HbAbstractItemView::Appear ? d->mAnimateItems : false;
   327         if (!d->mArrangeMode && d->animationEnabled(true)) {
   488         if (!d->mArrangeMode && animate) {
   328             d->startAppearEffect("viewitem", "appear", parent, start, end);
   489             d->startAppearEffect(parent, start, end);
       
   490         }
   329         }
   491     }
   330     }
   492 }
   331 }
   493 
   332 
   494 /*!
   333 /*!
   503             HbAbstractViewItem* item = viewItem(i);
   342             HbAbstractViewItem* item = viewItem(i);
   504             if (item) {
   343             if (item) {
   505                 if (d->mDraggedItem == item) {
   344                 if (d->mDraggedItem == item) {
   506                    d->mDraggedItem = 0;
   345                    d->mDraggedItem = 0;
   507                 }
   346                 }
   508                 bool animate = d->mEnabledAnimations & HbAbstractItemView::Disappear ? d->mAnimateItems : false;
   347 
   509                 if (!d->mArrangeMode && animate) {
   348                 if (!d->mArrangeMode && d->animationEnabled(false)) {
   510                     d->mItemsAboutToBeDeleted.append(item);
   349                     d->mItemsAboutToBeDeleted.append(item);
   511                 }
   350                 }
   512             }
   351             }
   513         }
   352         }
   514     }
   353     }
   516 
   355 
   517 void HbListView::rowsRemoved(const QModelIndex &parent, int start, int end)
   356 void HbListView::rowsRemoved(const QModelIndex &parent, int start, int end)
   518 {
   357 {
   519     Q_D(HbListView);
   358     Q_D(HbListView);
   520     if (parent == d->mModelIterator->rootIndex()) {
   359     if (parent == d->mModelIterator->rootIndex()) {
   521         bool animate = d->mEnabledAnimations & HbAbstractItemView::Disappear ? d->mAnimateItems: false;
   360         if (d->animationEnabled(false)) {
   522         if (animate) {
       
   523             for (int i = 0; i < d->mItemsAboutToBeDeleted.count(); i++) {
   361             for (int i = 0; i < d->mItemsAboutToBeDeleted.count(); i++) {
   524                 HbEffect::start(d->mItemsAboutToBeDeleted.at(i), 
   362                 QGraphicsItem *item = d->mItemsAboutToBeDeleted.at(i);
       
   363                 HbEffect::cancel(item, "appear");
       
   364 
       
   365                 item->setFlag(QGraphicsItem::ItemSendsGeometryChanges, true);
       
   366                 HbEffect::start(item, 
   525                                 "viewitem", 
   367                                 "viewitem", 
   526                                 "disappear",
   368                                 "disappear",
   527                                 d->mContainer,
   369                                 d->mContainer,
   528                                 "animationFinished");    
   370                                 "animationFinished");  
   529             }
   371             }
   530             d->mItemsAboutToBeDeleted.clear();
   372             d->mItemsAboutToBeDeleted.clear();
   531         }
   373         }
   532         HbAbstractItemView::rowsRemoved(parent, start, end);
   374         HbAbstractItemView::rowsRemoved(parent, start, end);
   533     }
   375     }