File indexing completed on 2024-05-12 04:19:51

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 "oneandtwofingerswipe.h"
0022 
0023 // STL
0024 #include <cmath>
0025 
0026 // Qt
0027 #include <QGraphicsWidget>
0028 #include <QTouchEvent>
0029 
0030 // KF
0031 
0032 // Local
0033 #include "gwenview_lib_debug.h"
0034 #include "lib/touch/touch_helper.h"
0035 
0036 namespace Gwenview
0037 {
0038 struct OneAndTwoFingerSwipeRecognizerPrivate {
0039     OneAndTwoFingerSwipeRecognizer *q = nullptr;
0040     bool mTargetIsGrapicsWidget = false;
0041     qint64 mTouchBeginnTimestamp;
0042     bool mGestureAlreadyTriggered;
0043 };
0044 
0045 OneAndTwoFingerSwipeRecognizer::OneAndTwoFingerSwipeRecognizer()
0046     : QGestureRecognizer()
0047     , d(new OneAndTwoFingerSwipeRecognizerPrivate)
0048 {
0049     d->q = this;
0050 }
0051 
0052 OneAndTwoFingerSwipeRecognizer::~OneAndTwoFingerSwipeRecognizer()
0053 {
0054     delete d;
0055 }
0056 
0057 QGesture *OneAndTwoFingerSwipeRecognizer::create(QObject *)
0058 {
0059     return static_cast<QGesture *>(new OneAndTwoFingerSwipe());
0060 }
0061 
0062 QGestureRecognizer::Result OneAndTwoFingerSwipeRecognizer::recognize(QGesture *state, QObject *watched, QEvent *event)
0063 {
0064     // Because of a bug in Qt in a gesture event in a graphicsview, all gestures are trigger twice
0065     // https://bugreports.qt.io/browse/QTBUG-13103
0066     if (qobject_cast<QGraphicsWidget *>(watched))
0067         d->mTargetIsGrapicsWidget = true;
0068     if (d->mTargetIsGrapicsWidget && watched->isWidgetType())
0069         return Ignore;
0070 
0071     switch (event->type()) {
0072     case QEvent::TouchBegin: {
0073         auto touchEvent = static_cast<QTouchEvent *>(event);
0074         d->mTouchBeginnTimestamp = touchEvent->timestamp();
0075         d->mGestureAlreadyTriggered = false;
0076         state->setHotSpot(touchEvent->touchPoints().first().screenPos());
0077         return MayBeGesture;
0078     }
0079 
0080     case QEvent::TouchUpdate: {
0081         auto touchEvent = static_cast<QTouchEvent *>(event);
0082         const qint64 now = touchEvent->timestamp();
0083         const QPointF distance = touchEvent->touchPoints().first().startPos() - touchEvent->touchPoints().first().pos();
0084         state->setHotSpot(touchEvent->touchPoints().first().screenPos());
0085 
0086         if (touchEvent->touchPoints().size() >> 2) {
0087             d->mGestureAlreadyTriggered = false;
0088             return CancelGesture;
0089         }
0090 
0091         if (distance.manhattanLength() >= Touch_Helper::Touch::minDistanceForSwipe
0092             && (now - d->mTouchBeginnTimestamp) <= Touch_Helper::Touch::maxTimeFrameForSwipe && !d->mGestureAlreadyTriggered) {
0093             if (distance.x() < 0 && abs(distance.x()) >= abs(distance.y()) * 2) {
0094                 state->setProperty("right", true);
0095                 state->setProperty("left", false);
0096                 d->mGestureAlreadyTriggered = true;
0097                 return FinishGesture;
0098             }
0099             if (distance.x() > 0 && abs(distance.x()) >= abs(distance.y()) * 2) {
0100                 state->setProperty("right", false);
0101                 state->setProperty("left", true);
0102                 d->mGestureAlreadyTriggered = true;
0103                 return FinishGesture;
0104             }
0105             if ((now - d->mTouchBeginnTimestamp) <= Touch_Helper::Touch::maxTimeFrameForSwipe && !d->mGestureAlreadyTriggered) {
0106                 return MayBeGesture;
0107             } else {
0108                 d->mGestureAlreadyTriggered = false;
0109                 return CancelGesture;
0110             }
0111         }
0112         break;
0113     }
0114 
0115     default:
0116         return Ignore;
0117     }
0118     return Ignore;
0119 }
0120 
0121 OneAndTwoFingerSwipe::OneAndTwoFingerSwipe(QObject *parent)
0122     : QGesture(parent)
0123 {
0124 }
0125 
0126 } // namespace