From 3e2cef8f6a58949b887add8ff1bb5e457e7be542 Mon Sep 17 00:00:00 2001 From: Denis Dzyubenko Date: Thu, 12 Mar 2009 16:07:36 +0100 Subject: Added QGraphicsSceneGestureEvent that extends plain QGestureEvent by providing some additional info (like a widget that received a gesture - for coordinates conversions). --- examples/gestures/graphicsview/main.cpp | 4 +- src/corelib/kernel/qcoreevent.h | 1 + src/gui/graphicsview/qgraphicsscene.cpp | 34 +++--- src/gui/graphicsview/qgraphicsscene.h | 3 +- src/gui/graphicsview/qgraphicsscene_p.h | 1 - src/gui/graphicsview/qgraphicssceneevent.cpp | 148 +++++++++++++++++++++++++++ src/gui/graphicsview/qgraphicssceneevent.h | 40 ++++++++ src/gui/graphicsview/qgraphicsview.cpp | 12 ++- src/gui/kernel/qapplication.cpp | 1 - src/gui/kernel/qevent.cpp | 26 +++-- src/gui/kernel/qevent.h | 8 +- src/gui/kernel/qgesturemanager.cpp | 8 +- 12 files changed, 236 insertions(+), 50 deletions(-) diff --git a/examples/gestures/graphicsview/main.cpp b/examples/gestures/graphicsview/main.cpp index 250da06..1b325ee 100644 --- a/examples/gestures/graphicsview/main.cpp +++ b/examples/gestures/graphicsview/main.cpp @@ -94,8 +94,8 @@ public: bool sceneEvent(QEvent *event) { - if (event->type() == QEvent::Gesture) { - QGestureEvent *gestureEvent = static_cast(event); + if (event->type() == QEvent::GraphicsSceneGesture) { + QGraphicsSceneGestureEvent *gestureEvent = static_cast(event); if (gestureEvent->gesture(Qt::DoubleTap)) { event->accept(); colored = !colored; diff --git a/src/corelib/kernel/qcoreevent.h b/src/corelib/kernel/qcoreevent.h index 4ea3c70..cb24723 100644 --- a/src/corelib/kernel/qcoreevent.h +++ b/src/corelib/kernel/qcoreevent.h @@ -274,6 +274,7 @@ public: GraphicsSceneTouchEnd = 198, Gesture = 191, + GraphicsSceneGesture = 192, // 512 reserved for Qt Jambi's MetaCall event // 513 reserved for Qt Jambi's DeleteOnMainThread event diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 21c7c81..7e23620 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -3951,8 +3951,8 @@ bool QGraphicsScene::event(QEvent *event) // geometries that do not have an explicit style set. update(); break; - case QEvent::Gesture: - gestureEvent(static_cast(event)); + case QEvent::GraphicsSceneGesture: + gestureEvent(static_cast(event)); break; case QEvent::GraphicsSceneTouchBegin: d->touchBeginEvent(static_cast(event)); @@ -5604,36 +5604,32 @@ void QGraphicsScenePrivate::removeView(QGraphicsView *view) view->releaseGesture(gesture); } -void QGraphicsScenePrivate::sendGestureEvent(QGraphicsItem *item, QGestureEvent *event) -{ - //### TODO: position translation - sendEvent(item, event); -} - -void QGraphicsScene::gestureEvent(QGestureEvent *event) +void QGraphicsScene::gestureEvent(QGraphicsSceneGestureEvent *event) { Q_D(QGraphicsScene); QList gestureTypes = event->gestureTypes(); - QGraphicsView *view = qobject_cast(event->targetWidget()); + QGraphicsView *view = qobject_cast(event->widget()); if (!view) { - // something is wrong. - Q_ASSERT(view); + qWarning("QGraphicsScene::gestureEvent: gesture event was received without a view"); return; } + + // find graphics items that intersects with gestures hot spots. QPolygonF poly; - QMap hotSpots; + QMap sceneHotSpots; foreach(const Qt::GestureType &type, gestureTypes) { - QPointF pt = view->mapToScene(event->gesture(type)->hotSpot()); - hotSpots.insert(type, pt); + QPointF pt = event->mapToScene(event->gesture(type)->hotSpot()); + sceneHotSpots.insert(type, pt); poly << pt; } + QList itemsInGestureArea = items(poly, Qt::IntersectsItemBoundingRect); - foreach(QGraphicsItem *item, items(poly, Qt::IntersectsItemBoundingRect)) { - QMap::const_iterator it = hotSpots.begin(), - e = hotSpots.end(); + foreach(QGraphicsItem *item, itemsInGestureArea) { + QMap::const_iterator it = sceneHotSpots.begin(), + e = sceneHotSpots.end(); for(; it != e; ++it) { if (item->contains(item->mapFromScene(it.value())) && item->gestures().contains(it.key())) { - d->sendGestureEvent(item, event); + d->sendEvent(item, event); if (event->isAccepted()) break; } diff --git a/src/gui/graphicsview/qgraphicsscene.h b/src/gui/graphicsview/qgraphicsscene.h index 4680455..45def44 100644 --- a/src/gui/graphicsview/qgraphicsscene.h +++ b/src/gui/graphicsview/qgraphicsscene.h @@ -80,6 +80,7 @@ class QGraphicsSceneHelpEvent; class QGraphicsSceneHoverEvent; class QGraphicsSceneMouseEvent; class QGraphicsSceneWheelEvent; +class QGraphicsSceneGestureEvent; class QGraphicsSimpleTextItem; class QGraphicsTextItem; class QGraphicsView; @@ -255,7 +256,7 @@ protected: virtual void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event); virtual void wheelEvent(QGraphicsSceneWheelEvent *event); virtual void inputMethodEvent(QInputMethodEvent *event); - virtual void gestureEvent(QGestureEvent *event); + virtual void gestureEvent(QGraphicsSceneGestureEvent *event); virtual void drawBackground(QPainter *painter, const QRectF &rect); virtual void drawForeground(QPainter *painter, const QRectF &rect); diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index cea0553..1cd1788 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -271,7 +271,6 @@ public: QSet grabbedGestures; void grabGesture(QGraphicsItem *item, const Qt::GestureType &type); void releaseGesture(QGraphicsItem *item, const Qt::GestureType &type); - void sendGestureEvent(QGraphicsItem *item, QGestureEvent *event); mutable QVector sceneTransformCache; mutable QBitArray validTransforms; diff --git a/src/gui/graphicsview/qgraphicssceneevent.cpp b/src/gui/graphicsview/qgraphicssceneevent.cpp index 3c9799b..4d9e7bb 100644 --- a/src/gui/graphicsview/qgraphicssceneevent.cpp +++ b/src/gui/graphicsview/qgraphicssceneevent.cpp @@ -299,6 +299,8 @@ #include #include #include +#include "qgraphicsview.h" +#include "qgraphicsitem.h" QT_BEGIN_NAMESPACE @@ -1704,6 +1706,152 @@ void QGraphicsSceneMoveEvent::setNewPos(const QPointF &pos) d->newPos = pos; } +/*! + \class QGraphicsSceneGestureEvent + \brief The QGraphicsSceneGestureEvent class provides gesture events for + the graphics view framework. + \since 4.6 + \ingroup graphicsview-api + + QGraphicsSceneGestureEvent extends information provided by + QGestureEvent by adding some convenience functions like + \l{QGraphicsSceneEvent::}{widget()} to get a widget that received + original gesture event, and convenience functions mapToScene(), + mapToItem() for converting positions of the gesture into + QGraphicsScene and QGraphicsItem coordinate system respectively. + + The scene sends the event to the first QGraphicsItem under the + mouse cursor that accepts gestures; a graphics item is set to accept + gestures with \l{QGraphicsItem::}{grabGesture()}. +*/ + +/*! \fn bool QGraphicsSceneGestureEvent::contains(const Qt::GestureType &type) const + + Checks if the gesture event contains gesture of specific \a type. +*/ + +/*! \fn QList QGraphicsSceneGestureEvent::gestureTypes() const + + Returns a list of gesture names that the event contains. +*/ + +/*! \fn const QGesture* QGraphicsSceneGestureEvent::gesture(const Qt::GestureType &type) const + + Returns extended information about a gesture of specific \a type. +*/ + +/*! \fn QList > QGraphicsSceneGestureEvent::gestures() const + + Returns extended information about all triggered gestures. +*/ + +/*! \fn QSet QGraphicsSceneGestureEvent::cancelledGestures() const + + Returns a set of gesture names that used to be executed, but got + cancelled (i.e. they were not finished properly). +*/ + +/*! \fn void QGraphicsSceneGestureEvent::setCancelledGestures(const QSet &) + + Returns a set of gesture names that used to be executed, but got + cancelled (i.e. they were not finished properly). +*/ + +QGraphicsSceneGestureEvent::QGraphicsSceneGestureEvent() + : QGraphicsSceneEvent(QEvent::GraphicsSceneGesture) +{ +} + +QGraphicsSceneGestureEvent::~QGraphicsSceneGestureEvent() +{ +} + +/*! + Maps the point \a point, which is in a view coordinate system, to + scene coordinate system, and returns the mapped coordinate. + + \a Point is in coordinate system of the widget that received + gesture event. + + \sa mapToScene(const QRect &rect), + mapToItem(const QPoint &point, QGraphicsItem *item), + mapToItem(const QRect &rect, QGraphicsItem *item), + {The Graphics View Coordinate System} +*/ +QPointF QGraphicsSceneGestureEvent::mapToScene(const QPoint &point) const +{ + if (QGraphicsView *view = qobject_cast(widget())) + return view->mapToScene(point); + return QPointF(); +} + +/*! + Maps the rectangular \a rect, which is in a view coordinate system, to + scene coordinate system, and returns the mapped coordinate. + + \a Point is in coordinate system of the widget that received + gesture event. + + \sa mapToScene(const QPoint &rect), + mapToItem(const QPoint &point, QGraphicsItem *item), + mapToItem(const QRect &rect, QGraphicsItem *item), + {The Graphics View Coordinate System} +*/ +QPolygonF QGraphicsSceneGestureEvent::mapToScene(const QRect &rect) const +{ + if (QGraphicsView *view = qobject_cast(widget())) + return view->mapToScene(rect); + return QPolygonF(); +} + +/*! + Maps the point \a point, which is in a view coordinate system, to + item's \a item coordinate system, and returns the mapped coordinate. + + If \a item is 0, this function returns the same as mapToScene(). + + \sa mapToScene(const QPoint &rect), mapToScene(const QRect &rect), + mapToItem(const QRect &, QGraphicsItem *item), + {The Graphics View Coordinate System} +*/ +QPointF QGraphicsSceneGestureEvent::mapToItem(const QPoint &point, QGraphicsItem *item) const +{ + if (item) { + if (QGraphicsView *view = qobject_cast(widget())) + return item->mapFromScene(view->mapToScene(point)); + } else { + return mapToScene(point); + } + return QPointF(); +} + +/*! + Maps the point \a point, which is in a view coordinate system, to + item's \a item coordinate system, and returns the mapped coordinate. + + If \a item is 0, this function returns the same as mapToScene(). + + \sa mapToScene(const QPoint &rect), mapToScene(const QRect &rect), + mapToItem(const QPoint &point, QGraphicsItem *item), + {The Graphics View Coordinate System} +*/ +QPolygonF QGraphicsSceneGestureEvent::mapToItem(const QRect &rect, QGraphicsItem *item) const +{ + if (item) { + if (QGraphicsView *view = qobject_cast(widget())) + return item->mapFromScene(view->mapToScene(rect)); + } else { + return mapToScene(rect); + } + return QPolygonF(); +} + +void QGraphicsSceneGestureEvent::setGestures(const QList > &gestures) +{ + foreach(const QSharedPointer &g, gestures) + m_gestures.insert(g->gestureType(), g); +} + class QGraphicsSceneTouchEventPrivate : public QGraphicsSceneEventPrivate { Q_DECLARE_PUBLIC(QGraphicsSceneTouchEvent) diff --git a/src/gui/graphicsview/qgraphicssceneevent.h b/src/gui/graphicsview/qgraphicssceneevent.h index 8ae3a99..d3899cd 100644 --- a/src/gui/graphicsview/qgraphicssceneevent.h +++ b/src/gui/graphicsview/qgraphicssceneevent.h @@ -44,6 +44,11 @@ #include #include +#include +#include +#include +#include +#include QT_BEGIN_HEADER @@ -302,6 +307,41 @@ public: void setNewPos(const QPointF &pos); }; +class QGesture; +class QGraphicsItem; +class QGraphicsSceneGestureEventPrivate; +class Q_GUI_EXPORT QGraphicsSceneGestureEvent : public QGraphicsSceneEvent +{ + Q_DECLARE_PRIVATE(QGraphicsSceneGestureEvent) +public: + QGraphicsSceneGestureEvent(); + ~QGraphicsSceneGestureEvent(); + + inline bool contains(const Qt::GestureType &type) const + { return gesture(type) != 0; } + inline QList gestureTypes() const + { return m_gestures.keys(); } + inline const QGesture* gesture(const Qt::GestureType &type) const + { return m_gestures.value(type, QSharedPointer()).data(); } + inline QList > gestures() const + { return m_gestures.values(); } + void setGestures(const QList > &gestures); + + inline QSet cancelledGestures() const + { return m_cancelledGestures; } + void setCancelledGestures(const QSet &cancelledGestures) + { m_cancelledGestures = cancelledGestures; } + + QPointF mapToScene(const QPoint &point) const; + QPolygonF mapToScene(const QRect &rect) const; + QPointF mapToItem(const QPoint &point, QGraphicsItem *item) const; + QPolygonF mapToItem(const QRect &rect, QGraphicsItem *item) const; + +protected: + QHash > m_gestures; + QSet m_cancelledGestures; +}; + class QGraphicsSceneTouchEventPrivate; class QGraphicsSceneTouchEventTouchPointPrivate; class Q_GUI_EXPORT QGraphicsSceneTouchEvent : public QGraphicsSceneEvent diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index 97903d3..925763c 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -2862,10 +2862,16 @@ bool QGraphicsView::event(QEvent *event) } } break; - case QEvent::Gesture: - QApplication::sendEvent(d->scene, event); - if (event->isAccepted()) + case QEvent::Gesture: { + QGraphicsSceneGestureEvent gestureEvent; + gestureEvent.setWidget(this); + QGestureEvent *ev = static_cast(event); + gestureEvent.setGestures(ev->gestures()); + gestureEvent.setCancelledGestures(ev->cancelledGestures()); + QApplication::sendEvent(d->scene, &gestureEvent); + if (gestureEvent.isAccepted()) return true; + } break; default: break; diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp index 104271d..5774ae0 100644 --- a/src/gui/kernel/qapplication.cpp +++ b/src/gui/kernel/qapplication.cpp @@ -4037,7 +4037,6 @@ bool QApplication::notify(QObject *receiver, QEvent *e) // QGestureEvent ge(&qge, false); // ### TODO: fix widget-relative positions in gesture event. QGestureEvent ge = *g; - ge.m_targetWidget = w; ge.spont = g->spontaneous(); res = d->notify_helper(w, w == receiver ? g : &ge); g->spont = false; diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index d7d193c..6cdf781 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -3524,27 +3524,27 @@ QMenubarUpdatedEvent::QMenubarUpdatedEvent(QMenuBar * const menuBar) \sa QGesture */ -/*! \fn QWidget *QGestureEvent::targetWidget() const - - Returns the widget the gesture event is send to. -*/ - -/*! \fn bool contains(const Qt::GestureType &type) const +/*! \fn bool QGestureEvent::contains(const Qt::GestureType &type) const Checks if the gesture event contains gesture of specific \a type. */ -/*! \fn QList gestureTypes() const +/*! \fn QList QGestureEvent::gestureTypes() const Returns a list of gesture names that the event contains. */ -/*! \fn const QGesture* gesture(const Qt::GestureType &type) const +/*! \fn const QGesture* QGestureEvent::gesture(const Qt::GestureType &type) const Returns extended information about a gesture of specific \a type. */ -/*! \fn QSet cancelledGestures() const +/*! \fn QList > QGestureEvent::gestures() const + + Returns extended information about all triggered gestures. +*/ + +/*! \fn QSet QGestureEvent::cancelledGestures() const Returns a set of gesture names that used to be executed, but got cancelled (i.e. they were not finished properly). @@ -3553,18 +3553,16 @@ QMenubarUpdatedEvent::QMenubarUpdatedEvent(QMenuBar * const menuBar) -QGestureEvent::QGestureEvent(QWidget *targetWidget, const QList &gestures, +QGestureEvent::QGestureEvent(const QList &gestures, const QSet &cancelledGestures) - : QEvent(QEvent::Gesture), m_targetWidget(targetWidget), - m_cancelledGestures(cancelledGestures) + : QEvent(QEvent::Gesture), m_cancelledGestures(cancelledGestures) { foreach(QGesture *r, gestures) m_gestures.insert(r->gestureType(), QSharedPointer(r)); } QGestureEvent::QGestureEvent(const QGestureEvent &event, const QPoint &offset) - : QEvent(QEvent::Gesture), m_targetWidget(event.m_targetWidget), - m_gestures(event.m_gestures), + : QEvent(QEvent::Gesture), m_gestures(event.m_gestures), m_cancelledGestures(event.m_cancelledGestures) { //### use offset! diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h index cde7cb2..603f358 100644 --- a/src/gui/kernel/qevent.h +++ b/src/gui/kernel/qevent.h @@ -717,27 +717,25 @@ private: class Q_GUI_EXPORT QGestureEvent : public QEvent { public: - QGestureEvent(QWidget *targetWidget, const QList &gestures, + QGestureEvent(const QList &gestures, const QSet &cancelledGestures = QSet()); // internal ctor QGestureEvent(const QGestureEvent &gestures, const QPoint &offset); ~QGestureEvent(); - QWidget *targetWidget() const - { return m_targetWidget; } - inline bool contains(const Qt::GestureType &type) const { return gesture(type) != 0; } inline QList gestureTypes() const { return m_gestures.keys(); } inline const QGesture* gesture(const Qt::GestureType &type) const { return m_gestures.value(type, QSharedPointer()).data(); } + inline QList > gestures() const + { return m_gestures.values(); } inline QSet cancelledGestures() const { return m_cancelledGestures; } protected: - QWidget *m_targetWidget; QHash > m_gestures; QSet m_cancelledGestures; diff --git a/src/gui/kernel/qgesturemanager.cpp b/src/gui/kernel/qgesturemanager.cpp index 7954ae9..9a287a0 100644 --- a/src/gui/kernel/qgesturemanager.cpp +++ b/src/gui/kernel/qgesturemanager.cpp @@ -178,7 +178,7 @@ bool QGestureManager::filterEvent(QEvent *event) gestures << gesture; } Q_ASSERT(!gestures.isEmpty()); - QGestureEvent event(targetWidget, gestures); + QGestureEvent event(gestures); ret = qt_sendGestureEvent(targetWidget, &event); ret = ret && event.isAccepted(); @@ -283,7 +283,7 @@ bool QGestureManager::filterEvent(QEvent *event) foreach(QGestureRecognizer *r, cancelledGestures) cancelledGestureNames << r->gestureType(); if(!gestures.isEmpty()) { - QGestureEvent event(targetWidget, gestures, cancelledGestureNames); + QGestureEvent event(gestures, cancelledGestureNames); ret = qt_sendGestureEvent(targetWidget, &event); ret = ret && event.isAccepted(); } @@ -375,7 +375,7 @@ void QGestureManager::recognizerTriggered(QGestureRecognizer::Result result) if (QGesture *gesture = recognizer->makeEvent()) gestures << gesture; if(!gestures.isEmpty()) { - QGestureEvent event(targetWidget, gestures); + QGestureEvent event(gestures); qt_sendGestureEvent(targetWidget, &event); } if (result == QGestureRecognizer::GestureFinished) @@ -385,7 +385,7 @@ void QGestureManager::recognizerTriggered(QGestureRecognizer::Result result) case QGestureRecognizer::MaybeGesture: { DEBUG() << "QGestureManager: maybe gesture: " << recognizer; if (activeGestures.contains(recognizer)) { - QGestureEvent event(targetWidget, QList(), + QGestureEvent event(QList(), QSet() << recognizer->gestureType()); qt_sendGestureEvent(targetWidget, &event); } -- cgit v0.12