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 { |
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); |
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; |