summaryrefslogtreecommitdiffstats
path: root/tests/auto/qgraphicsitem
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/qgraphicsitem')
-rw-r--r--tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp3574
1 files changed, 3291 insertions, 283 deletions
diff --git a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp
index 215334c..9545198 100644
--- a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp
+++ b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp
@@ -44,6 +44,8 @@
#include <private/qtextcontrol_p.h>
#include <private/qgraphicsitem_p.h>
+#include <private/qgraphicsview_p.h>
+#include <QStyleOptionGraphicsItem>
#include <QAbstractTextDocumentLayout>
#include <QBitmap>
#include <QCursor>
@@ -58,6 +60,8 @@
#include <QPainter>
#include <QScrollBar>
#include <QVBoxLayout>
+#include <QGraphicsEffect>
+
#include "../../shared/util.h"
//TESTED_CLASS=
@@ -78,6 +82,130 @@ Q_DECLARE_METATYPE(QRectF)
#define Q_CHECK_PAINTEVENTS
#endif
+static void sendMousePress(QGraphicsScene *scene, const QPointF &point, Qt::MouseButton button = Qt::LeftButton)
+{
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
+ event.setScenePos(point);
+ event.setButton(button);
+ event.setButtons(button);
+ QApplication::sendEvent(scene, &event);
+}
+
+static void sendMouseMove(QGraphicsScene *scene, const QPointF &point,
+ Qt::MouseButton button = Qt::NoButton, Qt::MouseButtons buttons = 0)
+{
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseMove);
+ event.setScenePos(point);
+ event.setButton(button);
+ event.setButtons(button);
+ QApplication::sendEvent(scene, &event);
+}
+
+static void sendMouseRelease(QGraphicsScene *scene, const QPointF &point, Qt::MouseButton button = Qt::LeftButton)
+{
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseRelease);
+ event.setScenePos(point);
+ event.setButton(button);
+ QApplication::sendEvent(scene, &event);
+}
+
+static void sendMouseClick(QGraphicsScene *scene, const QPointF &point, Qt::MouseButton button = Qt::LeftButton)
+{
+ sendMousePress(scene, point, button);
+ sendMouseRelease(scene, point, button);
+}
+
+static void sendKeyPress(QGraphicsScene *scene, Qt::Key key)
+{
+ QKeyEvent keyEvent(QEvent::KeyPress, key, Qt::NoModifier);
+ QApplication::sendEvent(scene, &keyEvent);
+}
+
+static void sendKeyRelease(QGraphicsScene *scene, Qt::Key key)
+{
+ QKeyEvent keyEvent(QEvent::KeyRelease, key, Qt::NoModifier);
+ QApplication::sendEvent(scene, &keyEvent);
+}
+
+static void sendKeyClick(QGraphicsScene *scene, Qt::Key key)
+{
+ sendKeyPress(scene, key);
+ sendKeyRelease(scene, key);
+}
+
+class EventSpy : public QGraphicsWidget
+{
+ Q_OBJECT
+public:
+ EventSpy(QObject *watched, QEvent::Type type)
+ : _count(0), spied(type)
+ {
+ watched->installEventFilter(this);
+ }
+
+ EventSpy(QGraphicsScene *scene, QGraphicsItem *watched, QEvent::Type type)
+ : _count(0), spied(type)
+ {
+ scene->addItem(this);
+ watched->installSceneEventFilter(this);
+ }
+
+ int count() const { return _count; }
+
+protected:
+ bool eventFilter(QObject *watched, QEvent *event)
+ {
+ Q_UNUSED(watched);
+ if (event->type() == spied)
+ ++_count;
+ return false;
+ }
+
+ bool sceneEventFilter(QGraphicsItem *watched, QEvent *event)
+ {
+ Q_UNUSED(watched);
+ if (event->type() == spied)
+ ++_count;
+ return false;
+ }
+
+ int _count;
+ QEvent::Type spied;
+};
+
+class EventSpy2 : public QGraphicsWidget
+{
+ Q_OBJECT
+public:
+ EventSpy2(QObject *watched)
+ {
+ watched->installEventFilter(this);
+ }
+
+ EventSpy2(QGraphicsScene *scene, QGraphicsItem *watched)
+ {
+ scene->addItem(this);
+ watched->installSceneEventFilter(this);
+ }
+
+ QMap<QEvent::Type, int> counts;
+
+protected:
+ bool eventFilter(QObject *watched, QEvent *event)
+ {
+ Q_UNUSED(watched);
+ ++counts[event->type()];
+ return false;
+ }
+
+ bool sceneEventFilter(QGraphicsItem *watched, QEvent *event)
+ {
+ Q_UNUSED(watched);
+ ++counts[event->type()];
+ return false;
+ }
+};
+
class EventTester : public QGraphicsItem
{
public:
@@ -124,11 +252,13 @@ private slots:
void construction();
void constructionWithParent();
void destruction();
+ void deleteChildItem();
void scene();
void parentItem();
void setParentItem();
void children();
void flags();
+ void inputMethodHints();
void toolTip();
void visible();
void explicitlyVisible();
@@ -173,7 +303,9 @@ private slots:
void boundingRects2();
void sceneBoundingRect();
void childrenBoundingRect();
+ void childrenBoundingRectTransformed();
void childrenBoundingRect2();
+ void childrenBoundingRect3();
void group();
void setGroup();
void nestedGroups();
@@ -182,6 +314,8 @@ private slots:
void handlesChildEvents();
void handlesChildEvents2();
void handlesChildEvents3();
+ void filtersChildEvents();
+ void filtersChildEvents2();
void ensureVisible();
void cursor();
//void textControlGetterSetter();
@@ -224,6 +358,38 @@ private slots:
void updateCachedItemAfterMove();
void deviceTransform_data();
void deviceTransform();
+ void update();
+ void setTransformProperties_data();
+ void setTransformProperties();
+ void itemUsesExtendedStyleOption();
+ void itemSendsGeometryChanges();
+ void moveItem();
+ void sorting_data();
+ void sorting();
+ void itemHasNoContents();
+ void hitTestUntransformableItem();
+ void hitTestGraphicsEffectItem();
+ void focusProxy();
+ void subFocus();
+ void focusProxyDeletion();
+ void negativeZStacksBehindParent();
+ void setGraphicsEffect();
+ void panel();
+ void addPanelToActiveScene();
+ void activate();
+ void setActivePanelOnInactiveScene();
+ void activationOnShowHide();
+ void moveWhileDeleting();
+ void ensureDirtySceneTransform();
+ void focusScope();
+ void stackBefore();
+ void sceneModality();
+ void panelModality();
+ void mixedModality();
+ void modality_hover();
+ void modality_mouseGrabber();
+ void modality_clickFocus();
+ void modality_keyEvents();
// task specific tests below me
void task141694_textItemEnsureVisible();
@@ -235,6 +401,9 @@ private slots:
void task243707_addChildBeforeParent();
void task197802_childrenVisibility();
void QTBUG_4233_updateCachedWithSceneRect();
+
+private:
+ QList<QGraphicsItem *> paintedItems;
};
void tst_QGraphicsItem::init()
@@ -254,50 +423,59 @@ void tst_QGraphicsItem::construction()
QCOMPARE(int(item->type()), int(QGraphicsEllipseItem::Type));
QCOMPARE(qgraphicsitem_cast<QGraphicsEllipseItem *>(item), (QGraphicsEllipseItem *)item);
QCOMPARE(qgraphicsitem_cast<QGraphicsRectItem *>(item), (QGraphicsRectItem *)0);
+ QCOMPARE(item->flags(), 0);
break;
case 1:
item = new QGraphicsLineItem;
QCOMPARE(int(item->type()), int(QGraphicsLineItem::Type));
QCOMPARE(qgraphicsitem_cast<QGraphicsLineItem *>(item), (QGraphicsLineItem *)item);
QCOMPARE(qgraphicsitem_cast<QGraphicsRectItem *>(item), (QGraphicsRectItem *)0);
+ QCOMPARE(item->flags(), 0);
break;
case 2:
item = new QGraphicsPathItem;
QCOMPARE(int(item->type()), int(QGraphicsPathItem::Type));
QCOMPARE(qgraphicsitem_cast<QGraphicsPathItem *>(item), (QGraphicsPathItem *)item);
QCOMPARE(qgraphicsitem_cast<QGraphicsRectItem *>(item), (QGraphicsRectItem *)0);
+ QCOMPARE(item->flags(), 0);
break;
case 3:
item = new QGraphicsPixmapItem;
QCOMPARE(int(item->type()), int(QGraphicsPixmapItem::Type));
QCOMPARE(qgraphicsitem_cast<QGraphicsPixmapItem *>(item), (QGraphicsPixmapItem *)item);
QCOMPARE(qgraphicsitem_cast<QGraphicsRectItem *>(item), (QGraphicsRectItem *)0);
+ QCOMPARE(item->flags(), 0);
break;
case 4:
item = new QGraphicsPolygonItem;
QCOMPARE(int(item->type()), int(QGraphicsPolygonItem::Type));
QCOMPARE(qgraphicsitem_cast<QGraphicsPolygonItem *>(item), (QGraphicsPolygonItem *)item);
QCOMPARE(qgraphicsitem_cast<QGraphicsRectItem *>(item), (QGraphicsRectItem *)0);
+ QCOMPARE(item->flags(), 0);
break;
case 5:
item = new QGraphicsRectItem;
QCOMPARE(int(item->type()), int(QGraphicsRectItem::Type));
QCOMPARE(qgraphicsitem_cast<QGraphicsRectItem *>(item), (QGraphicsRectItem *)item);
QCOMPARE(qgraphicsitem_cast<QGraphicsLineItem *>(item), (QGraphicsLineItem *)0);
+ QCOMPARE(item->flags(), 0);
break;
case 6:
- default:
item = new QGraphicsTextItem;
QCOMPARE(int(item->type()), int(QGraphicsTextItem::Type));
QCOMPARE(qgraphicsitem_cast<QGraphicsTextItem *>(item), (QGraphicsTextItem *)item);
QCOMPARE(qgraphicsitem_cast<QGraphicsRectItem *>(item), (QGraphicsRectItem *)0);
+ // This is the only item that uses an extended style option.
+ QCOMPARE(item->flags(), QGraphicsItem::GraphicsItemFlags(QGraphicsItem::ItemUsesExtendedStyleOption));
+ break;
+ default:
+ qFatal("You broke the logic, please fix!");
break;
}
QCOMPARE(item->scene(), (QGraphicsScene *)0);
QCOMPARE(item->parentItem(), (QGraphicsItem *)0);
QVERIFY(item->children().isEmpty());
- QCOMPARE(item->flags(), 0);
QVERIFY(item->isVisible());
QVERIFY(item->isEnabled());
QVERIFY(!item->isSelected());
@@ -522,6 +700,29 @@ void tst_QGraphicsItem::destruction()
QCOMPARE(itemDeleted, 59);
}
QCOMPARE(itemDeleted, 109);
+ {
+ QGraphicsScene *scene = new QGraphicsScene;
+ QGraphicsRectItem *parent = new QGraphicsRectItem;
+ Item *child = new Item;
+ child->setParentItem(parent);
+ parent->setVisible(false);
+ scene->addItem(parent);
+ QCOMPARE(child->parentItem(), static_cast<QGraphicsItem*>(parent));
+ delete scene;
+ QCOMPARE(itemDeleted, 110);
+ }
+}
+
+void tst_QGraphicsItem::deleteChildItem()
+{
+ QGraphicsScene scene;
+ QGraphicsItem *rect = scene.addRect(QRectF());
+ QGraphicsItem *child1 = new QGraphicsRectItem(rect);
+ QGraphicsItem *child2 = new QGraphicsRectItem(rect);
+ QGraphicsItem *child3 = new QGraphicsRectItem(rect);
+ delete child1;
+ child2->setParentItem(0);
+ delete child2;
}
void tst_QGraphicsItem::scene()
@@ -601,6 +802,9 @@ void tst_QGraphicsItem::flags()
QCOMPARE(item->flags(), 0);
QGraphicsScene scene;
+ QEvent activate(QEvent::WindowActivate);
+ QApplication::sendEvent(&scene, &activate);
+
scene.addItem(item);
{
@@ -689,6 +893,18 @@ void tst_QGraphicsItem::flags()
}
}
+class ImhTester : public QGraphicsItem
+{
+ QRectF boundingRect() const { return QRectF(); }
+ void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *) {}
+};
+
+void tst_QGraphicsItem::inputMethodHints()
+{
+ ImhTester item;
+ QCOMPARE(item.inputMethodHints(), Qt::ImhNone);
+}
+
void tst_QGraphicsItem::toolTip()
{
QString toolTip = "Qt rocks!";
@@ -773,6 +989,9 @@ void tst_QGraphicsItem::visible()
QVERIFY(item->isVisible());
QGraphicsScene scene;
+ QEvent activate(QEvent::WindowActivate);
+ QApplication::sendEvent(&scene, &activate);
+
scene.addItem(item);
QVERIFY(item->isVisible());
QCOMPARE(scene.itemAt(0, 0), item);
@@ -920,6 +1139,9 @@ void tst_QGraphicsItem::enabled()
item->setEnabled(false);
item->setFlag(QGraphicsItem::ItemIsFocusable);
QGraphicsScene scene;
+ QEvent activate(QEvent::WindowActivate);
+ QApplication::sendEvent(&scene, &activate);
+
scene.addItem(item);
item->setFocus();
QVERIFY(!item->hasFocus());
@@ -1125,6 +1347,7 @@ void tst_QGraphicsItem::selected()
QVERIFY(!item->isSelected());
// Click inside and check that it's selected
+ QTest::mouseMove(view.viewport());
QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item->scenePos()));
QCOMPARE(item->values.size(), 11);
QCOMPARE(item->values.last(), true);
@@ -1132,7 +1355,6 @@ void tst_QGraphicsItem::selected()
// Click outside and check that it's not selected
QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item->scenePos() + QPointF(item->boundingRect().width(), item->boundingRect().height())));
-
QCOMPARE(item->values.size(), 12);
QCOMPARE(item->values.last(), false);
QVERIFY(!item->isSelected());
@@ -1244,19 +1466,20 @@ void tst_QGraphicsItem::selected_textItem()
QGraphicsView view(&scene);
view.show();
- QTest::qWait(1000);
+ QTest::qWaitForWindowShown(&view);
+ QTest::qWait(20);
- QVERIFY(!text->isSelected());
+ QTRY_VERIFY(!text->isSelected());
QTest::mouseClick(view.viewport(), Qt::LeftButton, 0,
view.mapFromScene(text->mapToScene(0, 0)));
- QVERIFY(text->isSelected());
+ QTRY_VERIFY(text->isSelected());
text->setSelected(false);
text->setTextInteractionFlags(Qt::TextEditorInteraction);
QTest::mouseClick(view.viewport(), Qt::LeftButton, 0,
view.mapFromScene(text->mapToScene(0, 0)));
- QVERIFY(text->isSelected());
+ QTRY_VERIFY(text->isSelected());
}
void tst_QGraphicsItem::selected_multi()
@@ -1288,91 +1511,91 @@ void tst_QGraphicsItem::selected_multi()
// Click on item1
QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item1->scenePos()));
- QTest::qWait(200);
+ QTest::qWait(20);
QVERIFY(item1->isSelected());
QVERIFY(!item2->isSelected());
// Click on item2
QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item2->scenePos()));
- QTest::qWait(200);
+ QTest::qWait(20);
QVERIFY(item2->isSelected());
QVERIFY(!item1->isSelected());
// Ctrl-click on item1
QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(item1->scenePos()));
- QTest::qWait(200);
+ QTest::qWait(20);
QVERIFY(item2->isSelected());
QVERIFY(item1->isSelected());
// Ctrl-click on item1 again
QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(item1->scenePos()));
- QTest::qWait(200);
+ QTest::qWait(20);
QVERIFY(item2->isSelected());
QVERIFY(!item1->isSelected());
// Ctrl-click on item2
QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(item2->scenePos()));
- QTest::qWait(200);
+ QTest::qWait(20);
QVERIFY(!item2->isSelected());
QVERIFY(!item1->isSelected());
// Click on item1
QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item1->scenePos()));
- QTest::qWait(200);
+ QTest::qWait(20);
QVERIFY(item1->isSelected());
QVERIFY(!item2->isSelected());
// Click on scene
QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(0, 0));
- QTest::qWait(200);
+ QTest::qWait(20);
QVERIFY(!item1->isSelected());
QVERIFY(!item2->isSelected());
// Click on item1
QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item1->scenePos()));
- QTest::qWait(200);
+ QTest::qWait(20);
QVERIFY(item1->isSelected());
QVERIFY(!item2->isSelected());
// Ctrl-click on scene
QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(0, 0));
- QTest::qWait(200);
+ QTest::qWait(20);
QVERIFY(!item1->isSelected());
QVERIFY(!item2->isSelected());
// Click on item1
QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item1->scenePos()));
- QTest::qWait(200);
+ QTest::qWait(20);
QVERIFY(item1->isSelected());
QVERIFY(!item2->isSelected());
// Press on item2
QTest::mousePress(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item2->scenePos()));
- QTest::qWait(200);
+ QTest::qWait(20);
QVERIFY(!item1->isSelected());
QVERIFY(item2->isSelected());
// Release on item2
QTest::mouseRelease(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item2->scenePos()));
- QTest::qWait(200);
+ QTest::qWait(20);
QVERIFY(!item1->isSelected());
QVERIFY(item2->isSelected());
// Click on item1
QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item1->scenePos()));
- QTest::qWait(200);
+ QTest::qWait(20);
QVERIFY(item1->isSelected());
QVERIFY(!item2->isSelected());
// Ctrl-click on item1
QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(item1->scenePos()));
- QTest::qWait(200);
+ QTest::qWait(20);
QVERIFY(!item1->isSelected());
QVERIFY(!item2->isSelected());
// Ctrl-press on item1
QTest::mousePress(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(item1->scenePos()));
- QTest::qWait(200);
+ QTest::qWait(20);
QVERIFY(!item1->isSelected());
QVERIFY(!item2->isSelected());
@@ -1380,14 +1603,14 @@ void tst_QGraphicsItem::selected_multi()
// Ctrl-move on item1
QMouseEvent event(QEvent::MouseMove, view.mapFromScene(item1->scenePos()) + QPoint(1, 0), Qt::LeftButton, Qt::LeftButton, Qt::ControlModifier);
QApplication::sendEvent(view.viewport(), &event);
- QTest::qWait(200);
+ QTest::qWait(20);
QVERIFY(!item1->isSelected());
QVERIFY(!item2->isSelected());
}
// Release on item1
QTest::mouseRelease(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(item1->scenePos()));
- QTest::qWait(200);
+ QTest::qWait(20);
QVERIFY(item1->isSelected());
QVERIFY(!item2->isSelected());
@@ -1396,7 +1619,7 @@ void tst_QGraphicsItem::selected_multi()
// Ctrl-press on item1
QTest::mousePress(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(item1->scenePos()));
- QTest::qWait(200);
+ QTest::qWait(20);
QVERIFY(!item1->isSelected());
QVERIFY(!item2->isSelected());
@@ -1404,14 +1627,14 @@ void tst_QGraphicsItem::selected_multi()
// Ctrl-move on item1
QMouseEvent event(QEvent::MouseMove, view.mapFromScene(item1->scenePos()) + QPoint(1, 0), Qt::LeftButton, Qt::LeftButton, Qt::ControlModifier);
QApplication::sendEvent(view.viewport(), &event);
- QTest::qWait(200);
+ QTest::qWait(20);
QVERIFY(item1->isSelected());
QVERIFY(!item2->isSelected());
}
// Release on item1
QTest::mouseRelease(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(item1->scenePos()));
- QTest::qWait(200);
+ QTest::qWait(20);
QVERIFY(item1->isSelected());
QVERIFY(!item2->isSelected());
}
@@ -1599,6 +1822,9 @@ void tst_QGraphicsItem::hasFocus()
QVERIFY(!line->hasFocus());
QGraphicsScene scene;
+ QEvent activate(QEvent::WindowActivate);
+ QApplication::sendEvent(&scene, &activate);
+
scene.addItem(line);
line->setFocus();
@@ -1608,6 +1834,8 @@ void tst_QGraphicsItem::hasFocus()
QVERIFY(line->hasFocus());
QGraphicsScene scene2;
+ QApplication::sendEvent(&scene2, &activate);
+
scene2.addItem(line);
QVERIFY(!line->hasFocus());
@@ -1778,15 +2006,15 @@ void tst_QGraphicsItem::setMatrix()
QCOMPARE(rlist.at(2), unrotatedRect); // From post-update (update current state)
}
-static QList<QGraphicsItem *> paintedItems;
+static QList<QGraphicsItem *> _paintedItems;
class PainterItem : public QGraphicsItem
{
protected:
QRectF boundingRect() const
{ return QRectF(-10, -10, 20, 20); }
- void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *)
- { paintedItems << this; }
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
+ { _paintedItems << this; painter->fillRect(boundingRect(), Qt::red); }
};
void tst_QGraphicsItem::zValue()
@@ -1818,10 +2046,10 @@ void tst_QGraphicsItem::zValue()
QApplication::sendPostedEvents(); //glib workaround
#endif
- QVERIFY(!paintedItems.isEmpty());
- QVERIFY((paintedItems.size() % 4) == 0);
+ QTRY_VERIFY(!_paintedItems.isEmpty());
+ QVERIFY((_paintedItems.size() % 4) == 0);
for (int i = 0; i < 3; ++i)
- QVERIFY(paintedItems.at(i)->zValue() < paintedItems.at(i + 1)->zValue());
+ QVERIFY(_paintedItems.at(i)->zValue() < _paintedItems.at(i + 1)->zValue());
}
void tst_QGraphicsItem::shape()
@@ -2789,19 +3017,16 @@ void tst_QGraphicsItem::hoverEventsGenerateRepaints()
Q_CHECK_PAINTEVENTS
QGraphicsScene scene;
- EventTester *tester = new EventTester;
- scene.addItem(tester);
- tester->setAcceptsHoverEvents(true);
-
QGraphicsView view(&scene);
view.show();
-#ifdef Q_WS_X11
- qt_x11_wait_for_window_manager(&view);
-#endif
+ QTest::qWaitForWindowShown(&view);
+ QTest::qWait(150);
- qApp->processEvents();
- qApp->processEvents();
+ EventTester *tester = new EventTester;
+ scene.addItem(tester);
+ tester->setAcceptsHoverEvents(true);
+ QTRY_COMPARE(tester->repaints, 1);
// Send a hover enter event
QGraphicsSceneHoverEvent hoverEnterEvent(QEvent::GraphicsSceneHoverEnter);
@@ -2813,7 +3038,7 @@ void tst_QGraphicsItem::hoverEventsGenerateRepaints()
int npaints = tester->repaints;
qApp->processEvents();
qApp->processEvents();
- QCOMPARE(tester->events.size(), 2); // enter + move
+ QCOMPARE(tester->events.size(), 2); // enter + move
QCOMPARE(tester->repaints, npaints + 1);
QCOMPARE(tester->events.last(), QEvent::GraphicsSceneHoverMove);
@@ -2920,9 +3145,58 @@ void tst_QGraphicsItem::childrenBoundingRect()
childChild->setParentItem(child);
childChild->setPos(500, 500);
child->rotate(90);
+
+
+ scene.addPolygon(parent->mapToScene(parent->boundingRect() | parent->childrenBoundingRect()))->setPen(QPen(Qt::red));;
+
+ QGraphicsView view(&scene);
+ view.show();
+
+ QTest::qWaitForWindowShown(&view);
+ QTest::qWait(30);
+
QCOMPARE(parent->childrenBoundingRect(), QRectF(-500, -100, 600, 800));
}
+void tst_QGraphicsItem::childrenBoundingRectTransformed()
+{
+ QGraphicsScene scene;
+
+ QGraphicsRectItem *rect = scene.addRect(QRectF(0, 0, 100, 100));
+ QGraphicsRectItem *rect2 = scene.addRect(QRectF(0, 0, 100, 100));
+ QGraphicsRectItem *rect3 = scene.addRect(QRectF(0, 0, 100, 100));
+ QGraphicsRectItem *rect4 = scene.addRect(QRectF(0, 0, 100, 100));
+ QGraphicsRectItem *rect5 = scene.addRect(QRectF(0, 0, 100, 100));
+ rect2->setParentItem(rect);
+ rect3->setParentItem(rect2);
+ rect4->setParentItem(rect3);
+ rect5->setParentItem(rect4);
+
+ rect2->setTransform(QTransform().translate(50, 50).rotate(45));
+ rect2->setPos(25, 25);
+ rect3->setTransform(QTransform().translate(50, 50).rotate(45));
+ rect3->setPos(25, 25);
+ rect4->setTransform(QTransform().translate(50, 50).rotate(45));
+ rect4->setPos(25, 25);
+ rect5->setTransform(QTransform().translate(50, 50).rotate(45));
+ rect5->setPos(25, 25);
+
+ QRectF subTreeRect = rect->childrenBoundingRect();
+ QCOMPARE(subTreeRect.left(), qreal(-206.0660171779821));
+ QCOMPARE(subTreeRect.top(), qreal(75.0));
+ QCOMPARE(subTreeRect.width(), qreal(351.7766952966369));
+ QCOMPARE(subTreeRect.height(), qreal(251.7766952966369));
+
+ rect->rotate(45);
+ rect2->rotate(-45);
+ rect3->rotate(45);
+ rect4->rotate(-45);
+ rect5->rotate(45);
+
+ subTreeRect = rect->childrenBoundingRect();
+ QCOMPARE(rect->childrenBoundingRect(), QRectF(-100, 75, 275, 250));
+}
+
void tst_QGraphicsItem::childrenBoundingRect2()
{
QGraphicsItemGroup box;
@@ -2933,6 +3207,39 @@ void tst_QGraphicsItem::childrenBoundingRect2()
QCOMPARE(box.childrenBoundingRect(), QRectF(0, 0, 100, 100));
}
+void tst_QGraphicsItem::childrenBoundingRect3()
+{
+ QGraphicsScene scene;
+
+ QGraphicsRectItem *rect = scene.addRect(QRectF(0, 0, 100, 100));
+ QGraphicsRectItem *rect2 = scene.addRect(QRectF(0, 0, 100, 100));
+ QGraphicsRectItem *rect3 = scene.addRect(QRectF(0, 0, 100, 100));
+ QGraphicsRectItem *rect4 = scene.addRect(QRectF(0, 0, 100, 100));
+ QGraphicsRectItem *rect5 = scene.addRect(QRectF(0, 0, 100, 100));
+ rect2->setParentItem(rect);
+ rect3->setParentItem(rect2);
+ rect4->setParentItem(rect3);
+ rect5->setParentItem(rect4);
+
+ rect2->setTransform(QTransform().translate(50, 50).rotate(45));
+ rect2->setPos(25, 25);
+ rect3->setTransform(QTransform().translate(50, 50).rotate(45));
+ rect3->setPos(25, 25);
+ rect4->setTransform(QTransform().translate(50, 50).rotate(45));
+ rect4->setPos(25, 25);
+ rect5->setTransform(QTransform().translate(50, 50).rotate(45));
+ rect5->setPos(25, 25);
+
+ // Try to mess up the cached bounding rect.
+ (void)rect2->childrenBoundingRect();
+
+ QRectF subTreeRect = rect->childrenBoundingRect();
+ QCOMPARE(subTreeRect.left(), qreal(-206.0660171779821));
+ QCOMPARE(subTreeRect.top(), qreal(75.0));
+ QCOMPARE(subTreeRect.width(), qreal(351.7766952966369));
+ QCOMPARE(subTreeRect.height(), qreal(251.7766952966369));
+}
+
void tst_QGraphicsItem::group()
{
QGraphicsScene scene;
@@ -2951,7 +3258,8 @@ void tst_QGraphicsItem::group()
QGraphicsView view(&scene);
view.show();
- QTest::qWait(250);
+ QTest::qWaitForWindowShown(&view);
+ QApplication::processEvents();
QGraphicsItemGroup *group = new QGraphicsItemGroup;
group->setSelected(true);
@@ -2967,7 +3275,7 @@ void tst_QGraphicsItem::group()
QCOMPARE(scene.items().size(), 4);
QCOMPARE(scene.items(group->sceneBoundingRect()).size(), 3);
- QTest::qWait(250);
+ QTest::qWait(25);
QRectF parent2SceneBoundingRect = parent2->sceneBoundingRect();
group->addToGroup(parent2);
@@ -2979,7 +3287,7 @@ void tst_QGraphicsItem::group()
QCOMPARE(scene.items().size(), 4);
QCOMPARE(scene.items(group->sceneBoundingRect()).size(), 4);
- QTest::qWait(250);
+ QTest::qWait(25);
QList<QGraphicsItem *> newItems;
for (int i = 0; i < 100; ++i) {
@@ -3131,150 +3439,134 @@ protected:
void mouseReleaseEvent(QGraphicsSceneMouseEvent *)
{ ++counter; }
};
+
void tst_QGraphicsItem::handlesChildEvents()
{
- ChildEventTester *item2_level2 = new ChildEventTester(QRectF(0, 0, 25, 25));
- ChildEventTester *item1_level1 = new ChildEventTester(QRectF(0, 0, 50, 50));
- ChildEventTester *item_level0 = new ChildEventTester(QRectF(0, 0, 100, 100));
- ChildEventTester *item1_level2 = new ChildEventTester(QRectF(0, 0, 25, 25));
- ChildEventTester *item2_level1 = new ChildEventTester(QRectF(0, 0, 50, 50));
-
- item_level0->setBrush(QBrush(Qt::blue));
- item1_level1->setBrush(QBrush(Qt::red));
- item2_level1->setBrush(QBrush(Qt::yellow));
- item1_level2->setBrush(QBrush(Qt::green));
- item2_level2->setBrush(QBrush(Qt::gray));
- item1_level1->setPos(50, 0);
- item2_level1->setPos(50, 50);
- item1_level2->setPos(25, 0);
- item2_level2->setPos(25, 25);
- item1_level1->setParentItem(item_level0);
- item2_level1->setParentItem(item_level0);
- item1_level2->setParentItem(item1_level1);
- item2_level2->setParentItem(item1_level1);
+ ChildEventTester *blue = new ChildEventTester(QRectF(0, 0, 100, 100));
+ ChildEventTester *red = new ChildEventTester(QRectF(0, 0, 50, 50));
+ ChildEventTester *green = new ChildEventTester(QRectF(0, 0, 25, 25));
+ ChildEventTester *gray = new ChildEventTester(QRectF(0, 0, 25, 25));
+ ChildEventTester *yellow = new ChildEventTester(QRectF(0, 0, 50, 50));
+
+ blue->setBrush(QBrush(Qt::blue));
+ red->setBrush(QBrush(Qt::red));
+ yellow->setBrush(QBrush(Qt::yellow));
+ green->setBrush(QBrush(Qt::green));
+ gray->setBrush(QBrush(Qt::gray));
+ red->setPos(50, 0);
+ yellow->setPos(50, 50);
+ green->setPos(25, 0);
+ gray->setPos(25, 25);
+ red->setParentItem(blue);
+ yellow->setParentItem(blue);
+ green->setParentItem(red);
+ gray->setParentItem(red);
QGraphicsScene scene;
- scene.addItem(item_level0);
-
- // Pull out the items, closest item first
- QList<QGraphicsItem *> items = scene.items(scene.itemsBoundingRect());
- QCOMPARE(items.at(4), (QGraphicsItem *)item_level0);
- if (item1_level1 < item2_level1) {
- QCOMPARE(items.at(3), (QGraphicsItem *)item1_level1);
- if (item1_level2 < item2_level2) {
- QCOMPARE(items.at(2), (QGraphicsItem *)item1_level2);
- QCOMPARE(items.at(1), (QGraphicsItem *)item2_level2);
- } else {
- QCOMPARE(items.at(2), (QGraphicsItem *)item2_level2);
- QCOMPARE(items.at(1), (QGraphicsItem *)item1_level2);
- }
- QCOMPARE(items.at(0), (QGraphicsItem *)item2_level1);
- } else {
- QCOMPARE(items.at(3), (QGraphicsItem *)item2_level1);
- QCOMPARE(items.at(2), (QGraphicsItem *)item1_level1);
- if (item1_level2 < item2_level2) {
- QCOMPARE(items.at(1), (QGraphicsItem *)item1_level2);
- QCOMPARE(items.at(0), (QGraphicsItem *)item2_level2);
- } else {
- QCOMPARE(items.at(1), (QGraphicsItem *)item2_level2);
- QCOMPARE(items.at(0), (QGraphicsItem *)item1_level2);
- }
- }
+ scene.addItem(blue);
QGraphicsView view(&scene);
view.show();
+ QTest::qWaitForWindowShown(&view);
+ QTest::qWait(20);
- QTest::qWait(1000);
+ // Pull out the items, closest item first
+ QList<QGraphicsItem *> items = scene.items(scene.itemsBoundingRect());
+ QCOMPARE(items.at(0), (QGraphicsItem *)yellow);
+ QCOMPARE(items.at(1), (QGraphicsItem *)gray);
+ QCOMPARE(items.at(2), (QGraphicsItem *)green);
+ QCOMPARE(items.at(3), (QGraphicsItem *)red);
+ QCOMPARE(items.at(4), (QGraphicsItem *)blue);
- QCOMPARE(item_level0->counter, 0);
+ QCOMPARE(blue->counter, 0);
// Send events to the toplevel item
QGraphicsSceneMouseEvent pressEvent(QEvent::GraphicsSceneMousePress);
QGraphicsSceneMouseEvent releaseEvent(QEvent::GraphicsSceneMouseRelease);
pressEvent.setButton(Qt::LeftButton);
- pressEvent.setScenePos(item_level0->mapToScene(5, 5));
+ pressEvent.setScenePos(blue->mapToScene(5, 5));
pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
releaseEvent.setButton(Qt::LeftButton);
- releaseEvent.setScenePos(item_level0->mapToScene(5, 5));
+ releaseEvent.setScenePos(blue->mapToScene(5, 5));
releaseEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
QApplication::sendEvent(&scene, &pressEvent);
QApplication::sendEvent(&scene, &releaseEvent);
- QCOMPARE(item_level0->counter, 2);
+ QCOMPARE(blue->counter, 2);
// Send events to a level1 item
- pressEvent.setScenePos(item1_level1->mapToScene(5, 5));
+ pressEvent.setScenePos(red->mapToScene(5, 5));
pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
- releaseEvent.setScenePos(item1_level1->mapToScene(5, 5));
+ releaseEvent.setScenePos(red->mapToScene(5, 5));
releaseEvent.setScreenPos(view.mapFromScene(releaseEvent.scenePos()));
QApplication::sendEvent(&scene, &pressEvent);
QApplication::sendEvent(&scene, &releaseEvent);
- QCOMPARE(item_level0->counter, 2);
- QCOMPARE(item1_level1->counter, 2);
+ QCOMPARE(blue->counter, 2);
+ QCOMPARE(red->counter, 2);
// Send events to a level2 item
- pressEvent.setScenePos(item1_level2->mapToScene(5, 5));
+ pressEvent.setScenePos(green->mapToScene(5, 5));
pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
- releaseEvent.setScenePos(item1_level2->mapToScene(5, 5));
+ releaseEvent.setScenePos(green->mapToScene(5, 5));
releaseEvent.setScreenPos(view.mapFromScene(releaseEvent.scenePos()));
QApplication::sendEvent(&scene, &pressEvent);
QApplication::sendEvent(&scene, &releaseEvent);
- QCOMPARE(item_level0->counter, 2);
- QCOMPARE(item1_level1->counter, 2);
- QCOMPARE(item1_level2->counter, 2);
+ QCOMPARE(blue->counter, 2);
+ QCOMPARE(red->counter, 2);
+ QCOMPARE(green->counter, 2);
- item_level0->setHandlesChildEvents(true);
+ blue->setHandlesChildEvents(true);
// Send events to a level1 item
- pressEvent.setScenePos(item1_level1->mapToScene(5, 5));
+ pressEvent.setScenePos(red->mapToScene(5, 5));
pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
- releaseEvent.setScenePos(item1_level1->mapToScene(5, 5));
+ releaseEvent.setScenePos(red->mapToScene(5, 5));
releaseEvent.setScreenPos(view.mapFromScene(releaseEvent.scenePos()));
QApplication::sendEvent(&scene, &pressEvent);
QApplication::sendEvent(&scene, &releaseEvent);
- QCOMPARE(item_level0->counter, 4);
- QCOMPARE(item1_level1->counter, 2);
+ QCOMPARE(blue->counter, 4);
+ QCOMPARE(red->counter, 2);
// Send events to a level2 item
- pressEvent.setScenePos(item1_level2->mapToScene(5, 5));
+ pressEvent.setScenePos(green->mapToScene(5, 5));
pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
- releaseEvent.setScenePos(item1_level2->mapToScene(5, 5));
+ releaseEvent.setScenePos(green->mapToScene(5, 5));
releaseEvent.setScreenPos(view.mapFromScene(releaseEvent.scenePos()));
QApplication::sendEvent(&scene, &pressEvent);
QApplication::sendEvent(&scene, &releaseEvent);
- QCOMPARE(item_level0->counter, 6);
- QCOMPARE(item1_level1->counter, 2);
- QCOMPARE(item1_level2->counter, 2);
+ QCOMPARE(blue->counter, 6);
+ QCOMPARE(red->counter, 2);
+ QCOMPARE(green->counter, 2);
- item_level0->setHandlesChildEvents(false);
+ blue->setHandlesChildEvents(false);
// Send events to a level1 item
- pressEvent.setScenePos(item1_level1->mapToScene(5, 5));
+ pressEvent.setScenePos(red->mapToScene(5, 5));
pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
- releaseEvent.setScenePos(item1_level1->mapToScene(5, 5));
+ releaseEvent.setScenePos(red->mapToScene(5, 5));
releaseEvent.setScreenPos(view.mapFromScene(releaseEvent.scenePos()));
QApplication::sendEvent(&scene, &pressEvent);
QApplication::sendEvent(&scene, &releaseEvent);
- QCOMPARE(item_level0->counter, 6);
- QCOMPARE(item1_level1->counter, 4);
+ QCOMPARE(blue->counter, 6);
+ QCOMPARE(red->counter, 4);
// Send events to a level2 item
- pressEvent.setScenePos(item1_level2->mapToScene(5, 5));
+ pressEvent.setScenePos(green->mapToScene(5, 5));
pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
- releaseEvent.setScenePos(item1_level2->mapToScene(5, 5));
+ releaseEvent.setScenePos(green->mapToScene(5, 5));
releaseEvent.setScreenPos(view.mapFromScene(releaseEvent.scenePos()));
QApplication::sendEvent(&scene, &pressEvent);
QApplication::sendEvent(&scene, &releaseEvent);
- QCOMPARE(item_level0->counter, 6);
- QCOMPARE(item1_level1->counter, 4);
- QCOMPARE(item1_level2->counter, 4);
+ QCOMPARE(blue->counter, 6);
+ QCOMPARE(red->counter, 4);
+ QCOMPARE(green->counter, 4);
}
void tst_QGraphicsItem::handlesChildEvents2()
@@ -3299,19 +3591,22 @@ void tst_QGraphicsItem::handlesChildEvents2()
QGraphicsView view(&scene);
view.show();
-
- QTestEventLoop::instance().enterLoop(1);
+ QTest::qWaitForWindowShown(&view);
+ QApplication::processEvents();
QMouseEvent event(QEvent::MouseButtonPress, view.mapFromScene(5, 5),
view.viewport()->mapToGlobal(view.mapFromScene(5, 5)), Qt::LeftButton, 0, 0);
QApplication::sendEvent(view.viewport(), &event);
- QCOMPARE(root->counter, 1);
+ QTRY_COMPARE(root->counter, 1);
}
void tst_QGraphicsItem::handlesChildEvents3()
{
QGraphicsScene scene;
+ QEvent activate(QEvent::WindowActivate);
+ QApplication::sendEvent(&scene, &activate);
+
ChildEventTester *group2 = new ChildEventTester(QRectF(), 0);
ChildEventTester *group1 = new ChildEventTester(QRectF(), group2);
ChildEventTester *leaf = new ChildEventTester(QRectF(), group1);
@@ -3348,6 +3643,128 @@ void tst_QGraphicsItem::handlesChildEvents3()
QCOMPARE(group2->counter, 3);
}
+
+class ChildEventFilterTester : public ChildEventTester
+{
+public:
+ ChildEventFilterTester(const QRectF &rect, QGraphicsItem *parent = 0)
+ : ChildEventTester(rect, parent), filter(QEvent::None)
+ { }
+
+ QEvent::Type filter;
+
+protected:
+ bool sceneEventFilter(QGraphicsItem *item, QEvent *event)
+ {
+ Q_UNUSED(item);
+ if (event->type() == filter) {
+ ++counter;
+ return true;
+ }
+ return false;
+ }
+};
+
+void tst_QGraphicsItem::filtersChildEvents()
+{
+ QGraphicsScene scene;
+ ChildEventFilterTester *root = new ChildEventFilterTester(QRectF(0, 0, 10, 10));
+ ChildEventFilterTester *filter = new ChildEventFilterTester(QRectF(10, 10, 10, 10), root);
+ ChildEventTester *child = new ChildEventTester(QRectF(20, 20, 10, 10), filter);
+
+ // setup filter
+ filter->setFiltersChildEvents(true);
+ filter->filter = QEvent::GraphicsSceneMousePress;
+
+ scene.addItem(root);
+
+ QGraphicsView view(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QTest::qWait(20);
+
+ QGraphicsSceneMouseEvent pressEvent(QEvent::GraphicsSceneMousePress);
+ QGraphicsSceneMouseEvent releaseEvent(QEvent::GraphicsSceneMouseRelease);
+
+ // send event to child
+ pressEvent.setButton(Qt::LeftButton);
+ pressEvent.setScenePos(QPointF(25, 25));//child->mapToScene(5, 5));
+ pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
+ releaseEvent.setButton(Qt::LeftButton);
+ releaseEvent.setScenePos(QPointF(25, 25));//child->mapToScene(5, 5));
+ releaseEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
+ QApplication::sendEvent(&scene, &pressEvent);
+ QApplication::sendEvent(&scene, &releaseEvent);
+
+ QTRY_COMPARE(child->counter, 1); // mouse release is not filtered
+ QCOMPARE(filter->counter, 1); // mouse press is filtered
+ QCOMPARE(root->counter, 0);
+
+ // add another filter
+ root->setFiltersChildEvents(true);
+ root->filter = QEvent::GraphicsSceneMouseRelease;
+
+ // send event to child
+ QApplication::sendEvent(&scene, &pressEvent);
+ QApplication::sendEvent(&scene, &releaseEvent);
+
+ QCOMPARE(child->counter, 1);
+ QCOMPARE(filter->counter, 2); // mouse press is filtered
+ QCOMPARE(root->counter, 1); // mouse release is filtered
+
+ // reparent to another sub-graph
+ ChildEventTester *parent = new ChildEventTester(QRectF(10, 10, 10, 10), root);
+ child->setParentItem(parent);
+
+ // send event to child
+ QApplication::sendEvent(&scene, &pressEvent);
+ QApplication::sendEvent(&scene, &releaseEvent);
+
+ QCOMPARE(child->counter, 2); // mouse press is _not_ filtered
+ QCOMPARE(parent->counter, 0);
+ QCOMPARE(filter->counter, 2);
+ QCOMPARE(root->counter, 2); // mouse release is filtered
+}
+
+void tst_QGraphicsItem::filtersChildEvents2()
+{
+ ChildEventFilterTester *root = new ChildEventFilterTester(QRectF(0, 0, 10, 10));
+ root->setFiltersChildEvents(true);
+ root->filter = QEvent::GraphicsSceneMousePress;
+ QVERIFY(root->filtersChildEvents());
+
+ ChildEventTester *child = new ChildEventTester(QRectF(0, 0, 10, 10), root);
+ QVERIFY(!child->filtersChildEvents());
+
+ ChildEventTester *child2 = new ChildEventTester(QRectF(0, 0, 10, 10));
+ ChildEventTester *child3 = new ChildEventTester(QRectF(0, 0, 10, 10), child2);
+ ChildEventTester *child4 = new ChildEventTester(QRectF(0, 0, 10, 10), child3);
+
+ child2->setParentItem(root);
+ QVERIFY(!child2->filtersChildEvents());
+ QVERIFY(!child3->filtersChildEvents());
+ QVERIFY(!child4->filtersChildEvents());
+
+ QGraphicsScene scene;
+ scene.addItem(root);
+
+ QGraphicsView view(&scene);
+ view.show();
+
+ QTest::qWaitForWindowShown(&view);
+ QApplication::processEvents();
+
+ QMouseEvent event(QEvent::MouseButtonPress, view.mapFromScene(5, 5),
+ view.viewport()->mapToGlobal(view.mapFromScene(5, 5)), Qt::LeftButton, 0, 0);
+ QApplication::sendEvent(view.viewport(), &event);
+
+ QTRY_COMPARE(root->counter, 1);
+ QCOMPARE(child->counter, 0);
+ QCOMPARE(child2->counter, 0);
+ QCOMPARE(child3->counter, 0);
+ QCOMPARE(child4->counter, 0);
+}
+
class CustomItem : public QGraphicsItem
{
public:
@@ -3382,21 +3799,22 @@ void tst_QGraphicsItem::ensureVisible()
QGraphicsView view(&scene);
view.setFixedSize(300, 300);
view.show();
+ QTest::qWaitForWindowShown(&view);
for (int i = 0; i < 25; ++i) {
view.scale(qreal(1.06), qreal(1.06));
- QTest::qWait(25);
+ QApplication::processEvents();
}
item->ensureVisible(-100, -100, 25, 25);
- QTest::qWait(250);
+ QTest::qWait(25);
for (int x = -100; x < 100; x += 25) {
for (int y = -100; y < 100; y += 25) {
int xmargin = rand() % 75;
int ymargin = rand() % 75;
item->ensureVisible(x, y, 25, 25, xmargin, ymargin);
- QTest::qWait(25);
+ QApplication::processEvents();
QPolygonF viewScenePoly;
viewScenePoly << view.mapToScene(view.rect().topLeft())
@@ -3423,7 +3841,7 @@ void tst_QGraphicsItem::ensureVisible()
}
item->ensureVisible(100, 100, 25, 25);
- QTest::qWait(250);
+ QTest::qWait(25);
}
void tst_QGraphicsItem::cursor()
@@ -3464,7 +3882,7 @@ void tst_QGraphicsItem::cursor()
view.show();
QTest::mouseMove(&view, view.rect().center());
- QTest::qWait(250);
+ QTest::qWait(25);
QCursor cursor = view.viewport()->cursor();
@@ -3473,7 +3891,7 @@ void tst_QGraphicsItem::cursor()
QApplication::sendEvent(view.viewport(), &event);
}
- QTest::qWait(250);
+ QTest::qWait(25);
QCOMPARE(view.viewport()->cursor().shape(), cursor.shape());
@@ -3498,7 +3916,7 @@ void tst_QGraphicsItem::cursor()
QApplication::sendEvent(view.viewport(), &event);
}
- QTest::qWait(250);
+ QTest::qWait(25);
QCOMPARE(view.viewport()->cursor().shape(), item2->cursor().shape());
@@ -3508,7 +3926,7 @@ void tst_QGraphicsItem::cursor()
QApplication::sendEvent(view.viewport(), &event);
}
- QTest::qWait(250);
+ QTest::qWait(25);
QCOMPARE(view.viewport()->cursor().shape(), cursor.shape());
#endif
@@ -3692,8 +4110,20 @@ void tst_QGraphicsItem::defaultItemTest_QGraphicsEllipseItem()
class ItemChangeTester : public QGraphicsRectItem
{
public:
- ItemChangeTester(){}
- ItemChangeTester(QGraphicsItem *parent) : QGraphicsRectItem(parent) {}
+ ItemChangeTester()
+ { setFlag(ItemSendsGeometryChanges); clear(); }
+ ItemChangeTester(QGraphicsItem *parent) : QGraphicsRectItem(parent)
+ { setFlag(ItemSendsGeometryChanges); clear(); }
+
+ void clear()
+ {
+ itemChangeReturnValue = QVariant();
+ itemSceneChangeTargetScene = 0;
+ changes.clear();
+ values.clear();
+ oldValues.clear();
+ }
+
QVariant itemChangeReturnValue;
QGraphicsScene *itemSceneChangeTargetScene;
@@ -3870,6 +4300,20 @@ void tst_QGraphicsItem::itemChange()
QCOMPARE(tester.pos(), QPointF(42, 0));
}
{
+ // ItemZValueChange / ItemZValueHasChanged
+ tester.itemChangeReturnValue = qreal(2.0);
+ tester.setZValue(1.0);
+ ++changeCount; // notification sent too
+ ++changeCount;
+ QCOMPARE(tester.changes.size(), changeCount);
+ QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemZValueChange);
+ QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemZValueHasChanged);
+ QCOMPARE(tester.values.at(tester.changes.size() - 2), QVariant(qreal(1.0)));
+ QCOMPARE(tester.values.at(tester.changes.size() - 1), QVariant(qreal(2.0)));
+ QCOMPARE(tester.oldValues.last(), QVariant(qreal(0.0)));
+ QCOMPARE(tester.zValue(), qreal(2.0));
+ }
+ {
// ItemFlagsChange
tester.itemChangeReturnValue = QGraphicsItem::ItemIsSelectable;
tester.setFlag(QGraphicsItem::ItemIsSelectable, false);
@@ -3880,7 +4324,8 @@ void tst_QGraphicsItem::itemChange()
QCOMPARE(tester.changes.size(), changeCount);
QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemFlagsChange);
QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemFlagsHaveChanged);
- QCOMPARE(tester.values.at(tester.values.size() - 2), qVariantFromValue<quint32>(QGraphicsItem::ItemIsSelectable));
+ QVariant expectedFlags = qVariantFromValue<quint32>(QGraphicsItem::GraphicsItemFlags(QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemSendsGeometryChanges));
+ QCOMPARE(tester.values.at(tester.values.size() - 2), expectedFlags);
QCOMPARE(tester.values.at(tester.values.size() - 1), qVariantFromValue<quint32>(QGraphicsItem::ItemIsSelectable));
}
{
@@ -4137,8 +4582,12 @@ protected:
void tst_QGraphicsItem::sceneEventFilter()
{
QGraphicsScene scene;
+
QGraphicsView view(&scene);
view.show();
+ QApplication::setActiveWindow(&view);
+ QTest::qWaitForWindowShown(&view);
+ QTest::qWait(25);
QGraphicsTextItem *text1 = scene.addText(QLatin1String("Text1"));
QGraphicsTextItem *text2 = scene.addText(QLatin1String("Text2"));
@@ -4150,10 +4599,10 @@ void tst_QGraphicsItem::sceneEventFilter()
EventFilterTesterItem *tester = new EventFilterTesterItem;
scene.addItem(tester);
- QVERIFY(!text1->hasFocus());
+ QTRY_VERIFY(!text1->hasFocus());
text1->installSceneEventFilter(tester);
text1->setFocus();
- QVERIFY(text1->hasFocus());
+ QTRY_VERIFY(text1->hasFocus());
QCOMPARE(tester->filteredEvents.size(), 1);
QCOMPARE(tester->filteredEvents.at(0), QEvent::FocusIn);
@@ -4201,13 +4650,14 @@ void tst_QGraphicsItem::sceneEventFilter()
QGraphicsTextItem *ti3 = anotherScene->addText("This is a test #3");
gv.setScene(anotherScene);
gv.show();
- QTest::qWait(250);
+ QTest::qWaitForWindowShown(&gv);
+ QTest::qWait(25);
ti->installSceneEventFilter(ti2);
ti3->installSceneEventFilter(ti);
delete ti2;
//we souldn't crash
QTest::mouseMove(gv.viewport(), gv.mapFromScene(ti->scenePos()));
- QTest::qWait(250);
+ QTest::qWait(30);
delete ti;
}
@@ -4255,8 +4705,8 @@ void tst_QGraphicsItem::paint()
QGraphicsView view(&scene);
view.show();
- QTest::qWait(250);
-
+ QTest::qWaitForWindowShown(&view);
+ QApplication::processEvents();
#ifdef Q_OS_WIN32
//we try to switch the desktop: if it fails, we skip the test
if (::SwitchDesktop( ::GetThreadDesktop( ::GetCurrentThreadId() ) ) == 0) {
@@ -4264,43 +4714,39 @@ void tst_QGraphicsItem::paint()
}
#endif
- QVERIFY(paintTester.widget == view.viewport());
-
+ QTRY_COMPARE(paintTester.widget, view.viewport());
view.hide();
QGraphicsScene scene2;
+ QGraphicsView view2(&scene2);
+ view2.show();
+ QTest::qWaitForWindowShown(&view2);
+ QTest::qWait(25);
PaintTester tester2;
scene2.addItem(&tester2);
-
- QGraphicsView view2(&scene2);
- view2.show();
qApp->processEvents();
- QTest::qWait(250);
//First show one paint
- QVERIFY(tester2.painted == 1);
+ QTRY_COMPARE(tester2.painted, 1);
//nominal case, update call paint
tester2.update();
qApp->processEvents();
- QTest::qWait(250);
- QVERIFY(tester2.painted == 2);
+ QTRY_VERIFY(tester2.painted == 2);
//we remove the item from the scene, number of updates is still the same
tester2.update();
scene2.removeItem(&tester2);
qApp->processEvents();
- QTest::qWait(250);
- QVERIFY(tester2.painted == 2);
+ QTRY_VERIFY(tester2.painted == 2);
//We re-add the item, the number of paint should increase
scene2.addItem(&tester2);
tester2.update();
qApp->processEvents();
- QTest::qWait(250);
- QVERIFY(tester2.painted == 3);
+ QTRY_VERIFY(tester2.painted == 3);
}
class HarakiriItem : public QGraphicsRectItem
@@ -4316,11 +4762,11 @@ public:
{
QGraphicsRectItem::paint(painter, option, widget);
if (harakiri == 0) {
- // delete unsupported since 4.5
- /*
+ // delete unsupported since 4.5
+ /*
dead = 1;
- delete this;
- */
+ delete this;
+ */
}
}
@@ -4678,7 +5124,7 @@ void tst_QGraphicsItem::itemClipsChildrenToShape2()
QPainter painter(&image);
scene.render(&painter);
painter.end();
-
+
QCOMPARE(image.pixel(5, 5), QColor(0, 0, 255).rgba());
QCOMPARE(image.pixel(5, 10), QRgb(0));
QCOMPARE(image.pixel(10, 5), QRgb(0));
@@ -5099,6 +5545,8 @@ void tst_QGraphicsItem::untransformable()
view.setBackgroundBrush(QBrush(Qt::black, Qt::DiagCrossPattern));
#endif
+ QTest::qWaitForWindowShown(&view);
+
for (int i = 0; i < 10; ++i) {
QPoint center = view.viewport()->rect().center();
QCOMPARE(view.itemAt(center), item1);
@@ -5123,7 +5571,7 @@ void tst_QGraphicsItem::untransformable()
view.rotate(13);
view.shear(qreal(0.01), qreal(0.01));
view.translate(10, 10);
- QTest::qWait(250);
+ QTest::qWait(25);
}
}
@@ -5159,10 +5607,9 @@ void tst_QGraphicsItem::contextMenuEventPropagation()
QGraphicsView view(&scene);
view.setAlignment(Qt::AlignLeft | Qt::AlignTop);
view.show();
-#ifdef Q_WS_X11
- qt_x11_wait_for_window_manager(&view);
-#endif
view.resize(200, 200);
+ QTest::qWaitForWindowShown(&view);
+ QTest::qWait(20);
QContextMenuEvent event(QContextMenuEvent::Mouse, QPoint(10, 10),
view.viewport()->mapToGlobal(QPoint(10, 10)));
@@ -5263,15 +5710,16 @@ void tst_QGraphicsItem::task141694_textItemEnsureVisible()
QGraphicsView view(&scene);
view.setFixedSize(200, 200);
view.show();
+ QTest::qWaitForWindowShown(&view);
view.ensureVisible(-1000, -1000, 5, 5);
int hscroll = view.horizontalScrollBar()->value();
int vscroll = view.verticalScrollBar()->value();
- QTestEventLoop::instance().enterLoop(1);
+ QTest::qWait(10);
// This should not cause the view to scroll
- QCOMPARE(view.horizontalScrollBar()->value(), hscroll);
+ QTRY_COMPARE(view.horizontalScrollBar()->value(), hscroll);
QCOMPARE(view.verticalScrollBar()->value(), vscroll);
}
@@ -5339,6 +5787,9 @@ void tst_QGraphicsItem::task240400_clickOnTextItem()
QFETCH(int, textFlags);
QGraphicsScene scene;
+ QEvent activate(QEvent::WindowActivate);
+ QApplication::sendEvent(&scene, &activate);
+
QGraphicsTextItem *item = scene.addText("Hello");
item->setFlags(QGraphicsItem::GraphicsItemFlags(flags));
item->setTextInteractionFlags(Qt::TextInteractionFlags(textFlags));
@@ -5404,7 +5855,7 @@ void tst_QGraphicsItem::task240400_clickOnTextItem()
QVERIFY(selectable ? item->isSelected() : !item->isSelected());
- //
+ //
if (textFlags & Qt::TextEditorInteraction)
QVERIFY(item->textCursor().columnNumber() > column);
else
@@ -5431,17 +5882,19 @@ public:
void tst_QGraphicsItem::ensureUpdateOnTextItem()
{
QGraphicsScene scene;
- TextItem *text1 = new TextItem(QLatin1String("123"));
- scene.addItem(text1);
QGraphicsView view(&scene);
view.show();
- QTest::qWait(250);
- QCOMPARE(text1->updates,1);
+ QTest::qWaitForWindowShown(&view);
+ QTest::qWait(25);
+ TextItem *text1 = new TextItem(QLatin1String("123"));
+ scene.addItem(text1);
+ qApp->processEvents();
+ QTRY_COMPARE(text1->updates,1);
//same bouding rect but we have to update
text1->setText(QLatin1String("321"));
- QTest::qWait(250);
- QCOMPARE(text1->updates,2);
+ qApp->processEvents();
+ QTRY_COMPARE(text1->updates,2);
}
void tst_QGraphicsItem::task243707_addChildBeforeParent()
@@ -5729,10 +6182,8 @@ void tst_QGraphicsItem::opacity2()
MyGraphicsView view(&scene);
view.show();
-#ifdef Q_WS_X11
- qt_x11_wait_for_window_manager(&view);
-#endif
- QTest::qWait(250);
+ QTest::qWaitForWindowShown(&view);
+ QTRY_COMPARE(view.repaints, 1);
#define RESET_REPAINT_COUNTERS \
parent->repaints = 0; \
@@ -5743,8 +6194,8 @@ void tst_QGraphicsItem::opacity2()
RESET_REPAINT_COUNTERS
child->setOpacity(0.0);
- QTest::qWait(100);
- QCOMPARE(view.repaints, 1);
+ QTest::qWait(10);
+ QTRY_COMPARE(view.repaints, 1);
QCOMPARE(parent->repaints, 1);
QCOMPARE(child->repaints, 0);
QCOMPARE(grandChild->repaints, 0);
@@ -5752,8 +6203,8 @@ void tst_QGraphicsItem::opacity2()
RESET_REPAINT_COUNTERS
child->setOpacity(1.0);
- QTest::qWait(100);
- QCOMPARE(view.repaints, 1);
+ QTest::qWait(10);
+ QTRY_COMPARE(view.repaints, 1);
QCOMPARE(parent->repaints, 1);
QCOMPARE(child->repaints, 1);
QCOMPARE(grandChild->repaints, 1);
@@ -5761,8 +6212,8 @@ void tst_QGraphicsItem::opacity2()
RESET_REPAINT_COUNTERS
parent->setOpacity(0.0);
- QTest::qWait(100);
- QCOMPARE(view.repaints, 1);
+ QTest::qWait(10);
+ QTRY_COMPARE(view.repaints, 1);
QCOMPARE(parent->repaints, 0);
QCOMPARE(child->repaints, 0);
QCOMPARE(grandChild->repaints, 0);
@@ -5770,8 +6221,8 @@ void tst_QGraphicsItem::opacity2()
RESET_REPAINT_COUNTERS
parent->setOpacity(1.0);
- QTest::qWait(100);
- QCOMPARE(view.repaints, 1);
+ QTest::qWait(10);
+ QTRY_COMPARE(view.repaints, 1);
QCOMPARE(parent->repaints, 1);
QCOMPARE(child->repaints, 1);
QCOMPARE(grandChild->repaints, 1);
@@ -5780,8 +6231,8 @@ void tst_QGraphicsItem::opacity2()
RESET_REPAINT_COUNTERS
child->setOpacity(0.0);
- QTest::qWait(100);
- QCOMPARE(view.repaints, 1);
+ QTest::qWait(10);
+ QTRY_COMPARE(view.repaints, 1);
QCOMPARE(parent->repaints, 1);
QCOMPARE(child->repaints, 0);
QCOMPARE(grandChild->repaints, 1);
@@ -5789,8 +6240,8 @@ void tst_QGraphicsItem::opacity2()
RESET_REPAINT_COUNTERS
child->setOpacity(0.0); // Already 0.0; no change.
- QTest::qWait(100);
- QCOMPARE(view.repaints, 0);
+ QTest::qWait(10);
+ QTRY_COMPARE(view.repaints, 0);
QCOMPARE(parent->repaints, 0);
QCOMPARE(child->repaints, 0);
QCOMPARE(grandChild->repaints, 0);
@@ -5822,15 +6273,13 @@ void tst_QGraphicsItem::opacityZeroUpdates()
MyGraphicsView view(&scene);
view.show();
-#ifdef Q_WS_X11
- qt_x11_wait_for_window_manager(&view);
-#endif
- QTest::qWait(250);
+ QTest::qWaitForWindowShown(&view);
+ QTRY_VERIFY(view.repaints > 0);
view.reset();
parent->setOpacity(0.0);
- QTest::qWait(200);
+ QTest::qWait(20);
// transforming items bounding rect to view coordinates
const QRect childDeviceBoundingRect = child->deviceTransform(view.viewportTransform())
@@ -5841,22 +6290,39 @@ void tst_QGraphicsItem::opacityZeroUpdates()
QRegion expectedRegion = parentDeviceBoundingRect.adjusted(-2, -2, 2, 2);
expectedRegion += childDeviceBoundingRect.adjusted(-2, -2, 2, 2);
- QCOMPARE(view.paintedRegion, expectedRegion);
+ QTRY_COMPARE(view.paintedRegion, expectedRegion);
}
+class StacksBehindParentHelper : public QGraphicsRectItem
+{
+public:
+ StacksBehindParentHelper(QList<QGraphicsItem *> *paintedItems, const QRectF &rect, QGraphicsItem *parent = 0)
+ : QGraphicsRectItem(rect, parent), paintedItems(paintedItems)
+ { }
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+ {
+ QGraphicsRectItem::paint(painter, option, widget);
+ paintedItems->append(this);
+ }
+
+private:
+ QList<QGraphicsItem *> *paintedItems;
+};
+
void tst_QGraphicsItem::itemStacksBehindParent()
{
- QGraphicsRectItem *parent1 = new QGraphicsRectItem(QRectF(0, 0, 100, 50));
- QGraphicsRectItem *child11 = new QGraphicsRectItem(QRectF(-10, 10, 50, 50), parent1);
- QGraphicsRectItem *grandChild111 = new QGraphicsRectItem(QRectF(-20, 20, 50, 50), child11);
- QGraphicsRectItem *child12 = new QGraphicsRectItem(QRectF(60, 10, 50, 50), parent1);
- QGraphicsRectItem *grandChild121 = new QGraphicsRectItem(QRectF(70, 20, 50, 50), child12);
+ StacksBehindParentHelper *parent1 = new StacksBehindParentHelper(&paintedItems, QRectF(0, 0, 100, 50));
+ StacksBehindParentHelper *child11 = new StacksBehindParentHelper(&paintedItems, QRectF(-10, 10, 50, 50), parent1);
+ StacksBehindParentHelper *grandChild111 = new StacksBehindParentHelper(&paintedItems, QRectF(-20, 20, 50, 50), child11);
+ StacksBehindParentHelper *child12 = new StacksBehindParentHelper(&paintedItems, QRectF(60, 10, 50, 50), parent1);
+ StacksBehindParentHelper *grandChild121 = new StacksBehindParentHelper(&paintedItems, QRectF(70, 20, 50, 50), child12);
- QGraphicsRectItem *parent2 = new QGraphicsRectItem(QRectF(0, 0, 100, 50));
- QGraphicsRectItem *child21 = new QGraphicsRectItem(QRectF(-10, 10, 50, 50), parent2);
- QGraphicsRectItem *grandChild211 = new QGraphicsRectItem(QRectF(-20, 20, 50, 50), child21);
- QGraphicsRectItem *child22 = new QGraphicsRectItem(QRectF(60, 10, 50, 50), parent2);
- QGraphicsRectItem *grandChild221 = new QGraphicsRectItem(QRectF(70, 20, 50, 50), child22);
+ StacksBehindParentHelper *parent2 = new StacksBehindParentHelper(&paintedItems, QRectF(0, 0, 100, 50));
+ StacksBehindParentHelper *child21 = new StacksBehindParentHelper(&paintedItems, QRectF(-10, 10, 50, 50), parent2);
+ StacksBehindParentHelper *grandChild211 = new StacksBehindParentHelper(&paintedItems, QRectF(-20, 20, 50, 50), child21);
+ StacksBehindParentHelper *child22 = new StacksBehindParentHelper(&paintedItems, QRectF(60, 10, 50, 50), parent2);
+ StacksBehindParentHelper *grandChild221 = new StacksBehindParentHelper(&paintedItems, QRectF(70, 20, 50, 50), child22);
parent1->setData(0, "parent1");
child11->setData(0, "child11");
@@ -5878,25 +6344,56 @@ void tst_QGraphicsItem::itemStacksBehindParent()
scene.addItem(parent1);
scene.addItem(parent2);
- QCOMPARE(scene.items(0, 0, 100, 100), (QList<QGraphicsItem *>()
+ QGraphicsView view(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QTRY_VERIFY(!paintedItems.isEmpty());
+ QTest::qWait(100);
+ paintedItems.clear();
+ view.viewport()->update();
+ QApplication::processEvents();
+ QTRY_COMPARE(scene.items(0, 0, 100, 100), (QList<QGraphicsItem *>()
<< grandChild111 << child11
<< grandChild121 << child12 << parent1
<< grandChild211 << child21
<< grandChild221 << child22 << parent2));
+ QTRY_COMPARE(paintedItems, QList<QGraphicsItem *>()
+ << parent2 << child22 << grandChild221
+ << child21 << grandChild211
+ << parent1 << child12 << grandChild121
+ << child11 << grandChild111);
child11->setFlag(QGraphicsItem::ItemStacksBehindParent);
- QCOMPARE(scene.items(0, 0, 100, 100), (QList<QGraphicsItem *>()
+ scene.update();
+ paintedItems.clear();
+ QApplication::processEvents();
+
+ QTRY_COMPARE(scene.items(0, 0, 100, 100), (QList<QGraphicsItem *>()
<< grandChild121 << child12 << parent1
<< grandChild111 << child11
<< grandChild211 << child21
<< grandChild221 << child22 << parent2));
+ QCOMPARE(paintedItems, QList<QGraphicsItem *>()
+ << parent2 << child22 << grandChild221
+ << child21 << grandChild211
+ << child11 << grandChild111
+ << parent1 << child12 << grandChild121);
child12->setFlag(QGraphicsItem::ItemStacksBehindParent);
- QCOMPARE(scene.items(0, 0, 100, 100), (QList<QGraphicsItem *>()
+ paintedItems.clear();
+ scene.update();
+ QApplication::processEvents();
+
+ QTRY_COMPARE(scene.items(0, 0, 100, 100), (QList<QGraphicsItem *>()
<< parent1 << grandChild111 << child11
<< grandChild121 << child12
<< grandChild211 << child21
<< grandChild221 << child22 << parent2));
+ QCOMPARE(paintedItems, QList<QGraphicsItem *>()
+ << parent2 << child22 << grandChild221
+ << child21 << grandChild211
+ << child12 << grandChild121
+ << child11 << grandChild111 << parent1);
}
class ClippingAndTransformsScene : public QGraphicsScene
@@ -5943,8 +6440,9 @@ void tst_QGraphicsItem::nestedClipping()
l1->setData(0, "l1");
l2->setData(0, "l2");
l3->setData(0, "l3");
-
+
QGraphicsView view(&scene);
+ view.setOptimizationFlag(QGraphicsView::IndirectPainting);
view.show();
#ifdef Q_WS_X11
qt_x11_wait_for_window_manager(&view);
@@ -5971,7 +6469,7 @@ void tst_QGraphicsItem::nestedClipping()
QCOMPARE(image.pixel(80, 130), qRgba(255, 255, 0, 255));
QCOMPARE(image.pixel(92, 105), qRgba(0, 255, 0, 255));
QCOMPARE(image.pixel(105, 105), qRgba(0, 0, 255, 255));
-#if 0
+#if 0
// Enable this to compare if the test starts failing.
image.save("nestedClipping_reference.png");
#endif
@@ -6113,7 +6611,7 @@ void tst_QGraphicsItem::tabChangesFocus_data()
void tst_QGraphicsItem::tabChangesFocus()
{
QFETCH(bool, tabChangesFocus);
-
+
QGraphicsScene scene;
QGraphicsTextItem *item = scene.addText("Hello");
item->setTabChangesFocus(tabChangesFocus);
@@ -6122,6 +6620,7 @@ void tst_QGraphicsItem::tabChangesFocus()
QDial *dial1 = new QDial;
QGraphicsView *view = new QGraphicsView(&scene);
+
QDial *dial2 = new QDial;
QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(dial1);
@@ -6131,29 +6630,29 @@ void tst_QGraphicsItem::tabChangesFocus()
QWidget widget;
widget.setLayout(layout);
widget.show();
-#ifdef Q_WS_X11
- qt_x11_wait_for_window_manager(&widget);
-#endif
+ QTest::qWaitForWindowShown(&widget);
+
+ QTRY_VERIFY(scene.isActive());
dial1->setFocus();
- QTest::qWait(125);
- QVERIFY(dial1->hasFocus());
+ QTest::qWait(15);
+ QTRY_VERIFY(dial1->hasFocus());
QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
- QTest::qWait(125);
- QVERIFY(view->hasFocus());
- QVERIFY(item->hasFocus());
+ QTest::qWait(15);
+ QTRY_VERIFY(view->hasFocus());
+ QTRY_VERIFY(item->hasFocus());
QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
- QTest::qWait(125);
+ QTest::qWait(15);
if (tabChangesFocus) {
- QVERIFY(!view->hasFocus());
- QVERIFY(!item->hasFocus());
- QVERIFY(dial2->hasFocus());
+ QTRY_VERIFY(!view->hasFocus());
+ QTRY_VERIFY(!item->hasFocus());
+ QTRY_VERIFY(dial2->hasFocus());
} else {
- QVERIFY(view->hasFocus());
- QVERIFY(item->hasFocus());
+ QTRY_VERIFY(view->hasFocus());
+ QTRY_VERIFY(item->hasFocus());
QCOMPARE(item->toPlainText(), QString("\tHello"));
}
}
@@ -6164,9 +6663,12 @@ void tst_QGraphicsItem::cacheMode()
QGraphicsView view(&scene);
view.resize(150, 150);
view.show();
-#ifdef Q_WS_X11
- qt_x11_wait_for_window_manager(&view);
-#endif
+ QApplication::setActiveWindow(&view);
+ QTest::qWaitForWindowShown(&view);
+
+ // Increase the probability of window activation
+ // not causing another repaint of test items.
+ QTest::qWait(50);
EventTester *tester = new EventTester;
EventTester *testerChild = new EventTester;
@@ -6176,24 +6678,24 @@ void tst_QGraphicsItem::cacheMode()
testerChild2->setFlag(QGraphicsItem::ItemIgnoresTransformations);
scene.addItem(tester);
- QTest::qWait(250);
+ QTest::qWait(10);
for (int i = 0; i < 2; ++i) {
// No visual change.
- QCOMPARE(tester->repaints, 1);
+ QTRY_COMPARE(tester->repaints, 1);
QCOMPARE(testerChild->repaints, 1);
QCOMPARE(testerChild2->repaints, 1);
tester->setCacheMode(QGraphicsItem::NoCache);
testerChild->setCacheMode(QGraphicsItem::NoCache);
testerChild2->setCacheMode(QGraphicsItem::NoCache);
- QTest::qWait(250);
- QCOMPARE(tester->repaints, 1);
+ QTest::qWait(25);
+ QTRY_COMPARE(tester->repaints, 1);
QCOMPARE(testerChild->repaints, 1);
QCOMPARE(testerChild2->repaints, 1);
tester->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
testerChild->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
testerChild2->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
- QTest::qWait(250);
+ QTest::qWait(25);
}
// The first move causes a repaint as the item is painted into its pixmap.
@@ -6201,8 +6703,8 @@ void tst_QGraphicsItem::cacheMode()
tester->setPos(10, 10);
testerChild->setPos(10, 10);
testerChild2->setPos(10, 10);
- QTest::qWait(250);
- QCOMPARE(tester->repaints, 2);
+ QTest::qWait(25);
+ QTRY_COMPARE(tester->repaints, 2);
QCOMPARE(testerChild->repaints, 2);
QCOMPARE(testerChild2->repaints, 2);
@@ -6217,15 +6719,15 @@ void tst_QGraphicsItem::cacheMode()
// Translating does not result in a repaint.
tester->translate(10, 10);
- QTest::qWait(250);
- QCOMPARE(tester->repaints, 2);
+ QTest::qWait(25);
+ QTRY_COMPARE(tester->repaints, 2);
QCOMPARE(testerChild->repaints, 2);
QCOMPARE(testerChild2->repaints, 2);
// Rotating results in a repaint.
tester->rotate(45);
- QTest::qWait(250);
- QCOMPARE(tester->repaints, 3);
+ QTest::qWait(25);
+ QTRY_COMPARE(tester->repaints, 3);
QCOMPARE(testerChild->repaints, 3);
QCOMPARE(testerChild2->repaints, 2);
@@ -6233,8 +6735,8 @@ void tst_QGraphicsItem::cacheMode()
tester->setCacheMode(QGraphicsItem::ItemCoordinateCache); // autosize
testerChild->setCacheMode(QGraphicsItem::ItemCoordinateCache); // autosize
testerChild2->setCacheMode(QGraphicsItem::ItemCoordinateCache); // autosize
- QTest::qWait(250);
- QCOMPARE(tester->repaints, 4);
+ QTest::qWait(25);
+ QTRY_COMPARE(tester->repaints, 4);
QCOMPARE(testerChild->repaints, 4);
QCOMPARE(testerChild2->repaints, 3);
@@ -6242,30 +6744,30 @@ void tst_QGraphicsItem::cacheMode()
tester->rotate(22);
testerChild->rotate(22);
testerChild2->rotate(22);
- QTest::qWait(250);
- QCOMPARE(tester->repaints, 4);
+ QTest::qWait(25);
+ QTRY_COMPARE(tester->repaints, 4);
QCOMPARE(testerChild->repaints, 4);
QCOMPARE(testerChild2->repaints, 3);
// Explicit update causes a repaint.
tester->update(0, 0, 5, 5);
- QTest::qWait(250);
- QCOMPARE(tester->repaints, 5);
+ QTest::qWait(25);
+ QTRY_COMPARE(tester->repaints, 5);
QCOMPARE(testerChild->repaints, 4);
QCOMPARE(testerChild2->repaints, 3);
// Updating outside the item's bounds does not cause a repaint.
tester->update(10, 10, 5, 5);
- QTest::qWait(250);
- QCOMPARE(tester->repaints, 5);
+ QTest::qWait(25);
+ QTRY_COMPARE(tester->repaints, 5);
QCOMPARE(testerChild->repaints, 4);
QCOMPARE(testerChild2->repaints, 3);
// Resizing an item should cause a repaint of that item. (because of
// autosize).
tester->setGeometry(QRectF(-15, -15, 30, 30));
- QTest::qWait(250);
- QCOMPARE(tester->repaints, 6);
+ QTest::qWait(25);
+ QTRY_COMPARE(tester->repaints, 6);
QCOMPARE(testerChild->repaints, 4);
QCOMPARE(testerChild2->repaints, 3);
@@ -6273,22 +6775,22 @@ void tst_QGraphicsItem::cacheMode()
tester->setCacheMode(QGraphicsItem::ItemCoordinateCache, QSize(30, 30));
testerChild->setCacheMode(QGraphicsItem::ItemCoordinateCache, QSize(30, 30));
testerChild2->setCacheMode(QGraphicsItem::ItemCoordinateCache, QSize(30, 30));
- QTest::qWait(250);
- QCOMPARE(tester->repaints, 7);
+ QTest::qWait(20);
+ QTRY_COMPARE(tester->repaints, 7);
QCOMPARE(testerChild->repaints, 5);
QCOMPARE(testerChild2->repaints, 4);
// Resizing the item should cause a repaint.
testerChild->setGeometry(QRectF(-15, -15, 30, 30));
- QTest::qWait(250);
- QCOMPARE(tester->repaints, 7);
+ QTest::qWait(25);
+ QTRY_COMPARE(tester->repaints, 7);
QCOMPARE(testerChild->repaints, 6);
QCOMPARE(testerChild2->repaints, 4);
// Scaling the view does not cause a repaint.
view.scale(0.7, 0.7);
- QTest::qWait(250);
- QCOMPARE(tester->repaints, 7);
+ QTest::qWait(25);
+ QTRY_COMPARE(tester->repaints, 7);
QCOMPARE(testerChild->repaints, 6);
QCOMPARE(testerChild2->repaints, 4);
@@ -6296,54 +6798,54 @@ void tst_QGraphicsItem::cacheMode()
tester->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
testerChild->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
testerChild2->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
- QTest::qWait(250);
- QCOMPARE(tester->repaints, 8);
+ QTest::qWait(25);
+ QTRY_COMPARE(tester->repaints, 8);
QCOMPARE(testerChild->repaints, 7);
QCOMPARE(testerChild2->repaints, 5);
// Scaling the view back should cause repaints for two of the items.
view.setTransform(QTransform());
- QTest::qWait(250);
- QCOMPARE(tester->repaints, 9);
+ QTest::qWait(25);
+ QTRY_COMPARE(tester->repaints, 9);
QCOMPARE(testerChild->repaints, 8);
QCOMPARE(testerChild2->repaints, 5);
// Rotating the base item (perspective) should repaint two items.
tester->setTransform(QTransform().rotate(10, Qt::XAxis));
- QTest::qWait(250);
- QCOMPARE(tester->repaints, 10);
+ QTest::qWait(25);
+ QTRY_COMPARE(tester->repaints, 10);
QCOMPARE(testerChild->repaints, 9);
QCOMPARE(testerChild2->repaints, 5);
// Moving the middle item should case a repaint even if it's a move,
// because the parent is rotated with a perspective.
testerChild->setPos(1, 1);
- QTest::qWait(250);
- QCOMPARE(tester->repaints, 10);
+ QTest::qWait(25);
+ QTRY_COMPARE(tester->repaints, 10);
QCOMPARE(testerChild->repaints, 10);
QCOMPARE(testerChild2->repaints, 5);
// Make a huge item
tester->setGeometry(QRectF(-4000, -4000, 8000, 8000));
- QTest::qWait(250);
- QCOMPARE(tester->repaints, 11);
+ QTest::qWait(25);
+ QTRY_COMPARE(tester->repaints, 11);
QCOMPARE(testerChild->repaints, 10);
QCOMPARE(testerChild2->repaints, 5);
// Move the large item - will cause a repaint as the
// cache is clipped.
tester->setPos(5, 0);
- QTest::qWait(250);
- QCOMPARE(tester->repaints, 12);
+ QTest::qWait(25);
+ QTRY_COMPARE(tester->repaints, 12);
QCOMPARE(testerChild->repaints, 10);
QCOMPARE(testerChild2->repaints, 5);
// Hiding and showing should invalidate the cache
tester->hide();
- QTest::qWait(250);
+ QTest::qWait(25);
tester->show();
- QTest::qWait(250);
- QCOMPARE(tester->repaints, 13);
+ QTest::qWait(25);
+ QTRY_COMPARE(tester->repaints, 13);
QCOMPARE(testerChild->repaints, 11);
QCOMPARE(testerChild2->repaints, 6);
}
@@ -6360,32 +6862,32 @@ void tst_QGraphicsItem::updateCachedItemAfterMove()
scene.addItem(tester);
QGraphicsView view(&scene);
view.show();
-#ifdef Q_WS_X11
- qt_x11_wait_for_window_manager(&view);
-#endif
- QTest::qWait(125);
+ QTest::qWaitForWindowShown(&view);
+
+ QTest::qWait(12);
+ QTRY_VERIFY(tester->repaints > 0);
tester->repaints = 0;
// Move the item, should not cause repaints
tester->setPos(10, 0);
- QTest::qWait(125);
+ QTest::qWait(12);
QCOMPARE(tester->repaints, 0);
// Move then update, should cause one repaint
tester->setPos(20, 0);
tester->update();
- QTest::qWait(125);
+ QTest::qWait(12);
QCOMPARE(tester->repaints, 1);
// Hiding the item doesn't cause a repaint
tester->hide();
- QTest::qWait(125);
+ QTest::qWait(12);
QCOMPARE(tester->repaints, 1);
// Moving a hidden item doesn't cause a repaint
tester->setPos(30, 0);
tester->update();
- QTest::qWait(125);
+ QTest::qWait(12);
QCOMPARE(tester->repaints, 1);
}
@@ -6403,7 +6905,7 @@ public:
QGraphicsRectItem::paint(painter, option, widget);
painter->drawText(boundingRect(), Qt::AlignCenter, QString("%1x%2\n%3x%4").arg(p.x()).arg(p.y()).arg(sp.x()).arg(sp.y()));
}
-
+
protected:
void hoverMoveEvent(QGraphicsSceneHoverEvent *event)
{
@@ -6497,6 +6999,1593 @@ void tst_QGraphicsItem::deviceTransform()
QCOMPARE(rect3->deviceTransform(deviceX).map(QPointF(50, 50)), mapResult3);
}
+class MyGraphicsView : public QGraphicsView
+{
+public:
+ int repaints;
+ QRegion paintedRegion;
+ MyGraphicsView(QGraphicsScene *scene) : QGraphicsView(scene), repaints(0) {}
+ void paintEvent(QPaintEvent *e)
+ {
+ paintedRegion += e->region();
+ ++repaints;
+ QGraphicsView::paintEvent(e);
+ }
+ void reset() { repaints = 0; paintedRegion = QRegion(); }
+};
+
+void tst_QGraphicsItem::update()
+{
+ QGraphicsScene scene;
+ scene.setSceneRect(-100, -100, 200, 200);
+ MyGraphicsView view(&scene);
+
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+ QTest::qWait(100);
+
+ EventTester *item = new EventTester;
+ scene.addItem(item);
+ QTest::qWait(100); // Make sure all pending updates are processed.
+ item->repaints = 0;
+
+ item->update(); // Item marked as dirty
+ scene.update(); // Entire scene marked as dirty
+ qApp->processEvents();
+ QCOMPARE(item->repaints, 1);
+
+ // Make sure the dirty state from the previous update is reset so that
+ // the item don't think it is already dirty and discards this update.
+ item->update();
+ qApp->processEvents();
+ QCOMPARE(item->repaints, 2);
+
+ // Make sure a partial update doesn't cause a full update to be discarded.
+ view.reset();
+ item->repaints = 0;
+ item->update(QRectF(0, 0, 5, 5));
+ item->update();
+ qApp->processEvents();
+ QCOMPARE(item->repaints, 1);
+ QCOMPARE(view.repaints, 1);
+ QRect itemDeviceBoundingRect = item->deviceTransform(view.viewportTransform())
+ .mapRect(item->boundingRect()).toRect();
+ QRegion expectedRegion = itemDeviceBoundingRect.adjusted(-2, -2, 2, 2);
+ // The entire item's bounding rect (adjusted for antialiasing) should have been painted.
+ QCOMPARE(view.paintedRegion, expectedRegion);
+
+ // Make sure update requests outside the bounding rect are discarded.
+ view.reset();
+ item->repaints = 0;
+ item->update(-15, -15, 5, 5); // Item's brect: (-10, -10, 20, 20)
+ qApp->processEvents();
+ QCOMPARE(item->repaints, 0);
+ QCOMPARE(view.repaints, 0);
+
+ // Make sure the area occupied by an item is repainted when hiding it.
+ view.reset();
+ item->repaints = 0;
+ item->update(); // Full update; all sub-sequent update requests are discarded.
+ item->hide(); // visible set to 0. ignoreVisible must be set to 1; the item won't be processed otherwise.
+ qApp->processEvents();
+ QCOMPARE(item->repaints, 0);
+ QCOMPARE(view.repaints, 1);
+ // The entire item's bounding rect (adjusted for antialiasing) should have been painted.
+ QCOMPARE(view.paintedRegion, expectedRegion);
+
+ // Make sure item is repainted when shown (after being hidden).
+ view.reset();
+ item->repaints = 0;
+ item->show();
+ qApp->processEvents();
+ QCOMPARE(item->repaints, 1);
+ QCOMPARE(view.repaints, 1);
+ // The entire item's bounding rect (adjusted for antialiasing) should have been painted.
+ QCOMPARE(view.paintedRegion, expectedRegion);
+
+ item->repaints = 0;
+ item->hide();
+ qApp->processEvents();
+ view.reset();
+ const QPointF originalPos = item->pos();
+ item->setPos(5000, 5000);
+ qApp->processEvents();
+ QCOMPARE(item->repaints, 0);
+ QCOMPARE(view.repaints, 0);
+ qApp->processEvents();
+
+ item->setPos(originalPos);
+ qApp->processEvents();
+ QCOMPARE(item->repaints, 0);
+ QCOMPARE(view.repaints, 0);
+ item->show();
+ qApp->processEvents();
+ QCOMPARE(item->repaints, 1);
+ QCOMPARE(view.repaints, 1);
+ // The entire item's bounding rect (adjusted for antialiasing) should have been painted.
+ QCOMPARE(view.paintedRegion, expectedRegion);
+
+ QGraphicsViewPrivate *viewPrivate = static_cast<QGraphicsViewPrivate *>(qt_widget_private(&view));
+ item->setPos(originalPos + QPoint(50, 50));
+ viewPrivate->updateAll();
+ QVERIFY(viewPrivate->fullUpdatePending);
+ QTest::qWait(50);
+ item->repaints = 0;
+ view.reset();
+ item->setPos(originalPos);
+ QTest::qWait(50);
+ qApp->processEvents();
+ QCOMPARE(item->repaints, 1);
+ QCOMPARE(view.repaints, 1);
+ QCOMPARE(view.paintedRegion, expectedRegion + expectedRegion.translated(50, 50));
+
+ // Make sure moving a parent item triggers an update on the children
+ // (even though the parent itself is outside the viewport).
+ QGraphicsRectItem *parent = new QGraphicsRectItem(0, 0, 10, 10);
+ parent->setPos(-400, 0);
+ item->setParentItem(parent);
+ item->setPos(400, 0);
+ scene.addItem(parent);
+ QTest::qWait(50);
+ itemDeviceBoundingRect = item->deviceTransform(view.viewportTransform())
+ .mapRect(item->boundingRect()).toRect();
+ expectedRegion = itemDeviceBoundingRect.adjusted(-2, -2, 2, 2);
+ view.reset();
+ item->repaints = 0;
+ parent->translate(-400, 0);
+ qApp->processEvents();
+ QCOMPARE(item->repaints, 0);
+ QCOMPARE(view.repaints, 1);
+ QCOMPARE(view.paintedRegion, expectedRegion);
+ view.reset();
+ item->repaints = 0;
+ parent->translate(400, 0);
+ qApp->processEvents();
+ QCOMPARE(item->repaints, 1);
+ QCOMPARE(view.repaints, 1);
+ QCOMPARE(view.paintedRegion, expectedRegion);
+ QCOMPARE(view.paintedRegion, expectedRegion);
+}
+
+void tst_QGraphicsItem::setTransformProperties_data()
+{
+ QTest::addColumn<QPointF>("origin");
+ QTest::addColumn<qreal>("rotation");
+ QTest::addColumn<qreal>("scale");
+
+ QTest::newRow("nothing") << QPointF() << qreal(0.0) << qreal(1.0);
+
+ QTest::newRow("rotation") << QPointF() << qreal(42.2) << qreal(1.0);
+
+ QTest::newRow("rotation dicentred") << QPointF(qreal(22.3), qreal(-56.2))
+ << qreal(-2578.2)
+ << qreal(1.0);
+
+ QTest::newRow("Scale") << QPointF() << qreal(0.0)
+ << qreal(6);
+
+ QTest::newRow("Everything dicentred") << QPointF(qreal(22.3), qreal(-56.2)) << qreal(-175) << qreal(196);
+}
+
+/**
+ * the normal QCOMPARE doesn't work because it doesn't use qFuzzyCompare
+ */
+#define QCOMPARE_TRANSFORM(X1, X2) QVERIFY(((X1)*(X2).inverted()).isIdentity())
+
+void tst_QGraphicsItem::setTransformProperties()
+{
+ QFETCH(QPointF,origin);
+ QFETCH(qreal,rotation);
+ QFETCH(qreal,scale);
+
+ QTransform result;
+ result.translate(origin.x(), origin.y());
+ result.rotate(rotation, Qt::ZAxis);
+ result.scale(scale, scale);
+ result.translate(-origin.x(), -origin.y());
+
+ QGraphicsScene scene;
+ QGraphicsRectItem *item = new QGraphicsRectItem(QRectF(0, 0, 100, 100));
+ scene.addItem(item);
+
+ item->setRotation(rotation);
+ item->setScale(scale);
+ item->setTransformOriginPoint(origin);
+
+ QCOMPARE(item->rotation(), rotation);
+ QCOMPARE(item->scale(), scale);
+ QCOMPARE(item->transformOriginPoint(), origin);
+
+ QCOMPARE(QTransform(), item->transform());
+ QCOMPARE(result, item->sceneTransform());
+
+ //-----------------------------------------------------------------
+ //Change the rotation Z
+ item->setRotation(45);
+ QTransform result2;
+ result2.translate(origin.x(), origin.y());
+ result2.rotate(45);
+ result2.scale(scale, scale);
+ result2.translate(-origin.x(), -origin.y());
+
+ QCOMPARE(item->rotation(), 45.);
+ QCOMPARE(item->scale(), scale);
+ QCOMPARE(item->transformOriginPoint(), origin);
+
+ QCOMPARE(QTransform(), item->transform());
+ QCOMPARE(result2, item->sceneTransform());
+
+ //-----------------------------------------------------------------
+ // calling setTransform() and setPos should change the sceneTransform
+ item->setTransform(result);
+ item->setPos(100, -150.5);
+
+ QCOMPARE(item->rotation(), 45.);
+ QCOMPARE(item->scale(), scale);
+ QCOMPARE(item->transformOriginPoint(), origin);
+ QCOMPARE(result, item->transform());
+
+ QTransform result3(result);
+
+ result3.translate(origin.x(), origin.y());
+ result3.rotate(45);
+ result3.scale(scale, scale);
+ result3.translate(-origin.x(), -origin.y());
+
+ result3 *= QTransform::fromTranslate(100, -150.5); //the pos;
+
+ QCOMPARE(result3, item->sceneTransform());
+
+ //-----------------------------------------------------
+ // setting the propertiees should be the same as setting a transform
+ {//with center origin on the matrix
+ QGraphicsRectItem *item1 = new QGraphicsRectItem(QRectF(50.2, -150, 230.5, 119));
+ scene.addItem(item1);
+ QGraphicsRectItem *item2 = new QGraphicsRectItem(QRectF(50.2, -150, 230.5, 119));
+ scene.addItem(item2);
+
+ item1->setPos(12.3, -5);
+ item2->setPos(12.3, -5);
+ item1->setRotation(rotation);
+ item1->setScale(scale);
+ item1->setTransformOriginPoint(origin);
+
+ item2->setTransform(result);
+
+ QCOMPARE_TRANSFORM(item1->sceneTransform(), item2->sceneTransform());
+
+ QCOMPARE_TRANSFORM(item1->itemTransform(item2), QTransform());
+ QCOMPARE_TRANSFORM(item2->itemTransform(item1), QTransform());
+ }
+}
+
+class MyStyleOptionTester : public QGraphicsRectItem
+{
+public:
+ MyStyleOptionTester(const QRectF &rect)
+ : QGraphicsRectItem(rect), startTrack(false)
+ {}
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0)
+ {
+ if (startTrack) {
+ //Doesn't use the extended style option so the exposed rect is the boundingRect
+ if (!(flags() & QGraphicsItem::ItemUsesExtendedStyleOption)) {
+ QCOMPARE(option->exposedRect, boundingRect());
+ QCOMPARE(option->matrix, QMatrix());
+ } else {
+ QVERIFY(option->exposedRect != QRect());
+ QVERIFY(option->exposedRect != boundingRect());
+ QCOMPARE(option->matrix, sceneTransform().toAffine());
+ }
+ }
+ QGraphicsRectItem::paint(painter, option, widget);
+ }
+ bool startTrack;
+};
+
+void tst_QGraphicsItem::itemUsesExtendedStyleOption()
+{
+ QGraphicsScene scene(0, 0, 300, 300);
+ QGraphicsPixmapItem item;
+ item.setFlag(QGraphicsItem::ItemUsesExtendedStyleOption, true);
+ QCOMPARE(item.flags(), QGraphicsItem::GraphicsItemFlags(QGraphicsItem::ItemUsesExtendedStyleOption));
+ item.setFlag(QGraphicsItem::ItemUsesExtendedStyleOption, false);
+ QCOMPARE(item.flags(), 0);
+
+ //We now test the content of the style option
+ MyStyleOptionTester *rect = new MyStyleOptionTester(QRect(0, 0, 100, 100));
+ scene.addItem(rect);
+ rect->setPos(200, 200);
+ QGraphicsView view(&scene);
+ rect->startTrack = false;
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ rect->startTrack = true;
+ rect->update(10, 10, 10, 10);
+ QTest::qWait(12);
+ rect->startTrack = false;
+ rect->setFlag(QGraphicsItem::ItemUsesExtendedStyleOption, true);
+ QVERIFY((rect->flags() & QGraphicsItem::ItemUsesExtendedStyleOption));
+ QTest::qWait(12);
+ rect->startTrack = true;
+ rect->update(10, 10, 10, 10);
+ QTest::qWait(12);
+}
+
+void tst_QGraphicsItem::itemSendsGeometryChanges()
+{
+ ItemChangeTester item;
+ item.setFlags(0);
+ item.clear();
+
+ QTransform x = QTransform().rotate(45);
+ QPointF pos(10, 10);
+ qreal o(0.5);
+ item.setTransform(x);
+ item.setPos(pos);
+ QCOMPARE(item.transform(), x);
+ QCOMPARE(item.pos(), pos);
+ QCOMPARE(item.changes.size(), 0);
+
+ item.setOpacity(o);
+ QCOMPARE(item.changes.size(), 2); // opacity
+
+ item.setFlag(QGraphicsItem::ItemSendsGeometryChanges);
+ QCOMPARE(item.changes.size(), 4); // flags
+ item.setTransform(QTransform());
+ item.setPos(QPointF());
+ QCOMPARE(item.changes.size(), 8); // transform + pos
+ QCOMPARE(item.transform(), QTransform());
+ QCOMPARE(item.pos(), QPointF());
+ QCOMPARE(item.opacity(), o);
+
+ QCOMPARE(item.changes, QList<QGraphicsItem::GraphicsItemChange>()
+ << QGraphicsItem::ItemOpacityChange
+ << QGraphicsItem::ItemOpacityHasChanged
+ << QGraphicsItem::ItemFlagsChange
+ << QGraphicsItem::ItemFlagsHaveChanged
+ << QGraphicsItem::ItemTransformChange
+ << QGraphicsItem::ItemTransformHasChanged
+ << QGraphicsItem::ItemPositionChange
+ << QGraphicsItem::ItemPositionHasChanged);
+}
+
+// Make sure we update moved items correctly.
+void tst_QGraphicsItem::moveItem()
+{
+ QGraphicsScene scene;
+ scene.setSceneRect(-50, -50, 200, 200);
+
+ MyGraphicsView view(&scene);
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+ QTest::qWait(100);
+
+ EventTester *parent = new EventTester;
+ EventTester *child = new EventTester(parent);
+ EventTester *grandChild = new EventTester(child);
+
+#define RESET_COUNTERS \
+ parent->repaints = 0; \
+ child->repaints = 0; \
+ grandChild->repaints = 0; \
+ view.reset();
+
+ scene.addItem(parent);
+ QTest::qWait(100);
+
+ RESET_COUNTERS
+
+ // Item's boundingRect: (-10, -10, 20, 20).
+ QRect parentDeviceBoundingRect = parent->deviceTransform(view.viewportTransform())
+ .mapRect(parent->boundingRect()).toRect()
+ .adjusted(-2, -2, 2, 2); // Adjusted for antialiasing.
+
+ parent->setPos(20, 20);
+ qApp->processEvents();
+ QCOMPARE(parent->repaints, 1);
+ QCOMPARE(view.repaints, 1);
+ QRegion expectedParentRegion = parentDeviceBoundingRect; // old position
+ parentDeviceBoundingRect.translate(20, 20);
+ expectedParentRegion += parentDeviceBoundingRect; // new position
+ QCOMPARE(view.paintedRegion, expectedParentRegion);
+
+ RESET_COUNTERS
+
+ child->setPos(20, 20);
+ qApp->processEvents();
+ QCOMPARE(parent->repaints, 1);
+ QCOMPARE(child->repaints, 1);
+ QCOMPARE(view.repaints, 1);
+ const QRegion expectedChildRegion = expectedParentRegion.translated(20, 20);
+ QCOMPARE(view.paintedRegion, expectedChildRegion);
+
+ RESET_COUNTERS
+
+ grandChild->setPos(20, 20);
+ qApp->processEvents();
+ QCOMPARE(parent->repaints, 1);
+ QCOMPARE(child->repaints, 1);
+ QCOMPARE(grandChild->repaints, 1);
+ QCOMPARE(view.repaints, 1);
+ const QRegion expectedGrandChildRegion = expectedParentRegion.translated(40, 40);
+ QCOMPARE(view.paintedRegion, expectedGrandChildRegion);
+
+ RESET_COUNTERS
+
+ parent->translate(20, 20);
+ qApp->processEvents();
+ QCOMPARE(parent->repaints, 1);
+ QCOMPARE(child->repaints, 1);
+ QCOMPARE(grandChild->repaints, 1);
+ QCOMPARE(view.repaints, 1);
+ expectedParentRegion.translate(20, 20);
+ expectedParentRegion += expectedChildRegion.translated(20, 20);
+ expectedParentRegion += expectedGrandChildRegion.translated(20, 20);
+ QCOMPARE(view.paintedRegion, expectedParentRegion);
+}
+
+void tst_QGraphicsItem::sorting_data()
+{
+ QTest::addColumn<int>("index");
+
+ QTest::newRow("NoIndex") << int(QGraphicsScene::NoIndex);
+ QTest::newRow("BspTreeIndex") << int(QGraphicsScene::BspTreeIndex);
+}
+
+void tst_QGraphicsItem::sorting()
+{
+ _paintedItems.clear();
+
+ QGraphicsScene scene;
+ QGraphicsItem *grid[100][100];
+ for (int x = 0; x < 100; ++x) {
+ for (int y = 0; y < 100; ++y) {
+ PainterItem *item = new PainterItem;
+ item->setPos(x * 25, y * 25);
+ item->setData(0, QString("%1x%2").arg(x).arg(y));
+ grid[x][y] = item;
+ scene.addItem(item);
+ }
+ }
+
+ PainterItem *item1 = new PainterItem;
+ PainterItem *item2 = new PainterItem;
+ item1->setData(0, "item1");
+ item2->setData(0, "item2");
+ scene.addItem(item1);
+ scene.addItem(item2);
+
+ QGraphicsView view(&scene);
+ view.setResizeAnchor(QGraphicsView::NoAnchor);
+ view.setTransformationAnchor(QGraphicsView::NoAnchor);
+ view.resize(120, 100);
+ view.setFrameStyle(0);
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+ QTest::qWait(100);
+
+ _paintedItems.clear();
+
+ view.viewport()->repaint();
+#ifdef Q_WS_MAC
+ // There's no difference between repaint and update on the Mac,
+ // so we have to process events here to make sure we get the event.
+ QTest::qWait(100);
+#endif
+
+ QCOMPARE(_paintedItems, QList<QGraphicsItem *>()
+ << grid[0][0] << grid[0][1] << grid[0][2] << grid[0][3]
+ << grid[1][0] << grid[1][1] << grid[1][2] << grid[1][3]
+ << grid[2][0] << grid[2][1] << grid[2][2] << grid[2][3]
+ << grid[3][0] << grid[3][1] << grid[3][2] << grid[3][3]
+ << grid[4][0] << grid[4][1] << grid[4][2] << grid[4][3]
+ << item1 << item2);
+}
+
+void tst_QGraphicsItem::itemHasNoContents()
+{
+ PainterItem *item1 = new PainterItem;
+ PainterItem *item2 = new PainterItem;
+ item2->setParentItem(item1);
+ item2->setPos(50, 50);
+ item1->setFlag(QGraphicsItem::ItemHasNoContents);
+ item1->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
+
+ QGraphicsScene scene;
+ scene.addItem(item1);
+
+ QGraphicsView view(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QTRY_VERIFY(!_paintedItems.isEmpty());
+
+ _paintedItems.clear();
+
+ view.viewport()->repaint();
+#ifdef Q_WS_MAC
+ // There's no difference between update() and repaint() on the Mac,
+ // so we have to process events here to make sure we get the event.
+ QTest::qWait(10);
+#endif
+
+ QTRY_COMPARE(_paintedItems, QList<QGraphicsItem *>() << item2);
+}
+
+void tst_QGraphicsItem::hitTestUntransformableItem()
+{
+ QGraphicsScene scene;
+ scene.setSceneRect(-100, -100, 200, 200);
+
+ QGraphicsView view(&scene);
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+ QTest::qWait(100);
+
+ // Confuse the BSP with dummy items.
+ QGraphicsRectItem *dummy = new QGraphicsRectItem(0, 0, 20, 20);
+ dummy->setPos(-100, -100);
+ scene.addItem(dummy);
+ for (int i = 0; i < 100; ++i) {
+ QGraphicsItem *parent = dummy;
+ dummy = new QGraphicsRectItem(0, 0, 20, 20);
+ dummy->setPos(-100 + i, -100 + i);
+ dummy->setParentItem(parent);
+ }
+
+ QGraphicsRectItem *item1 = new QGraphicsRectItem(0, 0, 20, 20);
+ item1->setPos(-200, -200);
+
+ QGraphicsRectItem *item2 = new QGraphicsRectItem(0, 0, 20, 20);
+ item2->setFlag(QGraphicsItem::ItemIgnoresTransformations);
+ item2->setParentItem(item1);
+ item2->setPos(200, 200);
+
+ QGraphicsRectItem *item3 = new QGraphicsRectItem(0, 0, 20, 20);
+ item3->setParentItem(item2);
+ item3->setPos(80, 80);
+
+ scene.addItem(item1);
+ QTest::qWait(100);
+
+ QList<QGraphicsItem *> items = scene.items(QPointF(80, 80));
+ QCOMPARE(items.size(), 1);
+ QCOMPARE(items.at(0), static_cast<QGraphicsItem*>(item3));
+
+ scene.setItemIndexMethod(QGraphicsScene::NoIndex);
+ QTest::qWait(100);
+
+ items = scene.items(QPointF(80, 80));
+ QCOMPARE(items.size(), 1);
+ QCOMPARE(items.at(0), static_cast<QGraphicsItem*>(item3));
+}
+
+void tst_QGraphicsItem::hitTestGraphicsEffectItem()
+{
+ QGraphicsScene scene;
+ scene.setSceneRect(-100, -100, 200, 200);
+
+ QGraphicsView view(&scene);
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+ QTest::qWait(100);
+
+ // Confuse the BSP with dummy items.
+ QGraphicsRectItem *dummy = new QGraphicsRectItem(0, 0, 20, 20);
+ dummy->setPos(-100, -100);
+ scene.addItem(dummy);
+ for (int i = 0; i < 100; ++i) {
+ QGraphicsItem *parent = dummy;
+ dummy = new QGraphicsRectItem(0, 0, 20, 20);
+ dummy->setPos(-100 + i, -100 + i);
+ dummy->setParentItem(parent);
+ }
+
+ const QRectF itemBoundingRect(0, 0, 20, 20);
+ EventTester *item1 = new EventTester;
+ item1->br = itemBoundingRect;
+ item1->setPos(-200, -200);
+
+ EventTester *item2 = new EventTester;
+ item2->br = itemBoundingRect;
+ item2->setFlag(QGraphicsItem::ItemIgnoresTransformations);
+ item2->setParentItem(item1);
+ item2->setPos(200, 200);
+
+ EventTester *item3 = new EventTester;
+ item3->br = itemBoundingRect;
+ item3->setParentItem(item2);
+ item3->setPos(80, 80);
+
+ scene.addItem(item1);
+ QTest::qWait(100);
+
+ item1->repaints = 0;
+ item2->repaints = 0;
+ item3->repaints = 0;
+
+ // Apply shadow effect to the entire sub-tree.
+ QGraphicsDropShadowEffect *shadow = new QGraphicsDropShadowEffect;
+ shadow->setOffset(-20, -20);
+ item1->setGraphicsEffect(shadow);
+ QTest::qWait(50);
+
+ // Make sure all items are repainted.
+ QCOMPARE(item1->repaints, 1);
+ QCOMPARE(item2->repaints, 1);
+ QCOMPARE(item3->repaints, 1);
+
+ // Make sure an item doesn't respond to a click on its shadow.
+ QList<QGraphicsItem *> items = scene.items(QPointF(75, 75));
+ QVERIFY(items.isEmpty());
+ items = scene.items(QPointF(80, 80));
+ QCOMPARE(items.size(), 1);
+ QCOMPARE(items.at(0), static_cast<EventTester *>(item3));
+
+ item1->repaints = 0;
+ item2->repaints = 0;
+ item3->repaints = 0;
+
+ view.viewport()->update(75, 75, 20, 20);
+ QTest::qWait(50);
+
+ // item1 is the effect source and must therefore be repainted.
+ // item2 intersects with the exposed region
+ // item3 is just another child outside the exposed region
+ QCOMPARE(item1->repaints, 1);
+ QCOMPARE(item2->repaints, 1);
+ QCOMPARE(item3->repaints, 0);
+
+ scene.setItemIndexMethod(QGraphicsScene::NoIndex);
+ QTest::qWait(100);
+
+ items = scene.items(QPointF(75, 75));
+ QVERIFY(items.isEmpty());
+ items = scene.items(QPointF(80, 80));
+ QCOMPARE(items.size(), 1);
+ QCOMPARE(items.at(0), static_cast<EventTester *>(item3));
+}
+
+void tst_QGraphicsItem::focusProxy()
+{
+ QGraphicsScene scene;
+ QEvent activate(QEvent::WindowActivate);
+ QApplication::sendEvent(&scene, &activate);
+
+ QGraphicsItem *item = scene.addRect(0, 0, 10, 10);
+ item->setFlag(QGraphicsItem::ItemIsFocusable);
+ QVERIFY(!item->focusProxy());
+
+ QGraphicsItem *item2 = scene.addRect(0, 0, 10, 10);
+ item2->setFlag(QGraphicsItem::ItemIsFocusable);
+ item->setFocusProxy(item2);
+ QCOMPARE(item->focusProxy(), item2);
+
+ item->setFocus();
+ QVERIFY(item->hasFocus());
+ QVERIFY(item2->hasFocus());
+
+ // Try to make a focus chain loop
+ QString err;
+ QTextStream stream(&err);
+ stream << "QGraphicsItem::setFocusProxy: "
+ << (void*)item << " is already in the focus proxy chain" << flush;
+ QTest::ignoreMessage(QtWarningMsg, err.toLatin1().constData());
+ item2->setFocusProxy(item); // fails
+ QCOMPARE(item->focusProxy(), (QGraphicsItem *)item2);
+ QCOMPARE(item2->focusProxy(), (QGraphicsItem *)0);
+
+ // Try to assign self as focus proxy
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsItem::setFocusProxy: cannot assign self as focus proxy");
+ item->setFocusProxy(item); // fails
+ QCOMPARE(item->focusProxy(), (QGraphicsItem *)item2);
+ QCOMPARE(item2->focusProxy(), (QGraphicsItem *)0);
+
+ // Reset the focus proxy
+ item->setFocusProxy(0);
+ QCOMPARE(item->focusProxy(), (QGraphicsItem *)0);
+ QVERIFY(!item->hasFocus());
+ QVERIFY(item2->hasFocus());
+
+ // Test deletion
+ item->setFocusProxy(item2);
+ QCOMPARE(item->focusProxy(), (QGraphicsItem *)item2);
+ delete item2;
+ QCOMPARE(item->focusProxy(), (QGraphicsItem *)0);
+
+ // Test event delivery
+ item2 = scene.addRect(0, 0, 10, 10);
+ item2->setFlag(QGraphicsItem::ItemIsFocusable);
+ item->setFocusProxy(item2);
+ item->clearFocus();
+
+ EventSpy focusInSpy(&scene, item, QEvent::FocusIn);
+ EventSpy focusOutSpy(&scene, item, QEvent::FocusOut);
+ EventSpy focusInSpy2(&scene, item2, QEvent::FocusIn);
+ EventSpy focusOutSpy2(&scene, item2, QEvent::FocusOut);
+ QCOMPARE(focusInSpy.count(), 0);
+ QCOMPARE(focusOutSpy.count(), 0);
+ QCOMPARE(focusInSpy2.count(), 0);
+ QCOMPARE(focusOutSpy2.count(), 0);
+
+ item->setFocus();
+ QCOMPARE(focusInSpy.count(), 0);
+ QCOMPARE(focusInSpy2.count(), 1);
+ item->clearFocus();
+ QCOMPARE(focusOutSpy.count(), 0);
+ QCOMPARE(focusOutSpy2.count(), 1);
+
+ // Test two items proxying one item.
+ QGraphicsItem *item3 = scene.addRect(0, 0, 10, 10);
+ item3->setFlag(QGraphicsItem::ItemIsFocusable);
+ item3->setFocusProxy(item2); // item and item3 use item2 as proxy
+
+ QCOMPARE(item->focusProxy(), item2);
+ QCOMPARE(item2->focusProxy(), (QGraphicsItem *)0);
+ QCOMPARE(item3->focusProxy(), item2);
+ delete item2;
+ QCOMPARE(item->focusProxy(), (QGraphicsItem *)0);
+ QCOMPARE(item3->focusProxy(), (QGraphicsItem *)0);
+}
+
+void tst_QGraphicsItem::subFocus()
+{
+ // Construct a text item that's not part of a scene (yet)
+ // and has no parent. Setting focus on it will not make
+ // the item gain input focus; that requires a scene. But
+ // it does set subfocus, indicating that the item wishes
+ // to gain focus later.
+ QGraphicsTextItem *text = new QGraphicsTextItem("Hello");
+ text->setTextInteractionFlags(Qt::TextEditorInteraction);
+ QVERIFY(!text->hasFocus());
+ text->setFocus();
+ QVERIFY(!text->hasFocus());
+ QCOMPARE(text->focusItem(), (QGraphicsItem *)text);
+
+ // Add a sibling.
+ QGraphicsTextItem *text2 = new QGraphicsTextItem("Hi");
+ text2->setTextInteractionFlags(Qt::TextEditorInteraction);
+ text2->setPos(30, 30);
+
+ // Add both items to a scene and check that it's text that
+ // got input focus.
+ QGraphicsScene scene;
+ QEvent activate(QEvent::WindowActivate);
+ QApplication::sendEvent(&scene, &activate);
+
+ scene.addItem(text);
+ scene.addItem(text2);
+ QVERIFY(text->hasFocus());
+
+ text->setData(0, "text");
+ text2->setData(0, "text2");
+
+ // Remove text2 and set subfocus on it. Then readd. Reparent it onto the
+ // other item and see that it gains input focus.
+ scene.removeItem(text2);
+ text2->setFocus();
+ scene.addItem(text2);
+ QCOMPARE(text2->focusItem(), (QGraphicsItem *)text2);
+ text2->setParentItem(text);
+ QCOMPARE(text->focusItem(), (QGraphicsItem *)text2);
+ QCOMPARE(text2->focusItem(), (QGraphicsItem *)text2);
+ QVERIFY(!text->hasFocus());
+ QVERIFY(text2->hasFocus());
+
+ // Remove both items from the scene, restore subfocus and
+ // readd them. Now the subfocus should kick in and give
+ // text2 focus.
+ scene.removeItem(text);
+ QCOMPARE(text->focusItem(), (QGraphicsItem *)0);
+ QCOMPARE(text2->focusItem(), (QGraphicsItem *)0);
+ text2->setFocus();
+ QCOMPARE(text->focusItem(), (QGraphicsItem *)text2);
+ QCOMPARE(text2->focusItem(), (QGraphicsItem *)text2);
+ scene.addItem(text);
+
+ // Hiding and showing text should pass focus to text2.
+ QCOMPARE(text->focusItem(), (QGraphicsItem *)text2);
+ QVERIFY(text2->hasFocus());
+
+ // Subfocus should repropagate to root when reparenting.
+ QGraphicsRectItem *rect = new QGraphicsRectItem;
+ QGraphicsRectItem *rect2 = new QGraphicsRectItem(rect);
+ QGraphicsRectItem *rect3 = new QGraphicsRectItem(rect2);
+ rect3->setFlag(QGraphicsItem::ItemIsFocusable);
+
+ text->setData(0, "text");
+ text2->setData(0, "text2");
+ rect->setData(0, "rect");
+ rect2->setData(0, "rect2");
+ rect3->setData(0, "rect3");
+
+ rect3->setFocus();
+ QVERIFY(!rect3->hasFocus());
+ QCOMPARE(rect->focusItem(), (QGraphicsItem *)rect3);
+ QCOMPARE(rect2->focusItem(), (QGraphicsItem *)rect3);
+ QCOMPARE(rect3->focusItem(), (QGraphicsItem *)rect3);
+ rect->setParentItem(text2);
+ QCOMPARE(text->focusItem(), (QGraphicsItem *)rect3);
+ QCOMPARE(text2->focusItem(), (QGraphicsItem *)rect3);
+ QCOMPARE(rect->focusItem(), (QGraphicsItem *)rect3);
+ QCOMPARE(rect2->focusItem(), (QGraphicsItem *)rect3);
+ QCOMPARE(rect3->focusItem(), (QGraphicsItem *)rect3);
+ QVERIFY(!rect->hasFocus());
+ QVERIFY(!rect2->hasFocus());
+ QVERIFY(rect3->hasFocus());
+
+ delete rect2;
+ QCOMPARE(text->focusItem(), (QGraphicsItem *)0);
+ QCOMPARE(text2->focusItem(), (QGraphicsItem *)0);
+ QCOMPARE(rect->focusItem(), (QGraphicsItem *)0);
+}
+
+void tst_QGraphicsItem::focusProxyDeletion()
+{
+ QGraphicsRectItem *rect = new QGraphicsRectItem;
+ QGraphicsRectItem *rect2 = new QGraphicsRectItem;
+ rect->setFocusProxy(rect2);
+ QCOMPARE(rect->focusProxy(), (QGraphicsItem *)rect2);
+
+ delete rect2;
+ QCOMPARE(rect->focusProxy(), (QGraphicsItem *)0);
+
+ rect2 = new QGraphicsRectItem;
+ rect->setFocusProxy(rect2);
+ delete rect; // don't crash
+
+ rect = new QGraphicsRectItem;
+ rect->setFocusProxy(rect2);
+ QGraphicsScene *scene = new QGraphicsScene;
+ scene->addItem(rect);
+ scene->addItem(rect2);
+ delete rect2;
+ QCOMPARE(rect->focusProxy(), (QGraphicsItem *)0);
+
+ rect2 = new QGraphicsRectItem;
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsItem::setFocusProxy: focus proxy must be in same scene");
+ rect->setFocusProxy(rect2);
+ QCOMPARE(rect->focusProxy(), (QGraphicsItem *)0);
+ scene->addItem(rect2);
+ rect->setFocusProxy(rect2);
+ QCOMPARE(rect->focusProxy(), (QGraphicsItem *)rect2);
+ delete rect; // don't crash
+
+ rect = new QGraphicsRectItem;
+ rect2 = new QGraphicsRectItem;
+ rect->setFocusProxy(rect2);
+ QCOMPARE(rect->focusProxy(), (QGraphicsItem *)rect2);
+ scene->addItem(rect);
+ scene->addItem(rect2);
+ rect->setFocusProxy(rect2);
+ delete scene; // don't crash
+}
+
+void tst_QGraphicsItem::negativeZStacksBehindParent()
+{
+ QGraphicsRectItem rect;
+ QCOMPARE(rect.zValue(), qreal(0.0));
+ QVERIFY(!(rect.flags() & QGraphicsItem::ItemNegativeZStacksBehindParent));
+ QVERIFY(!(rect.flags() & QGraphicsItem::ItemStacksBehindParent));
+ rect.setZValue(-1);
+ QCOMPARE(rect.zValue(), qreal(-1.0));
+ QVERIFY(!(rect.flags() & QGraphicsItem::ItemStacksBehindParent));
+ rect.setZValue(0);
+ rect.setFlag(QGraphicsItem::ItemNegativeZStacksBehindParent);
+ QVERIFY(rect.flags() & QGraphicsItem::ItemNegativeZStacksBehindParent);
+ QVERIFY(!(rect.flags() & QGraphicsItem::ItemStacksBehindParent));
+ rect.setZValue(-1);
+ QVERIFY(rect.flags() & QGraphicsItem::ItemStacksBehindParent);
+ rect.setZValue(0);
+ QVERIFY(!(rect.flags() & QGraphicsItem::ItemStacksBehindParent));
+ rect.setFlag(QGraphicsItem::ItemNegativeZStacksBehindParent, false);
+ rect.setZValue(-1);
+ rect.setFlag(QGraphicsItem::ItemNegativeZStacksBehindParent, true);
+ QVERIFY(rect.flags() & QGraphicsItem::ItemStacksBehindParent);
+ rect.setFlag(QGraphicsItem::ItemNegativeZStacksBehindParent, false);
+ QVERIFY(rect.flags() & QGraphicsItem::ItemStacksBehindParent);
+}
+
+void tst_QGraphicsItem::setGraphicsEffect()
+{
+ // Check that we don't have any effect by default.
+ QGraphicsItem *item = new QGraphicsRectItem(0, 0, 10, 10);
+ QVERIFY(!item->graphicsEffect());
+
+ // SetGet check.
+ QPointer<QGraphicsEffect> blurEffect = new QGraphicsBlurEffect;
+ item->setGraphicsEffect(blurEffect);
+ QCOMPARE(item->graphicsEffect(), static_cast<QGraphicsEffect *>(blurEffect));
+
+ // Ensure the existing effect is deleted when setting a new one.
+ QPointer<QGraphicsEffect> shadowEffect = new QGraphicsDropShadowEffect;
+ item->setGraphicsEffect(shadowEffect);
+ QVERIFY(!blurEffect);
+ QCOMPARE(item->graphicsEffect(), static_cast<QGraphicsEffect *>(shadowEffect));
+ blurEffect = new QGraphicsBlurEffect;
+
+ // Ensure the effect is uninstalled when setting it on a new target.
+ QGraphicsItem *anotherItem = new QGraphicsRectItem(0, 0, 10, 10);
+ anotherItem->setGraphicsEffect(blurEffect);
+ item->setGraphicsEffect(blurEffect);
+ QVERIFY(!anotherItem->graphicsEffect());
+ QVERIFY(!shadowEffect);
+
+ // Ensure the existing effect is deleted when deleting the item.
+ delete item;
+ QVERIFY(!blurEffect);
+ delete anotherItem;
+}
+
+void tst_QGraphicsItem::panel()
+{
+ QGraphicsScene scene;
+
+ QGraphicsRectItem *panel1 = new QGraphicsRectItem;
+ QGraphicsRectItem *panel2 = new QGraphicsRectItem;
+ QGraphicsRectItem *panel3 = new QGraphicsRectItem;
+ QGraphicsRectItem *panel4 = new QGraphicsRectItem;
+ QGraphicsRectItem *notPanel1 = new QGraphicsRectItem;
+ QGraphicsRectItem *notPanel2 = new QGraphicsRectItem;
+ panel1->setFlag(QGraphicsItem::ItemIsPanel);
+ panel2->setFlag(QGraphicsItem::ItemIsPanel);
+ panel3->setFlag(QGraphicsItem::ItemIsPanel);
+ panel4->setFlag(QGraphicsItem::ItemIsPanel);
+ scene.addItem(panel1);
+ scene.addItem(panel2);
+ scene.addItem(panel3);
+ scene.addItem(panel4);
+ scene.addItem(notPanel1);
+ scene.addItem(notPanel2);
+
+ EventSpy spy_activate_panel1(&scene, panel1, QEvent::WindowActivate);
+ EventSpy spy_deactivate_panel1(&scene, panel1, QEvent::WindowDeactivate);
+ EventSpy spy_activate_panel2(&scene, panel2, QEvent::WindowActivate);
+ EventSpy spy_deactivate_panel2(&scene, panel2, QEvent::WindowDeactivate);
+ EventSpy spy_activate_panel3(&scene, panel3, QEvent::WindowActivate);
+ EventSpy spy_deactivate_panel3(&scene, panel3, QEvent::WindowDeactivate);
+ EventSpy spy_activate_panel4(&scene, panel4, QEvent::WindowActivate);
+ EventSpy spy_deactivate_panel4(&scene, panel4, QEvent::WindowDeactivate);
+ EventSpy spy_activate_notPanel1(&scene, notPanel1, QEvent::WindowActivate);
+ EventSpy spy_deactivate_notPanel1(&scene, notPanel1, QEvent::WindowDeactivate);
+ EventSpy spy_activate_notPanel2(&scene, notPanel1, QEvent::WindowActivate);
+ EventSpy spy_deactivate_notPanel2(&scene, notPanel1, QEvent::WindowDeactivate);
+
+ QCOMPARE(spy_activate_panel1.count(), 0);
+ QCOMPARE(spy_deactivate_panel1.count(), 0);
+ QCOMPARE(spy_activate_panel2.count(), 0);
+ QCOMPARE(spy_deactivate_panel2.count(), 0);
+ QCOMPARE(spy_activate_panel3.count(), 0);
+ QCOMPARE(spy_deactivate_panel3.count(), 0);
+ QCOMPARE(spy_activate_panel4.count(), 0);
+ QCOMPARE(spy_deactivate_panel4.count(), 0);
+ QCOMPARE(spy_activate_notPanel1.count(), 0);
+ QCOMPARE(spy_deactivate_notPanel1.count(), 0);
+ QCOMPARE(spy_activate_notPanel2.count(), 0);
+ QCOMPARE(spy_deactivate_notPanel2.count(), 0);
+
+ QVERIFY(!scene.activePanel());
+ QVERIFY(!scene.isActive());
+
+ QEvent activate(QEvent::WindowActivate);
+ QEvent deactivate(QEvent::WindowDeactivate);
+
+ QApplication::sendEvent(&scene, &activate);
+
+ // No previous activation, so the scene is active.
+ QVERIFY(scene.isActive());
+ QCOMPARE(scene.activePanel(), (QGraphicsItem *)panel1);
+ QVERIFY(panel1->isActive());
+ QVERIFY(!panel2->isActive());
+ QVERIFY(!panel3->isActive());
+ QVERIFY(!panel4->isActive());
+ QVERIFY(!notPanel1->isActive());
+ QVERIFY(!notPanel2->isActive());
+ QCOMPARE(spy_deactivate_notPanel1.count(), 0);
+ QCOMPARE(spy_deactivate_notPanel2.count(), 0);
+ QCOMPARE(spy_activate_panel1.count(), 1);
+ QCOMPARE(spy_activate_panel2.count(), 0);
+ QCOMPARE(spy_activate_panel3.count(), 0);
+ QCOMPARE(spy_activate_panel4.count(), 0);
+
+ // Switch back to scene.
+ scene.setActivePanel(0);
+ QVERIFY(!scene.activePanel());
+ QVERIFY(!panel1->isActive());
+ QVERIFY(!panel2->isActive());
+ QVERIFY(!panel3->isActive());
+ QVERIFY(!panel4->isActive());
+ QVERIFY(notPanel1->isActive());
+ QVERIFY(notPanel2->isActive());
+ QCOMPARE(spy_activate_notPanel1.count(), 1);
+ QCOMPARE(spy_activate_notPanel2.count(), 1);
+
+ // Deactivate the scene
+ QApplication::sendEvent(&scene, &deactivate);
+ QVERIFY(!scene.activePanel());
+ QVERIFY(!panel1->isActive());
+ QVERIFY(!panel2->isActive());
+ QVERIFY(!panel3->isActive());
+ QVERIFY(!panel4->isActive());
+ QVERIFY(!notPanel1->isActive());
+ QVERIFY(!notPanel2->isActive());
+ QCOMPARE(spy_deactivate_notPanel1.count(), 1);
+ QCOMPARE(spy_deactivate_notPanel2.count(), 1);
+
+ // Reactivate the scene
+ QApplication::sendEvent(&scene, &activate);
+ QVERIFY(!scene.activePanel());
+ QVERIFY(!panel1->isActive());
+ QVERIFY(!panel2->isActive());
+ QVERIFY(!panel3->isActive());
+ QVERIFY(!panel4->isActive());
+ QVERIFY(notPanel1->isActive());
+ QVERIFY(notPanel2->isActive());
+ QCOMPARE(spy_activate_notPanel1.count(), 2);
+ QCOMPARE(spy_activate_notPanel2.count(), 2);
+
+ // Switch to panel1
+ scene.setActivePanel(panel1);
+ QVERIFY(panel1->isActive());
+ QCOMPARE(spy_deactivate_notPanel1.count(), 2);
+ QCOMPARE(spy_deactivate_notPanel2.count(), 2);
+ QCOMPARE(spy_activate_panel1.count(), 2);
+
+ // Deactivate the scene
+ QApplication::sendEvent(&scene, &deactivate);
+ QVERIFY(!panel1->isActive());
+ QCOMPARE(spy_deactivate_panel1.count(), 2);
+
+ // Reactivate the scene
+ QApplication::sendEvent(&scene, &activate);
+ QVERIFY(panel1->isActive());
+ QCOMPARE(spy_activate_panel1.count(), 3);
+
+ // Deactivate the scene
+ QApplication::sendEvent(&scene, &deactivate);
+ QVERIFY(!panel1->isActive());
+ QVERIFY(!scene.activePanel());
+ scene.setActivePanel(0);
+
+ // Reactivate the scene
+ QApplication::sendEvent(&scene, &activate);
+ QVERIFY(!panel1->isActive());
+}
+
+void tst_QGraphicsItem::addPanelToActiveScene()
+{
+ QGraphicsScene scene;
+ QVERIFY(!scene.isActive());
+
+ QGraphicsRectItem *rect = new QGraphicsRectItem;
+ scene.addItem(rect);
+ QVERIFY(!rect->isActive());
+ scene.removeItem(rect);
+
+ QEvent activate(QEvent::WindowActivate);
+ QEvent deactivate(QEvent::WindowDeactivate);
+
+ QApplication::sendEvent(&scene, &activate);
+ QVERIFY(scene.isActive());
+ scene.addItem(rect);
+ QVERIFY(rect->isActive());
+ scene.removeItem(rect);
+
+ rect->setFlag(QGraphicsItem::ItemIsPanel);
+ scene.addItem(rect);
+ QVERIFY(rect->isActive());
+ QCOMPARE(scene.activePanel(), (QGraphicsItem *)rect);
+
+ QGraphicsRectItem *rect2 = new QGraphicsRectItem;
+ scene.addItem(rect2);
+ QVERIFY(rect->isActive());
+ QCOMPARE(scene.activePanel(), (QGraphicsItem *)rect);
+}
+
+void tst_QGraphicsItem::activate()
+{
+ QGraphicsScene scene;
+ QGraphicsRectItem *rect = scene.addRect(-10, -10, 20, 20);
+ QVERIFY(!rect->isActive());
+
+ QEvent activate(QEvent::WindowActivate);
+ QEvent deactivate(QEvent::WindowDeactivate);
+
+ QApplication::sendEvent(&scene, &activate);
+
+ // Non-panel item (active when scene is active).
+ QVERIFY(rect->isActive());
+
+ QGraphicsRectItem *rect2 = new QGraphicsRectItem;
+ rect2->setFlag(QGraphicsItem::ItemIsPanel);
+ QGraphicsRectItem *rect3 = new QGraphicsRectItem;
+ rect3->setFlag(QGraphicsItem::ItemIsPanel);
+
+ // Test normal activation.
+ QVERIFY(!rect2->isActive());
+ scene.addItem(rect2);
+ QVERIFY(rect2->isActive()); // first panel item is activated
+ scene.addItem(rect3);
+ QVERIFY(!rect3->isActive()); // second panel item is _not_ activated
+ rect3->setActive(true);
+ QVERIFY(rect3->isActive());
+ scene.removeItem(rect3);
+ QVERIFY(!rect3->isActive()); // no panel is active anymore
+ QCOMPARE(scene.activePanel(), (QGraphicsItem *)0);
+ scene.addItem(rect3);
+ QVERIFY(rect3->isActive()); // second panel item is activated
+
+ // Test pending activation.
+ scene.removeItem(rect3);
+ rect2->setActive(true);
+ QVERIFY(rect2->isActive()); // first panel item is activated
+ rect3->setActive(true);
+ QVERIFY(!rect3->isActive()); // not active (yet)
+ scene.addItem(rect3);
+ QVERIFY(rect3->isActive()); // now becomes active
+
+ // Test pending deactivation.
+ scene.removeItem(rect3);
+ rect3->setActive(false);
+ scene.addItem(rect3);
+ QVERIFY(!rect3->isActive()); // doesn't become active
+
+ // Child of panel activation.
+ rect3->setActive(true);
+ QGraphicsRectItem *rect4 = new QGraphicsRectItem;
+ rect4->setFlag(QGraphicsItem::ItemIsPanel);
+ QGraphicsRectItem *rect5 = new QGraphicsRectItem(rect4);
+ QGraphicsRectItem *rect6 = new QGraphicsRectItem(rect5);
+ scene.addItem(rect4);
+ QCOMPARE(scene.activePanel(), (QGraphicsItem *)rect3);
+ scene.removeItem(rect4);
+ rect6->setActive(true);
+ scene.addItem(rect4);
+ QVERIFY(rect4->isActive());
+ QVERIFY(rect5->isActive());
+ QVERIFY(rect6->isActive());
+ QCOMPARE(scene.activePanel(), (QGraphicsItem *)rect4);
+ scene.removeItem(rect4); // no active panel
+ rect6->setActive(false);
+ scene.addItem(rect4);
+ QVERIFY(!rect4->isActive());
+ QVERIFY(!rect5->isActive());
+ QVERIFY(!rect6->isActive());
+ QCOMPARE(scene.activePanel(), (QGraphicsItem *)0);
+
+ // Controlling auto-activation when the scene changes activation.
+ rect4->setActive(true);
+ QApplication::sendEvent(&scene, &deactivate);
+ QVERIFY(!scene.isActive());
+ QVERIFY(!rect4->isActive());
+ rect4->setActive(false);
+ QApplication::sendEvent(&scene, &activate);
+ QVERIFY(scene.isActive());
+ QVERIFY(!scene.activePanel());
+ QVERIFY(!rect4->isActive());
+}
+
+void tst_QGraphicsItem::setActivePanelOnInactiveScene()
+{
+ QGraphicsScene scene;
+ QGraphicsRectItem *item = scene.addRect(QRectF());
+ QGraphicsRectItem *panel = scene.addRect(QRectF());
+ panel->setFlag(QGraphicsItem::ItemIsPanel);
+
+ EventSpy itemActivateSpy(&scene, item, QEvent::WindowActivate);
+ EventSpy itemDeactivateSpy(&scene, item, QEvent::WindowDeactivate);
+ EventSpy panelActivateSpy(&scene, panel, QEvent::WindowActivate);
+ EventSpy panelDeactivateSpy(&scene, panel, QEvent::WindowDeactivate);
+ EventSpy sceneActivationChangeSpy(&scene, QEvent::ActivationChange);
+
+ scene.setActivePanel(panel);
+ QCOMPARE(scene.activePanel(), (QGraphicsItem *)0);
+ QCOMPARE(itemActivateSpy.count(), 0);
+ QCOMPARE(itemDeactivateSpy.count(), 0);
+ QCOMPARE(panelActivateSpy.count(), 0);
+ QCOMPARE(panelDeactivateSpy.count(), 0);
+ QCOMPARE(sceneActivationChangeSpy.count(), 0);
+}
+
+void tst_QGraphicsItem::activationOnShowHide()
+{
+ QGraphicsScene scene;
+ QEvent activate(QEvent::WindowActivate);
+ QApplication::sendEvent(&scene, &activate);
+
+ QGraphicsRectItem *rootPanel = scene.addRect(QRectF());
+ rootPanel->setFlag(QGraphicsItem::ItemIsPanel);
+ rootPanel->setActive(true);
+
+ QGraphicsRectItem *subPanel = new QGraphicsRectItem;
+ subPanel->setFlag(QGraphicsItem::ItemIsPanel);
+
+ // Reparenting onto an active panel auto-activates the child panel.
+ subPanel->setParentItem(rootPanel);
+ QVERIFY(subPanel->isActive());
+ QVERIFY(!rootPanel->isActive());
+
+ // Hiding an active child panel will reactivate the parent panel.
+ subPanel->hide();
+ QVERIFY(rootPanel->isActive());
+
+ // Showing a child panel will auto-activate it.
+ subPanel->show();
+ QVERIFY(subPanel->isActive());
+ QVERIFY(!rootPanel->isActive());
+
+ // Adding an unrelated panel doesn't affect activation.
+ QGraphicsRectItem *otherPanel = new QGraphicsRectItem;
+ otherPanel->setFlag(QGraphicsItem::ItemIsPanel);
+ scene.addItem(otherPanel);
+ QVERIFY(subPanel->isActive());
+
+ // Showing an unrelated panel doesn't affect activation.
+ otherPanel->hide();
+ otherPanel->show();
+ QVERIFY(subPanel->isActive());
+
+ // Add a non-panel item.
+ QGraphicsRectItem *otherItem = new QGraphicsRectItem;
+ scene.addItem(otherItem);
+ otherItem->setActive(true);
+ QVERIFY(otherItem->isActive());
+
+ // Reparent a panel onto an active non-panel item.
+ subPanel->setParentItem(otherItem);
+ QVERIFY(subPanel->isActive());
+
+ // Showing a child panel of a non-panel item will activate it.
+ subPanel->hide();
+ QVERIFY(!subPanel->isActive());
+ QVERIFY(otherItem->isActive());
+ subPanel->show();
+ QVERIFY(subPanel->isActive());
+
+ // Hiding a toplevel active panel will pass activation back
+ // to the non-panel items.
+ rootPanel->setActive(true);
+ rootPanel->hide();
+ QVERIFY(!rootPanel->isActive());
+ QVERIFY(otherItem->isActive());
+}
+
+class MoveWhileDying : public QGraphicsRectItem
+{
+public:
+ MoveWhileDying(QGraphicsItem *parent = 0)
+ : QGraphicsRectItem(parent)
+ { }
+ ~MoveWhileDying()
+ {
+ foreach (QGraphicsItem *c, childItems()) {
+ foreach (QGraphicsItem *cc, c->childItems()) {
+ cc->moveBy(10, 10);
+ }
+ c->moveBy(10, 10);
+ }
+ if (QGraphicsItem *p = parentItem()) { p->moveBy(10, 10); }
+ }
+};
+
+void tst_QGraphicsItem::moveWhileDeleting()
+{
+ QGraphicsScene scene;
+ QGraphicsRectItem *rect = new QGraphicsRectItem;
+ MoveWhileDying *silly = new MoveWhileDying(rect);
+ QGraphicsRectItem *child = new QGraphicsRectItem(silly);
+ scene.addItem(rect);
+ delete rect; // don't crash!
+
+ rect = new QGraphicsRectItem;
+ silly = new MoveWhileDying(rect);
+ child = new QGraphicsRectItem(silly);
+
+ QGraphicsView view(&scene);
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+ QTest::qWait(125);
+
+ delete rect;
+
+ rect = new QGraphicsRectItem;
+ rect->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
+ silly = new MoveWhileDying(rect);
+ child = new QGraphicsRectItem(silly);
+
+ QTest::qWait(125);
+
+ delete rect;
+
+ rect = new MoveWhileDying;
+ rect->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
+ child = new QGraphicsRectItem(rect);
+ silly = new MoveWhileDying(child);
+
+ QTest::qWait(125);
+
+ delete rect;
+}
+
+class MyRectItem : public QGraphicsWidget
+{
+ Q_OBJECT
+public:
+ MyRectItem(QGraphicsItem *parent = 0) : QGraphicsWidget(parent)
+ {
+
+ }
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
+ {
+ painter->setBrush(brush);
+ painter->drawRect(boundingRect());
+ }
+ void move()
+ {
+ setPos(-100,-100);
+ topLevel->collidingItems(Qt::IntersectsItemBoundingRect);
+ }
+public:
+ QGraphicsItem *topLevel;
+ QBrush brush;
+};
+
+
+void tst_QGraphicsItem::ensureDirtySceneTransform()
+{
+ QGraphicsScene scene;
+
+ MyRectItem *topLevel = new MyRectItem;
+ topLevel->setGeometry(0, 0, 100, 100);
+ topLevel->setPos(-50, -50);
+ topLevel->brush = QBrush(QColor(Qt::black));
+ scene.addItem(topLevel);
+
+ MyRectItem *parent = new MyRectItem;
+ parent->topLevel = topLevel;
+ parent->setGeometry(0, 0, 100, 100);
+ parent->setPos(0, 0);
+ parent->brush = QBrush(QColor(Qt::magenta));
+ parent->setObjectName("parent");
+ scene.addItem(parent);
+
+ MyRectItem *child = new MyRectItem(parent);
+ child->setGeometry(0, 0, 80, 80);
+ child->setPos(10, 10);
+ child->setObjectName("child");
+ child->brush = QBrush(QColor(Qt::blue));
+
+ MyRectItem *child2 = new MyRectItem(parent);
+ child2->setGeometry(0, 0, 80, 80);
+ child2->setPos(15, 15);
+ child2->setObjectName("child2");
+ child2->brush = QBrush(QColor(Qt::green));
+
+ MyRectItem *child3 = new MyRectItem(parent);
+ child3->setGeometry(0, 0, 80, 80);
+ child3->setPos(20, 20);
+ child3->setObjectName("child3");
+ child3->brush = QBrush(QColor(Qt::gray));
+
+ QGraphicsView view(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QTRY_COMPARE(QApplication::activeWindow(), &view);
+
+ //We move the parent
+ parent->move();
+ QApplication::processEvents();
+
+ //We check if all items moved
+ QCOMPARE(child->pos(), QPointF(10, 10));
+ QCOMPARE(child2->pos(), QPointF(15, 15));
+ QCOMPARE(child3->pos(), QPointF(20, 20));
+
+ QCOMPARE(child->sceneBoundingRect(), QRectF(-90, -90, 80, 80));
+ QCOMPARE(child2->sceneBoundingRect(), QRectF(-85, -85, 80, 80));
+ QCOMPARE(child3->sceneBoundingRect(), QRectF(-80, -80, 80, 80));
+
+ QCOMPARE(child->sceneTransform(), QTransform::fromTranslate(-90, -90));
+ QCOMPARE(child2->sceneTransform(), QTransform::fromTranslate(-85, -85));
+ QCOMPARE(child3->sceneTransform(), QTransform::fromTranslate(-80, -80));
+}
+
+void tst_QGraphicsItem::focusScope()
+{
+ // ItemIsFocusScope is an internal feature (for now).
+ QGraphicsScene scene;
+
+ QGraphicsRectItem *scope3 = new QGraphicsRectItem;
+ scope3->setData(0, "scope3");
+ scope3->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsFocusScope);
+ scope3->setFocus();
+ QVERIFY(!scope3->focusScopeItem());
+ QCOMPARE(scope3->focusItem(), (QGraphicsItem *)scope3);
+
+ QGraphicsRectItem *scope2 = new QGraphicsRectItem;
+ scope2->setData(0, "scope2");
+ scope2->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsFocusScope);
+ scope2->setFocus();
+ QVERIFY(!scope2->focusScopeItem());
+ scope3->setParentItem(scope2);
+ QCOMPARE(scope2->focusScopeItem(), (QGraphicsItem *)scope3);
+ QCOMPARE(scope2->focusItem(), (QGraphicsItem *)scope2);
+
+ QGraphicsRectItem *scope1 = new QGraphicsRectItem;
+ scope1->setData(0, "scope1");
+ scope1->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsFocusScope);
+ scope1->setFocus();
+ QVERIFY(!scope1->focusScopeItem());
+ scope2->setParentItem(scope1);
+
+ QCOMPARE(scope1->focusItem(), (QGraphicsItem *)scope1);
+ QCOMPARE(scope2->focusItem(), (QGraphicsItem *)0);
+ QCOMPARE(scope3->focusItem(), (QGraphicsItem *)0);
+ QCOMPARE(scope1->focusScopeItem(), (QGraphicsItem *)scope2);
+ QCOMPARE(scope2->focusScopeItem(), (QGraphicsItem *)scope3);
+ QCOMPARE(scope3->focusScopeItem(), (QGraphicsItem *)0);
+
+ scene.addItem(scope1);
+
+ QEvent windowActivate(QEvent::WindowActivate);
+ qApp->sendEvent(&scene, &windowActivate);
+ scene.setFocus();
+
+ QCOMPARE(scope1->focusItem(), (QGraphicsItem *)scope3);
+ QCOMPARE(scope2->focusItem(), (QGraphicsItem *)scope3);
+ QCOMPARE(scope3->focusItem(), (QGraphicsItem *)scope3);
+ QCOMPARE(scope1->focusScopeItem(), (QGraphicsItem *)scope2);
+ QCOMPARE(scope2->focusScopeItem(), (QGraphicsItem *)scope3);
+ QCOMPARE(scope3->focusScopeItem(), (QGraphicsItem *)0);
+
+ QVERIFY(scope3->hasFocus());
+
+ scope3->hide();
+ QVERIFY(scope2->hasFocus());
+ scope2->hide();
+ QVERIFY(scope1->hasFocus());
+ scope2->show();
+ QVERIFY(scope2->hasFocus());
+ scope3->show();
+ QVERIFY(scope3->hasFocus());
+ scope1->hide();
+ QVERIFY(!scope3->hasFocus());
+ scope1->show();
+ QVERIFY(scope3->hasFocus());
+ scope3->clearFocus();
+ QVERIFY(scope2->hasFocus());
+ scope2->clearFocus();
+ QVERIFY(scope1->hasFocus());
+ scope2->hide();
+ scope2->show();
+ QVERIFY(!scope2->hasFocus());
+ QVERIFY(scope3->hasFocus());
+
+ QGraphicsRectItem *rect4 = new QGraphicsRectItem;
+ rect4->setData(0, "rect4");
+ rect4->setParentItem(scope3);
+
+ QGraphicsRectItem *rect5 = new QGraphicsRectItem;
+ rect5->setData(0, "rect5");
+ rect5->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsFocusScope);
+ rect5->setFocus();
+ rect5->setParentItem(rect4);
+ QCOMPARE(scope3->focusScopeItem(), (QGraphicsItem *)rect5);
+ QVERIFY(!rect5->hasFocus());
+
+ rect4->setParentItem(0);
+ QCOMPARE(scope3->focusScopeItem(), (QGraphicsItem *)0);
+ QVERIFY(scope3->hasFocus());
+
+ QGraphicsRectItem *rectA = new QGraphicsRectItem;
+ QGraphicsRectItem *scopeA = new QGraphicsRectItem(rectA);
+ scopeA->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsFocusScope);
+ scopeA->setFocus();
+ QGraphicsRectItem *scopeB = new QGraphicsRectItem(scopeA);
+ scopeB->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsFocusScope);
+ scopeB->setFocus();
+
+ scene.addItem(rectA);
+ QVERIFY(!rect5->hasFocus());
+ QVERIFY(!scopeB->hasFocus());
+
+ scopeA->setFocus();
+ QVERIFY(scopeB->hasFocus());
+ QCOMPARE(scopeB->focusItem(), (QGraphicsItem *)scopeB);
+}
+
+void tst_QGraphicsItem::stackBefore()
+{
+ QGraphicsRectItem parent;
+ QGraphicsRectItem *child1 = new QGraphicsRectItem(QRectF(0, 0, 5, 5), &parent);
+ QGraphicsRectItem *child2 = new QGraphicsRectItem(QRectF(0, 0, 5, 5), &parent);
+ QGraphicsRectItem *child3 = new QGraphicsRectItem(QRectF(0, 0, 5, 5), &parent);
+ QGraphicsRectItem *child4 = new QGraphicsRectItem(QRectF(0, 0, 5, 5), &parent);
+ QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child1 << child2 << child3 << child4));
+ child1->setData(0, "child1");
+ child2->setData(0, "child2");
+ child3->setData(0, "child3");
+ child4->setData(0, "child4");
+
+ // Remove and append
+ child2->setParentItem(0);
+ child2->setParentItem(&parent);
+ QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child1 << child3 << child4 << child2));
+
+ // Move child2 before child1
+ child2->stackBefore(child1);
+ QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child2 << child1 << child3 << child4));
+ child2->stackBefore(child2);
+ QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child2 << child1 << child3 << child4));
+ child1->setZValue(1);
+ QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child2 << child3 << child4 << child1));
+ child1->stackBefore(child2); // no effect
+ QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child2 << child3 << child4 << child1));
+ child1->setZValue(0);
+ QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child2 << child1 << child3 << child4));
+ child4->stackBefore(child1);
+ QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child2 << child4 << child1 << child3));
+ child4->setZValue(1);
+ QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child2 << child1 << child3 << child4));
+ child3->stackBefore(child1);
+ QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child2 << child3 << child1 << child4));
+ child4->setZValue(0);
+ QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child2 << child4 << child3 << child1));
+
+ // Make them all toplevels
+ child1->setParentItem(0);
+ child2->setParentItem(0);
+ child3->setParentItem(0);
+ child4->setParentItem(0);
+
+ QGraphicsScene scene;
+ scene.addItem(child1);
+ scene.addItem(child2);
+ scene.addItem(child3);
+ scene.addItem(child4);
+ QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder),
+ (QList<QGraphicsItem *>() << child1 << child2 << child3 << child4));
+
+ // Remove and append
+ scene.removeItem(child2);
+ scene.addItem(child2);
+ QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child1 << child3 << child4 << child2));
+
+ // Move child2 before child1
+ child2->stackBefore(child1);
+ QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child2 << child1 << child3 << child4));
+ child2->stackBefore(child2);
+ QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child2 << child1 << child3 << child4));
+ child1->setZValue(1);
+ QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child2 << child3 << child4 << child1));
+ child1->stackBefore(child2); // no effect
+ QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child2 << child3 << child4 << child1));
+ child1->setZValue(0);
+ QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child2 << child1 << child3 << child4));
+ child4->stackBefore(child1);
+ QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child2 << child4 << child1 << child3));
+ child4->setZValue(1);
+ QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child2 << child1 << child3 << child4));
+ child3->stackBefore(child1);
+ QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child2 << child3 << child1 << child4));
+ child4->setZValue(0);
+ QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child2 << child4 << child3 << child1));
+}
+
void tst_QGraphicsItem::QTBUG_4233_updateCachedWithSceneRect()
{
EventTester *tester = new EventTester;
@@ -6508,9 +8597,10 @@ void tst_QGraphicsItem::QTBUG_4233_updateCachedWithSceneRect()
QGraphicsView view(&scene);
view.show();
+ QTest::qWaitForWindowShown(&view);
QTRY_COMPARE(QApplication::activeWindow(), (QWidget *)&view);
- QCOMPARE(tester->repaints, 1);
+ QTRY_COMPARE(tester->repaints, 1);
scene.update(); // triggers "updateAll" optimization
qApp->processEvents();
@@ -6526,5 +8616,923 @@ void tst_QGraphicsItem::QTBUG_4233_updateCachedWithSceneRect()
QCOMPARE(tester->repaints, 2);
}
+void tst_QGraphicsItem::sceneModality()
+{
+ // 1) Test mouse events (delivery/propagation/redirection)
+ // 2) Test hover events (incl. leave on block, enter on unblock)
+ // 3) Test cursor stuff (incl. unset on block, set on unblock)
+ // 4) Test clickfocus
+ // 5) Test grab/ungrab events (possibly ungrab on block, regrab on unblock)
+ // 6) ### modality for non-panels is unsupported for now
+ QGraphicsScene scene;
+
+ QGraphicsRectItem *bottomItem = scene.addRect(-150, -100, 300, 200);
+ bottomItem->setFlag(QGraphicsItem::ItemIsFocusable);
+ bottomItem->setBrush(Qt::yellow);
+
+ QGraphicsRectItem *leftParent = scene.addRect(-50, -50, 100, 100);
+ leftParent->setFlag(QGraphicsItem::ItemIsPanel);
+ leftParent->setBrush(Qt::blue);
+
+ QGraphicsRectItem *leftChild = scene.addRect(-25, -25, 50, 50);
+ leftChild->setFlag(QGraphicsItem::ItemIsPanel);
+ leftChild->setBrush(Qt::green);
+ leftChild->setParentItem(leftParent);
+
+ QGraphicsRectItem *rightParent = scene.addRect(-50, -50, 100, 100);
+ rightParent->setFlag(QGraphicsItem::ItemIsPanel);
+ rightParent->setBrush(Qt::red);
+ QGraphicsRectItem *rightChild = scene.addRect(-25, -25, 50, 50);
+ rightChild->setFlag(QGraphicsItem::ItemIsPanel);
+ rightChild->setBrush(Qt::gray);
+ rightChild->setParentItem(rightParent);
+
+ leftParent->setPos(-75, 0);
+ rightParent->setPos(75, 0);
+
+ bottomItem->setData(0, "bottomItem");
+ leftParent->setData(0, "leftParent");
+ leftChild->setData(0, "leftChild");
+ rightParent->setData(0, "rightParent");
+ rightChild->setData(0, "rightChild");
+
+ scene.setSceneRect(scene.itemsBoundingRect().adjusted(-50, -50, 50, 50));
+
+ EventSpy2 leftParentSpy(&scene, leftParent);
+ EventSpy2 leftChildSpy(&scene, leftChild);
+ EventSpy2 rightParentSpy(&scene, rightParent);
+ EventSpy2 rightChildSpy(&scene, rightChild);
+ EventSpy2 bottomItemSpy(&scene, bottomItem);
+
+ // Scene modality, also test multiple scene modal items
+ leftChild->setPanelModality(QGraphicsItem::SceneModal);
+ QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0);
+ QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(bottomItemSpy.counts[QEvent::WindowBlocked], 0); // not a panel
+
+ // Click inside left child
+ sendMouseClick(&scene, leftChild->scenePos(), Qt::LeftButton);
+ QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 1);
+ QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMouseRelease], 0); // no grab
+ QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+ QCOMPARE(rightParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+ QCOMPARE(rightChildSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+ QCOMPARE(bottomItemSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+
+ // Click on left parent, event goes to modal child
+ sendMouseClick(&scene, leftParent->sceneBoundingRect().topLeft() + QPointF(5, 5), Qt::LeftButton);
+ QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 2);
+ QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMouseRelease], 0); // no grab
+ QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+ QCOMPARE(rightParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+ QCOMPARE(rightChildSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+ QCOMPARE(bottomItemSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+
+ // Click on all other items and outside the items
+ sendMouseClick(&scene, rightParent->sceneBoundingRect().topLeft() + QPointF(5, 5), Qt::LeftButton);
+ QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 3);
+ sendMouseClick(&scene, rightChild->scenePos(), Qt::LeftButton);
+ QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 4);
+ sendMouseClick(&scene, bottomItem->scenePos(), Qt::LeftButton);
+ QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 5);
+ sendMouseClick(&scene, QPointF(10000, 10000), Qt::LeftButton);
+ QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 6);
+ QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMouseRelease], 0); // no grab
+ QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+ QCOMPARE(rightParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+ QCOMPARE(rightChildSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+ QCOMPARE(bottomItemSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+
+ leftChildSpy.counts.clear();
+ rightChildSpy.counts.clear();
+ leftParentSpy.counts.clear();
+ rightParentSpy.counts.clear();
+ bottomItemSpy.counts.clear();
+
+ leftChild->setPanelModality(QGraphicsItem::NonModal);
+ QCOMPARE(leftChildSpy.counts[QEvent::WindowUnblocked], 0);
+ QCOMPARE(rightChildSpy.counts[QEvent::WindowUnblocked], 1);
+ QCOMPARE(leftParentSpy.counts[QEvent::WindowUnblocked], 1);
+ QCOMPARE(rightParentSpy.counts[QEvent::WindowUnblocked], 1);
+ QCOMPARE(bottomItemSpy.counts[QEvent::WindowUnblocked], 0);
+
+ // Left parent enters scene modality.
+ leftParent->setPanelModality(QGraphicsItem::SceneModal);
+ QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0);
+ QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 0);
+ QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(bottomItemSpy.counts[QEvent::WindowBlocked], 0);
+
+ // Click inside left child.
+ sendMouseClick(&scene, leftChild->scenePos(), Qt::LeftButton);
+ QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 1);
+ QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMouseRelease], 0);
+ QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // panel stops propagation
+ QCOMPARE(rightParentSpy.counts[QEvent::GraphicsSceneMousePress], 0);
+ QCOMPARE(rightChildSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+ QCOMPARE(bottomItemSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+
+ // Click on left parent.
+ sendMouseClick(&scene, leftParent->sceneBoundingRect().topLeft() + QPointF(5, 5), Qt::LeftButton);
+ QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 1);
+ QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMouseRelease], 0);
+ QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 1);
+ QCOMPARE(rightParentSpy.counts[QEvent::GraphicsSceneMousePress], 0);
+ QCOMPARE(rightChildSpy.counts[QEvent::GraphicsSceneMousePress], 0);
+ QCOMPARE(bottomItemSpy.counts[QEvent::GraphicsSceneMousePress], 0);
+
+ // Click on all other items and outside the items
+ sendMouseClick(&scene, rightParent->sceneBoundingRect().topLeft() + QPointF(5, 5), Qt::LeftButton);
+ QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 2);
+ sendMouseClick(&scene, rightChild->scenePos(), Qt::LeftButton);
+ QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 3);
+ sendMouseClick(&scene, bottomItem->scenePos(), Qt::LeftButton);
+ QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 4);
+ sendMouseClick(&scene, QPointF(10000, 10000), Qt::LeftButton);
+ QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 5);
+ QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMouseRelease], 0);
+ QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 1);
+ QCOMPARE(rightParentSpy.counts[QEvent::GraphicsSceneMousePress], 0);
+ QCOMPARE(rightChildSpy.counts[QEvent::GraphicsSceneMousePress], 0);
+ QCOMPARE(bottomItemSpy.counts[QEvent::GraphicsSceneMousePress], 0);
+
+ leftChildSpy.counts.clear();
+ rightChildSpy.counts.clear();
+ leftParentSpy.counts.clear();
+ rightParentSpy.counts.clear();
+ bottomItemSpy.counts.clear();
+
+ // Now both left parent and child are scene modal. Left parent is blocked.
+ leftChild->setPanelModality(QGraphicsItem::SceneModal);
+ QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0);
+ QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 0);
+ QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 0);
+ QCOMPARE(bottomItemSpy.counts[QEvent::WindowBlocked], 0);
+
+ // Click inside left child
+ sendMouseClick(&scene, leftChild->scenePos(), Qt::LeftButton);
+ QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 1);
+ QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMouseRelease], 0); // no grab
+ QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+ QCOMPARE(rightParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+ QCOMPARE(rightChildSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+ QCOMPARE(bottomItemSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+
+ // Click on left parent, event goes to modal child
+ sendMouseClick(&scene, leftParent->sceneBoundingRect().topLeft() + QPointF(5, 5), Qt::LeftButton);
+ QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 2);
+ QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMouseRelease], 0); // no grab
+ QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+ QCOMPARE(rightParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+ QCOMPARE(rightChildSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+ QCOMPARE(bottomItemSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+
+ // Click on all other items and outside the items
+ sendMouseClick(&scene, rightParent->sceneBoundingRect().topLeft() + QPointF(5, 5), Qt::LeftButton);
+ QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 3);
+ sendMouseClick(&scene, rightChild->scenePos(), Qt::LeftButton);
+ QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 4);
+ sendMouseClick(&scene, bottomItem->scenePos(), Qt::LeftButton);
+ QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 5);
+ sendMouseClick(&scene, QPointF(10000, 10000), Qt::LeftButton);
+ QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 6);
+ QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMouseRelease], 0); // no grab
+ QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+ QCOMPARE(rightParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+ QCOMPARE(rightChildSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+ QCOMPARE(bottomItemSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+
+ leftChildSpy.counts.clear();
+ rightChildSpy.counts.clear();
+ leftParentSpy.counts.clear();
+ rightParentSpy.counts.clear();
+ bottomItemSpy.counts.clear();
+
+ // Right child enters scene modality, only left child is blocked.
+ rightChild->setPanelModality(QGraphicsItem::SceneModal);
+ QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 0);
+ QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 0);
+ QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 0);
+ QCOMPARE(bottomItemSpy.counts[QEvent::WindowBlocked], 0);
+}
+
+void tst_QGraphicsItem::panelModality()
+{
+ // 1) Test mouse events (delivery/propagation/redirection)
+ // 2) Test hover events (incl. leave on block, enter on unblock)
+ // 3) Test cursor stuff (incl. unset on block, set on unblock)
+ // 4) Test clickfocus
+ // 5) Test grab/ungrab events (possibly ungrab on block, regrab on unblock)
+ // 6) ### modality for non-panels is unsupported for now
+ QGraphicsScene scene;
+
+ QGraphicsRectItem *bottomItem = scene.addRect(-150, -100, 300, 200);
+ bottomItem->setFlag(QGraphicsItem::ItemIsFocusable);
+ bottomItem->setBrush(Qt::yellow);
+
+ QGraphicsRectItem *leftParent = scene.addRect(-50, -50, 100, 100);
+ leftParent->setFlag(QGraphicsItem::ItemIsPanel);
+ leftParent->setBrush(Qt::blue);
+
+ QGraphicsRectItem *leftChild = scene.addRect(-25, -25, 50, 50);
+ leftChild->setFlag(QGraphicsItem::ItemIsPanel);
+ leftChild->setBrush(Qt::green);
+ leftChild->setParentItem(leftParent);
+
+ QGraphicsRectItem *rightParent = scene.addRect(-50, -50, 100, 100);
+ rightParent->setFlag(QGraphicsItem::ItemIsPanel);
+ rightParent->setBrush(Qt::red);
+ QGraphicsRectItem *rightChild = scene.addRect(-25, -25, 50, 50);
+ rightChild->setFlag(QGraphicsItem::ItemIsPanel);
+ rightChild->setBrush(Qt::gray);
+ rightChild->setParentItem(rightParent);
+
+ leftParent->setPos(-75, 0);
+ rightParent->setPos(75, 0);
+
+ bottomItem->setData(0, "bottomItem");
+ leftParent->setData(0, "leftParent");
+ leftChild->setData(0, "leftChild");
+ rightParent->setData(0, "rightParent");
+ rightChild->setData(0, "rightChild");
+
+ scene.setSceneRect(scene.itemsBoundingRect().adjusted(-50, -50, 50, 50));
+
+ EventSpy2 leftParentSpy(&scene, leftParent);
+ EventSpy2 leftChildSpy(&scene, leftChild);
+ EventSpy2 rightParentSpy(&scene, rightParent);
+ EventSpy2 rightChildSpy(&scene, rightChild);
+ EventSpy2 bottomItemSpy(&scene, bottomItem);
+
+ // Left Child enters panel modality, only left parent is blocked.
+ leftChild->setPanelModality(QGraphicsItem::PanelModal);
+ QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0);
+ QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 0);
+ QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 0);
+ QCOMPARE(bottomItemSpy.counts[QEvent::WindowBlocked], 0);
+
+ leftChild->setPanelModality(QGraphicsItem::NonModal);
+ leftChildSpy.counts.clear();
+ rightChildSpy.counts.clear();
+ leftParentSpy.counts.clear();
+ rightParentSpy.counts.clear();
+ bottomItemSpy.counts.clear();
+
+ // Left parent enter panel modality, nothing is blocked.
+ leftParent->setPanelModality(QGraphicsItem::PanelModal);
+ QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0);
+ QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 0);
+ QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 0);
+ QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 0);
+ QCOMPARE(bottomItemSpy.counts[QEvent::WindowBlocked], 0);
+
+ // Left child enters panel modality, left parent is blocked again.
+ leftChild->setPanelModality(QGraphicsItem::PanelModal);
+ QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0);
+ QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 0);
+ QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 0);
+ QCOMPARE(bottomItemSpy.counts[QEvent::WindowBlocked], 0);
+
+ leftChildSpy.counts.clear();
+ rightChildSpy.counts.clear();
+ leftParentSpy.counts.clear();
+ rightParentSpy.counts.clear();
+ bottomItemSpy.counts.clear();
+
+ leftChild->setPanelModality(QGraphicsItem::NonModal);
+ QCOMPARE(leftParentSpy.counts[QEvent::WindowUnblocked], 1);
+ leftParent->setPanelModality(QGraphicsItem::NonModal);
+ QCOMPARE(leftChildSpy.counts[QEvent::WindowUnblocked], 0);
+ QCOMPARE(rightChildSpy.counts[QEvent::WindowUnblocked], 0);
+ QCOMPARE(leftParentSpy.counts[QEvent::WindowUnblocked], 1);
+ QCOMPARE(rightParentSpy.counts[QEvent::WindowUnblocked], 0);
+ QCOMPARE(bottomItemSpy.counts[QEvent::WindowUnblocked], 0);
+
+ leftChildSpy.counts.clear();
+ rightChildSpy.counts.clear();
+ leftParentSpy.counts.clear();
+ rightParentSpy.counts.clear();
+ bottomItemSpy.counts.clear();
+
+ // Left and right child enter panel modality, both parents are blocked.
+ rightChild->setPanelModality(QGraphicsItem::PanelModal);
+ QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 0);
+ QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 1);
+ leftChild->setPanelModality(QGraphicsItem::PanelModal);
+ QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 1);
+}
+
+void tst_QGraphicsItem::mixedModality()
+{
+ // 1) Test mouse events (delivery/propagation/redirection)
+ // 2) Test hover events (incl. leave on block, enter on unblock)
+ // 3) Test cursor stuff (incl. unset on block, set on unblock)
+ // 4) Test clickfocus
+ // 5) Test grab/ungrab events (possibly ungrab on block, regrab on unblock)
+ // 6) ### modality for non-panels is unsupported for now
+ QGraphicsScene scene;
+
+ QGraphicsRectItem *bottomItem = scene.addRect(-150, -100, 300, 200);
+ bottomItem->setFlag(QGraphicsItem::ItemIsFocusable);
+ bottomItem->setBrush(Qt::yellow);
+
+ QGraphicsRectItem *leftParent = scene.addRect(-50, -50, 100, 100);
+ leftParent->setFlag(QGraphicsItem::ItemIsPanel);
+ leftParent->setBrush(Qt::blue);
+
+ QGraphicsRectItem *leftChild = scene.addRect(-25, -25, 50, 50);
+ leftChild->setFlag(QGraphicsItem::ItemIsPanel);
+ leftChild->setBrush(Qt::green);
+ leftChild->setParentItem(leftParent);
+
+ QGraphicsRectItem *rightParent = scene.addRect(-50, -50, 100, 100);
+ rightParent->setFlag(QGraphicsItem::ItemIsPanel);
+ rightParent->setBrush(Qt::red);
+ QGraphicsRectItem *rightChild = scene.addRect(-25, -25, 50, 50);
+ rightChild->setFlag(QGraphicsItem::ItemIsPanel);
+ rightChild->setBrush(Qt::gray);
+ rightChild->setParentItem(rightParent);
+
+ leftParent->setPos(-75, 0);
+ rightParent->setPos(75, 0);
+
+ bottomItem->setData(0, "bottomItem");
+ leftParent->setData(0, "leftParent");
+ leftChild->setData(0, "leftChild");
+ rightParent->setData(0, "rightParent");
+ rightChild->setData(0, "rightChild");
+
+ scene.setSceneRect(scene.itemsBoundingRect().adjusted(-50, -50, 50, 50));
+
+ EventSpy2 leftParentSpy(&scene, leftParent);
+ EventSpy2 leftChildSpy(&scene, leftChild);
+ EventSpy2 rightParentSpy(&scene, rightParent);
+ EventSpy2 rightChildSpy(&scene, rightChild);
+ EventSpy2 bottomItemSpy(&scene, bottomItem);
+
+ // Left Child enters panel modality, only left parent is blocked.
+ leftChild->setPanelModality(QGraphicsItem::PanelModal);
+ QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0);
+ QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 0);
+ QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 0);
+
+ // Left parent enters scene modality, which blocks everything except the child.
+ leftParent->setPanelModality(QGraphicsItem::SceneModal);
+ QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0);
+ QCOMPARE(leftChildSpy.counts[QEvent::WindowUnblocked], 0);
+ QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(rightChildSpy.counts[QEvent::WindowUnblocked], 0);
+ QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(leftParentSpy.counts[QEvent::WindowUnblocked], 0);
+ QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(rightParentSpy.counts[QEvent::WindowUnblocked], 0);
+
+ // Right child enters panel modality (changes nothing).
+ rightChild->setPanelModality(QGraphicsItem::PanelModal);
+ QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0);
+ QCOMPARE(leftChildSpy.counts[QEvent::WindowUnblocked], 0);
+ QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(rightChildSpy.counts[QEvent::WindowUnblocked], 0);
+ QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(leftParentSpy.counts[QEvent::WindowUnblocked], 0);
+ QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(rightParentSpy.counts[QEvent::WindowUnblocked], 0);
+
+ // Left parent leaves modality. Right child is unblocked.
+ leftParent->setPanelModality(QGraphicsItem::NonModal);
+ QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0);
+ QCOMPARE(leftChildSpy.counts[QEvent::WindowUnblocked], 0);
+ QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(rightChildSpy.counts[QEvent::WindowUnblocked], 1);
+ QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(leftParentSpy.counts[QEvent::WindowUnblocked], 0);
+ QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(rightParentSpy.counts[QEvent::WindowUnblocked], 0);
+
+ // Right child "upgrades" its modality to scene modal. Left child is blocked.
+ // Right parent is unaffected.
+ rightChild->setPanelModality(QGraphicsItem::SceneModal);
+ QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(leftChildSpy.counts[QEvent::WindowUnblocked], 0);
+ QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(rightChildSpy.counts[QEvent::WindowUnblocked], 1);
+ QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(leftParentSpy.counts[QEvent::WindowUnblocked], 0);
+ QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(rightParentSpy.counts[QEvent::WindowUnblocked], 0);
+
+ // "downgrade" right child back to panel modal, left child is unblocked
+ rightChild->setPanelModality(QGraphicsItem::PanelModal);
+ QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(leftChildSpy.counts[QEvent::WindowUnblocked], 1);
+ QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(rightChildSpy.counts[QEvent::WindowUnblocked], 1);
+ QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(leftParentSpy.counts[QEvent::WindowUnblocked], 0);
+ QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(rightParentSpy.counts[QEvent::WindowUnblocked], 0);
+}
+
+void tst_QGraphicsItem::modality_hover()
+{
+ QGraphicsScene scene;
+ QGraphicsRectItem *rect1 = scene.addRect(-50, -50, 100, 100);
+ rect1->setFlag(QGraphicsItem::ItemIsPanel);
+ rect1->setAcceptHoverEvents(true);
+ rect1->setData(0, "rect1");
+
+ QGraphicsRectItem *rect2 = scene.addRect(-50, -50, 100, 100);
+ rect2->setParentItem(rect1);
+ rect2->setFlag(QGraphicsItem::ItemIsPanel);
+ rect2->setAcceptHoverEvents(true);
+ rect2->setPos(50, 50);
+ rect2->setPanelModality(QGraphicsItem::SceneModal);
+ rect2->setData(0, "rect2");
+
+ EventSpy2 rect1Spy(&scene, rect1);
+ EventSpy2 rect2Spy(&scene, rect2);
+
+ sendMouseMove(&scene, QPointF(-25, -25));
+
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverEnter], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverMove], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverLeave], 0);
+
+ sendMouseMove(&scene, QPointF(75, 75));
+
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverEnter], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverMove], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverLeave], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverEnter], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverMove], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverLeave], 0);
+
+ sendMouseMove(&scene, QPointF(-25, -25));
+
+ QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverLeave], 1);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverEnter], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverMove], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverLeave], 0);
+
+ rect2->setPanelModality(QGraphicsItem::NonModal);
+
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverEnter], 1);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverMove], 1);
+
+ sendMouseMove(&scene, QPointF(75, 75));
+
+ QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverEnter], 2);
+ QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverMove], 2);
+
+ rect2->setPanelModality(QGraphicsItem::SceneModal);
+
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverLeave], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverEnter], 2);
+ // changing modality causes a spurious GraphicsSceneHoveMove, even though the mouse didn't
+ // actually move
+ QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverMove], 3);
+
+ sendMouseMove(&scene, QPointF(-25, -25));
+
+ QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverLeave], 2);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverEnter], 1);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverMove], 1);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverLeave], 1);
+
+ rect2->setPanelModality(QGraphicsItem::PanelModal);
+
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverEnter], 1);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverMove], 1);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverLeave], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverEnter], 2);
+ QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverMove], 3);
+ QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverLeave], 2);
+
+ rect2->setPanelModality(QGraphicsItem::NonModal);
+
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverEnter], 2);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverMove], 2);
+ QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverEnter], 2);
+ QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverMove], 3);
+ QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverLeave], 2);
+}
+
+void tst_QGraphicsItem::modality_mouseGrabber()
+{
+ QGraphicsScene scene;
+ QGraphicsRectItem *rect1 = scene.addRect(-50, -50, 100, 100);
+ rect1->setFlag(QGraphicsItem::ItemIsPanel);
+ rect1->setFlag(QGraphicsItem::ItemIsMovable);
+ rect1->setData(0, "rect1");
+
+ QGraphicsRectItem *rect2 = scene.addRect(-50, -50, 100, 100);
+ rect2->setParentItem(rect1);
+ rect2->setFlag(QGraphicsItem::ItemIsPanel);
+ rect2->setFlag(QGraphicsItem::ItemIsMovable);
+ rect2->setPos(50, 50);
+ rect2->setData(0, "rect2");
+
+ EventSpy2 rect1Spy(&scene, rect1);
+ EventSpy2 rect2Spy(&scene, rect2);
+
+ {
+ // pressing mouse on rect1 starts implicit grab
+ sendMousePress(&scene, QPoint(-25, -25));
+ QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 1);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMousePress], 1);
+ QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) rect1);
+
+ // grab lost when rect1 is modally shadowed
+ rect2->setPanelModality(QGraphicsItem::SceneModal);
+ QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 1);
+ QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
+
+ // releasing goes nowhere
+ sendMouseRelease(&scene, QPoint(-25, -25));
+ QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 1);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMouseRelease], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneMouseRelease], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
+
+ // pressing mouse on rect1 starts implicit grab on rect2 (since it is modal)
+ sendMouseClick(&scene, QPoint(-25, -25));
+ QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 1);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMousePress], 1);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMouseRelease], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneMousePress], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneMouseRelease], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1);
+
+ rect2->setPanelModality(QGraphicsItem::NonModal);
+
+ // pressing mouse on rect1 starts implicit grab
+ sendMousePress(&scene, QPoint(-25, -25));
+ QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 2);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMousePress], 2);
+ QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) rect1);
+
+ // grab lost to rect2 when rect1 is modally shadowed
+ rect2->setPanelModality(QGraphicsItem::SceneModal);
+ QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 2);
+ QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 2);
+ QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
+
+ // rect1 does *not* re-grab when rect2 is no longer modal
+ rect2->setPanelModality(QGraphicsItem::NonModal);
+ QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 2);
+ QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 2);
+ QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
+
+ // release goes nowhere
+ sendMouseRelease(&scene, QPoint(-25, -25));
+ QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 2);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMouseRelease], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 2);
+ QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
+ }
+ {
+ // repeat the test using PanelModal
+ rect2->setPanelModality(QGraphicsItem::NonModal);
+ rect1Spy.counts.clear();
+ rect2Spy.counts.clear();
+
+ // pressing mouse on rect1 starts implicit grab
+ sendMousePress(&scene, QPoint(-25, -25));
+ QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 1);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMousePress], 1);
+ QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) rect1);
+
+ // grab lost when rect1 is modally shadowed
+ rect2->setPanelModality(QGraphicsItem::PanelModal);
+ QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 1);
+ QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
+
+ // releasing goes nowhere
+ sendMouseRelease(&scene, QPoint(-25, -25));
+ QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 1);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMouseRelease], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneMouseRelease], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
+
+ // pressing mouse on rect1 starts implicit grab on rect2 (since it is modal)
+ sendMouseClick(&scene, QPoint(-25, -25));
+ QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 1);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMousePress], 1);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMouseRelease], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneMousePress], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneMouseRelease], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1);
+
+ rect2->setPanelModality(QGraphicsItem::NonModal);
+
+ // pressing mouse on rect1 starts implicit grab
+ sendMousePress(&scene, QPoint(-25, -25));
+ QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 2);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMousePress], 2);
+ QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) rect1);
+
+ // grab lost to rect2 when rect1 is modally shadowed
+ rect2->setPanelModality(QGraphicsItem::PanelModal);
+ QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 2);
+ QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 2);
+ QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
+
+ // rect1 does *not* re-grab when rect2 is no longer modal
+ rect2->setPanelModality(QGraphicsItem::NonModal);
+ QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 2);
+ QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 2);
+ QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
+
+ // release goes nowhere
+ sendMouseRelease(&scene, QPoint(-25, -25));
+ QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 2);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMouseRelease], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 2);
+ QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
+ }
+
+ {
+ // repeat the PanelModal tests, but this time the mouse events will be on a non-modal item,
+ // meaning normal grabbing should work
+ rect2->setPanelModality(QGraphicsItem::NonModal);
+ rect1Spy.counts.clear();
+ rect2Spy.counts.clear();
+
+ QGraphicsRectItem *rect3 = scene.addRect(-50, -50, 100, 100);
+ rect3->setFlag(QGraphicsItem::ItemIsPanel);
+ rect3->setFlag(QGraphicsItem::ItemIsMovable);
+ rect3->setPos(150, 50);
+ rect3->setData(0, "rect3");
+
+ EventSpy2 rect3Spy(&scene, rect3);
+
+ // pressing mouse on rect3 starts implicit grab
+ sendMousePress(&scene, QPoint(150, 50));
+ QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
+ QCOMPARE(rect3Spy.counts[QEvent::GrabMouse], 1);
+ QCOMPARE(rect3Spy.counts[QEvent::GraphicsSceneMousePress], 1);
+ QCOMPARE(rect3Spy.counts[QEvent::UngrabMouse], 0);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) rect3);
+
+ // grab is *not* lost when rect1 is modally shadowed by rect2
+ rect2->setPanelModality(QGraphicsItem::PanelModal);
+ QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
+ QCOMPARE(rect3Spy.counts[QEvent::GrabMouse], 1);
+ QCOMPARE(rect3Spy.counts[QEvent::UngrabMouse], 0);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) rect3);
+
+ // releasing goes to rect3
+ sendMouseRelease(&scene, QPoint(150, 50));
+ QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
+ QCOMPARE(rect3Spy.counts[QEvent::GrabMouse], 1);
+ QCOMPARE(rect3Spy.counts[QEvent::GraphicsSceneMouseRelease], 1);
+ QCOMPARE(rect3Spy.counts[QEvent::UngrabMouse], 1);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
+
+ rect2->setPanelModality(QGraphicsItem::NonModal);
+
+ // pressing mouse on rect3 starts implicit grab
+ sendMousePress(&scene, QPoint(150, 50));
+ QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
+ QCOMPARE(rect3Spy.counts[QEvent::GrabMouse], 2);
+ QCOMPARE(rect3Spy.counts[QEvent::UngrabMouse], 1);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) rect3);
+
+ // grab is not lost
+ rect2->setPanelModality(QGraphicsItem::PanelModal);
+ QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
+ QCOMPARE(rect3Spy.counts[QEvent::GrabMouse], 2);
+ QCOMPARE(rect3Spy.counts[QEvent::UngrabMouse], 1);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) rect3);
+
+ // grab stays on rect3
+ rect2->setPanelModality(QGraphicsItem::NonModal);
+ QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
+ QCOMPARE(rect3Spy.counts[QEvent::GrabMouse], 2);
+ QCOMPARE(rect3Spy.counts[QEvent::UngrabMouse], 1);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) rect3);
+
+ // release goes to rect3
+ sendMouseRelease(&scene, QPoint(150, 50));
+ QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
+ QCOMPARE(rect3Spy.counts[QEvent::GrabMouse], 2);
+ QCOMPARE(rect3Spy.counts[QEvent::UngrabMouse], 2);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
+ }
+}
+
+void tst_QGraphicsItem::modality_clickFocus()
+{
+ QGraphicsScene scene;
+ QGraphicsRectItem *rect1 = scene.addRect(-50, -50, 100, 100);
+ rect1->setFlag(QGraphicsItem::ItemIsPanel);
+ rect1->setFlag(QGraphicsItem::ItemIsFocusable);
+ rect1->setData(0, "rect1");
+
+ QGraphicsRectItem *rect2 = scene.addRect(-50, -50, 100, 100);
+ rect2->setParentItem(rect1);
+ rect2->setFlag(QGraphicsItem::ItemIsPanel);
+ rect2->setFlag(QGraphicsItem::ItemIsFocusable);
+ rect2->setPos(50, 50);
+ rect2->setData(0, "rect2");
+
+ QEvent windowActivateEvent(QEvent::WindowActivate);
+ QApplication::sendEvent(&scene, &windowActivateEvent);
+
+ EventSpy2 rect1Spy(&scene, rect1);
+ EventSpy2 rect2Spy(&scene, rect2);
+
+ // activate rect1, it should not get focus
+ rect1->setActive(true);
+ QCOMPARE(scene.focusItem(), (QGraphicsItem *) 0);
+
+ // focus stays unset when rect2 becomes modal
+ rect2->setPanelModality(QGraphicsItem::SceneModal);
+ QCOMPARE(scene.focusItem(), (QGraphicsItem *) 0);
+ QCOMPARE(rect1Spy.counts[QEvent::FocusIn], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::FocusOut], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::FocusIn], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::FocusOut], 0);
+
+ // clicking on rect1 should not set it's focus item
+ sendMouseClick(&scene, QPointF(-25, -25));
+ QCOMPARE(rect1->focusItem(), (QGraphicsItem *) 0);
+ QCOMPARE(rect1Spy.counts[QEvent::FocusIn], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::FocusOut], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::FocusIn], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::FocusOut], 0);
+
+ // clicking on rect2 gives it focus
+ rect2->setActive(true);
+ sendMouseClick(&scene, QPointF(75, 75));
+ QCOMPARE(scene.focusItem(), (QGraphicsItem *) rect2);
+ QCOMPARE(rect1Spy.counts[QEvent::FocusIn], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::FocusOut], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::FocusIn], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::FocusOut], 0);
+
+ // clicking on rect1 does *not* give it focus
+ rect1->setActive(true);
+ sendMouseClick(&scene, QPointF(-25, -25));
+ QCOMPARE(scene.focusItem(), (QGraphicsItem *) 0);
+ QCOMPARE(rect1Spy.counts[QEvent::FocusIn], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::FocusOut], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::FocusIn], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::FocusOut], 1);
+
+ // focus doesn't change when leaving modality either
+ rect2->setPanelModality(QGraphicsItem::NonModal);
+ QCOMPARE(scene.focusItem(), (QGraphicsItem *) 0);
+ QCOMPARE(rect1Spy.counts[QEvent::FocusIn], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::FocusOut], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::FocusIn], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::FocusOut], 1);
+
+ // click on rect1, it should get focus now
+ sendMouseClick(&scene, QPointF(-25, -25));
+ QCOMPARE(scene.focusItem(), (QGraphicsItem *) rect1);
+ QCOMPARE(rect1Spy.counts[QEvent::FocusIn], 1);
+ QCOMPARE(rect1Spy.counts[QEvent::FocusOut], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::FocusIn], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::FocusOut], 1);
+}
+
+void tst_QGraphicsItem::modality_keyEvents()
+{
+ QGraphicsScene scene;
+ QGraphicsRectItem *rect1 = scene.addRect(-50, -50, 100, 100);
+ rect1->setFlag(QGraphicsItem::ItemIsPanel);
+ rect1->setFlag(QGraphicsItem::ItemIsFocusable);
+ rect1->setData(0, "rect1");
+
+ QGraphicsRectItem *rect1child = scene.addRect(-10, -10, 20, 20);
+ rect1child->setParentItem(rect1);
+ rect1child->setFlag(QGraphicsItem::ItemIsFocusable);
+ rect1child->setData(0, "rect1child1");
+
+ QGraphicsRectItem *rect2 = scene.addRect(-50, -50, 100, 100);
+ rect2->setParentItem(rect1);
+ rect2->setFlag(QGraphicsItem::ItemIsPanel);
+ rect2->setFlag(QGraphicsItem::ItemIsFocusable);
+ rect2->setPos(50, 50);
+ rect2->setData(0, "rect2");
+
+ QGraphicsRectItem *rect2child = scene.addRect(-10, -10, 20, 20);
+ rect2child->setParentItem(rect2);
+ rect2child->setFlag(QGraphicsItem::ItemIsFocusable);
+ rect2child->setData(0, "rect2child1");
+
+ QEvent windowActivateEvent(QEvent::WindowActivate);
+ QApplication::sendEvent(&scene, &windowActivateEvent);
+
+ EventSpy2 rect1Spy(&scene, rect1);
+ EventSpy2 rect1childSpy(&scene, rect1child);
+ EventSpy2 rect2Spy(&scene, rect2);
+ EventSpy2 rect2childSpy(&scene, rect2child);
+
+ // activate rect1 and give it rect1child focus
+ rect1->setActive(true);
+ rect1child->setFocus();
+ QCOMPARE(scene.focusItem(), (QGraphicsItem *) rect1child);
+
+ // focus stays on rect1child when rect2 becomes modal
+ rect2->setPanelModality(QGraphicsItem::SceneModal);
+ QCOMPARE(scene.focusItem(), (QGraphicsItem *) rect1child);
+
+ // but key events to rect1child should be neither delivered nor propagated
+ sendKeyClick(&scene, Qt::Key_A);
+ sendKeyClick(&scene, Qt::Key_S);
+ sendKeyClick(&scene, Qt::Key_D);
+ sendKeyClick(&scene, Qt::Key_F);
+ QCOMPARE(rect1childSpy.counts[QEvent::KeyPress], 0);
+ QCOMPARE(rect1childSpy.counts[QEvent::KeyRelease], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::KeyPress], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::KeyRelease], 0);
+
+ // change to panel modality, rect1child1 keeps focus
+ rect2->setPanelModality(QGraphicsItem::PanelModal);
+ QCOMPARE(scene.focusItem(), (QGraphicsItem *) rect1child);
+
+ // still no key events
+ sendKeyClick(&scene, Qt::Key_J);
+ sendKeyClick(&scene, Qt::Key_K);
+ sendKeyClick(&scene, Qt::Key_L);
+ sendKeyClick(&scene, Qt::Key_Semicolon);
+ QCOMPARE(rect1childSpy.counts[QEvent::KeyPress], 0);
+ QCOMPARE(rect1childSpy.counts[QEvent::KeyRelease], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::KeyPress], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::KeyRelease], 0);
+}
+
QTEST_MAIN(tst_QGraphicsItem)
#include "tst_qgraphicsitem.moc"