+bool KItemListController::gestureEvent(QGestureEvent* event, const QTransform& transform)
+{
+ if (!m_view) {
+ return false;
+ }
+
+ //you can touch on different views at the same time, but only one QWidget gets a mousePressEvent
+ //we use this to get the right QWidget
+ //the only exception is a tap gesture with state GestureStarted, we need to reset some variable
+ if (!m_mousePress) {
+ if (QGesture* tap = event->gesture(Qt::TapGesture)) {
+ QTapGesture* tapGesture = static_cast<QTapGesture*>(tap);
+ if (tapGesture->state() == Qt::GestureStarted) {
+ tapTriggered(tapGesture, transform);
+ }
+ }
+ return false;
+ }
+
+ bool accepted = false;
+
+ if (QGesture* tap = event->gesture(Qt::TapGesture)) {
+ tapTriggered(static_cast<QTapGesture*>(tap), transform);
+ accepted = true;
+ }
+ if (event->gesture(Qt::TapAndHoldGesture)) {
+ tapAndHoldTriggered(event, transform);
+ accepted = true;
+ }
+ if (event->gesture(Qt::PinchGesture)) {
+ pinchTriggered(event, transform);
+ accepted = true;
+ }
+ if (event->gesture(m_swipeGesture)) {
+ swipeTriggered(event, transform);
+ accepted = true;
+ }
+ if (event->gesture(m_twoFingerTapGesture)) {
+ twoFingerTapTriggered(event, transform);
+ accepted = true;
+ }
+ return accepted;
+}
+
+void KItemListController::tapTriggered(QTapGesture* tap, const QTransform& transform)
+{
+ static bool scrollerWasActive = false;
+
+ if (tap->state() == Qt::GestureStarted) {
+ m_dragActionOrRightClick = false;
+ m_isSwipeGesture = false;
+ m_pinchGestureInProgress = false;
+ m_lastSource = Qt::MouseEventSynthesizedByQt;
+ scrollerWasActive = m_scrollerIsScrolling;
+ }
+
+ if (tap->state() == Qt::GestureFinished) {
+ m_mousePress = false;
+
+ //if at the moment of the gesture start the QScroller was active, the user made the tap
+ //to stop the QScroller and not to tap on an item
+ if (scrollerWasActive) {
+ return;
+ }
+
+ if (m_view->m_tapAndHoldIndicator->isActive()) {
+ m_view->m_tapAndHoldIndicator->setActive(false);
+ }
+
+ m_pressedMousePos = transform.map(tap->position());
+ m_pressedIndex = m_view->itemAt(m_pressedMousePos);
+
+ if (m_dragActionOrRightClick) {
+ onPress(tap->hotSpot().toPoint(), tap->position().toPoint(), Qt::NoModifier, Qt::RightButton);
+ onRelease(transform.map(tap->position()), Qt::NoModifier, Qt::RightButton, false);
+ m_dragActionOrRightClick = false;
+ }
+ else {
+ onPress(tap->hotSpot().toPoint(), tap->position().toPoint(), Qt::NoModifier, Qt::LeftButton);
+ onRelease(transform.map(tap->position()), Qt::NoModifier, Qt::LeftButton, true);
+ }
+ }
+}
+
+void KItemListController::tapAndHoldTriggered(QGestureEvent* event, const QTransform& transform)
+{
+
+ //the Qt TabAndHold gesture is triggerable with a mouse click, we don't want this
+ if (m_lastSource == Qt::MouseEventNotSynthesized) {
+ return;
+ }
+
+ const QTapAndHoldGesture* tap = static_cast<QTapAndHoldGesture*>(event->gesture(Qt::TapAndHoldGesture));
+ if (tap->state() == Qt::GestureFinished) {
+ //if a pinch gesture is in progress we don't want a TabAndHold gesture
+ if (m_pinchGestureInProgress) {
+ return;
+ }
+ m_pressedMousePos = transform.map(event->mapToGraphicsScene(tap->position()));
+ m_pressedIndex = m_view->itemAt(m_pressedMousePos);
+
+ if (m_pressedIndex >= 0 && !m_selectionManager->isSelected(m_pressedIndex)) {
+ m_selectionManager->clearSelection();
+ m_selectionManager->setSelected(m_pressedIndex);
+ } else if (m_pressedIndex == -1) {
+ m_selectionManager->clearSelection();
+ startRubberBand();
+ }
+
+ emit scrollerStop();
+
+ m_view->m_tapAndHoldIndicator->setStartPosition(m_pressedMousePos);
+ m_view->m_tapAndHoldIndicator->setActive(true);
+
+ m_dragActionOrRightClick = true;
+ }
+}
+
+void KItemListController::pinchTriggered(QGestureEvent* event, const QTransform& transform)
+{
+ Q_UNUSED(transform)
+
+ const QPinchGesture* pinch = static_cast<QPinchGesture*>(event->gesture(Qt::PinchGesture));
+ const qreal sensitivityModifier = 0.2;
+ static qreal counter = 0;
+
+ if (pinch->state() == Qt::GestureStarted) {
+ m_pinchGestureInProgress = true;
+ counter = 0;
+ }
+ if (pinch->state() == Qt::GestureUpdated) {
+ //if a swipe gesture was recognized or in progress, we don't want a pinch gesture to change the zoom
+ if (m_isSwipeGesture) {
+ return;
+ }
+ counter = counter + (pinch->scaleFactor() - 1);
+ if (counter >= sensitivityModifier) {
+ emit increaseZoom();
+ counter = 0;
+ } else if (counter <= -sensitivityModifier) {
+ emit decreaseZoom();
+ counter = 0;
+ }
+ }
+}
+
+void KItemListController::swipeTriggered(QGestureEvent* event, const QTransform& transform)
+{
+ Q_UNUSED(transform)
+
+ const KTwoFingerSwipe* swipe = static_cast<KTwoFingerSwipe*>(event->gesture(m_swipeGesture));
+
+ if (!swipe) {
+ return;
+ }
+ if (swipe->state() == Qt::GestureStarted) {
+ m_isSwipeGesture = true;
+ }
+
+ if (swipe->state() == Qt::GestureCanceled) {
+ m_isSwipeGesture = false;
+ }
+
+ if (swipe->state() == Qt::GestureFinished) {
+ emit scrollerStop();
+
+ if (swipe->swipeAngle() <= 20 || swipe->swipeAngle() >= 340) {
+ emit mouseButtonPressed(m_pressedIndex, Qt::BackButton);
+ } else if (swipe->swipeAngle() <= 200 && swipe->swipeAngle() >= 160) {
+ emit mouseButtonPressed(m_pressedIndex, Qt::ForwardButton);
+ } else if (swipe->swipeAngle() <= 110 && swipe->swipeAngle() >= 60) {
+ emit swipeUp();
+ }
+ m_isSwipeGesture = true;
+ }
+}
+
+void KItemListController::twoFingerTapTriggered(QGestureEvent* event, const QTransform& transform)
+{
+ const KTwoFingerTap* twoTap = static_cast<KTwoFingerTap*>(event->gesture(m_twoFingerTapGesture));
+
+ if (!twoTap) {
+ return;
+ }
+
+ if (twoTap->state() == Qt::GestureStarted) {
+ m_pressedMousePos = transform.map(twoTap->pos());
+ m_pressedIndex = m_view->itemAt(m_pressedMousePos);
+ if (m_pressedIndex >= 0) {
+ onPress(twoTap->screenPos().toPoint(), twoTap->pos().toPoint(), Qt::ControlModifier, Qt::LeftButton);
+ onRelease(transform.map(twoTap->pos()), Qt::ControlModifier, Qt::LeftButton, false);
+ }
+
+ }
+}
+