diff options
author | Thomas Zander <t.zander@nokia.com> | 2009-10-27 14:31:16 (GMT) |
---|---|---|
committer | Thomas Zander <thomas.zander@trolltech.com> | 2009-10-28 11:37:04 (GMT) |
commit | 4470801f73b86d3ee06a866fbbdafcaeb9f294a6 (patch) | |
tree | 0b587d391267b55b369c7c7439a7033bab087918 /src/gui | |
parent | 9a9cd7765bfe879b53488fe18bba75425e4c5c61 (diff) | |
download | Qt-4470801f73b86d3ee06a866fbbdafcaeb9f294a6.zip Qt-4470801f73b86d3ee06a866fbbdafcaeb9f294a6.tar.gz Qt-4470801f73b86d3ee06a866fbbdafcaeb9f294a6.tar.bz2 |
Introduce QGesture::GestureCancelPolicy, a way to auto-cancel gestures
On accepting one gesture Qt can automatically cancel other gestures
that belong to other targets. The policy is normally set to not cancel
any other gestures and can be set to cancel all active gestures in the
context. For example for all child widgets.
Reviewed-By: Denis Dzyubenko
Diffstat (limited to 'src/gui')
-rw-r--r-- | src/gui/kernel/qgesture.cpp | 33 | ||||
-rw-r--r-- | src/gui/kernel/qgesture.h | 10 | ||||
-rw-r--r-- | src/gui/kernel/qgesture_p.h | 10 | ||||
-rw-r--r-- | src/gui/kernel/qgesturemanager.cpp | 85 | ||||
-rw-r--r-- | src/gui/kernel/qgesturemanager_p.h | 2 |
5 files changed, 133 insertions, 7 deletions
diff --git a/src/gui/kernel/qgesture.cpp b/src/gui/kernel/qgesture.cpp index a161876..c302c51 100644 --- a/src/gui/kernel/qgesture.cpp +++ b/src/gui/kernel/qgesture.cpp @@ -175,6 +175,29 @@ void QGesture::unsetHotSpot() } /*! + \enum QGesture::GestureCancelPolicy + + This enum describes how accepting a gesture can cancel other gestures + automatically. + + \value CancelNone On accepting this gesture no other gestures will be affected. + \value CancelAllInContext On accepting this gesture all gestures that are active + in the context (Qt::GestureContext) will be cancelled. +*/ + +void QGesture::setGestureCancelPolicy(GestureCancelPolicy policy) +{ + Q_D(QGesture); + d->gestureCancelPolicy = static_cast<uint>(policy); +} + +QGesture::GestureCancelPolicy QGesture::gestureCancelPolicy() const +{ + Q_D(const QGesture); + return static_cast<GestureCancelPolicy>(d->gestureCancelPolicy); +} + +/*! \class QPanGesture \since 4.6 \brief The QPanGesture class describes a panning gesture made by the user. @@ -195,6 +218,16 @@ void QGesture::unsetHotSpot() */ /*! + \property QGesture::GestureCancelPolicy + \brief the policy for deciding what happens on accepting a gesture + + On accepting one gesture Qt can automatically cancel other gestures + that belong to other targets. The policy is normally set to not cancel + any other gestures and can be set to cancel all active gestures in the + context. For example for all child widgets. +*/ + +/*! \property QPanGesture::lastOffset \brief the last offset recorded for this gesture diff --git a/src/gui/kernel/qgesture.h b/src/gui/kernel/qgesture.h index 6469959..524d26e 100644 --- a/src/gui/kernel/qgesture.h +++ b/src/gui/kernel/qgesture.h @@ -65,6 +65,7 @@ class Q_GUI_EXPORT QGesture : public QObject Q_PROPERTY(Qt::GestureState state READ state) Q_PROPERTY(Qt::GestureType gestureType READ gestureType) + Q_PROPERTY(QGesture::GestureCancelPolicy gestureCancelPolicy READ gestureCancelPolicy WRITE setGestureCancelPolicy) Q_PROPERTY(QPointF hotSpot READ hotSpot WRITE setHotSpot RESET unsetHotSpot) Q_PROPERTY(bool hasHotSpot READ hasHotSpot) @@ -81,6 +82,14 @@ public: bool hasHotSpot() const; void unsetHotSpot(); + enum GestureCancelPolicy { + CancelNone = 0, + CancelAllInContext + }; + + void setGestureCancelPolicy(GestureCancelPolicy policy); + GestureCancelPolicy gestureCancelPolicy() const; + protected: QGesture(QGesturePrivate &dd, QObject *parent); @@ -208,6 +217,7 @@ public: QT_END_NAMESPACE +Q_DECLARE_METATYPE(QGesture::GestureCancelPolicy) QT_END_HEADER #endif // QGESTURE_H diff --git a/src/gui/kernel/qgesture_p.h b/src/gui/kernel/qgesture_p.h index 975c0c9..d2ef8a7 100644 --- a/src/gui/kernel/qgesture_p.h +++ b/src/gui/kernel/qgesture_p.h @@ -67,16 +67,20 @@ class QGesturePrivate : public QObjectPrivate public: QGesturePrivate() - : gestureType(Qt::CustomGesture), state(Qt::NoGesture), isHotSpotSet(false), - targetObject(0) + : gestureType(Qt::CustomGesture), state(Qt::NoGesture), + targetObject(0), + isHotSpotSet(false), + gestureCancelPolicy(0) + { } Qt::GestureType gestureType; Qt::GestureState state; QPointF hotSpot; - bool isHotSpotSet; QObject *targetObject; + uint isHotSpotSet : 1; + uint gestureCancelPolicy : 2; }; class QPanGesturePrivate : public QGesturePrivate diff --git a/src/gui/kernel/qgesturemanager.cpp b/src/gui/kernel/qgesturemanager.cpp index 52f8eef..fc7c8b2 100644 --- a/src/gui/kernel/qgesturemanager.cpp +++ b/src/gui/kernel/qgesturemanager.cpp @@ -322,21 +322,96 @@ bool QGestureManager::filterEventThroughContexts(const QMap<QObject *, deliverEvents(startedGestures+triggeredGestures+finishedGestures+canceledGestures, &undeliveredGestures); + foreach (QGesture *g, startedGestures) { + if (undeliveredGestures.contains(g)) + continue; + if (g->gestureCancelPolicy() == QGesture::CancelAllInContext) { + DEBUG() << "lets try to cancel some"; + // find gestures in context in Qt::GestureStarted or Qt::GestureUpdated state and cancel them + cancelGesturesForChildren(g); + } + } + activeGestures -= undeliveredGestures; // reset gestures that ended QSet<QGesture *> endedGestures = finishedGestures + canceledGestures + undeliveredGestures; foreach (QGesture *gesture, endedGestures) { - if (QGestureRecognizer *recognizer = gestureToRecognizer.value(gesture, 0)) + if (QGestureRecognizer *recognizer = gestureToRecognizer.value(gesture, 0)) { + gesture->setGestureCancelPolicy(QGesture::CancelNone); recognizer->reset(gesture); - else + } else { cleanupGesturesForRemovedRecognizer(gesture); + } gestureTargets.remove(gesture); } return ret; } +// Cancel all gestures of children of the widget that original is associated with +void QGestureManager::cancelGesturesForChildren(QGesture *original) +{ + Q_ASSERT(original); + QWidget *originatingWidget = gestureTargets.value(original); + Q_ASSERT(originatingWidget); + + // iterate over all active gestures and all maybe gestures + // for each find the owner + // if the owner is part of our sub-hierarchy, cancel it. + + QSet<QGesture*> cancelledGestures; + QSet<QGesture*>::Iterator iter = activeGestures.begin(); + while (iter != activeGestures.end()) { + QWidget *widget = gestureTargets.value(*iter); + // note that we don't touch the gestures for our originatingWidget + if (widget != originatingWidget && originatingWidget->isAncestorOf(widget)) { + DEBUG() << " found a gesture to cancel" << (*iter); + (*iter)->d_func()->state = Qt::GestureCanceled; + cancelledGestures << *iter; + iter = activeGestures.erase(iter); + } else { + ++iter; + } + } + + // TODO handle 'maybe' gestures too + + // sort them per target widget by cherry picking from almostCanceledGestures and delivering + QSet<QGesture *> almostCanceledGestures = cancelledGestures; + while (!almostCanceledGestures.isEmpty()) { + QWidget *target = 0; + QSet<QGesture*> gestures; + iter = almostCanceledGestures.begin(); + // sort per target widget + while (iter != almostCanceledGestures.end()) { + QWidget *widget = gestureTargets.value(*iter); + if (target == 0) + target = widget; + if (target == widget) { + gestures << *iter; + iter = almostCanceledGestures.erase(iter); + } else { + ++iter; + } + } + Q_ASSERT(target); + + QSet<QGesture*> undeliveredGestures; + deliverEvents(gestures, &undeliveredGestures); + } + + for (iter = cancelledGestures.begin(); iter != cancelledGestures.end(); ++iter) { + QGestureRecognizer *recognizer = gestureToRecognizer.value(*iter, 0); + if (recognizer) { + (*iter)->setGestureCancelPolicy(QGesture::CancelNone); + recognizer->reset(*iter); + } else { + cleanupGesturesForRemovedRecognizer(*iter); + } + } +} + void QGestureManager::cleanupGesturesForRemovedRecognizer(QGesture *gesture) { QGestureRecognizer *recognizer = m_deletedRecognizers.value(gesture); @@ -585,10 +660,12 @@ void QGestureManager::timerEvent(QTimerEvent *event) DEBUG() << "QGestureManager::timerEvent: gesture stopped due to timeout:" << gesture; QGestureRecognizer *recognizer = gestureToRecognizer.value(gesture, 0); - if (recognizer) + if (recognizer) { + gesture->setGestureCancelPolicy(QGesture::CancelNone); recognizer->reset(gesture); - else + } else { cleanupGesturesForRemovedRecognizer(gesture); + } } else { ++it; } diff --git a/src/gui/kernel/qgesturemanager_p.h b/src/gui/kernel/qgesturemanager_p.h index 96c2fb7..e6a1d50 100644 --- a/src/gui/kernel/qgesturemanager_p.h +++ b/src/gui/kernel/qgesturemanager_p.h @@ -135,6 +135,8 @@ private: void getGestureTargets(const QSet<QGesture*> &gestures, QMap<QWidget *, QList<QGesture *> > *conflicts, QMap<QWidget *, QList<QGesture *> > *normal); + + void cancelGesturesForChildren(QGesture *originatingGesture); }; QT_END_NAMESPACE |