summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDenis Dzyubenko <denis.dzyubenko@nokia.com>2009-11-03 10:56:11 (GMT)
committerDenis Dzyubenko <denis.dzyubenko@nokia.com>2009-11-05 11:54:39 (GMT)
commit70c1c87a3df52e510413c3e8512d9e55df00e7bd (patch)
tree317c16985488478830bce6a508afa690662ba7a3
parentee88b2d8408396188eb2ce52d740c395c6cd4656 (diff)
downloadQt-70c1c87a3df52e510413c3e8512d9e55df00e7bd.zip
Qt-70c1c87a3df52e510413c3e8512d9e55df00e7bd.tar.gz
Qt-70c1c87a3df52e510413c3e8512d9e55df00e7bd.tar.bz2
Implemented QSwipeGesture recognizer using touch events.
Reviewed-by: Bradley T. Hughes
-rw-r--r--examples/gestures/imagegestures/imagewidget.cpp18
-rw-r--r--src/gui/kernel/qgesture_p.h8
-rw-r--r--src/gui/kernel/qgesturemanager.cpp1
-rw-r--r--src/gui/kernel/qstandardgestures.cpp153
-rw-r--r--src/gui/kernel/qstandardgestures_p.h9
5 files changed, 176 insertions, 13 deletions
diff --git a/examples/gestures/imagegestures/imagewidget.cpp b/examples/gestures/imagegestures/imagewidget.cpp
index df8f56d..96400c4 100644
--- a/examples/gestures/imagegestures/imagewidget.cpp
+++ b/examples/gestures/imagegestures/imagewidget.cpp
@@ -103,12 +103,12 @@ void ImageWidget::mouseDoubleClickEvent(QMouseEvent *)
//! [gesture event handler]
bool ImageWidget::gestureEvent(QGestureEvent *event)
{
- if (QGesture *pan = event->gesture(Qt::PanGesture))
+ if (QGesture *swipe = event->gesture(Qt::SwipeGesture))
+ swipeTriggered(static_cast<QSwipeGesture *>(swipe));
+ else if (QGesture *pan = event->gesture(Qt::PanGesture))
panTriggered(static_cast<QPanGesture *>(pan));
if (QGesture *pinch = event->gesture(Qt::PinchGesture))
pinchTriggered(static_cast<QPinchGesture *>(pinch));
- if (QGesture *swipe = event->gesture(Qt::SwipeGesture))
- swipeTriggered(static_cast<QSwipeGesture *>(swipe));
return true;
}
//! [gesture event handler]
@@ -154,12 +154,14 @@ void ImageWidget::pinchTriggered(QPinchGesture *gesture)
//! [swipe function]
void ImageWidget::swipeTriggered(QSwipeGesture *gesture)
{
- if (gesture->horizontalDirection() == QSwipeGesture::Left
+ if (gesture->state() == Qt::GestureFinished) {
+ if (gesture->horizontalDirection() == QSwipeGesture::Left
|| gesture->verticalDirection() == QSwipeGesture::Up)
- goPrevImage();
- else
- goNextImage();
- update();
+ goPrevImage();
+ else
+ goNextImage();
+ update();
+ }
}
//! [swipe function]
diff --git a/src/gui/kernel/qgesture_p.h b/src/gui/kernel/qgesture_p.h
index ae2e287..a571bdb 100644
--- a/src/gui/kernel/qgesture_p.h
+++ b/src/gui/kernel/qgesture_p.h
@@ -136,13 +136,19 @@ public:
QSwipeGesturePrivate()
: horizontalDirection(QSwipeGesture::NoDirection),
verticalDirection(QSwipeGesture::NoDirection),
- swipeAngle(0)
+ swipeAngle(0),
+ started(false), speed(0)
{
}
QSwipeGesture::SwipeDirection horizontalDirection;
QSwipeGesture::SwipeDirection verticalDirection;
qreal swipeAngle;
+
+ QPoint lastPositions[3];
+ bool started;
+ qreal speed;
+ QTime time;
};
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qgesturemanager.cpp b/src/gui/kernel/qgesturemanager.cpp
index 628892d..662a64b 100644
--- a/src/gui/kernel/qgesturemanager.cpp
+++ b/src/gui/kernel/qgesturemanager.cpp
@@ -90,6 +90,7 @@ QGestureManager::QGestureManager(QObject *parent)
#else
registerGestureRecognizer(new QPanGestureRecognizer);
registerGestureRecognizer(new QPinchGestureRecognizer);
+ registerGestureRecognizer(new QSwipeGestureRecognizer);
#if defined(Q_OS_WIN)
registerGestureRecognizer(new QWinNativePanGestureRecognizer);
#endif
diff --git a/src/gui/kernel/qstandardgestures.cpp b/src/gui/kernel/qstandardgestures.cpp
index dfd49eb..79346ed 100644
--- a/src/gui/kernel/qstandardgestures.cpp
+++ b/src/gui/kernel/qstandardgestures.cpp
@@ -45,6 +45,7 @@
#include "qevent.h"
#include "qwidget.h"
#include "qabstractscrollarea.h"
+#include "qdebug.h"
QT_BEGIN_NAMESPACE
@@ -66,7 +67,9 @@ QGesture *QPanGestureRecognizer::create(QObject *target)
return new QPanGesture;
}
-QGestureRecognizer::Result QPanGestureRecognizer::recognize(QGesture *state, QObject *, QEvent *event)
+QGestureRecognizer::Result QPanGestureRecognizer::recognize(QGesture *state,
+ QObject *,
+ QEvent *event)
{
QPanGesture *q = static_cast<QPanGesture *>(state);
QPanGesturePrivate *d = q->d_func();
@@ -155,7 +158,9 @@ QGesture *QPinchGestureRecognizer::create(QObject *target)
return new QPinchGesture;
}
-QGestureRecognizer::Result QPinchGestureRecognizer::recognize(QGesture *state, QObject *, QEvent *event)
+QGestureRecognizer::Result QPinchGestureRecognizer::recognize(QGesture *state,
+ QObject *,
+ QEvent *event)
{
QPinchGesture *q = static_cast<QPinchGesture *>(state);
QPinchGesturePrivate *d = q->d_func();
@@ -199,8 +204,9 @@ QGestureRecognizer::Result QPinchGestureRecognizer::recognize(QGesture *state, Q
d->centerPoint = centerPoint;
d->changeFlags |= QPinchGesture::CenterPointChanged;
- const qreal scaleFactor = QLineF(p1.pos(), p2.pos()).length()
- / QLineF(d->startPosition[0], d->startPosition[1]).length();
+ const qreal scaleFactor =
+ QLineF(p1.pos(), p2.pos()).length()
+ / QLineF(d->startPosition[0], d->startPosition[1]).length();
if (d->isNewSequence) {
d->lastScaleFactor = scaleFactor;
} else {
@@ -256,4 +262,143 @@ void QPinchGestureRecognizer::reset(QGesture *state)
QGestureRecognizer::reset(state);
}
+//
+// QSwipeGestureRecognizer
+//
+
+QSwipeGestureRecognizer::QSwipeGestureRecognizer()
+{
+}
+
+QGesture *QSwipeGestureRecognizer::create(QObject *target)
+{
+ if (target && target->isWidgetType()) {
+ static_cast<QWidget *>(target)->setAttribute(Qt::WA_AcceptTouchEvents);
+ }
+ return new QSwipeGesture;
+}
+
+QGestureRecognizer::Result QSwipeGestureRecognizer::recognize(QGesture *state,
+ QObject *,
+ QEvent *event)
+{
+ QSwipeGesture *q = static_cast<QSwipeGesture *>(state);
+ QSwipeGesturePrivate *d = q->d_func();
+
+ const QTouchEvent *ev = static_cast<const QTouchEvent *>(event);
+
+ QGestureRecognizer::Result result;
+
+ switch (event->type()) {
+ case QEvent::TouchBegin: {
+ d->speed = 1;
+ d->time = QTime::currentTime();
+ d->started = true;
+ result = QGestureRecognizer::MayBeGesture;
+ break;
+ }
+ case QEvent::TouchEnd: {
+ if (q->state() != Qt::NoGesture) {
+ result = QGestureRecognizer::FinishGesture;
+ } else {
+ result = QGestureRecognizer::CancelGesture;
+ }
+ break;
+ }
+ case QEvent::TouchUpdate: {
+ if (!d->started)
+ result = QGestureRecognizer::CancelGesture;
+ else if (ev->touchPoints().size() == 3) {
+ QTouchEvent::TouchPoint p1 = ev->touchPoints().at(0);
+ QTouchEvent::TouchPoint p2 = ev->touchPoints().at(1);
+ QTouchEvent::TouchPoint p3 = ev->touchPoints().at(2);
+
+ if (d->lastPositions[0].isNull()) {
+ d->lastPositions[0] = p1.startScreenPos().toPoint();
+ d->lastPositions[1] = p2.startScreenPos().toPoint();
+ d->lastPositions[2] = p3.startScreenPos().toPoint();
+ }
+ d->hotSpot = p1.screenPos();
+ d->isHotSpotSet = true;
+
+ int xDistance = (p1.screenPos().x() - d->lastPositions[0].x() +
+ p2.screenPos().x() - d->lastPositions[1].x() +
+ p3.screenPos().x() - d->lastPositions[2].x()) / 3;
+ int yDistance = (p1.screenPos().y() - d->lastPositions[0].y() +
+ p2.screenPos().y() - d->lastPositions[1].y() +
+ p3.screenPos().y() - d->lastPositions[2].y()) / 3;
+
+ const int distance = xDistance >= yDistance ? xDistance : yDistance;
+ int elapsedTime = d->time.msecsTo(QTime::currentTime());
+ if (!elapsedTime)
+ elapsedTime = 1;
+ d->speed = 0.9 * d->speed + distance / elapsedTime;
+ d->time = QTime::currentTime();
+ d->swipeAngle = QLineF(p1.startScreenPos(), p1.screenPos()).angle();
+
+ static const int MoveThreshold = 50;
+ if (xDistance > MoveThreshold || yDistance > MoveThreshold) {
+ // measure the distance to check if the direction changed
+ d->lastPositions[0] = p1.screenPos().toPoint();
+ d->lastPositions[1] = p2.screenPos().toPoint();
+ d->lastPositions[2] = p3.screenPos().toPoint();
+ QSwipeGesture::SwipeDirection horizontal =
+ xDistance > 0 ? QSwipeGesture::Right : QSwipeGesture::Left;
+ QSwipeGesture::SwipeDirection vertical =
+ yDistance > 0 ? QSwipeGesture::Down : QSwipeGesture::Up;
+ if (d->verticalDirection == QSwipeGesture::NoDirection)
+ d->verticalDirection = vertical;
+ if (d->horizontalDirection == QSwipeGesture::NoDirection)
+ d->horizontalDirection = horizontal;
+ if (d->verticalDirection != vertical || d->horizontalDirection != horizontal) {
+ // the user has changed the direction!
+ result = QGestureRecognizer::CancelGesture;
+ }
+ result = QGestureRecognizer::TriggerGesture;
+ } else {
+ if (q->state() != Qt::NoGesture)
+ result = QGestureRecognizer::TriggerGesture;
+ else
+ result = QGestureRecognizer::MayBeGesture;
+ }
+ } else if (ev->touchPoints().size() > 3) {
+ result = QGestureRecognizer::CancelGesture;
+ } else { // less than 3 touch points
+ if (d->started && (ev->touchPointStates() & Qt::TouchPointPressed))
+ result = QGestureRecognizer::CancelGesture;
+ else if (d->started)
+ result = QGestureRecognizer::Ignore;
+ else
+ result = QGestureRecognizer::MayBeGesture;
+ }
+ break;
+ }
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseMove:
+ case QEvent::MouseButtonRelease:
+ result = QGestureRecognizer::Ignore;
+ break;
+ default:
+ result = QGestureRecognizer::Ignore;
+ break;
+ }
+ return result;
+}
+
+void QSwipeGestureRecognizer::reset(QGesture *state)
+{
+ QSwipeGesture *q = static_cast<QSwipeGesture *>(state);
+ QSwipeGesturePrivate *d = q->d_func();
+
+ d->verticalDirection = d->horizontalDirection = QSwipeGesture::NoDirection;
+ d->swipeAngle = 0;
+
+ d->lastPositions[0] = d->lastPositions[1] = d->lastPositions[2] = QPoint();
+ d->started = false;
+ d->speed = 0;
+ d->time = QTime();
+
+ QGestureRecognizer::reset(state);
+}
+
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qstandardgestures_p.h b/src/gui/kernel/qstandardgestures_p.h
index e6f346c..90f995d 100644
--- a/src/gui/kernel/qstandardgestures_p.h
+++ b/src/gui/kernel/qstandardgestures_p.h
@@ -74,7 +74,16 @@ public:
QPinchGestureRecognizer();
QGesture *create(QObject *target);
+ QGestureRecognizer::Result recognize(QGesture *state, QObject *watched, QEvent *event);
+ void reset(QGesture *state);
+};
+class QSwipeGestureRecognizer : public QGestureRecognizer
+{
+public:
+ QSwipeGestureRecognizer();
+
+ QGesture *create(QObject *target);
QGestureRecognizer::Result recognize(QGesture *state, QObject *watched, QEvent *event);
void reset(QGesture *state);
};