ganeswidgets/src/HgContainer.cpp
changeset 13 8bf920201dea
parent 9 dde80bf4a8c7
child 16 0e550c9259fd
equal deleted inserted replaced
9:dde80bf4a8c7 13:8bf920201dea
    61     mLongPressTimer(NULL),
    61     mLongPressTimer(NULL),
    62     mHitItemIndex(-1),
    62     mHitItemIndex(-1),
    63     mItemSizePolicy(HgWidget::ItemSizeAutomatic),
    63     mItemSizePolicy(HgWidget::ItemSizeAutomatic),
    64     mOrientation(Qt::Vertical),
    64     mOrientation(Qt::Vertical),
    65     mDelayedScrollToIndex(),
    65     mDelayedScrollToIndex(),
    66     mIgnoreGestureAction(false)
    66     mIgnoreGestureAction(false),
       
    67     mHandleLongPress(false)
    67 {
    68 {
    68     FUNC_LOG;
    69     FUNC_LOG;
    69 
    70 
    70     setFlag(QGraphicsItem::ItemHasNoContents, false);
    71     setFlag(QGraphicsItem::ItemHasNoContents, false);
    71 
    72 
    94         HgWidgetItem* item = new HgWidgetItem(mQuadRenderer);
    95         HgWidgetItem* item = new HgWidgetItem(mQuadRenderer);
    95         mItems.append(item);
    96         mItems.append(item);
    96     }
    97     }
    97 }
    98 }
    98 
    99 
       
   100 // TODO: This does exactly the same as HgContainer::imageCount(), should this be thus removed?
    99 int HgContainer::itemCount() const
   101 int HgContainer::itemCount() const
   100 {
   102 {
   101     return mItems.count();
   103     return mItems.count();
   102 }
   104 }
   103 
   105 
   391     }
   393     }
   392     // else do nothing
   394     // else do nothing
   393     scrollTo(mSelectionModel->currentIndex());
   395     scrollTo(mSelectionModel->currentIndex());
   394 }
   396 }
   395 
   397 
       
   398 // TODO: This does exactly the same as HgContainer::itemCount(), should this be thus removed?
   396 int HgContainer::imageCount() const
   399 int HgContainer::imageCount() const
   397 {
   400 {
   398     return mItems.count();
   401     return mItems.count();
   399 }
   402 }
   400 
   403 
   414         }
   417         }
   415     }
   418     }
   416     return 0;
   419     return 0;
   417 }
   420 }
   418 
   421 
   419 const HgImage *HgContainer::indicator(int flags) const
   422 const HgImage *HgContainer::indicator(int flags)
   420 {
   423 {
       
   424     if (flags != 0 && (!mMarkImageOff || !mMarkImageOn)) {
       
   425         // indicators haven't been loaded yet.
       
   426         loadIndicatorGraphics();
       
   427     }
       
   428     
   421     if (flags & 1) {
   429     if (flags & 1) {
   422         return mMarkImageOn;
   430         return mMarkImageOn;
   423     }
   431     }
   424     else if (flags & 2) {
   432     else if (flags & 2) {
   425         return mMarkImageOff;
   433         return mMarkImageOff;
   491     if (mDelayedScrollToIndex.isValid()) {
   499     if (mDelayedScrollToIndex.isValid()) {
   492         scrollTo(mDelayedScrollToIndex);
   500         scrollTo(mDelayedScrollToIndex);
   493         // set scrollto index to invalid value.
   501         // set scrollto index to invalid value.
   494         mDelayedScrollToIndex = QModelIndex();
   502         mDelayedScrollToIndex = QModelIndex();
   495     }
   503     }
       
   504     // Indicator size depends from the item size so
       
   505     // indicators need to be updated. Indicators are created
       
   506     // in runtime only for need so if they dont exists they aren't created.
       
   507     loadIndicatorGraphics(true);
   496 }
   508 }
   497 
   509 
   498 // this needs to be implemented for gesture framework to work
   510 // this needs to be implemented for gesture framework to work
   499 void HgContainer::mousePressEvent(QGraphicsSceneMouseEvent *event)
   511 void HgContainer::mousePressEvent(QGraphicsSceneMouseEvent *event)
   500 {
   512 {
   514     bool eventHandled(false);
   526     bool eventHandled(false);
   515     // Event may contain more than one gesture type
   527     // Event may contain more than one gesture type
   516     HbTapGesture *tap = 0;
   528     HbTapGesture *tap = 0;
   517     if (QGesture *gesture = event->gesture(Qt::TapGesture)) {
   529     if (QGesture *gesture = event->gesture(Qt::TapGesture)) {
   518         tap = static_cast<HbTapGesture *>(event->gesture(Qt::TapGesture));
   530         tap = static_cast<HbTapGesture *>(event->gesture(Qt::TapGesture));
   519         if (tap->tapStyleHint() == HbTapGesture::TapAndHold) {
   531         if (mHandleLongPress && tap->tapStyleHint() == HbTapGesture::TapAndHold) {
   520             eventHandled = handleLongTap(tap->state(),
   532             eventHandled = handleLongTap(tap->state(),
   521                     mapFromScene(event->mapToGraphicsScene(tap->hotSpot())));
   533                     mapFromScene(event->mapToGraphicsScene(tap->hotSpot())));
   522         
   534         
   523         } else {
   535         } else {
   524             eventHandled = handleTap(tap->state(),
   536             eventHandled = handleTap(tap->state(),
   545     mRenderer = createRenderer(scrollDirection);
   557     mRenderer = createRenderer(scrollDirection);
   546     mOrientation = scrollDirection;
   558     mOrientation = scrollDirection;
   547 
   559 
   548     mQuadRenderer = mRenderer->getRenderer();
   560     mQuadRenderer = mRenderer->getRenderer();
   549 
   561 
   550     // Fetch icons for marking mode (on and off states).
       
   551 
       
   552     mMarkImageOn = mQuadRenderer->createNativeImage();
       
   553     HANDLE_ERROR_NULL(mMarkImageOn);
       
   554     mMarkImageOff = mQuadRenderer->createNativeImage();
       
   555     HANDLE_ERROR_NULL(mMarkImageOff);
       
   556 
       
   557     // Since there is no way to create the icons directly currently
       
   558     // lets create HbCheckBox and ask primitives from it.
       
   559     HbCheckBox* checkBox = new HbCheckBox();
       
   560     checkBox->setCheckState(Qt::Checked);
       
   561     QGraphicsItem *icon = checkBox->HbWidget::primitive("icon");
       
   562     HbIconItem *iconItem = 0;
       
   563     if (icon) {
       
   564         iconItem = static_cast<HbIconItem*>(icon);    
       
   565         if (mMarkImageOn) {
       
   566             mMarkImageOn->setPixmap(iconItem->icon().pixmap());
       
   567         }
       
   568     }
       
   569     checkBox->setCheckState(Qt::Unchecked);
       
   570     icon = checkBox->HbWidget::primitive("icon");    
       
   571     if (icon) {
       
   572         iconItem = static_cast<HbIconItem*>(icon);
       
   573         if (mMarkImageOff) {
       
   574             mMarkImageOff->setPixmap(iconItem->icon().pixmap());
       
   575         }
       
   576     }    
       
   577     delete checkBox;
       
   578 
       
   579     connect(&mSpring, SIGNAL(updated()), SLOT(updateBySpringPosition()));
   562     connect(&mSpring, SIGNAL(updated()), SLOT(updateBySpringPosition()));
   580     connect(&mSpring, SIGNAL(started()), SIGNAL(scrollingStarted()));
   563     connect(&mSpring, SIGNAL(started()), SIGNAL(scrollingStarted()));
   581     connect(&mSpring, SIGNAL(started()), SLOT(onScrollingStarted()));
   564     connect(&mSpring, SIGNAL(started()), SLOT(onScrollingStarted()));
   582     connect(&mSpring, SIGNAL(ended()), SIGNAL(scrollingEnded()));
   565     connect(&mSpring, SIGNAL(ended()), SIGNAL(scrollingEnded()));
   583     connect(&mSpring, SIGNAL(ended()), SLOT(onScrollingEnded()));
   566     connect(&mSpring, SIGNAL(ended()), SLOT(onScrollingEnded()));
   609 void HgContainer::boundSpring()
   592 void HgContainer::boundSpring()
   610 {
   593 {
   611     FUNC_LOG;
   594     FUNC_LOG;
   612 
   595 
   613     qreal x = mSpring.endPos().x();
   596     qreal x = mSpring.endPos().x();
   614     x = qBound(qreal(0), x, worldWidth());
       
   615     if (mRenderer->coverflowModeEnabled()) {
   597     if (mRenderer->coverflowModeEnabled()) {
   616         qreal i = floorf(x);
   598         qreal i = floorf(x);
   617         x = (x - i > 0.5f) ? ceilf(x) : i;
   599         x = (x - i > 0.5f) ? ceilf(x) : i;
   618         mSpring.animateToPos(QPointF(x, 0));
   600     }
   619     }
   601 
   620 
   602     mSpring.animateToPosAfterPanning(QPointF(x, 0), worldWidth());
   621     mSpring.animateToPos(QPointF(x, 0));
       
   622 
   603 
   623 }
   604 }
   624 
   605 
   625 bool HgContainer::handlePanning(QPanGesture *gesture)
   606 bool HgContainer::handlePanning(QPanGesture *gesture)
   626 {
   607 {
   677     else if (mDragged && gesture->state() == Qt::GestureFinished) {
   658     else if (mDragged && gesture->state() == Qt::GestureFinished) {
   678         mDrag.update(delta, pos, itemSide);
   659         mDrag.update(delta, pos, itemSide);
   679         mDragged = false;
   660         mDragged = false;
   680         qreal newPos(0);
   661         qreal newPos(0);
   681         if (mDrag.finish(pos, mRenderer->coverflowModeEnabled(), newPos)) {
   662         if (mDrag.finish(pos, mRenderer->coverflowModeEnabled(), newPos)) {
   682             mSpring.animateToPos(QPointF(qBound(qreal(0), newPos, worldWidth()), 0));
   663             
       
   664             mSpring.animateToPosAfterPanning(QPointF(newPos, 0), worldWidth());
       
   665             
   683             HgWidgetItem* item = itemByIndex(newPos);
   666             HgWidgetItem* item = itemByIndex(newPos);
   684             if (item && item->modelIndex() != mSelectionModel->currentIndex()) {
   667             if (item && item->modelIndex() != mSelectionModel->currentIndex()) {
   685             //    mSelectionModel->setCurrentIndex(item->modelIndex(), QItemSelectionModel::Current);
   668             //    mSelectionModel->setCurrentIndex(item->modelIndex(), QItemSelectionModel::Current);
   686             }
   669             }
   687         }
   670         }
   705 bool HgContainer::handleTap(Qt::GestureState state, const QPointF &pos)
   688 bool HgContainer::handleTap(Qt::GestureState state, const QPointF &pos)
   706 {
   689 {
   707     FUNC_LOG;
   690     FUNC_LOG;
   708     
   691     
   709     bool handleGesture = false;
   692     bool handleGesture = false;
   710 
   693     
   711     if (hasItemAt(pos)) {
   694     if (hasItemAt(pos)) {
   712         switch (state) 
   695         switch (state) 
   713             {
   696             {
   714             case Qt::GestureStarted:
   697             case Qt::GestureStarted:
   715                 {
   698                 {
   716                 if (mRenderer->coverflowModeEnabled() || !mSpring.isActive()) {
   699                 if (mRenderer->coverflowModeEnabled() || !mSpring.isActive()) {
   717                     mIgnoreGestureAction = false;
   700                     mIgnoreGestureAction = false;
   718                     startLongPressWatcher(pos);
   701 
       
   702                     if (mHandleLongPress) {
       
   703                         if (mRenderer->coverflowModeEnabled()) {
       
   704                             // in coverflow mode we react to longtap only if animation is not on and
       
   705                             // center item is tapped.
       
   706                             int temp = 0;
       
   707                             if (getItemAt(pos,temp)->modelIndex() == mSelectionModel->currentIndex() &&
       
   708                                     !mSpring.isActive()) {
       
   709                                 startLongPressWatcher(pos);
       
   710                             }
       
   711                         } else {
       
   712                             startLongPressWatcher(pos);
       
   713                         }
       
   714                     }
   719                 } else if(mSpring.isActive()) {
   715                 } else if(mSpring.isActive()) {
   720                     mSpring.cancel();
   716                     
       
   717                     int rowCount = mRenderer->getRowCount();
       
   718                     if(rowCount != 0)   //just in case, should not be zero 
       
   719                     {
       
   720                         qreal springPos = mSpring.pos().x();
       
   721                         int gridTotalHeightInImages = ceilf( mItems.count() / rowCount );
       
   722                         qreal currentViewHeightInImages;
       
   723                         if (scrollDirection() == Qt::Horizontal ) {
       
   724                             int rowHeight = mRenderer->getImageSize().width() + mRenderer->getSpacing().width();
       
   725                             currentViewHeightInImages = rect().width() / rowHeight;
       
   726                         } else {
       
   727                             int rowHeight = mRenderer->getImageSize().height() + mRenderer->getSpacing().height();
       
   728                             currentViewHeightInImages = rect().height() / rowHeight;
       
   729                         }
       
   730                         
       
   731                         // If list does not currently fill the whole screen (some theme background behind the list
       
   732                         // is visible), and list is moving, then do not react to tapping.
       
   733                         if( springPos >= 0 
       
   734                             && springPos <= (gridTotalHeightInImages - currentViewHeightInImages) )
       
   735                         {
       
   736                             mSpring.cancel();
       
   737                         }
       
   738                     }
   721                     mIgnoreGestureAction = true;
   739                     mIgnoreGestureAction = true;
   722                 }
   740                 }
   723                 break;
   741                 break;
   724                 }
   742                 }
   725             case Qt::GestureFinished:
   743             case Qt::GestureFinished:
   731                 break;
   749                 break;
   732             }
   750             }
   733         
   751         
   734         handleGesture = true;
   752         handleGesture = true;
   735     } else {
   753     } else {
   736        mIgnoreGestureAction = true;
   754         mIgnoreGestureAction = true;
   737     }    
   755     }    
   738     return handleGesture;
   756     return handleGesture;
   739 }
   757 }
   740 
   758 
   741 bool HgContainer::handleLongTap(Qt::GestureState state, const QPointF &pos)
   759 bool HgContainer::handleLongTap(Qt::GestureState state, const QPointF &pos)
   784     {
   802     {
   785         HgWidgetItem* item = itemByIndex(index);
   803         HgWidgetItem* item = itemByIndex(index);
   786         if (item && action != DoubleTap) {
   804         if (item && action != DoubleTap) {
   787             if (action == LongTap) {
   805             if (action == LongTap) {
   788                 INFO("Long tap:" << item->modelIndex().row());
   806                 INFO("Long tap:" << item->modelIndex().row());
       
   807 
       
   808                 bool currentPressed = item->modelIndex() == mSelectionModel->currentIndex();
   789                 
   809                 
   790                 if (!mRenderer->coverflowModeEnabled()) {
   810                 if (!mRenderer->coverflowModeEnabled()) {
   791                     selectItem(index);
   811                     selectItem(index);
   792                 } else {
   812                 } else {
   793                     mSelectionModel->setCurrentIndex(item->modelIndex(), QItemSelectionModel::Current);
   813                     mSelectionModel->setCurrentIndex(item->modelIndex(), QItemSelectionModel::Current);
       
   814                     mSpring.animateToPos(QPointF(index, 0));
   794                 }
   815                 }
   795 
   816 
   796                 if (!mIgnoreGestureAction) {
   817                 if (!mIgnoreGestureAction) {
   797                     emit longPressed(item->modelIndex(), pos);
   818                     if (mRenderer->coverflowModeEnabled() && mHandleLongPress) {
       
   819                         if( currentPressed && !mSpring.isActive()) {
       
   820                             emit longPressed(item->modelIndex(), pos);
       
   821                         }
       
   822                     } else if (mHandleLongPress){
       
   823                         emit longPressed(item->modelIndex(), pos);
       
   824                     }
   798                 } else {
   825                 } else {
   799                     mSpring.resetVelocity();
   826                     mSpring.resetVelocity();
   800                     update();
   827                     update();
   801                     mIgnoreGestureAction = false;
   828                     mIgnoreGestureAction = false;
   802                 }
   829                 }
  1151     if (mItemSizePolicy == HgWidget::ItemSizeUserDefined)
  1178     if (mItemSizePolicy == HgWidget::ItemSizeUserDefined)
  1152     {
  1179     {
  1153         mRenderer->setImageSize(mUserItemSize);
  1180         mRenderer->setImageSize(mUserItemSize);
  1154         mRenderer->setSpacing(mUserItemSpacing);
  1181         mRenderer->setSpacing(mUserItemSpacing);
  1155     }
  1182     }
       
  1183     // Indicator size depends from the item size so
       
  1184     // indicators need to be updated. Indicators are created
       
  1185     // in runtime only for need so if they dont exists they aren't created.
       
  1186     loadIndicatorGraphics(true);
  1156 }
  1187 }
  1157 
  1188 
  1158 QSizeF HgContainer::getAutoItemSize() const
  1189 QSizeF HgContainer::getAutoItemSize() const
  1159 {
  1190 {
  1160     return mUserItemSize;
  1191     return mUserItemSize;
  1173 qreal HgContainer::scrollPosition() const
  1204 qreal HgContainer::scrollPosition() const
  1174 {
  1205 {
  1175     return mSpring.pos().x();
  1206     return mSpring.pos().x();
  1176 }
  1207 }
  1177 
  1208 
       
  1209 void HgContainer::loadIndicatorGraphics(bool loadIfExists)
       
  1210 {
       
  1211     if (loadIfExists && !mMarkImageOn && !mMarkImageOff) return;
       
  1212     
       
  1213     if (!mMarkImageOn) {
       
  1214         mMarkImageOn = mQuadRenderer->createNativeImage();
       
  1215     }        
       
  1216     HANDLE_ERROR_NULL(mMarkImageOn);
       
  1217     if (!mMarkImageOff) {
       
  1218         mMarkImageOff = mQuadRenderer->createNativeImage();
       
  1219     }
       
  1220     
       
  1221     const QSizeF newIndicatorSize = itemSize()/2;
       
  1222     
       
  1223     // Validate if loading marking icons is really needed by comparing the sizes.
       
  1224     // Both marking icons have the same size so its enough to check one.
       
  1225     if (mMarkImageOn && mMarkImageOn->width() == newIndicatorSize.width() &&
       
  1226             mMarkImageOn->height() == newIndicatorSize.height() ) return;
       
  1227     
       
  1228     HANDLE_ERROR_NULL(mMarkImageOff);    
       
  1229     HbIcon selectedIcon(QLatin1String("qtg_small_selected"));
       
  1230     HbIcon unselectedIcon(QLatin1String("qtg_small_unselected"));
       
  1231     selectedIcon.setSize(newIndicatorSize);
       
  1232     unselectedIcon.setSize(newIndicatorSize);
       
  1233 
       
  1234     QPixmap selectedPixmap = selectedIcon.pixmap();
       
  1235     QPixmap unselectedPixmap = unselectedIcon.pixmap();
       
  1236 
       
  1237     if (!selectedPixmap.isNull() && !unselectedPixmap.isNull()) {
       
  1238         if (mMarkImageOn) {
       
  1239             mMarkImageOn->setPixmap(selectedPixmap);
       
  1240         }
       
  1241         if (mMarkImageOff) {
       
  1242             mMarkImageOff->setPixmap(unselectedPixmap);
       
  1243         }
       
  1244     }    
       
  1245 }
       
  1246 
       
  1247 void HgContainer::setHandleLongPress(bool handheLongPress)
       
  1248 {
       
  1249     // this is just a flag that is used in gesturehandling logic.
       
  1250     mHandleLongPress = handheLongPress;
       
  1251 }
  1178 // EOF
  1252 // EOF