From adb0848513198db72c6066b9a97077c7083df9fe Mon Sep 17 00:00:00 2001 From: Adriano Rezende Date: Sun, 26 Feb 2012 17:26:53 +0100 Subject: Add contains method to QQuickItem public API This method can be overwritten in order to provide fine grained control over the mouse events handled by the item. Change-Id: I23cb61958d3ac0b2f5091c47fa9e0ed07dc5e5d0 Reviewed-by: Martin Jones --- src/quick/items/qquickcanvas.cpp | 23 +++++++++++------------ src/quick/items/qquickflickable.cpp | 6 +++--- src/quick/items/qquickitem.cpp | 22 +++++++++++++++++++--- src/quick/items/qquickitem.h | 2 ++ src/quick/items/qquickmousearea.cpp | 16 ++++++++-------- src/quick/items/qquickmultipointtoucharea.cpp | 18 ++++++++---------- src/quick/items/qquickpathview.cpp | 13 ++++++------- src/quick/items/qquickpincharea.cpp | 6 +++--- 8 files changed, 60 insertions(+), 46 deletions(-) (limited to 'src/quick/items') diff --git a/src/quick/items/qquickcanvas.cpp b/src/quick/items/qquickcanvas.cpp index a288531beb..91102331a6 100644 --- a/src/quick/items/qquickcanvas.cpp +++ b/src/quick/items/qquickcanvas.cpp @@ -1039,7 +1039,7 @@ bool QQuickCanvasPrivate::deliverInitialMousePressEvent(QQuickItem *item, QMouse if (itemPrivate->flags & QQuickItem::ItemClipsChildrenToShape) { QPointF p = item->mapFromScene(event->windowPos()); - if (!QRectF(0, 0, item->width(), item->height()).contains(p)) + if (!item->contains(p)) return false; } @@ -1054,7 +1054,7 @@ bool QQuickCanvasPrivate::deliverInitialMousePressEvent(QQuickItem *item, QMouse if (itemPrivate->acceptedMouseButtons() & event->button()) { QPointF p = item->mapFromScene(event->windowPos()); - if (QRectF(0, 0, item->width(), item->height()).contains(p)) { + if (item->contains(p)) { QMouseEvent me(event->type(), p, event->windowPos(), event->screenPos(), event->button(), event->buttons(), event->modifiers()); me.accept(); @@ -1218,7 +1218,7 @@ bool QQuickCanvasPrivate::deliverHoverEvent(QQuickItem *item, const QPointF &sce if (itemPrivate->flags & QQuickItem::ItemClipsChildrenToShape) { QPointF p = item->mapFromScene(scenePos); - if (!QRectF(0, 0, item->width(), item->height()).contains(p)) + if (!item->contains(p)) return false; } @@ -1233,7 +1233,7 @@ bool QQuickCanvasPrivate::deliverHoverEvent(QQuickItem *item, const QPointF &sce if (itemPrivate->hoverEnabled) { QPointF p = item->mapFromScene(scenePos); - if (QRectF(0, 0, item->width(), item->height()).contains(p)) { + if (item->contains(p)) { if (!hoverItems.isEmpty() && hoverItems[0] == item) { //move accepted = sendHoverEvent(QEvent::HoverMove, item, scenePos, lastScenePos, modifiers, accepted); @@ -1286,7 +1286,7 @@ bool QQuickCanvasPrivate::deliverWheelEvent(QQuickItem *item, QWheelEvent *event if (itemPrivate->flags & QQuickItem::ItemClipsChildrenToShape) { QPointF p = item->mapFromScene(event->posF()); - if (!QRectF(0, 0, item->width(), item->height()).contains(p)) + if (!item->contains(p)) return false; } @@ -1300,7 +1300,8 @@ bool QQuickCanvasPrivate::deliverWheelEvent(QQuickItem *item, QWheelEvent *event } QPointF p = item->mapFromScene(event->posF()); - if (QRectF(0, 0, item->width(), item->height()).contains(p)) { + + if (item->contains(p)) { QWheelEvent wheel(p, p, event->pixelDelta(), event->angleDelta(), event->delta(), event->orientation(), event->buttons(), event->modifiers()); wheel.accept(); @@ -1422,10 +1423,9 @@ bool QQuickCanvasPrivate::deliverTouchPoints(QQuickItem *item, QTouchEvent *even return false; if (itemPrivate->flags & QQuickItem::ItemClipsChildrenToShape) { - QRectF bounds(0, 0, item->width(), item->height()); for (int i=0; imapFromScene(newPoints[i].scenePos()); - if (!bounds.contains(p)) + if (!item->contains(p)) return false; } } @@ -1441,12 +1441,11 @@ bool QQuickCanvasPrivate::deliverTouchPoints(QQuickItem *item, QTouchEvent *even QList matchingPoints; if (newPoints.count() > 0 && acceptedNewPoints->count() < newPoints.count()) { - QRectF bounds(0, 0, item->width(), item->height()); for (int i=0; icontains(newPoints[i].id())) continue; QPointF p = item->mapFromScene(newPoints[i].scenePos()); - if (bounds.contains(p)) + if (item->contains(p)) matchingPoints << newPoints[i]; } } @@ -1537,7 +1536,7 @@ void QQuickCanvasPrivate::deliverDragEvent(QQuickDragGrabber *grabber, QEvent *e moveEvent->setAccepted(true); for (++grabItem; grabItem != grabber->end();) { QPointF p = (**grabItem)->mapFromScene(moveEvent->pos()); - if (QRectF(0, 0, (**grabItem)->width(), (**grabItem)->height()).contains(p)) { + if ((**grabItem)->contains(p)) { QDragMoveEvent translatedEvent( p.toPoint(), moveEvent->possibleActions(), @@ -1582,7 +1581,7 @@ bool QQuickCanvasPrivate::deliverDragEvent(QQuickDragGrabber *grabber, QQuickIte return false; QPointF p = item->mapFromScene(event->pos()); - if (QRectF(0, 0, item->width(), item->height()).contains(p)) { + if (item->contains(p)) { if (event->type() == QEvent::DragMove || itemPrivate->flags & QQuickItem::ItemAcceptsDrops) { QDragMoveEvent translatedEvent( p.toPoint(), diff --git a/src/quick/items/qquickflickable.cpp b/src/quick/items/qquickflickable.cpp index 75c9919e34..76d36987dd 100644 --- a/src/quick/items/qquickflickable.cpp +++ b/src/quick/items/qquickflickable.cpp @@ -1772,14 +1772,14 @@ void QQuickFlickable::mouseUngrabEvent() bool QQuickFlickable::sendMouseEvent(QMouseEvent *event) { Q_D(QQuickFlickable); - QRectF myRect = mapRectToScene(QRectF(0, 0, width(), height())); + QPointF localPos = mapFromScene(event->windowPos()); QQuickCanvas *c = canvas(); QQuickItem *grabber = c ? c->mouseGrabberItem() : 0; bool disabledItem = grabber && !grabber->isEnabled(); bool stealThisEvent = d->stealMouse; - if ((stealThisEvent || myRect.contains(event->windowPos())) && (!grabber || !grabber->keepMouseGrab() || disabledItem)) { - QQuickMouseEventEx mouseEvent(event->type(), mapFromScene(event->windowPos()), + if ((stealThisEvent || contains(localPos)) && (!grabber || !grabber->keepMouseGrab() || disabledItem)) { + QQuickMouseEventEx mouseEvent(event->type(), localPos, event->windowPos(), event->screenPos(), event->button(), event->buttons(), event->modifiers()); QQuickMouseEventEx *eventEx = QQuickMouseEventEx::extended(event); diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index ffaec540a2..628e19dbec 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -4886,9 +4886,7 @@ bool QQuickItem::isUnderMouse() const return false; QPointF cursorPos = QGuiApplicationPrivate::lastCursorPosition; - if (QRectF(0, 0, width(), height()).contains(mapFromScene(cursorPos))) // ### refactor: d->canvas->mapFromGlobal(cursorPos)))) - return true; - return false; + return contains(mapFromScene(cursorPos)); // ### refactor: d->canvas->mapFromGlobal(cursorPos)))) } bool QQuickItem::acceptHoverEvents() const @@ -5055,6 +5053,24 @@ void QQuickItem::setKeepTouchGrab(bool keep) d->keepTouch = keep; } +/*! + Returns true if this item contains \a point, which is in local coordinates; + returns false otherwise. + + This function can be overwritten in order to handle point collisions in items + with custom shapes. The default implementation checks if the point is inside + the item's bounding rect. + + Note that it's normally used to check if the item is under the mouse cursor, + and for that reason, the implementation of this function should be as light-weight + as possible. +*/ +bool QQuickItem::contains(const QPointF &point) const +{ + Q_D(const QQuickItem); + return QRectF(0, 0, d->width, d->height).contains(point); +} + /*! \qmlmethod object QtQuick2::Item::mapFromItem(Item item, real x, real y) diff --git a/src/quick/items/qquickitem.h b/src/quick/items/qquickitem.h index 16dee80380..0d74cc0c4d 100644 --- a/src/quick/items/qquickitem.h +++ b/src/quick/items/qquickitem.h @@ -292,6 +292,8 @@ public: bool keepTouchGrab() const; void setKeepTouchGrab(bool); + Q_INVOKABLE virtual bool contains(const QPointF &point) const; + QTransform itemTransform(QQuickItem *, bool *) const; QPointF mapToItem(const QQuickItem *item, const QPointF &point) const; QPointF mapToScene(const QPointF &point) const; diff --git a/src/quick/items/qquickmousearea.cpp b/src/quick/items/qquickmousearea.cpp index b8555124eb..956ca09aac 100644 --- a/src/quick/items/qquickmousearea.cpp +++ b/src/quick/items/qquickmousearea.cpp @@ -263,7 +263,7 @@ bool QQuickMouseAreaPrivate::propagateHelper(QQuickMouseEvent *ev, QQuickItem *i if (itemPrivate->flags & QQuickItem::ItemClipsChildrenToShape) { QPointF p = item->mapFromScene(sp); - if (!QRectF(0, 0, item->width(), item->height()).contains(p)) + if (!item->contains(p)) return false; } @@ -293,7 +293,7 @@ bool QQuickMouseAreaPrivate::propagateHelper(QQuickMouseEvent *ev, QQuickItem *i break; } QPointF p = item->mapFromScene(sp); - if (QRectF(0, 0, item->width(), item->height()).contains(p)) { + if (item->contains(p)) { ev->setX(p.x()); ev->setY(p.y()); ev->setAccepted(true);//It is connected, they have to explicitly ignore to let it slide @@ -725,10 +725,10 @@ void QQuickMouseArea::mouseMoveEvent(QMouseEvent *event) // ### we should skip this if these signals aren't used // ### can GV handle this for us? - bool contains = boundingRect().contains(d->lastPos); - if (d->hovered && !contains) + const bool isInside = contains(d->lastPos); + if (d->hovered && !isInside) setHovered(false); - else if (!d->hovered && contains) + else if (!d->hovered && isInside) setHovered(true); if (d->drag && d->drag->target()) { @@ -921,13 +921,13 @@ void QQuickMouseArea::mouseUngrabEvent() bool QQuickMouseArea::sendMouseEvent(QMouseEvent *event) { Q_D(QQuickMouseArea); - QRectF myRect = mapRectToScene(QRectF(0, 0, width(), height())); + QPointF localPos = mapFromScene(event->windowPos()); QQuickCanvas *c = canvas(); QQuickItem *grabber = c ? c->mouseGrabberItem() : 0; bool stealThisEvent = d->stealMouse; - if ((stealThisEvent || myRect.contains(event->windowPos())) && (!grabber || !grabber->keepMouseGrab())) { - QMouseEvent mouseEvent(event->type(), mapFromScene(event->windowPos()), event->windowPos(), event->screenPos(), + if ((stealThisEvent || contains(localPos)) && (!grabber || !grabber->keepMouseGrab())) { + QMouseEvent mouseEvent(event->type(), localPos, event->windowPos(), event->screenPos(), event->button(), event->buttons(), event->modifiers()); mouseEvent.setAccepted(false); diff --git a/src/quick/items/qquickmultipointtoucharea.cpp b/src/quick/items/qquickmultipointtoucharea.cpp index 2ba7b80748..df5edfb00d 100644 --- a/src/quick/items/qquickmultipointtoucharea.cpp +++ b/src/quick/items/qquickmultipointtoucharea.cpp @@ -644,13 +644,13 @@ void QQuickMultiPointTouchArea::touchUngrabEvent() bool QQuickMultiPointTouchArea::sendMouseEvent(QMouseEvent *event) { - QRectF myRect = mapRectToScene(QRectF(0, 0, width(), height())); + QPointF localPos = mapFromScene(event->windowPos()); QQuickCanvas *c = canvas(); QQuickItem *grabber = c ? c->mouseGrabberItem() : 0; bool stealThisEvent = _stealMouse; - if ((stealThisEvent || myRect.contains(event->windowPos())) && (!grabber || !grabber->keepMouseGrab())) { - QMouseEvent mouseEvent(event->type(), mapFromScene(event->windowPos()), event->windowPos(), event->screenPos(), + if ((stealThisEvent || contains(localPos)) && (!grabber || !grabber->keepMouseGrab())) { + QMouseEvent mouseEvent(event->type(), localPos, event->windowPos(), event->screenPos(), event->button(), event->buttons(), event->modifiers()); mouseEvent.setAccepted(false); @@ -724,25 +724,23 @@ bool QQuickMultiPointTouchArea::shouldFilter(QEvent *event) QQuickItem *grabber = c ? c->mouseGrabberItem() : 0; bool disabledItem = grabber && !grabber->isEnabled(); bool stealThisEvent = _stealMouse; - bool contains = false; + bool containsPoint = false; if (!stealThisEvent) { switch (event->type()) { case QEvent::MouseButtonPress: case QEvent::MouseMove: case QEvent::MouseButtonRelease: { QMouseEvent *me = static_cast(event); - QRectF myRect = mapRectToScene(QRectF(0, 0, width(), height())); - contains = myRect.contains(me->windowPos()); + containsPoint = contains(mapFromScene(me->windowPos())); } break; case QEvent::TouchBegin: case QEvent::TouchUpdate: case QEvent::TouchEnd: { QTouchEvent *te = static_cast(event); - QRectF myRect = mapRectToScene(QRectF(0, 0, width(), height())); foreach (const QTouchEvent::TouchPoint &point, te->touchPoints()) { - if (myRect.contains(point.scenePos())) { - contains = true; + if (contains(mapFromScene(point.scenePos()))) { + containsPoint = true; break; } } @@ -752,7 +750,7 @@ bool QQuickMultiPointTouchArea::shouldFilter(QEvent *event) break; } } - if ((stealThisEvent || contains) && (!grabber || !grabber->keepMouseGrab() || disabledItem)) { + if ((stealThisEvent || containsPoint) && (!grabber || !grabber->keepMouseGrab() || disabledItem)) { return true; } ungrab(); diff --git a/src/quick/items/qquickpathview.cpp b/src/quick/items/qquickpathview.cpp index 836943c478..ba5b237596 100644 --- a/src/quick/items/qquickpathview.cpp +++ b/src/quick/items/qquickpathview.cpp @@ -1300,12 +1300,10 @@ void QQuickPathViewPrivate::handleMousePressEvent(QMouseEvent *event) if (!interactive || !items.count() || !model || !modelCount) return; velocityBuffer.clear(); - QPointF scenePoint = q->mapToScene(event->localPos()); int idx = 0; for (; idx < items.count(); ++idx) { - QRectF rect = items.at(idx)->boundingRect(); - rect = items.at(idx)->mapRectToScene(rect); - if (rect.contains(scenePoint)) + QQuickItem *item = items.at(idx); + if (item->contains(item->mapFromScene(event->windowPos()))) break; } if (idx == items.count() && dragMargin == 0.) // didn't click on an item @@ -1470,12 +1468,13 @@ void QQuickPathViewPrivate::handleMouseReleaseEvent(QMouseEvent *) bool QQuickPathView::sendMouseEvent(QMouseEvent *event) { Q_D(QQuickPathView); - QRectF myRect = mapRectToScene(QRectF(0, 0, width(), height())); + QPointF localPos = mapFromScene(event->windowPos()); + QQuickCanvas *c = canvas(); QQuickItem *grabber = c ? c->mouseGrabberItem() : 0; bool stealThisEvent = d->stealMouse; - if ((stealThisEvent || myRect.contains(event->windowPos())) && (!grabber || !grabber->keepMouseGrab())) { - QMouseEvent mouseEvent(event->type(), mapFromScene(event->windowPos()), event->windowPos(), event->screenPos(), + if ((stealThisEvent || contains(localPos)) && (!grabber || !grabber->keepMouseGrab())) { + QMouseEvent mouseEvent(event->type(), localPos, event->windowPos(), event->screenPos(), event->button(), event->buttons(), event->modifiers()); mouseEvent.setAccepted(false); diff --git a/src/quick/items/qquickpincharea.cpp b/src/quick/items/qquickpincharea.cpp index 6f79385d96..eba9d098ff 100644 --- a/src/quick/items/qquickpincharea.cpp +++ b/src/quick/items/qquickpincharea.cpp @@ -503,13 +503,13 @@ void QQuickPinchArea::mouseUngrabEvent() bool QQuickPinchArea::sendMouseEvent(QMouseEvent *event) { Q_D(QQuickPinchArea); - QRectF myRect = mapRectToScene(QRectF(0, 0, width(), height())); + QPointF localPos = mapFromScene(event->windowPos()); QQuickCanvas *c = canvas(); QQuickItem *grabber = c ? c->mouseGrabberItem() : 0; bool stealThisEvent = d->stealMouse; - if ((stealThisEvent || myRect.contains(event->windowPos())) && (!grabber || !grabber->keepMouseGrab())) { - QMouseEvent mouseEvent(event->type(), mapFromScene(event->windowPos()), event->windowPos(), event->screenPos(), + if ((stealThisEvent || contains(localPos)) && (!grabber || !grabber->keepMouseGrab())) { + QMouseEvent mouseEvent(event->type(), localPos, event->windowPos(), event->screenPos(), event->button(), event->buttons(), event->modifiers()); mouseEvent.setAccepted(false); -- cgit v1.2.3