From 5ec344cc7796b8708e2ae722f7cd184c56844504 Mon Sep 17 00:00:00 2001 From: Mitch Curtis Date: Tue, 16 Jul 2013 10:44:48 +0200 Subject: [PATCH] Make *ItemBoundingRect modes work with custom shapes. Currently, calling QGraphicsScene::items(QPointF(0, 0), Qt::IntersectsItemBoundingRect) or QGraphicsScene::items(QPointF(0, 0), Qt::ContainsItemBoundingRect) will exclude items whose shape does not contain QPointF(0, 0). This is because QGraphicsSceneIndexPointIntersector::intersect() also checks if the point is contained within the shape, instead of just checking if it is contained within the bounding rect. Task-number: QTBUG-19036 Change-Id: Ie701af2a5694d40cf9b3c9c19adbb09a53a4e398 Reviewed-by: Giuseppe D'Angelo Reviewed-by: Andreas Aardal Hanssen --- .../graphicsview/qgraphicssceneindex.cpp | 2 +- .../tst_qgraphicssceneindex.cpp | 52 +++++++++++++++++++ 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/src/widgets/graphicsview/qgraphicssceneindex.cpp b/src/widgets/graphicsview/qgraphicssceneindex.cpp index 4b1c990578..398e72e4c3 100644 --- a/src/widgets/graphicsview/qgraphicssceneindex.cpp +++ b/src/widgets/graphicsview/qgraphicssceneindex.cpp @@ -151,7 +151,7 @@ public: itemd->sceneTransform.dy()) : itemd->sceneTransform.mapRect(brect); keep = sceneBoundingRect.intersects(QRectF(scenePoint, QSizeF(1, 1))); - if (keep) { + if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) { QPointF p = itemd->sceneTransformTranslateOnly ? QPointF(scenePoint.x() - itemd->sceneTransform.dx(), scenePoint.y() - itemd->sceneTransform.dy()) diff --git a/tests/auto/widgets/graphicsview/qgraphicssceneindex/tst_qgraphicssceneindex.cpp b/tests/auto/widgets/graphicsview/qgraphicssceneindex/tst_qgraphicssceneindex.cpp index dd432912f3..55fcd96dc0 100644 --- a/tests/auto/widgets/graphicsview/qgraphicssceneindex/tst_qgraphicssceneindex.cpp +++ b/tests/auto/widgets/graphicsview/qgraphicssceneindex/tst_qgraphicssceneindex.cpp @@ -61,6 +61,8 @@ private slots: void movingItems(); void connectedToSceneRectChanged(); void items(); + void boundingRectPointIntersection_data(); + void boundingRectPointIntersection(); void removeItems(); void clear(); @@ -233,6 +235,56 @@ void tst_QGraphicsSceneIndex::items() QCOMPARE(scene.items().size(), 3); } +class CustomShapeItem : public QGraphicsItem +{ +public: + CustomShapeItem(const QPainterPath &shape) : QGraphicsItem(0), mShape(shape) {} + + QPainterPath shape() const { return mShape; } + QRectF boundingRect() const { return mShape.boundingRect(); } + void paint(QPainter*, const QStyleOptionGraphicsItem*, QWidget*) {} +private: + QPainterPath mShape; +}; + +Q_DECLARE_METATYPE(Qt::ItemSelectionMode) +Q_DECLARE_METATYPE(QPainterPath) + +void tst_QGraphicsSceneIndex::boundingRectPointIntersection_data() +{ + QTest::addColumn("itemShape"); + QTest::addColumn("mode"); + + QTest::newRow("zero shape - intersects rect") << QPainterPath() << Qt::IntersectsItemBoundingRect; + QTest::newRow("zero shape - contains rect") << QPainterPath() << Qt::ContainsItemBoundingRect; + + QPainterPath triangle; + triangle.moveTo(50, 0); + triangle.lineTo(0, 50); + triangle.lineTo(100, 50); + triangle.lineTo(50, 0); + QTest::newRow("triangle shape - intersects rect") << triangle << Qt::IntersectsItemBoundingRect; + QTest::newRow("triangle shape - contains rect") << triangle << Qt::ContainsItemBoundingRect; + + QPainterPath rect; + rect.addRect(QRectF(0, 0, 100, 100)); + QTest::newRow("rectangle shape - intersects rect") << rect << Qt::IntersectsItemBoundingRect; + QTest::newRow("rectangle shape - contains rect") << rect << Qt::ContainsItemBoundingRect; +} + +void tst_QGraphicsSceneIndex::boundingRectPointIntersection() +{ + QFETCH(QPainterPath, itemShape); + QFETCH(Qt::ItemSelectionMode, mode); + + QGraphicsScene scene; + CustomShapeItem *item = new CustomShapeItem(itemShape); + scene.addItem(item); + QList items = scene.items(QPointF(0, 0), mode, Qt::AscendingOrder); + QVERIFY(!items.isEmpty()); + QCOMPARE(items.first(), item); +} + class RectWidget : public QGraphicsWidget { Q_OBJECT