ganeswidgets/src/HgContainer.cpp
branchGCC_SURGE
changeset 10 c348b9772569
parent 9 dde80bf4a8c7
child 13 8bf920201dea
equal deleted inserted replaced
4:463f1934e292 10:c348b9772569
    16 */
    16 */
    17 
    17 
    18 #include <QGesture>
    18 #include <QGesture>
    19 #include <QPainter>
    19 #include <QPainter>
    20 #include <QTimer>
    20 #include <QTimer>
    21 #include <hbgridviewitem>
    21 #include <HbMainWindow>
    22 #include <hbmainwindow>
       
    23 #include "hgcontainer.h"
    22 #include "hgcontainer.h"
    24 #include "hgmediawallrenderer.h"
    23 #include "hgmediawallrenderer.h"
    25 #include "hgquad.h"
    24 #include "hgquad.h"
    26 #include "hgvgquadrenderer.h"
    25 #include "hgvgquadrenderer.h"
    27 #include "hgvgimage.h"
    26 #include "hgvgimage.h"
    28 #include "hgwidgetitem.h"
    27 #include "hgwidgetitem.h"
    29 #include "trace.h"
    28 #include "trace.h"
    30 
    29 
    31 //#include <hbstyleoptioncheckbox.h>
    30 #include <HbCheckBox>
    32 //#include <hbcheckbox>
    31 #include <HbGridViewItem>
    33 #include <hbgridviewitem>
    32 #include <HbGridView>
    34 #include <hbgridview>
    33 #include <HbIconItem>
    35 #include <hbiconitem>
    34 #include <QAbstractItemModel>
    36 #include <qabstractitemmodel>
    35 #include <HbTapGesture>
    37 #include "hglongpressvisualizer.h"
    36 #include "hglongpressvisualizer.h"
    38 
    37 
    39 static const qreal KSpringKScrolling(50.0);
    38 static const qreal KSpringKScrolling(50.0);
    40 static const qreal KSpringKScrollBar(10.0);
    39 static const qreal KSpringKScrollBar(10.0);
    41 static const qreal KSpringDampingScrolling(20.0);
    40 static const qreal KSpringDampingScrolling(20.0);
    62     mLongPressTimer(NULL),
    61     mLongPressTimer(NULL),
    63     mHitItemIndex(-1),
    62     mHitItemIndex(-1),
    64     mItemSizePolicy(HgWidget::ItemSizeAutomatic),
    63     mItemSizePolicy(HgWidget::ItemSizeAutomatic),
    65     mOrientation(Qt::Vertical),
    64     mOrientation(Qt::Vertical),
    66     mDelayedScrollToIndex(),
    65     mDelayedScrollToIndex(),
    67     mIgnoreTap(false)
    66     mIgnoreGestureAction(false)
    68 {
    67 {
    69     FUNC_LOG;
    68     FUNC_LOG;
       
    69 
       
    70     setFlag(QGraphicsItem::ItemHasNoContents, false);
    70 
    71 
    71     grabGesture(Qt::PanGesture);
    72     grabGesture(Qt::PanGesture);
    72     grabGesture(Qt::TapGesture);
    73     grabGesture(Qt::TapGesture);
    73     grabGesture(Qt::TapAndHoldGesture);
       
    74 }
    74 }
    75 
    75 
    76 HgContainer::~HgContainer()
    76 HgContainer::~HgContainer()
    77 {
    77 {
    78     FUNC_LOG;
    78     FUNC_LOG;
   132 /*!
   132 /*!
   133     Changes the selection model of the container.
   133     Changes the selection model of the container.
   134     Ownership is not transferred.
   134     Ownership is not transferred.
   135     Widget is redrawn to make new selection visible.
   135     Widget is redrawn to make new selection visible.
   136 */
   136 */
   137 void HgContainer::setSelectionModel(QItemSelectionModel *selectionModel)
   137 void HgContainer::setSelectionModel(QItemSelectionModel *selectionModel, const QModelIndex &defaultItem)
   138 {
   138 {
   139     FUNC_LOG;
   139     FUNC_LOG;
   140     HANDLE_ERROR_NULL(selectionModel); // Parameter is always a valid QItemSelectionModel
   140     HANDLE_ERROR_NULL(selectionModel); // Parameter is always a valid QItemSelectionModel
   141 
   141 
   142     if (mSelectionModel != selectionModel) {
   142     if (mSelectionModel == selectionModel) return;
   143         if (mSelectionModel) { // mSelectionModel is 0 when called first time
   143 
   144             mSelectionModel->disconnect(SIGNAL(currentChanged(QModelIndex,QModelIndex)), this);
   144     bool defaultCurrentSet(false);
   145 
   145 
   146             if (mSelectionModel->currentIndex().isValid() &&
   146     if (!selectionModel->currentIndex().isValid()) { // If there is valid current item, do not change it
   147                 !(selectionModel->currentIndex().isValid())) {
   147         if (!mSelectionModel && defaultItem.isValid()) { // mSelectionModel is 0 when called first time
   148                 selectionModel->setCurrentIndex(mSelectionModel->currentIndex(),
   148             selectionModel->setCurrentIndex(defaultItem, QItemSelectionModel::Current);
   149                     QItemSelectionModel::Current);
   149             defaultCurrentSet = true;
   150             }
   150         }
   151         }
   151         else if (mSelectionModel && mSelectionModel->currentIndex().isValid()) {
   152         mSelectionModel = selectionModel;
   152             selectionModel->setCurrentIndex(mSelectionModel->currentIndex(),
   153         connect(mSelectionModel, SIGNAL(currentChanged(QModelIndex,QModelIndex)),
   153             QItemSelectionModel::Current);
   154                                  SLOT(updateByCurrentIndex(QModelIndex)));
   154         }
       
   155     }
       
   156 
       
   157     mSelectionModel = selectionModel;
       
   158 
       
   159     if (mSelectionModel->currentIndex().isValid() && !defaultCurrentSet) {
       
   160         scrollTo(mSelectionModel->currentIndex());
       
   161     }
       
   162     else {
   155         update();
   163         update();
   156     }
   164     }
   157 }
   165 }
   158 
   166 
   159 /*!
   167 /*!
   217 }
   225 }
   218 
   226 
   219 void HgContainer::setOrientation(Qt::Orientation orientation, bool animate)
   227 void HgContainer::setOrientation(Qt::Orientation orientation, bool animate)
   220 {
   228 {
   221     FUNC_LOG;
   229     FUNC_LOG;
   222     
   230 
   223     mOrientation = orientation;
   231     mOrientation = orientation;
   224     mRenderer->setOrientation(orientation);
   232     mRenderer->setOrientation(orientation);
   225     mRenderer->setScrollDirection(orientation, animate);
   233     mRenderer->setScrollDirection(orientation, animate);
   226     if (!mSpring.isActive() && mSpring.pos().x() > worldWidth())
   234     if (mSpring.isActive()) {
   227         boundSpring();
   235         // Need to stop scrolling.
   228 
   236         mSpring.cancel();
       
   237     }
   229 }
   238 }
   230 
   239 
   231 void HgContainer::scrollToPosition(qreal value, bool animate)
   240 void HgContainer::scrollToPosition(qreal value, bool animate)
   232 {
   241 {
   233     FUNC_LOG;
   242     FUNC_LOG;
   249 }
   258 }
   250 
   259 
   251 void HgContainer::scrollTo(const QModelIndex &index)
   260 void HgContainer::scrollTo(const QModelIndex &index)
   252 {
   261 {
   253     FUNC_LOG;
   262     FUNC_LOG;
       
   263     INFO("Scrolling to" << index);
   254 
   264 
   255     if (index.isValid() && mRenderer->getRowCount() > 0 ) {
   265     if (index.isValid() && mRenderer->getRowCount() > 0 ) {
   256     
   266 
   257         QRectF containerRect(rect());
   267         QRectF containerRect(rect());
   258         if (containerRect.isNull()) {
   268         if (containerRect.isNull()) {
   259             // Container hasn't been resized yet. We need to know the container
   269             // Container hasn't been resized yet. We need to know the container
   260             // size before we can calculate if index we are scrolling to is valid.
   270             // size before we can calculate if index we are scrolling to is valid.
   261             // Store scrollTo index and scrolling is performed when container is resized.
   271             // Store scrollTo index and scrolling is performed when container is resized.
   262             mDelayedScrollToIndex = index;
   272             mDelayedScrollToIndex = index;
   263         }
   273             return;
   264         
   274         }
       
   275 
   265         // Container has some size. We can try to calculate if scrollto index is valid.
   276         // Container has some size. We can try to calculate if scrollto index is valid.
   266         // ScrollTo index will be the top item in grid and left item on coverflow.
   277         // ScrollTo index will be the top item in grid and left item on coverflow.
   267         
   278 
   268         if (!mRenderer->coverflowModeEnabled()) {
   279         if (!mRenderer->coverflowModeEnabled()) {
   269             // Grid case
   280             // Grid case
   270             int itemsOnScreen = 0;
   281             int itemsOnScreen = 0;
   271             if (scrollDirection()== Qt::Vertical) {
   282             if (scrollDirection()== Qt::Vertical) {
   272                 const int rowHeight = mRenderer->getImageSize().height() + mRenderer->getSpacing().height();
   283                 const int rowHeight = mRenderer->getImageSize().height() + mRenderer->getSpacing().height();
   275                     itemsOnScreen++;
   286                     itemsOnScreen++;
   276                 }
   287                 }
   277                 itemsOnScreen *= rowCount();
   288                 itemsOnScreen *= rowCount();
   278                 if (itemsOnScreen + index.row() > mItems.count()) {
   289                 if (itemsOnScreen + index.row() > mItems.count()) {
   279                     int newItem = mItems.count()-itemsOnScreen;
   290                     int newItem = mItems.count()-itemsOnScreen;
   280                     
   291 
   281                     if (mItems.count()%rowCount()) 
   292                     if (mItems.count()%rowCount())
   282                         newItem += rowCount() - (mItems.count()%rowCount());
   293                         newItem += rowCount() - (mItems.count()%rowCount());
   283                     if (newItem < 0) 
   294                     if (newItem < 0)
   284                         newItem = 0;
   295                         newItem = 0;
   285                     
   296 
   286                     scrollToPosition(QPointF(newItem/mRenderer->getRowCount(),0), false);
   297                     scrollToPosition(QPointF(newItem/mRenderer->getRowCount(),0), false);
   287                 } else {
   298                 } else {
   288                     scrollToPosition(QPointF(index.row()/mRenderer->getRowCount(), 0), false);
   299                     scrollToPosition(QPointF(index.row()/mRenderer->getRowCount(), 0), false);
   289                 }
   300                 }
   290             } else {
   301             } else {
   296                 }
   307                 }
   297                 itemsOnScreen *= rowCount();
   308                 itemsOnScreen *= rowCount();
   298                 if (itemsOnScreen + index.row() > mItems.count()) {
   309                 if (itemsOnScreen + index.row() > mItems.count()) {
   299                     int newItem = mItems.count()-itemsOnScreen;
   310                     int newItem = mItems.count()-itemsOnScreen;
   300 
   311 
   301                     if (mItems.count()%rowCount()) 
   312                     if (mItems.count()%rowCount())
   302                         newItem += rowCount() - (mItems.count()%rowCount());
   313                         newItem += rowCount() - (mItems.count()%rowCount());
   303                     if (newItem < 0) newItem = 0;
   314                     if (newItem < 0) newItem = 0;
   304                     
   315 
   305                     scrollToPosition(QPointF(newItem/mRenderer->getRowCount(),0), false);
   316                     scrollToPosition(QPointF(newItem/mRenderer->getRowCount(),0), false);
   306                 } else {
   317                 } else {
   307                     scrollToPosition(QPointF(index.row()/mRenderer->getRowCount(), 0), false);
   318                     scrollToPosition(QPointF(index.row()/mRenderer->getRowCount(), 0), false);
   308                 }
   319                 }
   309             }
   320             }
   310             updateBySpringPosition();            
   321             updateBySpringPosition();
   311         } else {
   322         } else {
   312             // Coverflow case. TODO, this will need some finetuning.
   323             // Coverflow case. TODO, this will need some finetuning.
   313             scrollToPosition(QPointF(index.row()/mRenderer->getRowCount(), 0), false);
   324             scrollToPosition(QPointF(index.row()/mRenderer->getRowCount(), 0), false);
   314             updateBySpringPosition();            
   325             updateBySpringPosition();
   315         }                    
   326         }
   316     }
   327     }
   317 }
   328 }
   318 
   329 
   319 void HgContainer::itemDataChanged(const QModelIndex &firstIndex, const QModelIndex &lastIndex)
   330 void HgContainer::itemDataChanged(const QModelIndex &firstIndex, const QModelIndex &lastIndex)
   320 {
   331 {
   394 
   405 
   395 int HgContainer::flags(int index) const
   406 int HgContainer::flags(int index) const
   396 {
   407 {
   397     if (index >= 0 && index < itemCount()) {
   408     if (index >= 0 && index < itemCount()) {
   398         if (mSelectionMode != HgWidget::NoSelection) {
   409         if (mSelectionMode != HgWidget::NoSelection) {
   399             // TODO, fix these returns values when we can use the checkbox indicators.
       
   400             if (mSelectionModel && mSelectionModel->isSelected(mSelectionModel->model()->index(index, 0))) {
   410             if (mSelectionModel && mSelectionModel->isSelected(mSelectionModel->model()->index(index, 0))) {
   401                 return 1; // TODO: Assign flag to mark indicator
   411                 return 1; // TODO: Assign flag to mark indicator
   402             } else
   412             } else
   403                 return 0;        
   413                 return 2;
   404         }
   414         }
   405     }
   415     }
   406     return 0;
   416     return 0;
   407 }
   417 }
   408 
   418 
   436 
   446 
   437 void HgContainer::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
   447 void HgContainer::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
   438 {
   448 {
   439     Q_UNUSED(option)
   449     Q_UNUSED(option)
   440     Q_UNUSED(widget)
   450     Q_UNUSED(widget)
   441     
   451 
   442     // update spring position at paint if needed, 
   452     // update spring position at paint if needed,
   443     // this is hack for scrollbar, since dragging it 
   453     // this is hack for scrollbar, since dragging it
   444     // causes also paint events in here
   454     // causes also paint events in here
   445     if (mSpring.updatePositionIfNeeded())
   455     if (mSpring.updatePositionIfNeeded())
   446     {
   456     {
   447         qreal pos = mSpring.pos().x();
   457         qreal pos = mSpring.pos().x();
   448         onScrollPositionChanged(pos);
   458         onScrollPositionChanged(pos);
   449         emit scrollPositionChanged(pos, true);        
   459         emit scrollPositionChanged(pos, true);
   450     }
   460     }
   451     
   461 
   452     QPainter::RenderHints hints = painter->renderHints();
   462     QPainter::RenderHints hints = painter->renderHints();
   453     painter->setRenderHint(QPainter::SmoothPixmapTransform, true);
   463     painter->setRenderHint(QPainter::SmoothPixmapTransform, true);
   454     
   464 
   455 
   465 
   456     // interpolate spring velocity towards zero, this is done
   466     // interpolate spring velocity towards zero, this is done
   457     // so that spring velocity for rendering doesn't drop directly to
   467     // so that spring velocity for rendering doesn't drop directly to
   458     // zero when dragging starts
   468     // zero when dragging starts
   459     qreal springVel = mSpring.velocity().x();
   469     qreal springVel = mSpring.velocity().x();
   467     mRenderer->setCameraDistance(getCameraDistance(springVel));
   477     mRenderer->setCameraDistance(getCameraDistance(springVel));
   468     mRenderer->setCameraRotationY(getCameraRotationY(springVel));
   478     mRenderer->setCameraRotationY(getCameraRotationY(springVel));
   469     mRenderer->draw(mSpring.startPos(), mSpring.pos(), mSpring.endPos(),
   479     mRenderer->draw(mSpring.startPos(), mSpring.pos(), mSpring.endPos(),
   470                     springVel, painter, sceneTransform(), rect());
   480                     springVel, painter, sceneTransform(), rect());
   471 
   481 
   472     painter->setRenderHint(QPainter::SmoothPixmapTransform, false);
   482     painter->setRenderHint(QPainter::SmoothPixmapTransform, (hints.testFlag(QPainter::SmoothPixmapTransform)) );
   473 }
   483 }
   474 
   484 
   475 void HgContainer::resizeEvent(QGraphicsSceneResizeEvent *event)
   485 void HgContainer::resizeEvent(QGraphicsSceneResizeEvent *event)
   476 {
   486 {
   477     FUNC_LOG;
   487     FUNC_LOG;
   487 
   497 
   488 // this needs to be implemented for gesture framework to work
   498 // this needs to be implemented for gesture framework to work
   489 void HgContainer::mousePressEvent(QGraphicsSceneMouseEvent *event)
   499 void HgContainer::mousePressEvent(QGraphicsSceneMouseEvent *event)
   490 {
   500 {
   491     Q_UNUSED(event);
   501     Q_UNUSED(event);
   492     if (mSpring.isActive() && !mRenderer->coverflowModeEnabled()) {
       
   493         // We could do some small animation when scrolling is stopped.
       
   494         mSpring.cancel();
       
   495         update();
       
   496         mIgnoreTap = true;
       
   497     } else {
       
   498         mIgnoreTap = false;
       
   499     }
       
   500 }
   502 }
   501 
   503 
   502 void HgContainer::gestureEvent(QGestureEvent *event)
   504 void HgContainer::gestureEvent(QGestureEvent *event)
   503 {
   505 {
   504     FUNC_LOG;
   506     FUNC_LOG;
   505 
   507 
       
   508     if (mItems.count() == 0) {
       
   509         // we have no items so no need to handle the gesture.
       
   510         event->ignore();
       
   511         return;
       
   512     }
       
   513     
   506     bool eventHandled(false);
   514     bool eventHandled(false);
   507     // Event may contain more than one gesture type
   515     // Event may contain more than one gesture type
   508     if (QGesture *gesture = event->gesture(Qt::TapAndHoldGesture)) {
   516     HbTapGesture *tap = 0;
   509         QTapAndHoldGesture *tapAndHold = static_cast<QTapAndHoldGesture *>(gesture);
   517     if (QGesture *gesture = event->gesture(Qt::TapGesture)) {
   510         if (handleLongTap(tapAndHold->state(),
   518         tap = static_cast<HbTapGesture *>(event->gesture(Qt::TapGesture));
   511                 mapFromScene(event->mapToGraphicsScene(tapAndHold->position())))) {
   519         if (tap->tapStyleHint() == HbTapGesture::TapAndHold) {
   512         }
   520             eventHandled = handleLongTap(tap->state(),
   513     }
   521                     mapFromScene(event->mapToGraphicsScene(tap->hotSpot())));
   514     else if (QGesture *gesture = event->gesture(Qt::TapGesture)) {
   522         
   515         // Tap and hold is not working yet in HW, tap gesture is delivered instead
   523         } else {
   516         QTapGesture *tap = static_cast<QTapGesture *>(gesture);
   524             eventHandled = handleTap(tap->state(),
   517         eventHandled = handleTap(tap->state(),
   525                     mapFromScene(event->mapToGraphicsScene(tap->hotSpot())));
   518             mapFromScene(event->mapToGraphicsScene(tap->position())));
   526         }
   519     }
   527     }
   520     else if (QGesture *pan = event->gesture(Qt::PanGesture)) {
   528     if (QGesture *pan = event->gesture(Qt::PanGesture)) {
   521         eventHandled = handlePanning(static_cast<QPanGesture*>(pan));
   529         eventHandled = handlePanning(static_cast<QPanGesture*>(pan));
   522     }
   530     } else if( mIgnoreGestureAction && tap && tap->state() == Qt::GestureCanceled ) {
   523 
   531         // user has tapped or long pressed in grid while scrolling so we need to
   524     if (eventHandled) {
   532         // stop the 3d effect.
   525         event->accept();
   533         mSpring.resetVelocity();
   526         event->accept(Qt::TapAndHoldGesture);
   534         update();
   527         event->accept(Qt::TapGesture);
   535         mIgnoreGestureAction = false;
   528         event->accept(Qt::PanGesture);
   536     }
   529     }
   537 
   530     else {
   538     eventHandled ? event->accept() : event->ignore();    
   531         event->ignore();
       
   532         event->ignore(Qt::TapAndHoldGesture);
       
   533         event->ignore(Qt::TapGesture);
       
   534         event->ignore(Qt::PanGesture);
       
   535     }
       
   536 }
   539 }
   537 
   540 
   538 void HgContainer::init(Qt::Orientation scrollDirection)
   541 void HgContainer::init(Qt::Orientation scrollDirection)
   539 {
   542 {
   540     FUNC_LOG;
   543     FUNC_LOG;
   542     mRenderer = createRenderer(scrollDirection);
   545     mRenderer = createRenderer(scrollDirection);
   543     mOrientation = scrollDirection;
   546     mOrientation = scrollDirection;
   544 
   547 
   545     mQuadRenderer = mRenderer->getRenderer();
   548     mQuadRenderer = mRenderer->getRenderer();
   546 
   549 
   547     QImage markImage(":/images/mark.svg");
   550     // Fetch icons for marking mode (on and off states).
   548     if (markImage.isNull()) {
   551 
   549         ERROR("Failed to load :/images/mark.svg");
       
   550     }
       
   551     mMarkImageOn = mQuadRenderer->createNativeImage();
   552     mMarkImageOn = mQuadRenderer->createNativeImage();
   552     HANDLE_ERROR_NULL(mMarkImageOn);
       
   553     if (mMarkImageOn) {
       
   554         mMarkImageOn->setImage(markImage);
       
   555     }
       
   556     
       
   557 /*    mMarkImageOn = mQuadRenderer->createNativeImage();
       
   558     HANDLE_ERROR_NULL(mMarkImageOn);
   553     HANDLE_ERROR_NULL(mMarkImageOn);
   559     mMarkImageOff = mQuadRenderer->createNativeImage();
   554     mMarkImageOff = mQuadRenderer->createNativeImage();
   560     HANDLE_ERROR_NULL(mMarkImageOff);
   555     HANDLE_ERROR_NULL(mMarkImageOff);
   561     
   556 
   562     // Fetch icons for marking mode (on and off states).
   557     // Since there is no way to create the icons directly currently
   563     QGraphicsItem* checkBox = style()->createPrimitive(HbStyle::P_CheckBox_icon, this); 
   558     // lets create HbCheckBox and ask primitives from it.
   564     HbIconItem* iconItem = static_cast<HbIconItem*>(checkBox);    
   559     HbCheckBox* checkBox = new HbCheckBox();
   565     HbStyleOptionCheckBox checkBoxOption;
   560     checkBox->setCheckState(Qt::Checked);
   566     checkBoxOption.state = QStyle::State_On;
   561     QGraphicsItem *icon = checkBox->HbWidget::primitive("icon");
   567     style()->updatePrimitive(iconItem, HbStyle::P_CheckBox_icon, &checkBoxOption);
   562     HbIconItem *iconItem = 0;
   568     
   563     if (icon) {
   569     if (mMarkImageOn) {
   564         iconItem = static_cast<HbIconItem*>(icon);    
   570         mMarkImageOn->setPixmap(iconItem->icon().pixmap());
   565         if (mMarkImageOn) {
   571     }
   566             mMarkImageOn->setPixmap(iconItem->icon().pixmap());
   572 
   567         }
   573     checkBoxOption.state = QStyle::State_Off;
   568     }
   574     style()->updatePrimitive(iconItem, HbStyle::P_CheckBox_icon, &checkBoxOption);
   569     checkBox->setCheckState(Qt::Unchecked);
   575     if (mMarkImageOff) {
   570     icon = checkBox->HbWidget::primitive("icon");    
   576         mMarkImageOff->setPixmap(iconItem->icon().pixmap());
   571     if (icon) {
   577     }
   572         iconItem = static_cast<HbIconItem*>(icon);
   578 
   573         if (mMarkImageOff) {
       
   574             mMarkImageOff->setPixmap(iconItem->icon().pixmap());
       
   575         }
       
   576     }    
   579     delete checkBox;
   577     delete checkBox;
   580 */    
   578 
   581     connect(&mSpring, SIGNAL(updated()), SLOT(updateBySpringPosition()));
   579     connect(&mSpring, SIGNAL(updated()), SLOT(updateBySpringPosition()));
   582     connect(&mSpring, SIGNAL(started()), SIGNAL(scrollingStarted()));
   580     connect(&mSpring, SIGNAL(started()), SIGNAL(scrollingStarted()));
   583     connect(&mSpring, SIGNAL(started()), SLOT(onScrollingStarted()));
   581     connect(&mSpring, SIGNAL(started()), SLOT(onScrollingStarted()));
   584     connect(&mSpring, SIGNAL(ended()), SIGNAL(scrollingEnded()));
   582     connect(&mSpring, SIGNAL(ended()), SIGNAL(scrollingEnded()));
   585     connect(&mSpring, SIGNAL(ended()), SLOT(onScrollingEnded()));
   583     connect(&mSpring, SIGNAL(ended()), SLOT(onScrollingEnded()));
   663         if (mDragged)
   661         if (mDragged)
   664         {
   662         {
   665             emit scrollingStarted();
   663             emit scrollingStarted();
   666 
   664 
   667             qreal newPosition = mDrag.update(delta, pos, itemSide);
   665             qreal newPosition = mDrag.update(delta, pos, itemSide);
   668             if (qAbs(newPosition - mSpring.pos().x()) > 0.01f)
   666             if (qAbs(newPosition - mSpring.pos().x()) > 0.01f) {
   669             {
       
   670                 mSpring.gotoPos(QPointF(newPosition, 0));
   667                 mSpring.gotoPos(QPointF(newPosition, 0));
   671                 emit scrollPositionChanged(newPosition,true);
   668                 if (mRenderer->coverflowModeEnabled()) {
   672                 update();
   669                     emit scrollPositionChanged(newPosition,true);
       
   670                     update();                
       
   671                 } else {
       
   672                     updateBySpringPosition();
       
   673                 }
   673             }
   674             }
   674         }
   675         }
   675     }
   676     }
   676     else if (mDragged && gesture->state() == Qt::GestureFinished) {
   677     else if (mDragged && gesture->state() == Qt::GestureFinished) {
   677         mDrag.update(delta, pos, itemSide);
   678         mDrag.update(delta, pos, itemSide);
   686         }
   687         }
   687         else {
   688         else {
   688             boundSpring();
   689             boundSpring();
   689         }
   690         }
   690     }
   691     }
       
   692     else if(!mDragged && gesture->state() == Qt::GestureFinished) {
       
   693         if (!mRenderer->coverflowModeEnabled()) {
       
   694             mSpring.resetVelocity();
       
   695             update();
       
   696         }
       
   697     }
   691     else if (gesture->state() == Qt::GestureCanceled) {
   698     else if (gesture->state() == Qt::GestureCanceled) {
   692         boundSpring();
   699         boundSpring();
   693     }
   700     }
   694 
   701 
   695     return true;
   702     return true;
   696 }
   703 }
   697 
   704 
   698 bool HgContainer::handleTap(Qt::GestureState state, const QPointF &pos)
   705 bool HgContainer::handleTap(Qt::GestureState state, const QPointF &pos)
   699 {
   706 {
   700     FUNC_LOG;
   707     FUNC_LOG;
   701 
   708     
   702     if (state == Qt::GestureStarted) {
   709     bool handleGesture = false;
   703         if (hasItemAt(pos)) {
   710 
   704             mTapDuration.start();
   711     if (hasItemAt(pos)) {
   705             startLongPressWatcher(pos);
   712         switch (state) 
   706             return true;
   713             {
   707         }
   714             case Qt::GestureStarted:
   708         return false;
   715                 {
   709     }
   716                 if (mRenderer->coverflowModeEnabled() || !mSpring.isActive()) {
   710     else if (state == Qt::GestureCanceled)
   717                     mIgnoreGestureAction = false;
   711     {
   718                     startLongPressWatcher(pos);
   712         stopLongPressWatcher();
   719                 } else if(mSpring.isActive()) {
   713 
   720                     mSpring.cancel();
   714         if (hasItemAt(pos)) {
   721                     mIgnoreGestureAction = true;
   715             return true;
   722                 }
   716         }
   723                 break;
   717         return false;
   724                 }
   718     }
   725             case Qt::GestureFinished:
   719     else if (state == Qt::GestureFinished) {
   726                 handleGesture = handleItemAction(pos, NormalTap);
   720         stopLongPressWatcher();
   727             case Qt::GestureUpdated:
   721         return handleItemAction(pos, mTapDuration.elapsed() > KLongTapDuration ? LongTap : NormalTap);
   728             case Qt::GestureCanceled:
   722     }
   729             default:
   723 
   730                 stopLongPressWatcher();
   724     return false;
   731                 break;
       
   732             }
       
   733         
       
   734         handleGesture = true;
       
   735     } else {
       
   736        mIgnoreGestureAction = true;
       
   737     }    
       
   738     return handleGesture;
   725 }
   739 }
   726 
   740 
   727 bool HgContainer::handleLongTap(Qt::GestureState state, const QPointF &pos)
   741 bool HgContainer::handleLongTap(Qt::GestureState state, const QPointF &pos)
   728 {
   742 {
   729     FUNC_LOG;
   743     FUNC_LOG;
   730 
   744 
       
   745     bool handleGesture = false;
       
   746     
   731     if (hasItemAt(pos)) {
   747     if (hasItemAt(pos)) {
   732         mAnimateUsingScrollBar = false;
   748 
   733         initSpringForScrolling();
   749         switch (state) 
   734 
   750             {
   735         if (state == Qt::GestureFinished) {
   751             case Qt::GestureUpdated:
   736             handleItemAction(pos, LongTap);
   752                 handleItemAction(pos,LongTap);
   737         }
   753             case Qt::GestureStarted:
   738         return true;
   754             case Qt::GestureCanceled:
   739     }
   755             case Qt::GestureFinished:
   740 
   756             default:
   741     return false;
   757                 stopLongPressWatcher();
       
   758                 break;                
       
   759             }
       
   760         handleGesture = true;
       
   761     } else {
       
   762         mIgnoreGestureAction = true;        
       
   763     }
       
   764 
       
   765     return handleGesture;
   742 }
   766 }
   743 
   767 
   744 /*!
   768 /*!
   745     Handle tap, lang tap and double tap action.
   769     Handle tap, lang tap and double tap action.
   746     Finds out the item in the tap position and sends out suitable signal,
   770     Finds out the item in the tap position and sends out suitable signal,
   761         HgWidgetItem* item = itemByIndex(index);
   785         HgWidgetItem* item = itemByIndex(index);
   762         if (item && action != DoubleTap) {
   786         if (item && action != DoubleTap) {
   763             if (action == LongTap) {
   787             if (action == LongTap) {
   764                 INFO("Long tap:" << item->modelIndex().row());
   788                 INFO("Long tap:" << item->modelIndex().row());
   765                 
   789                 
   766                 mSelectionModel->setCurrentIndex(item->modelIndex(), QItemSelectionModel::Current);
   790                 if (!mRenderer->coverflowModeEnabled()) {
   767                 
       
   768                 if (!mRenderer->coverflowModeEnabled())
       
   769                     selectItem(index);
   791                     selectItem(index);
   770                 
   792                 } else {
   771                 emit longPressed(item->modelIndex(), pos);
   793                     mSelectionModel->setCurrentIndex(item->modelIndex(), QItemSelectionModel::Current);
       
   794                 }
       
   795 
       
   796                 if (!mIgnoreGestureAction) {
       
   797                     emit longPressed(item->modelIndex(), pos);
       
   798                 } else {
       
   799                     mSpring.resetVelocity();
       
   800                     update();
       
   801                     mIgnoreGestureAction = false;
       
   802                 }
   772             }
   803             }
   773             else if (mSelectionMode == HgWidget::MultiSelection) {
   804             else if (mSelectionMode == HgWidget::MultiSelection) {
   774                 mSelectionModel->setCurrentIndex(item->modelIndex(), QItemSelectionModel::Current);
   805                 mSelectionModel->setCurrentIndex(item->modelIndex(), QItemSelectionModel::Current);
   775                 INFO("Select:" << item->modelIndex().row());
   806                 INFO("Select:" << item->modelIndex().row());
   776                 mSelectionModel->select(item->modelIndex(), QItemSelectionModel::Toggle);
   807                 mSelectionModel->select(item->modelIndex(), QItemSelectionModel::Toggle);
   815                     {
   846                     {
   816                         mSpring.animateToPos(QPointF(index, 0));
   847                         mSpring.animateToPos(QPointF(index, 0));
   817                     }
   848                     }
   818                 }
   849                 }
   819                 else {   //grid mode
   850                 else {   //grid mode
   820                     if (!mIgnoreTap) {
   851                     if (!mIgnoreGestureAction) {
   821                         mSelectionModel->setCurrentIndex(item->modelIndex(), QItemSelectionModel::Current);
   852                         // Current should be topleft item.
       
   853 //                        mSelectionModel->setCurrentIndex(item->modelIndex(), QItemSelectionModel::Current);
   822                         selectItem(index);
   854                         selectItem(index);
   823                         emit activated(item->modelIndex());                        
   855                         emit activated(item->modelIndex());                        
       
   856                     } else {
       
   857                         mSpring.resetVelocity();
       
   858                         update();
       
   859                         mIgnoreGestureAction = false;
   824                     }
   860                     }
   825                 }
   861                 }
   826             }
   862             }
   827         }
   863         }
   828 
   864 
   846     QList<HgQuad*> quads = mRenderer->getVisibleQuads();
   882     QList<HgQuad*> quads = mRenderer->getVisibleQuads();
   847     QList<QModelIndex> result;
   883     QList<QModelIndex> result;
   848     for (int i = 0; i < quads.count(); i++) {
   884     for (int i = 0; i < quads.count(); i++) {
   849         bool ok;
   885         bool ok;
   850         int index = quads.at(i)->userData().toInt(&ok);
   886         int index = quads.at(i)->userData().toInt(&ok);
   851         result.append(itemByIndex(index)->modelIndex());
   887         HgWidgetItem *item = itemByIndex(index);
       
   888         if (item)
       
   889             result.append(item->modelIndex());
   852     }
   890     }
   853     qSort(result);
   891     qSort(result);
   854     return result;
   892     return result;
   855 }
   893 }
   856 
   894 
   857 void HgContainer::itemDataChanged(const int &firstIndex, const int &lastIndex)
   895 void HgContainer::itemDataChanged(const int &firstIndex, const int &lastIndex)
   858 {
   896 {
   859     FUNC_LOG;
   897     FUNC_LOG;
   860 
   898     
   861     int firstItemOnScreen = 0, lastItemOnScreen = 0;
   899     int firstItemOnScreen = 0, lastItemOnScreen = 0;
   862     firstItemOnScreen = mSpring.pos().x();
   900     firstItemOnScreen = mSpring.pos().x();
   863     firstItemOnScreen *= rowCount();
   901     firstItemOnScreen *= rowCount();
   864 
   902 
   865     int itemsOnScreen = mRenderer->getVisibleQuads().count();
   903     int itemsOnScreen = mRenderer->getVisibleQuads().count();
   866     lastItemOnScreen = firstItemOnScreen+itemsOnScreen;
   904     lastItemOnScreen = firstItemOnScreen+itemsOnScreen;
   867 
   905 
   868     if ((firstIndex >= firstItemOnScreen && firstIndex < lastItemOnScreen) ||
   906     if ( itemsOnScreen == 0 || (firstIndex >= firstItemOnScreen && firstIndex < lastItemOnScreen) ||
   869         (lastIndex >= firstItemOnScreen && lastIndex < lastItemOnScreen)) {
   907         (lastIndex >= firstItemOnScreen && lastIndex < lastItemOnScreen)) {
   870         update();
   908         update();
   871     }
   909     }    
   872 }
   910 }
   873 
   911 
   874 void HgContainer::selectItem(int index)
   912 void HgContainer::selectItem(int index)
   875 {
   913 {
       
   914     Q_UNUSED(index)
   876     // TODO: replace this with own selection implementation
   915     // TODO: replace this with own selection implementation
   877 /*    if (index < 0 && index >= mItems.count())
   916 /*    if (index < 0 && index >= mItems.count())
   878         return;
   917         return;
   879     
   918     
   880     mHitItemIndex = index;
   919     mHitItemIndex = index;
   964         int frame = 100.0f * qreal(elapsed - 80) / qreal(KLongTapDuration - 80);
  1003         int frame = 100.0f * qreal(elapsed - 80) / qreal(KLongTapDuration - 80);
   965         mLongPressVisualizer->setFrame(frame);
  1004         mLongPressVisualizer->setFrame(frame);
   966     }
  1005     }
   967 }
  1006 }
   968 
  1007 
   969 void HgContainer::updateByCurrentIndex(const QModelIndex &current)
       
   970 {
       
   971     handleCurrentChanged(current);
       
   972 }
       
   973 
       
   974 bool HgContainer::hasItemAt(const QPointF& pos)
  1008 bool HgContainer::hasItemAt(const QPointF& pos)
   975 {
  1009 {
   976     int dummy;
  1010     int dummy;
   977     HgWidgetItem *item = getItemAt(pos, dummy);
  1011     HgWidgetItem *item = getItemAt(pos, dummy);
   978     if (item) {
  1012     if (item) {
  1064 void HgContainer::onScrollingEnded()
  1098 void HgContainer::onScrollingEnded()
  1065 {
  1099 {
  1066     // By default do nothing
  1100     // By default do nothing
  1067 }
  1101 }
  1068 
  1102 
  1069 void HgContainer::handleCurrentChanged(const QModelIndex &current)
       
  1070 {
       
  1071     Q_UNUSED(current)
       
  1072     // By default do nothing
       
  1073 }
       
  1074 
       
  1075 void HgContainer::setDefaultImage(QImage defaultImage)
  1103 void HgContainer::setDefaultImage(QImage defaultImage)
  1076 {
  1104 {
  1077     HgQuadRenderer *renderer = mRenderer->getRenderer();
  1105     HgQuadRenderer *renderer = mRenderer->getRenderer();
  1078     if (renderer) {
  1106     if (renderer) {
  1079         QImage scaled = defaultImage.scaled(mRenderer->getImageSize().toSize());
  1107         QImage scaled = defaultImage.scaled(mRenderer->getImageSize().toSize());
  1145 qreal HgContainer::scrollPosition() const
  1173 qreal HgContainer::scrollPosition() const
  1146 {
  1174 {
  1147     return mSpring.pos().x();
  1175     return mSpring.pos().x();
  1148 }
  1176 }
  1149 
  1177 
       
  1178 // EOF