diff options
Diffstat (limited to 'src/gui/graphicsview')
-rw-r--r-- | src/gui/graphicsview/qgraphicsitem.cpp | 25 | ||||
-rw-r--r-- | src/gui/graphicsview/qgraphicsitem.h | 2 | ||||
-rw-r--r-- | src/gui/graphicsview/qgraphicsitem_p.h | 2 | ||||
-rw-r--r-- | src/gui/graphicsview/qgraphicsscene.cpp | 166 | ||||
-rw-r--r-- | src/gui/graphicsview/qgraphicsscene_p.h | 6 | ||||
-rw-r--r-- | src/gui/graphicsview/qgraphicssceneevent.cpp | 338 | ||||
-rw-r--r-- | src/gui/graphicsview/qgraphicssceneevent.h | 64 | ||||
-rw-r--r-- | src/gui/graphicsview/qgraphicsview.cpp | 106 | ||||
-rw-r--r-- | src/gui/graphicsview/qgraphicsview_p.h | 5 |
9 files changed, 703 insertions, 11 deletions
diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 743c16d..3eef396 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -2106,6 +2106,31 @@ void QGraphicsItem::setAcceptsHoverEvents(bool enabled) setAcceptHoverEvents(enabled); } +/*! \since 4.6 + + Returns true if an item accepts touch events + (QGraphicsSceneTouchEvent); otherwise, returns false. By default, + items do not accept touch events. + + \sa setAcceptTouchEvents() +*/ +bool QGraphicsItem::acceptTouchEvents() const +{ + return d_ptr->acceptTouchEvents; +} + +/*! + \since 4.6 + + If \a enabled is true, this item will accept touch events; + otherwise, it will ignore them. By default, items do not accept + touch events. +*/ +void QGraphicsItem::setAcceptTouchEvents(bool enabled) +{ + d_ptr->acceptTouchEvents = quint32(enabled); +} + /*! Returns true if this item handles child events (i.e., all events intended for any of its children are instead sent to this item); diff --git a/src/gui/graphicsview/qgraphicsitem.h b/src/gui/graphicsview/qgraphicsitem.h index b98882d..ec3373a 100644 --- a/src/gui/graphicsview/qgraphicsitem.h +++ b/src/gui/graphicsview/qgraphicsitem.h @@ -203,6 +203,8 @@ public: void setAcceptsHoverEvents(bool enabled); // obsolete bool acceptHoverEvents() const; void setAcceptHoverEvents(bool enabled); + bool acceptTouchEvents() const; + void setAcceptTouchEvents(bool enabled); bool handlesChildEvents() const; void setHandlesChildEvents(bool enabled); diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index 2936cf1..5e77dfd 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -143,6 +143,7 @@ public: emptyClipPath(0), inSetPosHelper(0), allChildrenCombineOpacity(1), + acceptTouchEvents(0), globalStackingOrder(-1), sceneTransformIndex(-1), q_ptr(0) @@ -327,6 +328,7 @@ public: quint32 emptyClipPath : 1; quint32 inSetPosHelper : 1; quint32 allChildrenCombineOpacity : 1; + quint32 acceptTouchEvents : 1; // Optional stacking order int globalStackingOrder; diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 69e08d1..f322305 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -3796,6 +3796,9 @@ bool QGraphicsScene::event(QEvent *event) case QEvent::GraphicsSceneHoverEnter: case QEvent::GraphicsSceneHoverLeave: case QEvent::GraphicsSceneHoverMove: + case QEvent::GraphicsSceneTouchBegin: + case QEvent::GraphicsSceneTouchUpdate: + case QEvent::GraphicsSceneTouchEnd: // Reset the under-mouse list to ensure that this event gets fresh // item-under-mouse data. Be careful about this list; if people delete // items from inside event handlers, this list can quickly end up @@ -3947,6 +3950,15 @@ bool QGraphicsScene::event(QEvent *event) // geometries that do not have an explicit style set. update(); break; + case QEvent::GraphicsSceneTouchBegin: + d->touchBeginEvent(static_cast<QGraphicsSceneTouchEvent *>(event)); + break; + case QEvent::GraphicsSceneTouchUpdate: + d->touchUpdateEvent(static_cast<QGraphicsSceneTouchEvent *>(event)); + break; + case QEvent::GraphicsSceneTouchEnd: + d->touchEndEvent(static_cast<QGraphicsSceneTouchEvent *>(event)); + break; case QEvent::Timer: if (d->indexTimerId && static_cast<QTimerEvent *>(event)->timerId() == d->indexTimerId) { if (d->restartIndexTimer) { @@ -5574,6 +5586,160 @@ void QGraphicsScene::setActiveWindow(QGraphicsWidget *widget) } } +// ### FIXME: the code for touch event support is mosly copied from +// ### QGraphicsScenePrivate::mousePressEventHandler() and friends, need to +// ### refactor to reduce code duplication + +void QGraphicsScenePrivate::sendTouchEvent(QGraphicsSceneTouchEvent *touchEvent) +{ + if (touchEvent->type() == QEvent::GraphicsSceneTouchEnd && lastMouseGrabberItemHasImplicitMouseGrab) { + clearMouseGrabber(); + return; + } + + QGraphicsItem *item = mouseGrabberItems.last(); + QList<QGraphicsSceneTouchEvent::TouchPoint *> touchPoints = touchEvent->touchPoints(); + for (int i = 0; i < touchPoints.count(); ++i) { + QGraphicsSceneTouchEvent::TouchPoint *touchPoint = touchPoints.at(i); + touchPoint->setPos(item->d_ptr->genericMapFromScene(touchPoint->scenePos(), touchEvent->widget())); + touchPoint->setStartPos(item->d_ptr->genericMapFromScene(touchPoint->startScenePos(), touchEvent->widget())); + touchPoint->setLastPos(item->d_ptr->genericMapFromScene(touchPoint->lastScenePos(), touchEvent->widget())); + } + sendEvent(item, touchEvent); +} + +void QGraphicsScenePrivate::touchBeginEvent(QGraphicsSceneTouchEvent *touchEvent) +{ + Q_Q(QGraphicsScene); + + // Ignore by default, unless we find a mouse grabber that accepts it. + touchEvent->ignore(); + + // Deliver to any existing mouse grabber. + if (!mouseGrabberItems.isEmpty()) { + // The event is ignored by default, but we disregard the event's + // accepted state after delivery; the mouse is grabbed, after all. + sendTouchEvent(touchEvent); + return; + } + + // Start by determining the number of items at the current position. + // Reuse value from earlier calculations if possible. + if (cachedItemsUnderMouse.isEmpty()) { + QGraphicsSceneTouchEvent::TouchPoint *touchPoint = touchEvent->touchPoints().first(); + // ### FIXME: should the itemsAtPosition() function support sub-pixel screenPos? + cachedItemsUnderMouse = itemsAtPosition(touchPoint->screenPos().toPoint(), + touchPoint->scenePos(), + touchEvent->widget()); + } + + // Update window activation. + QGraphicsWidget *newActiveWindow = windowForItem(cachedItemsUnderMouse.value(0)); + if (newActiveWindow != activeWindow) + q->setActiveWindow(newActiveWindow); + + // Set focus on the topmost enabled item that can take focus. + bool setFocus = false; + foreach (QGraphicsItem *item, cachedItemsUnderMouse) { + if (item->isEnabled() && (item->flags() & QGraphicsItem::ItemIsFocusable)) { + if (!item->isWidget() || ((QGraphicsWidget *)item)->focusPolicy() & Qt::ClickFocus) { + setFocus = true; + if (item != q->focusItem()) + q->setFocusItem(item, Qt::MouseFocusReason); + break; + } + } + } + + // If nobody could take focus, clear it. + if (!stickyFocus && !setFocus) + q->setFocusItem(0, Qt::MouseFocusReason); + + // Find a mouse grabber by sending touch events to all mouse grabber + // candidates one at a time, until the event is accepted. It's accepted by + // default, so the receiver has to explicitly ignore it for it to pass + // through. + foreach (QGraphicsItem *item, cachedItemsUnderMouse) { + if (!item->acceptTouchEvents()) { + // Skip items that don't accept the touch events + continue; + } + + grabMouse(item, /* implicit = */ true); + touchEvent->accept(); + + // check if the item we are sending to are disabled (before we send the event) + bool disabled = !item->isEnabled(); + bool isWindow = item->isWindow(); + sendTouchEvent(touchEvent); + + bool dontSendUngrabEvents = mouseGrabberItems.isEmpty() || mouseGrabberItems.last() != item; + if (disabled) { + ungrabMouse(item, /* itemIsDying = */ dontSendUngrabEvents); + break; + } + if (touchEvent->isAccepted()) { + lastMouseGrabberItem = item; + return; + } + ungrabMouse(item, /* itemIsDying = */ dontSendUngrabEvents); + + // Don't propagate through windows. + if (isWindow) + break; + } + + // Is the event still ignored? Then the mouse press goes to the scene. + // Reset the mouse grabber, clear the selection, clear focus, and leave + // the event ignored so that it can propagate through the originating + // view. + if (!touchEvent->isAccepted()) { + clearMouseGrabber(); + + QGraphicsView *view = touchEvent->widget() ? qobject_cast<QGraphicsView *>(touchEvent->widget()->parentWidget()) : 0; + bool dontClearSelection = view && view->dragMode() == QGraphicsView::ScrollHandDrag; + if (!dontClearSelection) { + // Clear the selection if the originating view isn't in scroll + // hand drag mode. The view will clear the selection if no drag + // happened. + q->clearSelection(); + } + } +} + +void QGraphicsScenePrivate::touchUpdateEvent(QGraphicsSceneTouchEvent *touchEvent) +{ + if (mouseGrabberItems.isEmpty()) { + touchEvent->ignore(); + return; + } + + // Forward the event to the mouse grabber + sendTouchEvent(touchEvent); + touchEvent->accept(); +} + +void QGraphicsScenePrivate::touchEndEvent(QGraphicsSceneTouchEvent *touchEvent) +{ + if (mouseGrabberItems.isEmpty()) { + touchEvent->ignore(); + return; + } + + // Forward the event to the mouse grabber + sendTouchEvent(touchEvent); + touchEvent->accept(); + + // Reset the mouse grabber + if (!mouseGrabberItems.isEmpty()) { + lastMouseGrabberItem = mouseGrabberItems.last(); + if (lastMouseGrabberItemHasImplicitMouseGrab) + mouseGrabberItems.last()->ungrabMouse(); + } else { + lastMouseGrabberItem = 0; + } +} + QT_END_NAMESPACE #include "moc_qgraphicsscene.cpp" diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index 9ace725..de39205 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -73,6 +73,7 @@ QT_BEGIN_NAMESPACE class QGraphicsView; class QGraphicsWidget; +class QGraphicsSceneTouchEvent; class QGraphicsScenePrivate : public QObjectPrivate { @@ -266,6 +267,11 @@ public: mutable QVector<QTransform> sceneTransformCache; mutable QBitArray validTransforms; mutable QVector<int> freeSceneTransformSlots; + + void sendTouchEvent(QGraphicsSceneTouchEvent *touchEvent); + void touchBeginEvent(QGraphicsSceneTouchEvent *touchEvent); + void touchUpdateEvent(QGraphicsSceneTouchEvent *touchEvent); + void touchEndEvent(QGraphicsSceneTouchEvent *touchEvent); }; QT_END_NAMESPACE diff --git a/src/gui/graphicsview/qgraphicssceneevent.cpp b/src/gui/graphicsview/qgraphicssceneevent.cpp index b819c2c..3c9799b 100644 --- a/src/gui/graphicsview/qgraphicssceneevent.cpp +++ b/src/gui/graphicsview/qgraphicssceneevent.cpp @@ -76,14 +76,14 @@ received by the view (see \l{QGraphicsSceneMouseEvent::}{lastScreenPos()}, \l{QGraphicsSceneMouseEvent::}{lastScenePos()}, and - \l{QGraphicsSceneMouseEvent::}{lastPos()}). + \l{QGraphicsSceneMouseEvent::}{lastPos()}). \sa QEvent */ /*! \class QGraphicsSceneMouseEvent - \brief The QGraphicsSceneMouseEvent class provides mouse events + \brief The QGraphicsSceneMouseEvent class provides mouse events in the graphics view framework. \since 4.2 \ingroup multimedia @@ -106,7 +106,7 @@ /*! \class QGraphicsSceneWheelEvent - \brief The QGraphicsSceneWheelEvent class provides wheel events + \brief The QGraphicsSceneWheelEvent class provides wheel events in the graphics view framework. \brief The QGraphicsSceneWheelEvent class provides wheel events in the graphics view framework. @@ -157,7 +157,7 @@ /*! \class QGraphicsSceneHoverEvent - \brief The QGraphicsSceneHoverEvent class provides hover events + \brief The QGraphicsSceneHoverEvent class provides hover events in the graphics view framework. \since 4.2 \ingroup multimedia @@ -173,7 +173,7 @@ /*! \class QGraphicsSceneHelpEvent - \brief The QGraphicsSceneHelpEvent class provides events when a + \brief The QGraphicsSceneHelpEvent class provides events when a tooltip is requested. \since 4.2 \ingroup multimedia @@ -199,7 +199,7 @@ /*! \class QGraphicsSceneDragDropEvent \brief The QGraphicsSceneDragDropEvent class provides events for - drag and drop in the graphics view framework. + drag and drop in the graphics view framework. \since 4.2 \ingroup multimedia \ingroup graphicsview-api @@ -257,6 +257,37 @@ QGraphicsItem::ItemPositionHasChanged */ +/*! + \class QGraphicsSceneTouchEvent + \brief The QGraphicsSceneTouchEvent class provides touch events in the graphics view framework. + \since 4.6 + \ingroup multimedia + \ingroup graphicsview-api + + When a QGraphicsView receives a QTouchEvent, it translates it to a + QGraphicsSceneTouchEvent. The event is then forwarded to the + QGraphicsScene associated with the view. + + The touchPoints() function returns a list of touch points for the + event. In addition to containing the item, scene, and screen + coordinates, each touch point also contains its starting and + previous coordinates. + + \sa QTouchEvent +*/ + +/*! + \class QGraphicsSceneTouchEvent::TouchPoint + \brief The QGraphicsSceneTouchEvent::TouchPoint class represents a single touch point in a QGraphicsSceneTouchEvent. + \since 4.6 + \ingroup multimedia + \ingroup graphicsview-api + + Each touch point in a QGraphicsSceneTouchEvent has an id() and + state() in addition to current, starting, and previous coordinates + for the touch point in item, scene, and screen coordinates. +*/ + #include "qgraphicssceneevent.h" #ifndef QT_NO_GRAPHICSVIEW @@ -522,7 +553,7 @@ void QGraphicsSceneMouseEvent::setLastPos(const QPointF &pos) } /*! - Returns the last recorded mouse cursor position in scene + Returns the last recorded mouse cursor position in scene coordinates. The last recorded position is the position of the previous mouse event received by the view that created the event. @@ -545,7 +576,7 @@ void QGraphicsSceneMouseEvent::setLastScenePos(const QPointF &pos) } /*! - Returns the last recorded mouse cursor position in screen + Returns the last recorded mouse cursor position in screen coordinates. The last recorded position is the position of the previous mouse event received by the view that created the event. @@ -1275,7 +1306,7 @@ QGraphicsSceneDragDropEvent::~QGraphicsSceneDragDropEvent() /*! Returns the mouse position of the event relative to the view that sent the event. - + \sa QGraphicsView, screenPos(), scenePos() */ QPointF QGraphicsSceneDragDropEvent::pos() const @@ -1373,7 +1404,7 @@ void QGraphicsSceneDragDropEvent::setButtons(Qt::MouseButtons buttons) /*! Returns the keyboard modifiers that were pressed when the drag - and drop event was created. + and drop event was created. \sa Qt::KeyboardModifiers */ @@ -1428,7 +1459,7 @@ void QGraphicsSceneDragDropEvent::setPossibleActions(Qt::DropActions actions) The action must be one of the possible actions as defined by \c possibleActions(). - \sa Qt::DropAction, possibleActions() + \sa Qt::DropAction, possibleActions() */ Qt::DropAction QGraphicsSceneDragDropEvent::proposedAction() const @@ -1673,6 +1704,291 @@ void QGraphicsSceneMoveEvent::setNewPos(const QPointF &pos) d->newPos = pos; } +class QGraphicsSceneTouchEventPrivate : public QGraphicsSceneEventPrivate +{ + Q_DECLARE_PUBLIC(QGraphicsSceneTouchEvent) +public: + inline QGraphicsSceneTouchEventPrivate() + : modifiers(Qt::NoModifier) + { } + + QList<QGraphicsSceneTouchEvent::TouchPoint *> touchPoints; + Qt::KeyboardModifiers modifiers; +}; + +/*! + \internal + + Constructs a generic QGraphicsSceneTouchEvent of type \a type. +*/ +QGraphicsSceneTouchEvent::QGraphicsSceneTouchEvent(Type type) + : QGraphicsSceneEvent(*new QGraphicsSceneTouchEventPrivate, type) +{ } + +/*! + Destroys the QGraphicsSceneTouchEvent. +*/ +QGraphicsSceneTouchEvent::~QGraphicsSceneTouchEvent() +{ + Q_D(QGraphicsSceneTouchEvent); + qDeleteAll(d->touchPoints); +} + +/*! + Returns the list of touch points for this event. + + \sa QGraphicsSceneTouchEvent::TouchPoint +*/ +const QList<QGraphicsSceneTouchEvent::TouchPoint *> &QGraphicsSceneTouchEvent::touchPoints() const +{ + Q_D(const QGraphicsSceneTouchEvent); + return d->touchPoints; +} + +/*! \internal */ +void QGraphicsSceneTouchEvent::setTouchPoints(const QList<QGraphicsSceneTouchEvent::TouchPoint *> &touchPoints) +{ + Q_D(QGraphicsSceneTouchEvent); + d->touchPoints = touchPoints; +} + +/*! + Returns the keyboard modifiers in use at the time the event was + sent. +*/ +Qt::KeyboardModifiers QGraphicsSceneTouchEvent::modifiers() const +{ + Q_D(const QGraphicsSceneTouchEvent); + return d->modifiers; +} + +/*! \internal */ +void QGraphicsSceneTouchEvent::setModifiers(Qt::KeyboardModifiers modifiers) +{ + Q_D(QGraphicsSceneTouchEvent); + d->modifiers = modifiers; +} + +class QGraphicsSceneTouchEventTouchPointPrivate +{ +public: + inline QGraphicsSceneTouchEventTouchPointPrivate() + : id(-1), state(Qt::TouchPointReleased), pressure(qreal(0.)) + { } + + int id; + Qt::TouchPointState state; + QPointF pos, startPos, lastPos; + QPointF scenePos, startScenePos, lastScenePos; + QPointF screenPos, startScreenPos, lastScreenPos; + qreal pressure; +}; + +/*! \internal + + Constructs a new touch point for use in a QGraphicsSceneTouchEvent. +*/ +QGraphicsSceneTouchEvent::TouchPoint::TouchPoint() + : d(new QGraphicsSceneTouchEventTouchPointPrivate) +{ +} + +/*! \internal + + Destroys the QGraphicsSceneTouchEvent::TouchPoint. +*/ +QGraphicsSceneTouchEvent::TouchPoint::~TouchPoint() +{ + delete d; +} + +/*! + Returns the identifier for this touch point. +*/ +int QGraphicsSceneTouchEvent::TouchPoint::id() const +{ + return d->id; +} + +/*! \internal */ +void QGraphicsSceneTouchEvent::TouchPoint::setId(int id) +{ + d->id = id; +} + +/*! + Returns the state of this touch point at the time the + QGraphicsSceneTouchEvent occurred. +*/ +Qt::TouchPointState QGraphicsSceneTouchEvent::TouchPoint::state() const +{ + return d->state; +} + +/*! \internal */ +void QGraphicsSceneTouchEvent::TouchPoint::setState(Qt::TouchPointState state) +{ + d->state = state; +} + +/*! + Returns the current position of this touch point in item coordinates. + + \sa scenePos(), screenPos() +*/ +QPointF QGraphicsSceneTouchEvent::TouchPoint::pos() const +{ + return d->pos; +} + +/*! \internal */ +void QGraphicsSceneTouchEvent::TouchPoint::setPos(const QPointF &pos) +{ + d->pos = pos; +} + +/*! + Returns the starting position of this touch point in item coordinates. + + \sa startScenePos(), startScreenPos() +*/ +QPointF QGraphicsSceneTouchEvent::TouchPoint::startPos() const +{ + return d->startPos; +} + +/*! \internal */ +void QGraphicsSceneTouchEvent::TouchPoint::setStartPos(const QPointF &startPos) +{ + d->startPos = startPos; +} + +/*! + Returns the previous position of this touch point in item coordinates. + + \sa lastScenePos(), lastScreenPos() +*/ +QPointF QGraphicsSceneTouchEvent::TouchPoint::lastPos() const +{ + return d->lastPos; +} + +/*! \internal */ +void QGraphicsSceneTouchEvent::TouchPoint::setLastPos(const QPointF &lastPos) +{ + d->lastPos = lastPos; +} + +/*! + Returns the current position of this touch point in scene coordinates. + + \sa pos(), screenPos() +*/ +QPointF QGraphicsSceneTouchEvent::TouchPoint::scenePos() const +{ + return d->scenePos; +} + +/*! \internal */ +void QGraphicsSceneTouchEvent::TouchPoint::setScenePos(const QPointF &scenePos) +{ + d->scenePos = scenePos; +} + +/*! + Returns the starting position of this touch point in scene coordinates. + + \sa startPos(), startScreenPos() +*/ +QPointF QGraphicsSceneTouchEvent::TouchPoint::startScenePos() const +{ + return d->startScenePos; +} + +/*! \internal */ +void QGraphicsSceneTouchEvent::TouchPoint::setStartScenePos(const QPointF &startScenePos) +{ + d->startScenePos = startScenePos; +} + +/*! + Returns the previous position of this touch point in scene coordinates. + + \sa lastPos(), lastScreenPos() +*/ +QPointF QGraphicsSceneTouchEvent::TouchPoint::lastScenePos() const +{ + return d->lastScenePos; +} + +/*! \internal */ +void QGraphicsSceneTouchEvent::TouchPoint::setLastScenePos(const QPointF &lastScenePos) +{ + d->lastScenePos = lastScenePos; +} + +/*! + Returns the current position of this touch point in screen coordinates. + + \sa pos(), scenePos() +*/ +QPointF QGraphicsSceneTouchEvent::TouchPoint::screenPos() const +{ + return d->screenPos; +} + +/*! \internal */ +void QGraphicsSceneTouchEvent::TouchPoint::setScreenPos(const QPointF &screenPos) +{ + d->screenPos = screenPos; +} + +/*! + Returns the starting position of this touch point in screen coordinates. + + \sa startPos(), startScenePos() +*/ +QPointF QGraphicsSceneTouchEvent::TouchPoint::startScreenPos() const +{ + return d->startScreenPos; +} + +/*! \internal */ +void QGraphicsSceneTouchEvent::TouchPoint::setStartScreenPos(const QPointF &startScreenPos) +{ + d->startScreenPos = startScreenPos; +} + +/*! + Returns the previous position of this touch point in screen coordinates. + + \sa lastPos(), lastScenePos() +*/ +QPointF QGraphicsSceneTouchEvent::TouchPoint::lastScreenPos() const +{ + return d->lastScreenPos; +} + +/*! \internal */ +void QGraphicsSceneTouchEvent::TouchPoint::setLastScreenPos(const QPointF &lastScreenPos) +{ + d->lastScreenPos = lastScreenPos; +} + +/*! + Returns the pressure of this touch point. +*/ +qreal QGraphicsSceneTouchEvent::TouchPoint::pressure() const +{ + return d->pressure; +} + +/*! \internal */ +void QGraphicsSceneTouchEvent::TouchPoint::setPressure(qreal pressure) +{ + d->pressure = pressure; +} + QT_END_NAMESPACE #endif // QT_NO_GRAPHICSVIEW diff --git a/src/gui/graphicsview/qgraphicssceneevent.h b/src/gui/graphicsview/qgraphicssceneevent.h index be50e96..8ae3a99 100644 --- a/src/gui/graphicsview/qgraphicssceneevent.h +++ b/src/gui/graphicsview/qgraphicssceneevent.h @@ -302,6 +302,70 @@ public: void setNewPos(const QPointF &pos); }; +class QGraphicsSceneTouchEventPrivate; +class QGraphicsSceneTouchEventTouchPointPrivate; +class Q_GUI_EXPORT QGraphicsSceneTouchEvent : public QGraphicsSceneEvent +{ +public: + QGraphicsSceneTouchEvent(Type type = None); + ~QGraphicsSceneTouchEvent(); + + class Q_GUI_EXPORT TouchPoint + { + public: + TouchPoint(); + ~TouchPoint(); + + int id() const; + void setId(int id); + + Qt::TouchPointState state() const; + void setState(Qt::TouchPointState state); + + QPointF pos() const; + void setPos(const QPointF &pos); + + QPointF startPos() const; + void setStartPos(const QPointF &startPos); + + QPointF lastPos() const; + void setLastPos(const QPointF &lastPos); + + QPointF scenePos() const; + void setScenePos(const QPointF &scenePos); + + QPointF startScenePos() const; + void setStartScenePos(const QPointF &startScenePos); + + QPointF lastScenePos() const; + void setLastScenePos(const QPointF &lastScenePos); + + QPointF screenPos() const; + void setScreenPos(const QPointF &screenPos); + + QPointF startScreenPos() const; + void setStartScreenPos(const QPointF &startScreenPos); + + QPointF lastScreenPos() const; + void setLastScreenPos(const QPointF &lastScreenPos); + + qreal pressure() const; // 0.0 -> 1.0 + void setPressure(qreal pressure); + + private: + QGraphicsSceneTouchEventTouchPointPrivate *d; + }; + + const QList<TouchPoint *> &touchPoints() const; + void setTouchPoints(const QList<TouchPoint *> &touchPoints); + + Qt::KeyboardModifiers modifiers() const; + void setModifiers(Qt::KeyboardModifiers modifiers); + +private: + Q_DECLARE_PRIVATE(QGraphicsSceneTouchEvent); +}; + #endif // QT_NO_GRAPHICSVIEW QT_END_NAMESPACE diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index 2876016..1aaaab9 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -2940,6 +2940,28 @@ bool QGraphicsView::viewportEvent(QEvent *event) d->scene->d_func()->updateAll = false; } break; + case QEvent::TouchBegin: + case QEvent::TouchUpdate: + case QEvent::TouchEnd: + { + if (!isEnabled()) + return false; + QTouchEvent *touchEvent = static_cast<QTouchEvent *>(event); + switch (touchEvent->type()) { + case QEvent::TouchBegin: + d->touchBeginEvent(touchEvent); + break; + case QEvent::TouchUpdate: + d->touchUpdateEvent(touchEvent); + break; + case QEvent::TouchEnd: + d->touchEndEvent(touchEvent); + break; + default: + break; + } + return true; + } default: break; } @@ -3878,6 +3900,90 @@ void QGraphicsView::resetTransform() setTransform(QTransform()); } +static void qt_convertTouchEventToGraphicsSceneTouchEvent(QGraphicsViewPrivate *d, QTouchEvent *originalEvent, QGraphicsSceneTouchEvent *touchEvent) +{ + QList<QTouchEvent::TouchPoint *> originalTouchPoints = originalEvent->touchPoints(); + QList<QGraphicsSceneTouchEvent::TouchPoint *> touchPoints; + for (int i = 0; i < originalTouchPoints.count(); ++i) { + QTouchEvent::TouchPoint *originalTouchPoint = originalTouchPoints.at(i); + + QGraphicsSceneTouchEvent::TouchPoint *touchPoint = new QGraphicsSceneTouchEvent::TouchPoint(); + touchPoint->setId(originalTouchPoint->id()); + touchPoint->setState(originalTouchPoint->state()); + // the scene will set the pos before delivering to an item + touchPoint->setScenePos(d->mapToScene(originalTouchPoint->pos())); + touchPoint->setScreenPos(originalTouchPoint->globalPos()); + // the scene will set the startPos before delivering to an item + touchPoint->setStartScenePos(d->mapToScene(originalTouchPoint->startPos())); + touchPoint->setStartScreenPos(originalTouchPoint->startGlobalPos()); + // the scene will set the lastPos before delivering to an item + touchPoint->setLastScenePos(d->mapToScene(originalTouchPoint->lastPos())); + touchPoint->setLastScreenPos(originalTouchPoint->lastGlobalPos()); + touchPoint->setPressure(originalTouchPoint->pressure()); + + touchPoints.append(touchPoint); + } + + touchEvent->setTouchPoints(touchPoints); + touchEvent->setModifiers(originalEvent->modifiers()); +} + +QPointF QGraphicsViewPrivate::mapToScene(const QPointF &point) const +{ + QPointF p = point; + p.rx() += horizontalScroll(); + p.ry() += verticalScroll(); + return identityMatrix ? p : matrix.inverted().map(p); +} + +void QGraphicsViewPrivate::touchBeginEvent(QTouchEvent *event) +{ + Q_Q(QGraphicsView); + + if (!scene || !sceneInteractionAllowed) + return; + + // Convert and deliver the touch event to the scene. + QGraphicsSceneTouchEvent touchEvent(QEvent::GraphicsSceneTouchBegin); + touchEvent.setWidget(q->viewport()); + qt_convertTouchEventToGraphicsSceneTouchEvent(this, event, &touchEvent); + touchEvent.setAccepted(false); + QApplication::sendEvent(scene, &touchEvent); + event->setAccepted(touchEvent.isAccepted()); +} + +void QGraphicsViewPrivate::touchUpdateEvent(QTouchEvent *event) +{ + Q_Q(QGraphicsView); + + if (!scene || !sceneInteractionAllowed) + return; + + // Convert and deliver the touch event to the scene. + QGraphicsSceneTouchEvent touchEvent(QEvent::GraphicsSceneTouchUpdate); + touchEvent.setWidget(q->viewport()); + qt_convertTouchEventToGraphicsSceneTouchEvent(this, event, &touchEvent); + touchEvent.setAccepted(false); + QApplication::sendEvent(scene, &touchEvent); + event->setAccepted(touchEvent.isAccepted()); +} + +void QGraphicsViewPrivate::touchEndEvent(QTouchEvent *event) +{ + Q_Q(QGraphicsView); + + if (!scene || !sceneInteractionAllowed) + return; + + // Convert and deliver the touch event to the scene. + QGraphicsSceneTouchEvent touchEvent(QEvent::GraphicsSceneTouchEnd); + touchEvent.setWidget(q->viewport()); + qt_convertTouchEventToGraphicsSceneTouchEvent(this, event, &touchEvent); + touchEvent.setAccepted(false); + QApplication::sendEvent(scene, &touchEvent); + event->setAccepted(touchEvent.isAccepted()); +} + QT_END_NAMESPACE #include "moc_qgraphicsview.cpp" diff --git a/src/gui/graphicsview/qgraphicsview_p.h b/src/gui/graphicsview/qgraphicsview_p.h index a76279e..abab921 100644 --- a/src/gui/graphicsview/qgraphicsview_p.h +++ b/src/gui/graphicsview/qgraphicsview_p.h @@ -181,6 +181,11 @@ public: const QTransform &worldTransform, bool allItems, const QRegion &exposedRegion) const; + + QPointF mapToScene(const QPointF &point) const; + void touchBeginEvent(QTouchEvent *event); + void touchUpdateEvent(QTouchEvent *event); + void touchEndEvent(QTouchEvent *event); }; QT_END_NAMESPACE |