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 |
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: |
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 |