File indexing completed on 2024-05-19 04:21:33

0001 /*
0002 Gwenview: an image viewer
0003 Copyright 2019 Steffen Hartleib <steffenhartleib@t-online.de>
0004 
0005 This program is free software; you can redistribute it and/or
0006 modify it under the terms of the GNU General Public License
0007 as published by the Free Software Foundation; either version 2
0008 of the License, or (at your option) any later version.
0009 
0010 This program is distributed in the hope that it will be useful,
0011 but WITHOUT ANY WARRANTY; without even the implied warranty of
0012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0013 GNU General Public License for more details.
0014 
0015 You should have received a copy of the GNU General Public License
0016 along with this program; if not, write to the Free Software
0017 Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA.
0018 
0019 */
0020 // Self
0021 #include "tapholdandmoving.h"
0022 
0023 // Qt
0024 #include <QGraphicsWidget>
0025 #include <QTouchEvent>
0026 
0027 // KF
0028 
0029 // Local
0030 #include "gwenview_lib_debug.h"
0031 #include "lib/touch/touch_helper.h"
0032 
0033 namespace Gwenview
0034 {
0035 struct TapHoldAndMovingRecognizerPrivate {
0036     TapHoldAndMovingRecognizer *q = nullptr;
0037     bool mTargetIsGrapicsWidget = false;
0038     qint64 mTouchBeginnTimestamp;
0039     bool mTouchPointStationary;
0040     bool mGestureTriggered;
0041     Qt::GestureState mLastGestureState = Qt::NoGesture;
0042 };
0043 
0044 TapHoldAndMovingRecognizer::TapHoldAndMovingRecognizer()
0045     : QGestureRecognizer()
0046     , d(new TapHoldAndMovingRecognizerPrivate)
0047 {
0048     d->q = this;
0049 }
0050 
0051 TapHoldAndMovingRecognizer::~TapHoldAndMovingRecognizer()
0052 {
0053     delete d;
0054 }
0055 
0056 QGesture *TapHoldAndMovingRecognizer::create(QObject *)
0057 {
0058     return static_cast<QGesture *>(new TapHoldAndMoving());
0059 }
0060 
0061 QGestureRecognizer::Result TapHoldAndMovingRecognizer::recognize(QGesture *state, QObject *watched, QEvent *event)
0062 {
0063     // Because of a bug in Qt in a gesture event in a graphicsview, all gestures are trigger twice
0064     // https://bugreports.qt.io/browse/QTBUG-13103
0065     if (qobject_cast<QGraphicsWidget *>(watched))
0066         d->mTargetIsGrapicsWidget = true;
0067     if (d->mTargetIsGrapicsWidget && watched->isWidgetType())
0068         return Ignore;
0069 
0070     switch (event->type()) {
0071     case QEvent::TouchBegin: {
0072         auto touchEvent = static_cast<QTouchEvent *>(event);
0073         d->mTouchBeginnTimestamp = touchEvent->timestamp();
0074         d->mGestureTriggered = false;
0075         d->mTouchPointStationary = true;
0076         state->setHotSpot(touchEvent->touchPoints().first().screenPos());
0077         d->mLastGestureState = Qt::NoGesture;
0078         return MayBeGesture;
0079     }
0080 
0081     case QEvent::TouchUpdate: {
0082         auto touchEvent = static_cast<QTouchEvent *>(event);
0083         const qint64 now = touchEvent->timestamp();
0084         const QPoint pos = touchEvent->touchPoints().first().pos().toPoint();
0085         state->setHotSpot(touchEvent->touchPoints().first().screenPos());
0086 
0087         if (touchEvent->touchPoints().size() >> 1) {
0088             d->mGestureTriggered = false;
0089             d->mLastGestureState = Qt::GestureCanceled;
0090             return CancelGesture;
0091         }
0092 
0093         if (touchEvent->touchPoints().size() == 1 && d->mLastGestureState != Qt::GestureCanceled) {
0094             if (!d->mGestureTriggered && d->mTouchPointStationary && now - d->mTouchBeginnTimestamp >= Touch_Helper::Touch::durationForTapHold) {
0095                 d->mGestureTriggered = true;
0096             }
0097         }
0098         d->mTouchPointStationary = Touch_Helper::touchStationary(event);
0099 
0100         if (d->mGestureTriggered && d->mLastGestureState != Qt::GestureCanceled) {
0101             state->setProperty("pos", pos);
0102             d->mLastGestureState = Qt::GestureStarted;
0103             return TriggerGesture;
0104         }
0105         break;
0106     }
0107 
0108     case QEvent::TouchEnd: {
0109         auto touchEvent = static_cast<QTouchEvent *>(event);
0110         state->setHotSpot(touchEvent->touchPoints().first().screenPos());
0111         if (d->mGestureTriggered) {
0112             d->mLastGestureState = Qt::GestureFinished;
0113             return FinishGesture;
0114         }
0115         break;
0116     }
0117     default:
0118         return Ignore;
0119     }
0120     return Ignore;
0121 }
0122 
0123 TapHoldAndMoving::TapHoldAndMoving(QObject *parent)
0124     : QGesture(parent)
0125 {
0126 }
0127 
0128 } // namespace