1 /****************************************************************************
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
6 ** This file is part of the test suite of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
40 ****************************************************************************/
43 #include <QtTest/QtTest>
44 #if defined(Q_OS_WINCE)
50 #include <private/qgraphicsscene_p.h>
51 #include <private/qgraphicssceneindex_p.h>
53 #include "../../../gui/painting/qpathclipper/pathcompare.h"
54 #include "../../../shared/platforminputcontext.h"
55 #include <private/qinputmethod_p.h>
57 #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
59 #define Q_CHECK_PAINTEVENTS \
60 if (::SwitchDesktop(::GetThreadDesktop(::GetCurrentThreadId())) == 0) \
61 QSKIP("The Graphics View doesn't get the paint events");
63 #define Q_CHECK_PAINTEVENTS
66 Q_DECLARE_METATYPE(QList<int>)
67 Q_DECLARE_METATYPE(QList<QRectF>)
68 Q_DECLARE_METATYPE(QMatrix)
69 Q_DECLARE_METATYPE(QPainterPath)
70 Q_DECLARE_METATYPE(QPointF)
71 Q_DECLARE_METATYPE(QRectF)
72 Q_DECLARE_METATYPE(Qt::AspectRatioMode)
73 Q_DECLARE_METATYPE(Qt::ItemSelectionMode)
75 static const int randomX[] = {276, 40, 250, 864, -56, 426, 855, 825, 184, 955, -798, -804, 773,
76 282, 489, 686, 780, -220, 50, 749, -856, -205, 81, 492, -819, 518,
77 895, 57, -559, 788, -965, 68, -442, -247, -339, -648, 292, 891,
78 -865, 462, 864, 673, 640, 523, 194, 500, -727, 307, -243, 320,
79 -545, 415, 448, 341, -619, 652, 892, -16, -14, -659, -101, -934,
80 532, 356, 824, 132, 160, 130, 104, 886, -179, -174, 543, -644, 60,
81 -470, -354, -728, 689, 682, -587, -694, -221, -741, 37, 372, -289,
82 741, -300, 858, -320, 729, -602, -956, -544, -403, 203, 398, 284,
83 -972, -572, -946, 81, 51, -403, -580, 867, 546, 565, -580, -484,
84 659, 982, -518, -976, 423, -800, 659, -297, 712, 938, -19, -16,
85 824, -252, 197, 321, -837, 824, 136, 226, -980, -909, -826, -479,
86 -835, -503, -828, -901, -810, -641, -548, -179, 194, 749, -296, 539,
87 -37, -599, -235, 121, 35, -230, -915, 789, 764, -622, -382, -90, -701,
88 676, -407, 998, 267, 913, 817, -748, -370, -162, -797, 19, -556, 933,
89 -670, -101, -765, -941, -17, 360, 31, 960, 509, 933, -35, 974, -924,
90 -734, 589, 963, 724, 794, 843, 16, -272, -811, 721, 99, -122, 216,
91 -404, 158, 787, -443, -437, -337, 383, -342, 538, -641, 791, 637,
92 -848, 397, 820, 109, 11, 45, 809, 591, 933, 961, 625, -140, -592,
93 -694, -969, 317, 293, 777, -18, -282, 835, -455, -708, -407, -204,
94 748, 347, -501, -545, 292, -362, 176, 546, -573, -38, -854, -395,
95 560, -624, -940, -971, 66, -910, 782, 985};
97 static const int randomY[] = {603, 70, -318, 843, 450, -637, 199, -527, 407, 964, -54, 620, -207,
98 -736, -700, -476, -706, -142, 837, 621, 522, -98, 232, 292, -267, 900,
99 615, -356, -415, 783, 290, 462, -857, -314, 677, 36, 772, 424, -72,
100 -121, 547, -533, 537, -656, 289, 508, 914, 601, 434, 588, -779, -714,
101 -368, 628, -276, 432, -1, -929, 638, -36, 253, -922, -943, 979, -34,
102 -268, -193, 601, 686, -330, 165, 98, 75, -691, -605, 617, 773, 617,
103 619, 238, -42, -405, 17, 384, -472, -846, 520, 110, 591, -217, 936,
104 -373, 731, 734, 810, 961, 881, 939, 379, -905, -137, 437, 298, 688,
105 -71, -204, 573, -120, -821, 489, -722, -926, 529, -113, -243, 543,
106 868, -301, -781, -549, -842, -489, -80, -910, -928, 51, -91, 324,
107 204, -92, 867, 723, 248, 709, -357, 591, -365, -379, 266, -649, -95,
108 205, 551, 355, -631, 79, -186, 795, -7, -225, 46, -410, 665, -874,
109 -618, 845, -548, 443, 471, -644, 606, -607, 59, -619, 288, -244, 529,
110 690, 349, -738, -611, -879, -642, 801, -178, 823, -748, -552, -247,
111 -223, -408, 651, -62, 949, -795, 171, -107, -210, -207, -842, -86,
112 436, 528, 366, -178, 245, -695, 665, 613, -948, 667, -620, -979, -949,
113 905, 181, -412, -467, -437, -774, 750, -10, 54, 205, -674, -290, -924,
114 -361, -463, 912, -702, 622, -542, 220, 115, 832, 451, -38, -952, -230,
115 -588, 864, 234, 225, -303, 493, 246, 153, 338, -378, 377, -819, 140, 136,
116 467, -849, -326, -533, 166, 252, -994, -699, 904, -566, 621, -752};
118 class HoverItem : public QGraphicsRectItem
122 : QGraphicsRectItem(QRectF(-10, -10, 20, 20)), isHovered(false)
123 { setAcceptsHoverEvents(true); }
128 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *)
130 isHovered = (option->state & QStyle::State_MouseOver);
132 painter->setOpacity(0.75);
133 painter->setPen(Qt::NoPen);
134 painter->setBrush(Qt::darkGray);
135 painter->drawRoundRect(boundingRect().adjusted(3, 3, -3, -3), Qt::darkGray);
136 painter->setPen(Qt::black);
138 painter->setBrush(QColor(Qt::blue).light(120));
140 painter->setBrush(Qt::gray);
142 painter->drawRoundRect(boundingRect().adjusted(0, 0, -5, -5));
146 class EventSpy : public QGraphicsWidget
150 EventSpy(QObject *watched, QEvent::Type type)
151 : _count(0), spied(type)
153 watched->installEventFilter(this);
156 EventSpy(QGraphicsScene *scene, QGraphicsItem *watched, QEvent::Type type)
157 : _count(0), spied(type)
159 scene->addItem(this);
160 watched->installSceneEventFilter(this);
163 int count() const { return _count; }
166 bool eventFilter(QObject *watched, QEvent *event)
169 if (event->type() == spied)
174 bool sceneEventFilter(QGraphicsItem *watched, QEvent *event)
177 if (event->type() == spied)
186 class tst_QGraphicsScene : public QObject
196 void itemIndexMethod();
198 void itemsBoundingRect_data();
199 void itemsBoundingRect();
201 void items_QPointF_data();
202 void items_QPointF();
204 void items_QRectF_2_data();
205 void items_QRectF_2();
206 void items_QPolygonF();
207 void items_QPolygonF_2();
208 void items_QPainterPath();
209 void items_QPainterPath_2();
210 void selectionChanged();
211 void selectionChanged2();
222 void focusItemLostFocus();
224 void setFocusItem_inactive();
225 void mouseGrabberItem();
226 void hoverEvents_siblings();
227 void hoverEvents_parentChild();
228 void createItemGroup();
229 void mouseEventPropagation();
230 void mouseEventPropagation_ignore();
231 void mouseEventPropagation_focus();
232 void mouseEventPropagation_doubleclick();
233 void mouseEventPropagation_mouseMove();
234 #ifndef QT_NO_DRAGANDDROP
235 void dragAndDrop_simple();
236 void dragAndDrop_disabledOrInvisible();
237 void dragAndDrop_propagate();
241 void renderItemsWithNegativeWidthOrHeight();
242 void contextMenuEvent();
243 void contextMenuEvent_ItemIgnoresTransformations();
248 void eventsToDisabledItems();
250 void tabFocus_emptyScene();
251 void tabFocus_sceneWithFocusableItems();
252 void tabFocus_sceneWithFocusWidgets();
253 void tabFocus_sceneWithNestedFocusWidgets();
257 void changedSignal_data();
258 void changedSignal();
259 void stickyFocus_data();
262 void inputMethod_data();
264 void dispatchHoverOnPress();
265 void initialFocus_data();
270 void siblingIndexAlwaysValid();
271 void removeFullyTransparentItem();
274 // task specific tests below me
275 void task139710_bspTreeCrash();
276 void task139782_containsItemBoundingRect();
277 void task176178_itemIndexMethodBreaksSceneRect();
278 void task160653_selectionChanged();
279 void task250680_childClip();
280 void taskQTBUG_5904_crashWithDeviceCoordinateCache();
281 void taskQT657_paintIntoCacheWithTransparentParts();
282 void taskQTBUG_7863_paintIntoCacheWithTransparentParts();
283 void taskQT_3674_doNotCrash();
284 void taskQTBUG_15977_renderWithDeviceCoordinateCache();
285 void taskQTBUG_16401_focusItem();
288 void tst_QGraphicsScene::initTestCase()
290 #ifdef Q_OS_WINCE //disable magic for WindowsCE
291 qApp->setAutoMaximizeThreshold(-1);
295 void tst_QGraphicsScene::cleanup()
297 // ensure not even skipped tests with custom input context leave it dangling
298 QInputMethodPrivate *inputMethodPrivate = QInputMethodPrivate::get(qApp->inputMethod());
299 inputMethodPrivate->testContext = 0;
302 void tst_QGraphicsScene::construction()
304 QGraphicsScene scene;
305 QCOMPARE(scene.itemsBoundingRect(), QRectF());
306 QVERIFY(scene.items().isEmpty());
307 QVERIFY(scene.items(QPointF()).isEmpty());
308 QVERIFY(scene.items(QRectF()).isEmpty());
309 QVERIFY(scene.items(QPolygonF()).isEmpty());
310 QVERIFY(scene.items(QPainterPath()).isEmpty());
311 QTest::ignoreMessage(QtWarningMsg, "QGraphicsScene::collidingItems: cannot find collisions for null item");
312 QVERIFY(scene.collidingItems(0).isEmpty());
313 QVERIFY(!scene.itemAt(QPointF()));
314 QVERIFY(scene.selectedItems().isEmpty());
315 QVERIFY(!scene.focusItem());
318 void tst_QGraphicsScene::sceneRect()
320 QGraphicsScene scene;
321 QSignalSpy sceneRectChanged(&scene, SIGNAL(sceneRectChanged(QRectF)));
322 QCOMPARE(scene.sceneRect(), QRectF());
323 QCOMPARE(sceneRectChanged.count(), 0);
325 QGraphicsItem *item = scene.addRect(QRectF(0, 0, 10, 10));
326 item->setPos(-5, -5);
327 QCOMPARE(sceneRectChanged.count(), 0);
329 QCOMPARE(scene.itemAt(0, 0), item);
330 QCOMPARE(scene.itemAt(10, 10), (QGraphicsItem *)0);
331 QCOMPARE(sceneRectChanged.count(), 0);
332 QCOMPARE(scene.sceneRect(), QRectF(-5, -5, 10, 10));
333 QCOMPARE(sceneRectChanged.count(), 1);
334 QCOMPARE(sceneRectChanged.last().at(0).toRectF(), scene.sceneRect());
337 QCOMPARE(scene.sceneRect(), QRectF(-5, -5, 15, 15));
338 QCOMPARE(sceneRectChanged.count(), 2);
339 QCOMPARE(sceneRectChanged.last().at(0).toRectF(), scene.sceneRect());
341 scene.setSceneRect(-100, -100, 10, 10);
342 QCOMPARE(sceneRectChanged.count(), 3);
343 QCOMPARE(sceneRectChanged.last().at(0).toRectF(), scene.sceneRect());
345 QCOMPARE(scene.itemAt(0, 0), item);
346 QCOMPARE(scene.itemAt(10, 10), (QGraphicsItem *)0);
347 QCOMPARE(scene.sceneRect(), QRectF(-100, -100, 10, 10));
348 item->setPos(10, 10);
349 QCOMPARE(scene.sceneRect(), QRectF(-100, -100, 10, 10));
350 QCOMPARE(sceneRectChanged.count(), 3);
351 QCOMPARE(sceneRectChanged.last().at(0).toRectF(), scene.sceneRect());
353 scene.setSceneRect(QRectF());
355 QCOMPARE(scene.itemAt(10, 10), item);
356 QCOMPARE(scene.itemAt(20, 20), (QGraphicsItem *)0);
357 QCOMPARE(sceneRectChanged.count(), 4);
358 QCOMPARE(scene.sceneRect(), QRectF(-5, -5, 25, 25));
359 QCOMPARE(sceneRectChanged.count(), 5);
360 QCOMPARE(sceneRectChanged.last().at(0).toRectF(), scene.sceneRect());
363 void tst_QGraphicsScene::itemIndexMethod()
365 QGraphicsScene scene;
366 QCOMPARE(scene.itemIndexMethod(), QGraphicsScene::BspTreeIndex);
368 #ifdef Q_PROCESSOR_ARM
369 const int minY = -500;
370 const int maxY = 500;
371 const int minX = -500;
372 const int maxX = 500;
374 const int minY = -1000;
375 const int maxY = 2000;
376 const int minX = -1000;
377 const int maxX = 2000;
380 QList<QGraphicsItem *> items;
381 for (int y = minY; y < maxY; y += 100) {
382 for (int x = minX; x < maxX; x += 100) {
383 QGraphicsItem *item = scene.addRect(QRectF(0, 0, 10, 10));
385 QCOMPARE(scene.itemAt(x, y), item);
391 for (int y = minY; y < maxY; y += 100) {
392 for (int x = minX; x < maxX; x += 100)
393 QCOMPARE(scene.itemAt(x, y), items.at(n++));
396 scene.setItemIndexMethod(QGraphicsScene::NoIndex);
397 QCOMPARE(scene.itemIndexMethod(), QGraphicsScene::NoIndex);
400 for (int y = minY; y < maxY; y += 100) {
401 for (int x = minX; x < maxX; x += 100)
402 QCOMPARE(scene.itemAt(x, y), items.at(n++));
405 scene.setItemIndexMethod(QGraphicsScene::BspTreeIndex);
406 QCOMPARE(scene.itemIndexMethod(), QGraphicsScene::BspTreeIndex);
409 for (int y = minY; y < maxY; y += 100) {
410 for (int x = minX; x < maxX; x += 100)
411 QCOMPARE(scene.itemAt(x, y), items.at(n++));
415 void tst_QGraphicsScene::bspTreeDepth()
417 QGraphicsScene scene;
418 QCOMPARE(scene.itemIndexMethod(), QGraphicsScene::BspTreeIndex);
419 QCOMPARE(scene.bspTreeDepth(), 0);
420 scene.setBspTreeDepth(1);
421 QCOMPARE(scene.bspTreeDepth(), 1);
422 QTest::ignoreMessage(QtWarningMsg, "QGraphicsScene::setBspTreeDepth: invalid depth -1 ignored; must be >= 0");
423 scene.setBspTreeDepth(-1);
424 QCOMPARE(scene.bspTreeDepth(), 1);
427 void tst_QGraphicsScene::items()
429 #ifdef Q_PROCESSOR_ARM
430 const int minY = -500;
431 const int maxY = 500;
432 const int minX = -500;
433 const int maxX = 500;
435 const int minY = -1000;
436 const int maxY = 2000;
437 const int minX = -1000;
438 const int maxX = 2000;
442 QGraphicsScene scene;
444 QList<QGraphicsItem *> items;
445 for (int y = minY; y < maxY; y += 100) {
446 for (int x = minX; x < maxX; x += 100)
447 items << scene.addRect(QRectF(0, 0, 10, 10));
449 QCOMPARE(scene.items().size(), items.size());
450 scene.itemAt(0, 0); // trigger indexing
452 scene.removeItem(items.at(5));
454 QVERIFY(!scene.items().contains(0));
456 QVERIFY(!scene.items().contains(0));
459 QGraphicsScene scene;
460 QGraphicsLineItem *l1 = scene.addLine(-5, 0, 5, 0);
461 QGraphicsLineItem *l2 = scene.addLine(0, -5, 0, 5);
462 QVERIFY(!l1->sceneBoundingRect().intersects(l2->sceneBoundingRect()));
463 QVERIFY(!l2->sceneBoundingRect().intersects(l1->sceneBoundingRect()));
464 QList<QGraphicsItem *> items;
466 QCOMPARE(scene.items().size(), items.size());
467 QVERIFY(scene.items(-1, -1, 2, 2).contains(l1));
468 QVERIFY(scene.items(-1, -1, 2, 2).contains(l2));
472 void tst_QGraphicsScene::itemsBoundingRect_data()
474 QTest::addColumn<QList<QRectF> >("rects");
475 QTest::addColumn<QMatrix>("matrix");
476 QTest::addColumn<QRectF>("boundingRect");
478 QMatrix transformationMatrix;
479 transformationMatrix.translate(50, -50);
480 transformationMatrix.scale(2, 2);
481 transformationMatrix.rotate(90);
483 QTest::newRow("none")
487 QTest::newRow("{{0, 0, 10, 10}}")
488 << (QList<QRectF>() << QRectF(0, 0, 10, 10))
490 << QRectF(0, 0, 10, 10);
491 QTest::newRow("{{-10, -10, 10, 10}}")
492 << (QList<QRectF>() << QRectF(-10, -10, 10, 10))
494 << QRectF(-10, -10, 10, 10);
495 QTest::newRow("{{-1000, -1000, 1, 1}, {-10, -10, 10, 10}}")
496 << (QList<QRectF>() << QRectF(-1000, -1000, 1, 1) << QRectF(-10, -10, 10, 10))
498 << QRectF(-1000, -1000, 1000, 1000);
499 QTest::newRow("transformed {{0, 0, 10, 10}}")
500 << (QList<QRectF>() << QRectF(0, 0, 10, 10))
501 << transformationMatrix
502 << QRectF(30, -50, 20, 20);
503 QTest::newRow("transformed {{-10, -10, 10, 10}}")
504 << (QList<QRectF>() << QRectF(-10, -10, 10, 10))
505 << transformationMatrix
506 << QRectF(50, -70, 20, 20);
507 QTest::newRow("transformed {{-1000, -1000, 1, 1}, {-10, -10, 10, 10}}")
508 << (QList<QRectF>() << QRectF(-1000, -1000, 1, 1) << QRectF(-10, -10, 10, 10))
509 << transformationMatrix
510 << QRectF(50, -2050, 2000, 2000);
513 for (int i = 0; i < 256; ++i)
514 all << QRectF(randomX[i], randomY[i], 10, 10);
518 << QRectF(-980, -994, 1988, 1983);
519 QTest::newRow("transformed all")
521 << transformationMatrix
522 << QRectF(-1928, -2010, 3966, 3976);
525 void tst_QGraphicsScene::itemsBoundingRect()
527 QFETCH(QList<QRectF>, rects);
528 QFETCH(QMatrix, matrix);
529 QFETCH(QRectF, boundingRect);
531 QGraphicsScene scene;
533 foreach (QRectF rect, rects) {
536 scene.addPath(path)->setMatrix(matrix);
539 QCOMPARE(scene.itemsBoundingRect(), boundingRect);
542 void tst_QGraphicsScene::items_QPointF_data()
544 QTest::addColumn<QList<QRectF> >("items");
545 QTest::addColumn<QPointF>("point");
546 QTest::addColumn<QList<int> >("itemsAtPoint");
548 QTest::newRow("empty")
553 << (QList<QRectF>() << QRectF(0, 0, 10, 10))
555 << (QList<int>() << 0);
557 << (QList<QRectF>() << QRectF(0, 0, 10, 10))
559 << (QList<int>() << 0);
561 << (QList<QRectF>() << QRectF(0, 0, 10, 10))
563 << (QList<int>() << 0);
565 << (QList<QRectF>() << QRectF(0, 0, 10, 10))
569 << (QList<QRectF>() << QRectF(0, 0, 10, 10) << QRectF(9.9, 9.9, 10, 10))
571 << (QList<int>() << 1 << 0);
573 << (QList<QRectF>() << QRectF(0, 0, 10, 10) << QRectF(10, 10, 10, 10))
575 << (QList<int>() << 1);
577 << (QList<QRectF>() << QRectF(5, 5, 10, 10) << QRectF(10, 10, 10, 10))
579 << (QList<int>() << 1 << 0);
581 << (QList<QRectF>() << QRectF(5, 5, 10, 10) << QRectF(10, 10, 10, 10) << QRectF(0, 0, 20, 30))
583 << (QList<int>() << 2 << 1 << 0);
586 void tst_QGraphicsScene::items_QPointF()
588 QFETCH(QList<QRectF>, items);
589 QFETCH(QPointF, point);
590 QFETCH(QList<int>, itemsAtPoint);
592 QGraphicsScene scene;
595 QList<QGraphicsItem *> addedItems;
596 foreach(QRectF rect, items) {
598 path.addRect(0, 0, rect.width(), rect.height());
600 QGraphicsItem *item = scene.addPath(path);
601 item->setZValue(n++);
602 item->setPos(rect.topLeft());
606 QList<int> itemIndexes;
607 foreach (QGraphicsItem *item, scene.items(point))
608 itemIndexes << addedItems.indexOf(item);
610 QCOMPARE(itemIndexes, itemsAtPoint);
613 void tst_QGraphicsScene::items_QRectF()
615 QGraphicsScene scene;
616 QGraphicsItem *item1 = scene.addRect(QRectF(-10, -10, 10, 10));
617 QGraphicsItem *item2 = scene.addRect(QRectF(10, -10, 10, 10));
618 QGraphicsItem *item3 = scene.addRect(QRectF(10, 10, 10, 10));
619 QGraphicsItem *item4 = scene.addRect(QRectF(-10, 10, 10, 10));
626 QCOMPARE(scene.items(QRectF(-10, -10, 10, 10)), QList<QGraphicsItem *>() << item1);
627 QCOMPARE(scene.items(QRectF(10, -10, 10, 10)), QList<QGraphicsItem *>() << item2);
628 QCOMPARE(scene.items(QRectF(10, 10, 10, 10)), QList<QGraphicsItem *>() << item3);
629 QCOMPARE(scene.items(QRectF(-10, 10, 10, 10)), QList<QGraphicsItem *>() << item4);
630 QCOMPARE(scene.items(QRectF(-10, -10, 1, 1)), QList<QGraphicsItem *>() << item1);
631 QCOMPARE(scene.items(QRectF(10, -10, 1, 1)), QList<QGraphicsItem *>() << item2);
632 QCOMPARE(scene.items(QRectF(10, 10, 1, 1)), QList<QGraphicsItem *>() << item3);
633 QCOMPARE(scene.items(QRectF(-10, 10, 1, 1)), QList<QGraphicsItem *>() << item4);
635 QCOMPARE(scene.items(QRectF(-10, -10, 40, 10)), QList<QGraphicsItem *>() << item2 << item1);
636 QCOMPARE(scene.items(QRectF(-10, 10, 40, 10)), QList<QGraphicsItem *>() << item4 << item3);
643 QCOMPARE(scene.items(QRectF(-10, -10, 40, 10)), QList<QGraphicsItem *>() << item1 << item2);
644 QCOMPARE(scene.items(QRectF(-10, 10, 40, 10)), QList<QGraphicsItem *>() << item3 << item4);
647 void tst_QGraphicsScene::items_QRectF_2_data()
649 QTest::addColumn<QRectF>("ellipseRect");
650 QTest::addColumn<QRectF>("sceneRect");
651 QTest::addColumn<Qt::ItemSelectionMode>("selectionMode");
652 QTest::addColumn<bool>("contained");
653 QTest::addColumn<bool>("containedRotated");
655 // None of the rects contain the ellipse's shape nor bounding rect
656 QTest::newRow("1") << QRectF(0, 0, 100, 100) << QRectF(1, 1, 10, 10) << Qt::ContainsItemShape << false << false;
657 QTest::newRow("2") << QRectF(0, 0, 100, 100) << QRectF(1, 89, 10, 10) << Qt::ContainsItemShape << false << false;
658 QTest::newRow("3") << QRectF(0, 0, 100, 100) << QRectF(89, 1, 10, 10) << Qt::ContainsItemShape << false << false;
659 QTest::newRow("4") << QRectF(0, 0, 100, 100) << QRectF(89, 89, 10, 10) << Qt::ContainsItemShape << false << false;
660 QTest::newRow("5") << QRectF(0, 0, 100, 100) << QRectF(1, 1, 10, 10) << Qt::ContainsItemBoundingRect << false << false;
661 QTest::newRow("6") << QRectF(0, 0, 100, 100) << QRectF(1, 89, 10, 10) << Qt::ContainsItemBoundingRect << false << false;
662 QTest::newRow("7") << QRectF(0, 0, 100, 100) << QRectF(89, 1, 10, 10) << Qt::ContainsItemBoundingRect << false << false;
663 QTest::newRow("8") << QRectF(0, 0, 100, 100) << QRectF(89, 89, 10, 10) << Qt::ContainsItemBoundingRect << false << false;
664 QTest::newRow("9") << QRectF(0, 0, 100, 100) << QRectF(0, 0, 50, 50) << Qt::ContainsItemShape << false << false;
665 QTest::newRow("10") << QRectF(0, 0, 100, 100) << QRectF(0, 50, 50, 50) << Qt::ContainsItemShape << false << false;
666 QTest::newRow("11") << QRectF(0, 0, 100, 100) << QRectF(50, 0, 50, 50) << Qt::ContainsItemShape << false << false;
667 QTest::newRow("12") << QRectF(0, 0, 100, 100) << QRectF(50, 50, 50, 50) << Qt::ContainsItemShape << false << false;
668 QTest::newRow("13") << QRectF(0, 0, 100, 100) << QRectF(0, 0, 50, 50) << Qt::ContainsItemBoundingRect << false << false;
669 QTest::newRow("14") << QRectF(0, 0, 100, 100) << QRectF(0, 50, 50, 50) << Qt::ContainsItemBoundingRect << false << false;
670 QTest::newRow("15") << QRectF(0, 0, 100, 100) << QRectF(50, 0, 50, 50) << Qt::ContainsItemBoundingRect << false << false;
671 QTest::newRow("16") << QRectF(0, 0, 100, 100) << QRectF(50, 50, 50, 50) << Qt::ContainsItemBoundingRect << false << false;
672 QTest::newRow("17") << QRectF(0, 0, 100, 100) << QRectF(-50, -50, 100, 100) << Qt::ContainsItemShape << false << false;
673 QTest::newRow("18") << QRectF(0, 0, 100, 100) << QRectF(0, -50, 100, 100) << Qt::ContainsItemShape << false << false;
674 QTest::newRow("19") << QRectF(0, 0, 100, 100) << QRectF(-50, 0, 100, 100) << Qt::ContainsItemShape << false << false;
675 QTest::newRow("20") << QRectF(0, 0, 100, 100) << QRectF(0, 0, 100, 100) << Qt::ContainsItemShape << false << false;
676 QTest::newRow("21") << QRectF(0, 0, 100, 100) << QRectF(-50, -50, 100, 100) << Qt::ContainsItemBoundingRect << false << false;
677 QTest::newRow("22") << QRectF(0, 0, 100, 100) << QRectF(0, -50, 100, 100) << Qt::ContainsItemBoundingRect << false << false;
678 QTest::newRow("23") << QRectF(0, 0, 100, 100) << QRectF(-50, 0, 100, 100) << Qt::ContainsItemBoundingRect << false << false;
680 // The rect is the same as the ellipse's bounding rect
681 QTest::newRow("24") << QRectF(0, 0, 100, 100) << QRectF(0, 0, 100, 100) << Qt::ContainsItemBoundingRect << false << false;
683 // None intersects with the item's shape, but they all intersects with the
684 // item's bounding rect.
685 QTest::newRow("25") << QRectF(0, 0, 100, 100) << QRectF(1, 1, 10, 10) << Qt::IntersectsItemShape << false << false;
686 QTest::newRow("26") << QRectF(0, 0, 100, 100) << QRectF(1, 89, 10, 10) << Qt::IntersectsItemShape << false << true;
687 QTest::newRow("27") << QRectF(0, 0, 100, 100) << QRectF(89, 1, 10, 10) << Qt::IntersectsItemShape << false << false;
688 QTest::newRow("28") << QRectF(0, 0, 100, 100) << QRectF(89, 89, 10, 10) << Qt::IntersectsItemShape << false << false;
689 QTest::newRow("29") << QRectF(0, 0, 100, 100) << QRectF(1, 1, 10, 10) << Qt::IntersectsItemBoundingRect << true << true;
690 QTest::newRow("30") << QRectF(0, 0, 100, 100) << QRectF(1, 89, 10, 10) << Qt::IntersectsItemBoundingRect << true << true;
691 QTest::newRow("31") << QRectF(0, 0, 100, 100) << QRectF(89, 1, 10, 10) << Qt::IntersectsItemBoundingRect << true << false;
692 QTest::newRow("32") << QRectF(0, 0, 100, 100) << QRectF(89, 89, 10, 10) << Qt::IntersectsItemBoundingRect << true << false;
694 // This rect does not contain the shape nor the bounding rect
695 QTest::newRow("33") << QRectF(0, 0, 100, 100) << QRectF(5, 5, 90, 90) << Qt::ContainsItemShape << false << false;
696 QTest::newRow("34") << QRectF(0, 0, 100, 100) << QRectF(5, 5, 90, 90) << Qt::ContainsItemBoundingRect << false << false;
698 // It will, however, intersect with both
699 QTest::newRow("35") << QRectF(0, 0, 100, 100) << QRectF(5, 5, 90, 90) << Qt::IntersectsItemShape << true << true;
700 QTest::newRow("36") << QRectF(0, 0, 100, 100) << QRectF(5, 5, 90, 90) << Qt::IntersectsItemBoundingRect << true << true;
702 // A rect that contains the whole ellipse will both contain and intersect
703 // with both the ellipse's shape and bounding rect.
704 QTest::newRow("37") << QRectF(0, 0, 100, 100) << QRectF(-5, -5, 110, 110) << Qt::IntersectsItemBoundingRect << true << true;
705 QTest::newRow("38") << QRectF(0, 0, 100, 100) << QRectF(-5, -5, 110, 110) << Qt::IntersectsItemShape << true << true;
706 QTest::newRow("39") << QRectF(0, 0, 100, 100) << QRectF(-5, -5, 110, 110) << Qt::ContainsItemBoundingRect << true << false;
707 QTest::newRow("40") << QRectF(0, 0, 100, 100) << QRectF(-5, -5, 110, 110) << Qt::ContainsItemShape << true << false;
709 // A rect that is fully contained within the ellipse will intersect only
710 QTest::newRow("41") << QRectF(0, 0, 100, 100) << QRectF(40, 40, 20, 20) << Qt::ContainsItemShape << false << false;
711 QTest::newRow("42") << QRectF(0, 0, 100, 100) << QRectF(40, 40, 20, 20) << Qt::ContainsItemBoundingRect << false << false;
712 QTest::newRow("43") << QRectF(0, 0, 100, 100) << QRectF(40, 40, 20, 20) << Qt::IntersectsItemShape << true << true;
713 QTest::newRow("44") << QRectF(0, 0, 100, 100) << QRectF(40, 40, 20, 20) << Qt::IntersectsItemBoundingRect << true << true;
716 void tst_QGraphicsScene::items_QRectF_2()
718 QFETCH(QRectF, ellipseRect);
719 QFETCH(QRectF, sceneRect);
720 QFETCH(Qt::ItemSelectionMode, selectionMode);
721 QFETCH(bool, contained);
722 QFETCH(bool, containedRotated);
724 QGraphicsScene scene;
725 QGraphicsItem *item = scene.addEllipse(ellipseRect);
727 QCOMPARE(!scene.items(sceneRect, selectionMode).isEmpty(), contained);
729 QCOMPARE(!scene.items(sceneRect, selectionMode).isEmpty(), containedRotated);
732 void tst_QGraphicsScene::items_QPolygonF()
734 QGraphicsScene scene;
735 QGraphicsItem *item1 = scene.addRect(QRectF(-10, -10, 10, 10));
736 QGraphicsItem *item2 = scene.addRect(QRectF(10, -10, 10, 10));
737 QGraphicsItem *item3 = scene.addRect(QRectF(10, 10, 10, 10));
738 QGraphicsItem *item4 = scene.addRect(QRectF(-10, 10, 10, 10));
745 QPolygonF poly1(item1->boundingRect());
746 QPolygonF poly2(item2->boundingRect());
747 QPolygonF poly3(item3->boundingRect());
748 QPolygonF poly4(item4->boundingRect());
750 QCOMPARE(scene.items(poly1), QList<QGraphicsItem *>() << item1);
751 QCOMPARE(scene.items(poly2), QList<QGraphicsItem *>() << item2);
752 QCOMPARE(scene.items(poly3), QList<QGraphicsItem *>() << item3);
753 QCOMPARE(scene.items(poly4), QList<QGraphicsItem *>() << item4);
755 poly1 = QPolygonF(QRectF(-10, -10, 1, 1));
756 poly2 = QPolygonF(QRectF(10, -10, 1, 1));
757 poly3 = QPolygonF(QRectF(10, 10, 1, 1));
758 poly4 = QPolygonF(QRectF(-10, 10, 1, 1));
760 QCOMPARE(scene.items(poly1), QList<QGraphicsItem *>() << item1);
761 QCOMPARE(scene.items(poly2), QList<QGraphicsItem *>() << item2);
762 QCOMPARE(scene.items(poly3), QList<QGraphicsItem *>() << item3);
763 QCOMPARE(scene.items(poly4), QList<QGraphicsItem *>() << item4);
765 poly1 = QPolygonF(QRectF(-10, -10, 40, 10));
766 poly2 = QPolygonF(QRectF(-10, 10, 40, 10));
768 QCOMPARE(scene.items(poly1), QList<QGraphicsItem *>() << item2 << item1);
769 QCOMPARE(scene.items(poly2), QList<QGraphicsItem *>() << item4 << item3);
776 QCOMPARE(scene.items(poly1), QList<QGraphicsItem *>() << item1 << item2);
777 QCOMPARE(scene.items(poly2), QList<QGraphicsItem *>() << item3 << item4);
780 void tst_QGraphicsScene::items_QPolygonF_2()
782 QGraphicsScene scene;
783 QGraphicsItem *ellipse = scene.addEllipse(QRectF(0, 0, 100, 100));
785 // None of the rects contain the ellipse's shape nor bounding rect
786 QVERIFY(scene.items(QPolygonF(QRectF(1, 1, 10, 10)), Qt::ContainsItemShape).isEmpty());
787 QVERIFY(scene.items(QPolygonF(QRectF(1, 89, 10, 10)), Qt::ContainsItemShape).isEmpty());
788 QVERIFY(scene.items(QPolygonF(QRectF(89, 1, 10, 10)), Qt::ContainsItemShape).isEmpty());
789 QVERIFY(scene.items(QPolygonF(QRectF(89, 89, 10, 10)), Qt::ContainsItemShape).isEmpty());
790 QVERIFY(scene.items(QPolygonF(QRectF(1, 1, 10, 10)), Qt::ContainsItemBoundingRect).isEmpty());
791 QVERIFY(scene.items(QPolygonF(QRectF(1, 89, 10, 10)), Qt::ContainsItemBoundingRect).isEmpty());
792 QVERIFY(scene.items(QPolygonF(QRectF(89, 1, 10, 10)), Qt::ContainsItemBoundingRect).isEmpty());
793 QVERIFY(scene.items(QPolygonF(QRectF(89, 89, 10, 10)), Qt::ContainsItemBoundingRect).isEmpty());
795 // None intersects with the item's shape, but they all intersects with the
796 // item's bounding rect.
797 QVERIFY(scene.items(QPolygonF(QRectF(1, 1, 10, 10)), Qt::IntersectsItemShape).isEmpty());
798 QVERIFY(scene.items(QPolygonF(QRectF(1, 89, 10, 10)), Qt::IntersectsItemShape).isEmpty());
799 QVERIFY(scene.items(QPolygonF(QRectF(89, 1, 10, 10)), Qt::IntersectsItemShape).isEmpty());
800 QVERIFY(scene.items(QPolygonF(QRectF(89, 89, 10, 10)), Qt::IntersectsItemShape).isEmpty());
801 QCOMPARE(scene.items(QPolygonF(QRectF(1, 1, 10, 10)), Qt::IntersectsItemBoundingRect).first(), ellipse);
802 QCOMPARE(scene.items(QPolygonF(QRectF(1, 89, 10, 10)), Qt::IntersectsItemBoundingRect).first(), ellipse);
803 QCOMPARE(scene.items(QPolygonF(QRectF(89, 1, 10, 10)), Qt::IntersectsItemBoundingRect).first(), ellipse);
804 QCOMPARE(scene.items(QPolygonF(QRectF(89, 89, 10, 10)), Qt::IntersectsItemBoundingRect).first(), ellipse);
806 // This rect does not contain the shape nor the bounding rect
807 QVERIFY(scene.items(QPolygonF(QRectF(5, 5, 90, 90)), Qt::ContainsItemShape).isEmpty());
808 QVERIFY(scene.items(QPolygonF(QRectF(5, 5, 90, 90)), Qt::ContainsItemBoundingRect).isEmpty());
810 // It will, however, intersect with both
811 QCOMPARE(scene.items(QPolygonF(QRectF(5, 5, 90, 90)), Qt::IntersectsItemShape).first(), ellipse);
812 QCOMPARE(scene.items(QPolygonF(QRectF(5, 5, 90, 90)), Qt::IntersectsItemBoundingRect).first(), ellipse);
814 // A rect that contains the whole ellipse will both contain and intersect
815 // with both the ellipse's shape and bounding rect.
816 QCOMPARE(scene.items(QPolygonF(QRectF(-5, -5, 110, 110)), Qt::IntersectsItemShape).first(), ellipse);
817 QCOMPARE(scene.items(QPolygonF(QRectF(-5, -5, 110, 110)), Qt::ContainsItemShape).first(), ellipse);
818 QCOMPARE(scene.items(QPolygonF(QRectF(-5, -5, 110, 110)), Qt::IntersectsItemBoundingRect).first(), ellipse);
819 QCOMPARE(scene.items(QPolygonF(QRectF(-5, -5, 110, 110)), Qt::ContainsItemBoundingRect).first(), ellipse);
822 void tst_QGraphicsScene::items_QPainterPath()
824 QGraphicsScene scene;
825 QGraphicsItem *item1 = scene.addRect(QRectF(-10, -10, 10, 10));
826 QGraphicsItem *item2 = scene.addRect(QRectF(10, -10, 10, 10));
827 QGraphicsItem *item3 = scene.addRect(QRectF(10, 10, 10, 10));
828 QGraphicsItem *item4 = scene.addRect(QRectF(-10, 10, 10, 10));
835 QPainterPath path1; path1.addEllipse(item1->boundingRect());
836 QPainterPath path2; path2.addEllipse(item2->boundingRect());
837 QPainterPath path3; path3.addEllipse(item3->boundingRect());
838 QPainterPath path4; path4.addEllipse(item4->boundingRect());
840 QCOMPARE(scene.items(path1), QList<QGraphicsItem *>() << item1);
841 QCOMPARE(scene.items(path2), QList<QGraphicsItem *>() << item2);
842 QCOMPARE(scene.items(path3), QList<QGraphicsItem *>() << item3);
843 QCOMPARE(scene.items(path4), QList<QGraphicsItem *>() << item4);
845 path1 = QPainterPath(); path1.addEllipse(QRectF(-10, -10, 1, 1));
846 path2 = QPainterPath(); path2.addEllipse(QRectF(10, -10, 1, 1));
847 path3 = QPainterPath(); path3.addEllipse(QRectF(10, 10, 1, 1));
848 path4 = QPainterPath(); path4.addEllipse(QRectF(-10, 10, 1, 1));
850 QCOMPARE(scene.items(path1), QList<QGraphicsItem *>() << item1);
851 QCOMPARE(scene.items(path2), QList<QGraphicsItem *>() << item2);
852 QCOMPARE(scene.items(path3), QList<QGraphicsItem *>() << item3);
853 QCOMPARE(scene.items(path4), QList<QGraphicsItem *>() << item4);
855 path1 = QPainterPath(); path1.addRect(QRectF(-10, -10, 40, 10));
856 path2 = QPainterPath(); path2.addRect(QRectF(-10, 10, 40, 10));
858 QCOMPARE(scene.items(path1), QList<QGraphicsItem *>() << item2 << item1);
859 QCOMPARE(scene.items(path2), QList<QGraphicsItem *>() << item4 << item3);
866 QCOMPARE(scene.items(path1), QList<QGraphicsItem *>() << item1 << item2);
867 QCOMPARE(scene.items(path2), QList<QGraphicsItem *>() << item3 << item4);
870 void tst_QGraphicsScene::items_QPainterPath_2()
872 QGraphicsScene scene;
873 QGraphicsItem *ellipse = scene.addEllipse(QRectF(0, 0, 100, 100));
875 QPainterPath p1; p1.addRect(QRectF(1, 1, 10, 10));
876 QPainterPath p2; p2.addRect(QRectF(1, 89, 10, 10));
877 QPainterPath p3; p3.addRect(QRectF(89, 1, 10, 10));
878 QPainterPath p4; p4.addRect(QRectF(89, 89, 10, 10));
880 // None of the rects contain the ellipse's shape nor bounding rect
881 QVERIFY(scene.items(p1, Qt::ContainsItemShape).isEmpty());
882 QVERIFY(scene.items(p2, Qt::ContainsItemShape).isEmpty());
883 QVERIFY(scene.items(p3, Qt::ContainsItemShape).isEmpty());
884 QVERIFY(scene.items(p4, Qt::ContainsItemShape).isEmpty());
885 QVERIFY(scene.items(p1, Qt::ContainsItemBoundingRect).isEmpty());
886 QVERIFY(scene.items(p2, Qt::ContainsItemBoundingRect).isEmpty());
887 QVERIFY(scene.items(p3, Qt::ContainsItemBoundingRect).isEmpty());
888 QVERIFY(scene.items(p4, Qt::ContainsItemBoundingRect).isEmpty());
890 // None intersects with the item's shape, but they all intersects with the
891 // item's bounding rect.
892 QVERIFY(scene.items(p1, Qt::IntersectsItemShape).isEmpty());
893 QVERIFY(scene.items(p2, Qt::IntersectsItemShape).isEmpty());
894 QVERIFY(scene.items(p3, Qt::IntersectsItemShape).isEmpty());
895 QVERIFY(scene.items(p4, Qt::IntersectsItemShape).isEmpty());
896 QCOMPARE(scene.items(p1, Qt::IntersectsItemBoundingRect).first(), ellipse);
897 QCOMPARE(scene.items(p2, Qt::IntersectsItemBoundingRect).first(), ellipse);
898 QCOMPARE(scene.items(p3, Qt::IntersectsItemBoundingRect).first(), ellipse);
899 QCOMPARE(scene.items(p4, Qt::IntersectsItemBoundingRect).first(), ellipse);
902 p5.addRect(QRectF(5, 5, 90, 90));
904 // This rect does not contain the shape nor the bounding rect
905 QVERIFY(scene.items(p5, Qt::ContainsItemShape).isEmpty());
906 QVERIFY(scene.items(p5, Qt::ContainsItemBoundingRect).isEmpty());
908 // It will, however, intersect with both
909 QCOMPARE(scene.items(p5, Qt::IntersectsItemShape).first(), ellipse);
910 QCOMPARE(scene.items(p5, Qt::IntersectsItemBoundingRect).first(), ellipse);
913 p6.addRect(QRectF(-5, -5, 110, 110));
915 // A rect that contains the whole ellipse will both contain and intersect
916 // with both the ellipse's shape and bounding rect.
917 QCOMPARE(scene.items(p6, Qt::IntersectsItemShape).first(), ellipse);
918 QCOMPARE(scene.items(p6, Qt::ContainsItemShape).first(), ellipse);
919 QCOMPARE(scene.items(p6, Qt::IntersectsItemBoundingRect).first(), ellipse);
920 QCOMPARE(scene.items(p6, Qt::ContainsItemBoundingRect).first(), ellipse);
923 class CustomView : public QGraphicsView
926 CustomView() : repaints(0)
931 void paintEvent(QPaintEvent *event)
934 QGraphicsView::paintEvent(event);
938 void tst_QGraphicsScene::selectionChanged()
940 QGraphicsScene scene(0, 0, 1000, 1000);
941 QSignalSpy spy(&scene, SIGNAL(selectionChanged()));
942 QCOMPARE(spy.count(), 0);
945 path.addRect(scene.sceneRect());
946 QCOMPARE(scene.selectionArea(), QPainterPath());
947 scene.setSelectionArea(path);
948 QCOMPARE(scene.selectionArea(), path);
949 QCOMPARE(spy.count(), 0); // selection didn't change
950 QVERIFY(scene.selectedItems().isEmpty());
952 QGraphicsItem *rect = scene.addRect(QRectF(0, 0, 100, 100));
953 QCOMPARE(spy.count(), 0); // selection didn't change
955 rect->setSelected(true);
956 QVERIFY(!rect->isSelected());
957 QCOMPARE(spy.count(), 0); // selection didn't change, item isn't selectable
959 rect->setFlag(QGraphicsItem::ItemIsSelectable);
960 rect->setSelected(true);
961 QVERIFY(rect->isSelected());
962 QCOMPARE(spy.count(), 1); // selection changed
963 QCOMPARE(scene.selectedItems(), QList<QGraphicsItem *>() << rect);
965 rect->setSelected(false);
966 QVERIFY(!rect->isSelected());
967 QCOMPARE(spy.count(), 2); // selection changed
968 QVERIFY(scene.selectedItems().isEmpty());
970 QGraphicsEllipseItem *parentItem = new QGraphicsEllipseItem(QRectF(0, 0, 100, 100));
971 QGraphicsEllipseItem *childItem = new QGraphicsEllipseItem(QRectF(0, 0, 100, 100), parentItem);
972 QGraphicsEllipseItem *grandChildItem = new QGraphicsEllipseItem(QRectF(0, 0, 100, 100), childItem);
973 grandChildItem->setFlag(QGraphicsItem::ItemIsSelectable);
974 grandChildItem->setSelected(true);
975 grandChildItem->setSelected(false);
976 grandChildItem->setSelected(true);
977 scene.addItem(parentItem);
979 QCOMPARE(spy.count(), 3); // the grandchild was added, so the selection changed once
981 scene.removeItem(parentItem);
982 QCOMPARE(spy.count(), 4); // the grandchild was removed, so the selection changed
984 rect->setSelected(true);
985 QCOMPARE(spy.count(), 5); // the rect was reselected, so the selection changed
987 scene.clearSelection();
988 QCOMPARE(spy.count(), 6); // the scene selection was cleared
990 rect->setSelected(true);
991 QCOMPARE(spy.count(), 7); // the rect was reselected, so the selection changed
993 rect->setFlag(QGraphicsItem::ItemIsSelectable, false);
994 QCOMPARE(spy.count(), 8); // the rect was unselected, so the selection changed
996 rect->setSelected(true);
997 QCOMPARE(spy.count(), 8); // the rect is not longer selectable, so the selection does not change
1000 rect->setFlag(QGraphicsItem::ItemIsSelectable, true);
1001 rect->setSelected(true);
1002 QCOMPARE(spy.count(), 9); // the rect is again selectable, so the selection changed
1005 QCOMPARE(spy.count(), 10); // a selected item was deleted; selection changed
1008 void tst_QGraphicsScene::selectionChanged2()
1010 QGraphicsScene scene;
1011 QSignalSpy spy(&scene, SIGNAL(selectionChanged()));
1013 QGraphicsItem *item1 = scene.addRect(0, 0, 100, 100);
1014 QGraphicsItem *item2 = scene.addRect(100, 100, 100, 100);
1015 item1->setFlag(QGraphicsItem::ItemIsSelectable);
1016 item2->setFlag(QGraphicsItem::ItemIsSelectable);
1018 QCOMPARE(spy.count(), 0);
1020 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
1021 event.setScenePos(QPointF(50, 50));
1022 event.setButton(Qt::LeftButton);
1023 qApp->sendEvent(&scene, &event);
1026 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseRelease);
1027 event.setScenePos(QPointF(50, 50));
1028 event.setButton(Qt::LeftButton);
1029 qApp->sendEvent(&scene, &event);
1031 QVERIFY(item1->isSelected());
1032 QVERIFY(!item2->isSelected());
1033 QCOMPARE(spy.count(), 1);
1035 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
1036 event.setScenePos(QPointF(150, 150));
1037 event.setButton(Qt::LeftButton);
1038 qApp->sendEvent(&scene, &event);
1041 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseRelease);
1042 event.setScenePos(QPointF(150, 150));
1043 event.setButton(Qt::LeftButton);
1044 qApp->sendEvent(&scene, &event);
1046 QVERIFY(!item1->isSelected());
1047 QVERIFY(item2->isSelected());
1048 QCOMPARE(spy.count(), 2);
1050 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
1051 event.setScenePos(QPointF(50, 50));
1052 event.setButton(Qt::LeftButton);
1053 event.setModifiers(Qt::ControlModifier);
1054 qApp->sendEvent(&scene, &event);
1056 QVERIFY(!item1->isSelected());
1057 QVERIFY(item2->isSelected());
1058 QCOMPARE(spy.count(), 2);
1060 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseRelease);
1061 event.setScenePos(QPointF(50, 50));
1062 event.setButton(Qt::LeftButton);
1063 qApp->sendEvent(&scene, &event);
1065 QVERIFY(item1->isSelected());
1066 QVERIFY(!item2->isSelected());
1067 QCOMPARE(spy.count(), 3);
1070 void tst_QGraphicsScene::addItem()
1074 // 1) Create item, then scene, then add item
1075 QGraphicsItem *path = new QGraphicsEllipseItem(QRectF(-10, -10, 20, 20));
1076 QGraphicsScene scene;
1079 view.setScene(&scene);
1081 QVERIFY(QTest::qWaitForWindowExposed(&view));
1082 qApp->processEvents();
1085 scene.addItem(path);
1087 // Adding an item should always issue a repaint.
1088 QTRY_VERIFY(view.repaints > 0);
1091 QCOMPARE(scene.itemAt(0, 0), path);
1093 QGraphicsItem *path2 = new QGraphicsEllipseItem(QRectF(-10, -10, 20, 20));
1094 path2->setPos(100, 100);
1096 QCOMPARE(scene.itemAt(0, 0), path);
1097 QCOMPARE(scene.itemAt(100, 100), (QGraphicsItem *)0);
1098 scene.addItem(path2);
1100 // Adding an item should always issue a repaint.
1101 QTRY_VERIFY(view.repaints > 0);
1103 QCOMPARE(scene.itemAt(100, 100), path2);
1106 // 2) Create scene, then item, then add item
1107 QGraphicsScene scene;
1108 QGraphicsItem *path = new QGraphicsEllipseItem(QRectF(-10, -10, 20, 20));
1109 scene.addItem(path);
1111 QGraphicsItem *path2 = new QGraphicsEllipseItem(QRectF(-10, -10, 20, 20));
1112 path2->setPos(100, 100);
1113 scene.addItem(path2);
1115 QCOMPARE(scene.itemAt(0, 0), path);
1116 QCOMPARE(scene.itemAt(100, 100), path2);
1120 void tst_QGraphicsScene::addEllipse()
1122 QGraphicsScene scene;
1123 QGraphicsEllipseItem *ellipse = scene.addEllipse(QRectF(-10, -10, 20, 20),
1124 QPen(Qt::red), QBrush(Qt::blue));
1125 QCOMPARE(ellipse->pos(), QPointF());
1126 QCOMPARE(ellipse->pen(), QPen(Qt::red));
1127 QCOMPARE(ellipse->brush(), QBrush(Qt::blue));
1128 QCOMPARE(ellipse->rect(), QRectF(-10, -10, 20, 20));
1129 QCOMPARE(scene.itemAt(0, 0), (QGraphicsItem *)ellipse);
1130 QCOMPARE(scene.itemAt(-10, -10), (QGraphicsItem *)0);
1131 QCOMPARE(scene.itemAt(-9.9, 0), (QGraphicsItem *)ellipse);
1132 QCOMPARE(scene.itemAt(-10, 10), (QGraphicsItem *)0);
1133 QCOMPARE(scene.itemAt(0, -9.9), (QGraphicsItem *)ellipse);
1134 QCOMPARE(scene.itemAt(0, 9.9), (QGraphicsItem *)ellipse);
1135 QCOMPARE(scene.itemAt(10, -10), (QGraphicsItem *)0);
1136 QCOMPARE(scene.itemAt(9.9, 0), (QGraphicsItem *)ellipse);
1137 QCOMPARE(scene.itemAt(10, 10), (QGraphicsItem *)0);
1140 void tst_QGraphicsScene::addLine()
1142 QGraphicsScene scene;
1145 QGraphicsLineItem *line = scene.addLine(QLineF(-10, -10, 20, 20),
1147 QCOMPARE(line->pos(), QPointF());
1148 QCOMPARE(line->pen(), pen);
1149 QCOMPARE(line->line(), QLineF(-10, -10, 20, 20));
1150 QCOMPARE(scene.itemAt(0, 0), (QGraphicsItem *)line);
1151 QCOMPARE(scene.itemAt(-10, -10), (QGraphicsItem *)line);
1152 QCOMPARE(scene.itemAt(-9.9, 0), (QGraphicsItem *)0);
1153 QCOMPARE(scene.itemAt(-10, 10), (QGraphicsItem *)0);
1154 QCOMPARE(scene.itemAt(0, -9.9), (QGraphicsItem *)0);
1155 QCOMPARE(scene.itemAt(0, 9.9), (QGraphicsItem *)0);
1156 QCOMPARE(scene.itemAt(10, -10), (QGraphicsItem *)0);
1157 QCOMPARE(scene.itemAt(9.9, 0), (QGraphicsItem *)0);
1158 QCOMPARE(scene.itemAt(10, 10), (QGraphicsItem *)line);
1161 void tst_QGraphicsScene::addPath()
1163 QGraphicsScene scene;
1165 p.addEllipse(QRectF(-10, -10, 20, 20));
1166 p.addEllipse(QRectF(-10, 20, 20, 20));
1168 QGraphicsPathItem *path = scene.addPath(p, QPen(Qt::red), QBrush(Qt::blue));
1169 QCOMPARE(path->pos(), QPointF());
1170 QCOMPARE(path->pen(), QPen(Qt::red));
1171 QCOMPARE(path->path(), p);
1172 QCOMPARE(path->brush(), QBrush(Qt::blue));
1173 QCOMPARE(scene.itemAt(0, 0), (QGraphicsItem *)path);
1174 QCOMPARE(scene.itemAt(-9.9, 0), (QGraphicsItem *)path);
1175 QCOMPARE(scene.itemAt(9.9, 0), (QGraphicsItem *)path);
1176 QCOMPARE(scene.itemAt(0, -9.9), (QGraphicsItem *)path);
1177 QCOMPARE(scene.itemAt(0, 9.9), (QGraphicsItem *)path);
1178 QCOMPARE(scene.itemAt(0, 30), (QGraphicsItem *)path);
1179 QCOMPARE(scene.itemAt(-9.9, 30), (QGraphicsItem *)path);
1180 QCOMPARE(scene.itemAt(9.9, 30), (QGraphicsItem *)path);
1181 QCOMPARE(scene.itemAt(0, 20.1), (QGraphicsItem *)path);
1182 QCOMPARE(scene.itemAt(0, 39.9), (QGraphicsItem *)path);
1183 QCOMPARE(scene.itemAt(-10, -10), (QGraphicsItem *)0);
1184 QCOMPARE(scene.itemAt(10, -10), (QGraphicsItem *)0);
1185 QCOMPARE(scene.itemAt(-10, 10), (QGraphicsItem *)0);
1186 QCOMPARE(scene.itemAt(10, 10), (QGraphicsItem *)0);
1187 QCOMPARE(scene.itemAt(-10, 20), (QGraphicsItem *)0);
1188 QCOMPARE(scene.itemAt(10, 20), (QGraphicsItem *)0);
1189 if (sizeof(qreal) != sizeof(double))
1190 QWARN("Skipping test because of rounding errors when qreal != double");
1192 QCOMPARE(scene.itemAt(-10, 30), (QGraphicsItem *)0);
1193 QCOMPARE(scene.itemAt(10.1, 30), (QGraphicsItem *)0);
1196 void tst_QGraphicsScene::addPixmap()
1198 QGraphicsScene scene;
1199 QPixmap pix(":/Ash_European.jpg");
1200 QGraphicsPixmapItem *pixmap = scene.addPixmap(pix);
1202 QCOMPARE(pixmap->pos(), QPointF());
1203 QCOMPARE(pixmap->pixmap(), pix);
1204 QCOMPARE(scene.itemAt(0, 0), (QGraphicsItem *)pixmap);
1205 QCOMPARE(scene.itemAt(pix.width() - 1, 0), (QGraphicsItem *)pixmap);
1206 QCOMPARE(scene.itemAt(0, pix.height() - 1), (QGraphicsItem *)pixmap);
1207 QCOMPARE(scene.itemAt(pix.width() - 1, pix.height() - 1), (QGraphicsItem *)pixmap);
1208 QCOMPARE(scene.itemAt(-1, -1), (QGraphicsItem *)0);
1209 QCOMPARE(scene.itemAt(pix.width() - 1, -1), (QGraphicsItem *)0);
1210 QCOMPARE(scene.itemAt(-1, pix.height() - 1), (QGraphicsItem *)0);
1211 QCOMPARE(scene.itemAt(pix.width(), pix.height()), (QGraphicsItem *)0);
1212 QCOMPARE(scene.itemAt(0, pix.height()), (QGraphicsItem *)0);
1213 QCOMPARE(scene.itemAt(pix.width(), 0), (QGraphicsItem *)0);
1216 void tst_QGraphicsScene::addRect()
1218 QGraphicsScene scene;
1219 QGraphicsRectItem *rect = scene.addRect(QRectF(-10, -10, 20, 20),
1220 QPen(Qt::red), QBrush(Qt::blue));
1221 QCOMPARE(rect->pos(), QPointF());
1222 QCOMPARE(rect->pen(), QPen(Qt::red));
1223 QCOMPARE(rect->brush(), QBrush(Qt::blue));
1224 QCOMPARE(rect->rect(), QRectF(-10, -10, 20, 20));
1225 QCOMPARE(scene.itemAt(0, 0), (QGraphicsItem *)rect);
1226 QCOMPARE(scene.itemAt(-10, -10), (QGraphicsItem *)rect);
1227 QCOMPARE(scene.itemAt(-9.9, 0), (QGraphicsItem *)rect);
1228 QCOMPARE(scene.itemAt(-10, 10), (QGraphicsItem *)0);
1229 QCOMPARE(scene.itemAt(0, -9.9), (QGraphicsItem *)rect);
1230 QCOMPARE(scene.itemAt(0, 9.9), (QGraphicsItem *)rect);
1231 QCOMPARE(scene.itemAt(10, -10), (QGraphicsItem *)0);
1232 QCOMPARE(scene.itemAt(9.9, 0), (QGraphicsItem *)rect);
1233 QCOMPARE(scene.itemAt(10, 10), (QGraphicsItem *)0);
1236 void tst_QGraphicsScene::addText()
1238 QGraphicsScene scene;
1239 QGraphicsTextItem *text = scene.addText("Qt", QFont());
1240 QCOMPARE(text->pos(), QPointF());
1241 QCOMPARE(text->toPlainText(), QString("Qt"));
1242 QCOMPARE(text->font(), QFont());
1245 void tst_QGraphicsScene::removeItem()
1247 #if defined(Q_OS_WINCE) && !defined(GWES_ICONCURS)
1248 QSKIP("No mouse cursor support");
1250 QGraphicsScene scene;
1251 QGraphicsItem *item = scene.addRect(QRectF(0, 0, 10, 10));
1252 QCOMPARE(scene.itemAt(0, 0), item); // forces indexing
1253 scene.removeItem(item);
1254 QCOMPARE(scene.itemAt(0, 0), (QGraphicsItem *)0);
1257 QGraphicsItem *item2 = scene.addRect(QRectF(0, 0, 10, 10));
1258 item2->setFlag(QGraphicsItem::ItemIsSelectable);
1259 QCOMPARE(scene.itemAt(0, 0), item2);
1261 // Removing a selected item
1262 QVERIFY(scene.selectedItems().isEmpty());
1263 item2->setSelected(true);
1264 QVERIFY(scene.selectedItems().contains(item2));
1265 scene.removeItem(item2);
1266 QVERIFY(scene.selectedItems().isEmpty());
1268 // Check that we are in a state that can receive paint events
1269 // (i.e., not logged out on Windows).
1272 // Removing a hovered item
1273 HoverItem *hoverItem = new HoverItem;
1274 scene.addItem(hoverItem);
1275 scene.setSceneRect(-50, -50, 100, 100);
1277 QGraphicsView view(&scene);
1278 view.setFixedSize(150, 150);
1280 QApplication::setActiveWindow(&view);
1281 QVERIFY(QTest::qWaitForWindowActive(&view));
1282 QTest::mouseMove(view.viewport(), QPoint(-1, -1));
1284 QMouseEvent moveEvent(QEvent::MouseMove, view.mapFromScene(hoverItem->scenePos() + QPointF(20, 20)), Qt::NoButton, 0, 0);
1285 QApplication::sendEvent(view.viewport(), &moveEvent);
1287 qApp->processEvents(); // update
1288 qApp->processEvents(); // draw
1289 QVERIFY(!hoverItem->isHovered);
1293 QTest::mouseMove(view.viewport(), view.mapFromScene(hoverItem->scenePos()), Qt::NoButton);
1295 QMouseEvent moveEvent(QEvent::MouseMove, view.mapFromScene(hoverItem->scenePos()), Qt::NoButton, 0, 0);
1296 QApplication::sendEvent(view.viewport(), &moveEvent);
1298 qApp->processEvents(); // update
1299 qApp->processEvents(); // draw
1300 QVERIFY(hoverItem->isHovered);
1302 scene.removeItem(hoverItem);
1303 hoverItem->setAcceptsHoverEvents(false);
1304 scene.addItem(hoverItem);
1305 qApp->processEvents(); // <- delayed update is called
1306 qApp->processEvents(); // <- scene schedules pending update
1307 qApp->processEvents(); // <- pending update is sent to view
1308 QVERIFY(!hoverItem->isHovered);
1311 void tst_QGraphicsScene::focusItem()
1313 QGraphicsScene scene;
1314 QEvent activate(QEvent::WindowActivate);
1315 QApplication::sendEvent(&scene, &activate);
1317 QVERIFY(!scene.focusItem());
1318 QGraphicsItem *item = scene.addText("Qt");
1319 QVERIFY(!scene.focusItem());
1321 QVERIFY(!scene.focusItem());
1322 item->setFlag(QGraphicsItem::ItemIsFocusable);
1323 QVERIFY(!scene.focusItem());
1325 QCOMPARE(scene.focusItem(), item);
1327 QFocusEvent focusOut(QEvent::FocusOut);
1328 QApplication::sendEvent(&scene, &focusOut);
1330 QVERIFY(!scene.focusItem());
1332 QFocusEvent focusIn(QEvent::FocusIn);
1333 QApplication::sendEvent(&scene, &focusIn);
1334 QCOMPARE(scene.focusItem(), item);
1336 QGraphicsItem *item2 = scene.addText("Qt");
1337 item2->setFlag(QGraphicsItem::ItemIsFocusable);
1338 QCOMPARE(scene.focusItem(), item);
1341 QCOMPARE(scene.focusItem(), item2);
1343 QCOMPARE(scene.focusItem(), item);
1346 QCOMPARE(scene.focusItem(), item2);
1347 QApplication::sendEvent(&scene, &focusOut);
1348 QVERIFY(!scene.hasFocus());
1349 QVERIFY(!scene.focusItem());
1350 QApplication::sendEvent(&scene, &focusIn);
1351 QCOMPARE(scene.focusItem(), item2);
1353 QApplication::sendEvent(&scene, &focusOut);
1355 QVERIFY(!scene.focusItem());
1356 scene.removeItem(item2);
1359 QApplication::sendEvent(&scene, &focusIn);
1360 QVERIFY(!scene.focusItem());
1363 class FocusItem : public QGraphicsTextItem
1366 void focusOutEvent(QFocusEvent *)
1368 QVERIFY(!scene()->focusItem());
1372 void tst_QGraphicsScene::focusItemLostFocus()
1374 QGraphicsScene scene;
1375 QEvent activate(QEvent::WindowActivate);
1376 QApplication::sendEvent(&scene, &activate);
1378 FocusItem *item = new FocusItem;
1379 item->setTextInteractionFlags(Qt::TextEditorInteraction);
1380 scene.addItem(item);
1383 QCOMPARE(scene.focusItem(), (QGraphicsItem *)item);
1387 class ClearTestItem : public QGraphicsRectItem
1390 ClearTestItem(QGraphicsItem *parent = 0) : QGraphicsRectItem(parent) {}
1391 ~ClearTestItem() { qDeleteAll(items); }
1392 QList<QGraphicsItem *> items;
1395 void tst_QGraphicsScene::clear()
1397 QGraphicsScene scene;
1399 QVERIFY(scene.items().isEmpty());
1400 scene.addRect(0, 0, 100, 100);
1401 QCOMPARE(scene.sceneRect(), QRectF(0, 0, 100, 100));
1403 QVERIFY(scene.items().isEmpty());
1404 QCOMPARE(scene.sceneRect(), QRectF(0, 0, 100, 100));
1406 ClearTestItem *firstItem = new ClearTestItem;
1407 QGraphicsItem *secondItem = new QGraphicsRectItem;
1408 firstItem->items += secondItem;
1410 scene.setItemIndexMethod(QGraphicsScene::NoIndex);
1411 scene.addItem(firstItem);
1412 scene.addItem(secondItem);
1413 QCOMPARE(scene.items().at(0), (QGraphicsItem*)firstItem);
1414 QCOMPARE(scene.items().at(1), secondItem);
1416 ClearTestItem *thirdItem = new ClearTestItem(firstItem);
1417 QGraphicsItem *forthItem = new QGraphicsRectItem(firstItem);
1418 thirdItem->items += forthItem;
1420 // must not crash even if firstItem deletes secondItem
1422 QVERIFY(scene.items().isEmpty());
1425 void tst_QGraphicsScene::setFocusItem()
1427 QGraphicsScene scene;
1428 QEvent activate(QEvent::WindowActivate);
1429 QApplication::sendEvent(&scene, &activate);
1431 QGraphicsItem *item = scene.addText("Qt");
1432 QVERIFY(!scene.focusItem());
1433 QVERIFY(!scene.hasFocus());
1434 scene.setFocusItem(item);
1435 QVERIFY(!scene.hasFocus());
1436 QVERIFY(!scene.focusItem());
1437 item->setFlag(QGraphicsItem::ItemIsFocusable);
1439 for (int i = 0; i < 3; ++i) {
1440 scene.setFocusItem(item);
1441 QVERIFY(scene.hasFocus());
1442 QCOMPARE(scene.focusItem(), item);
1443 QVERIFY(item->hasFocus());
1446 QGraphicsItem *item2 = scene.addText("Qt");
1447 item2->setFlag(QGraphicsItem::ItemIsFocusable);
1449 scene.setFocusItem(item2);
1450 QVERIFY(!item->hasFocus());
1451 QVERIFY(item2->hasFocus());
1453 scene.setFocusItem(item);
1454 QVERIFY(item->hasFocus());
1455 QVERIFY(!item2->hasFocus());
1458 QVERIFY(!item->hasFocus());
1459 QVERIFY(!item2->hasFocus());
1462 QVERIFY(item->hasFocus());
1463 QVERIFY(!item2->hasFocus());
1465 scene.setFocusItem(0);
1466 QVERIFY(!item->hasFocus());
1467 QVERIFY(!item2->hasFocus());
1470 QVERIFY(!item->hasFocus());
1471 QVERIFY(!item2->hasFocus());
1474 void tst_QGraphicsScene::setFocusItem_inactive()
1476 QGraphicsScene scene;
1477 QGraphicsItem *item = scene.addText("Qt");
1478 QVERIFY(!scene.focusItem());
1479 QVERIFY(!scene.hasFocus());
1480 scene.setFocusItem(item);
1481 QVERIFY(!scene.hasFocus());
1482 QVERIFY(!scene.focusItem());
1483 item->setFlag(QGraphicsItem::ItemIsFocusable);
1485 for (int i = 0; i < 3; ++i) {
1486 scene.setFocusItem(item);
1487 QCOMPARE(scene.focusItem(), item);
1488 QVERIFY(!item->hasFocus());
1494 void tst_QGraphicsScene::mouseGrabberItem()
1496 QGraphicsScene scene;
1497 QVERIFY(!scene.mouseGrabberItem());
1499 QGraphicsItem *item = scene.addRect(QRectF(-10, -10, 20, 20));
1500 item->setFlag(QGraphicsItem::ItemIsMovable);
1503 QGraphicsItem *item2 = scene.addRect(QRectF(-10, -10, 20, 20));
1504 item2->setFlag(QGraphicsItem::ItemIsMovable);
1505 item2->setZValue(0);
1507 for (int i = 0; i < 3; ++i) {
1509 item2->setPos(0, 0);
1510 item->setZValue((i & 1) ? 0 : 1);
1511 item2->setZValue((i & 1) ? 1 : 0);
1512 QGraphicsItem *topMostItem = (i & 1) ? item2 : item;
1514 QGraphicsSceneMouseEvent pressEvent(QEvent::GraphicsSceneMousePress);
1515 pressEvent.setButton(Qt::LeftButton);
1516 pressEvent.setScenePos(QPointF(0, 0));
1517 pressEvent.setScreenPos(QPoint(100, 100));
1519 QApplication::sendEvent(&scene, &pressEvent);
1520 QCOMPARE(scene.mouseGrabberItem(), topMostItem);
1522 for (int i = 0; i < 1000; ++i) {
1523 QGraphicsSceneMouseEvent moveEvent(QEvent::GraphicsSceneMouseMove);
1524 moveEvent.setButtons(Qt::LeftButton);
1525 moveEvent.setScenePos(QPointF(i * 10, i * 10));
1526 moveEvent.setScreenPos(QPoint(100 + i * 10, 100 + i * 10));
1527 QApplication::sendEvent(&scene, &moveEvent);
1528 QCOMPARE(scene.mouseGrabberItem(), topMostItem);
1530 // Geometrical changes should not affect the mouse grabber.
1531 item->setZValue(rand() % 500);
1532 item2->setZValue(rand() % 500);
1533 item->setPos(rand() % 50000, rand() % 50000);
1534 item2->setPos(rand() % 50000, rand() % 50000);
1537 QGraphicsSceneMouseEvent releaseEvent(QEvent::GraphicsSceneMouseRelease);
1538 releaseEvent.setScenePos(QPointF(10000, 10000));
1539 releaseEvent.setScreenPos(QPoint(1000000, 1000000));
1540 QApplication::sendEvent(&scene, &releaseEvent);
1541 QVERIFY(!scene.mouseGrabberItem());
1544 // Structural change: deleting the mouse grabber
1547 item2->setPos(0, 0);
1548 item2->setZValue(0);
1549 QGraphicsSceneMouseEvent pressEvent(QEvent::GraphicsSceneMousePress);
1550 pressEvent.setButton(Qt::LeftButton);
1551 pressEvent.setScenePos(QPointF(0, 0));
1552 pressEvent.setScreenPos(QPoint(100, 100));
1554 QGraphicsSceneMouseEvent moveEvent(QEvent::GraphicsSceneMouseMove);
1555 moveEvent.setButtons(Qt::LeftButton);
1556 moveEvent.setScenePos(QPointF(0, 0));
1557 moveEvent.setScreenPos(QPoint(100, 100));
1559 QApplication::sendEvent(&scene, &pressEvent);
1560 QApplication::sendEvent(&scene, &moveEvent);
1561 QCOMPARE(scene.mouseGrabberItem(), item);
1562 item->setVisible(false);
1563 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
1564 QApplication::sendEvent(&scene, &pressEvent);
1565 QCOMPARE(scene.mouseGrabberItem(), item2);
1566 item2->setVisible(false);
1567 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
1568 QApplication::sendEvent(&scene, &moveEvent);
1569 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
1570 item2->setVisible(true);
1571 QApplication::sendEvent(&scene, &moveEvent);
1572 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
1573 QApplication::sendEvent(&scene, &pressEvent);
1574 QApplication::sendEvent(&scene, &moveEvent);
1575 QCOMPARE(scene.mouseGrabberItem(), item2);
1576 scene.removeItem(item2);
1578 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
1581 void tst_QGraphicsScene::hoverEvents_siblings()
1585 QGraphicsScene scene;
1586 QGraphicsItem *lastItem = 0;
1587 QList<HoverItem *> items;
1588 for (int i = 0; i < 15; ++i) {
1589 QGraphicsItem *item = new HoverItem;
1590 scene.addItem(item);
1591 items << (HoverItem *)item;
1593 item->setPos(lastItem->pos() + QPointF(sin(i / 3.0) * 17, cos(i / 3.0) * 17));
1599 QGraphicsView view(&scene);
1600 view.setRenderHint(QPainter::Antialiasing, true);
1601 #if defined(Q_OS_WINCE)
1602 view.setMinimumSize(230, 200);
1604 view.setMinimumSize(400, 300);
1607 view.scale(1.7, 1.7);
1609 qApp->setActiveWindow(&view);
1610 view.activateWindow();
1611 QVERIFY(QTest::qWaitForWindowActive(&view));
1613 QCursor::setPos(view.mapToGlobal(QPoint(-5, -5)));
1615 QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMouseMove);
1616 mouseEvent.setScenePos(QPointF(-1000, -1000));
1617 QApplication::sendEvent(&scene, &mouseEvent);
1621 for (int j = 1; j >= 0; --j) {
1625 QVERIFY(!items.at(i)->isHovered);
1627 QVERIFY(!items.at(i)->isHovered);
1628 QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMouseMove);
1629 mouseEvent.setScenePos(items.at(i)->mapToScene(0, 0));
1630 QApplication::sendEvent(&scene, &mouseEvent);
1632 qApp->processEvents(); // this posts updates from the scene to the view
1633 qApp->processEvents(); // which trigger a repaint here
1635 QTRY_VERIFY(items.at(i)->isHovered);
1637 QVERIFY(!items.at(i - 1)->isHovered);
1639 QVERIFY(!items.at(i + 1)->isHovered);
1641 if ((j && i == 15) || (!j && i == -1))
1645 QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMouseMove);
1646 mouseEvent.setScenePos(QPointF(-1000, -1000));
1647 QApplication::sendEvent(&scene, &mouseEvent);
1649 qApp->processEvents(); // this posts updates from the scene to the view
1650 qApp->processEvents(); // which trigger a repaint here
1654 void tst_QGraphicsScene::hoverEvents_parentChild()
1658 QGraphicsScene scene;
1659 QGraphicsItem *lastItem = 0;
1660 QList<HoverItem *> items;
1661 for (int i = 0; i < 15; ++i) {
1662 QGraphicsItem *item = new HoverItem;
1663 scene.addItem(item);
1664 items << (HoverItem *)item;
1666 item->setParentItem(lastItem);
1667 item->setPos(sin(i / 3.0) * 17, cos(i / 3.0) * 17);
1672 QGraphicsView view(&scene);
1673 view.setRenderHint(QPainter::Antialiasing, true);
1674 #if defined(Q_OS_WINCE)
1675 view.setMinimumSize(230, 200);
1677 view.setMinimumSize(400, 300);
1680 view.scale(1.7, 1.7);
1682 qApp->setActiveWindow(&view);
1683 QVERIFY(QTest::qWaitForWindowActive(&view));
1685 QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMouseMove);
1686 mouseEvent.setScenePos(QPointF(-1000, -1000));
1687 QApplication::sendEvent(&scene, &mouseEvent);
1689 for (int j = 1; j >= 0; --j) {
1693 QVERIFY(!items.at(i)->isHovered);
1696 QVERIFY(!items.at(13)->isHovered);
1698 mouseEvent.setScenePos(items.at(i)->mapToScene(0, 0));
1699 QApplication::sendEvent(&scene, &mouseEvent);
1701 qApp->processEvents(); // this posts updates from the scene to the view
1702 qApp->processEvents(); // which trigger a repaint here
1704 QTRY_VERIFY(items.at(i)->isHovered);
1706 QVERIFY(!items.at(i + 1)->isHovered);
1708 if ((j && i == 15) || (!j && i == -1))
1712 mouseEvent.setScenePos(QPointF(-1000, -1000));
1713 QApplication::sendEvent(&scene, &mouseEvent);
1715 qApp->processEvents(); // this posts updates from the scene to the view
1716 qApp->processEvents(); // which trigger a repaint here
1720 void tst_QGraphicsScene::createItemGroup()
1722 QGraphicsScene scene;
1724 QList<QGraphicsItem *> children1;
1725 children1 << scene.addRect(QRectF(-10, -10, 20, 20));
1726 children1 << scene.addRect(QRectF(-10, -10, 20, 20));
1727 children1 << scene.addRect(QRectF(-10, -10, 20, 20));
1728 children1 << scene.addRect(QRectF(-10, -10, 20, 20));
1730 QList<QGraphicsItem *> children2;
1731 children2 << scene.addRect(QRectF(-10, -10, 20, 20));
1732 children2 << scene.addRect(QRectF(-10, -10, 20, 20));
1733 children2 << scene.addRect(QRectF(-10, -10, 20, 20));
1734 children2 << scene.addRect(QRectF(-10, -10, 20, 20));
1736 QList<QGraphicsItem *> children3;
1737 children3 << scene.addRect(QRectF(-10, -10, 20, 20));
1738 children3 << scene.addRect(QRectF(-10, -10, 20, 20));
1739 children3 << scene.addRect(QRectF(-10, -10, 20, 20));
1740 children3 << scene.addRect(QRectF(-10, -10, 20, 20));
1742 // All items in children1 are children of parent1
1743 QGraphicsItem *parent1 = scene.addRect(QRectF(-10, -10, 20, 20));
1744 foreach (QGraphicsItem *item, children1)
1745 item->setParentItem(parent1);
1747 QGraphicsItemGroup *group = scene.createItemGroup(children1);
1748 QCOMPARE(group->parentItem(), parent1);
1749 QCOMPARE(children1.first()->parentItem(), (QGraphicsItem *)group);
1750 scene.destroyItemGroup(group);
1751 QCOMPARE(children1.first()->parentItem(), parent1);
1752 group = scene.createItemGroup(children1);
1753 QCOMPARE(group->parentItem(), parent1);
1754 QCOMPARE(children1.first()->parentItem(), (QGraphicsItem *)group);
1755 scene.destroyItemGroup(group);
1756 QCOMPARE(children1.first()->parentItem(), parent1);
1758 // All items in children2 are children of parent2
1759 QGraphicsItem *parent2 = scene.addRect(QRectF(-10, -10, 20, 20));
1760 foreach (QGraphicsItem *item, children2)
1761 item->setParentItem(parent2);
1763 // Now make parent2 a child of parent1, so all children2 are also children
1765 parent2->setParentItem(parent1);
1767 // The children2 group should still have parent2 as their common ancestor.
1768 group = scene.createItemGroup(children2);
1769 QCOMPARE(group->parentItem(), parent2);
1770 QCOMPARE(children2.first()->parentItem(), (QGraphicsItem *)group);
1771 scene.destroyItemGroup(group);
1772 QCOMPARE(children2.first()->parentItem(), parent2);
1774 // But the set of both children2 and children1 share only parent1.
1775 group = scene.createItemGroup(children2 + children1);
1776 QCOMPARE(group->parentItem(), parent1);
1777 QCOMPARE(children1.first()->parentItem(), (QGraphicsItem *)group);
1778 QCOMPARE(children2.first()->parentItem(), (QGraphicsItem *)group);
1779 scene.destroyItemGroup(group);
1780 QCOMPARE(children1.first()->parentItem(), parent1);
1781 QCOMPARE(children2.first()->parentItem(), parent1);
1783 // Fixup the parent-child chain
1784 foreach (QGraphicsItem *item, children2)
1785 item->setParentItem(parent2);
1787 // These share no common parent
1788 group = scene.createItemGroup(children3);
1789 QCOMPARE(group->parentItem(), (QGraphicsItem *)0);
1790 scene.destroyItemGroup(group);
1792 // Make children3 children of parent3
1793 QGraphicsItem *parent3 = scene.addRect(QRectF(-10, -10, 20, 20));
1794 foreach (QGraphicsItem *item, children3)
1795 item->setParentItem(parent3);
1797 // These should have parent3 as a parent
1798 group = scene.createItemGroup(children3);
1799 QCOMPARE(group->parentItem(), parent3);
1800 scene.destroyItemGroup(group);
1802 // Now make them all children of parent1
1803 parent3->setParentItem(parent1);
1805 group = scene.createItemGroup(children3);
1806 QCOMPARE(group->parentItem(), parent3);
1807 scene.destroyItemGroup(group);
1809 group = scene.createItemGroup(children2);
1810 QCOMPARE(group->parentItem(), parent2);
1811 scene.destroyItemGroup(group);
1813 group = scene.createItemGroup(children1);
1814 QCOMPARE(group->parentItem(), parent1);
1815 scene.destroyItemGroup(group);
1817 QGraphicsItemGroup *emptyGroup = scene.createItemGroup(QList<QGraphicsItem *>());
1818 QCOMPARE(emptyGroup->children(), QList<QGraphicsItem *>());
1819 QVERIFY(!emptyGroup->parentItem());
1820 QCOMPARE(emptyGroup->scene(), &scene);
1823 class EventTester : public QGraphicsEllipseItem
1827 : QGraphicsEllipseItem(QRectF(-10, -10, 20, 20)), ignoreMouse(false)
1831 QList<QEvent::Type> eventTypes;
1834 bool sceneEvent(QEvent *event)
1836 eventTypes << QEvent::Type(event->type());
1837 switch (event->type()) {
1838 case QEvent::GraphicsSceneMousePress:
1839 case QEvent::GraphicsSceneMouseMove:
1840 case QEvent::GraphicsSceneMouseRelease:
1849 return QGraphicsEllipseItem::sceneEvent(event);
1853 void tst_QGraphicsScene::mouseEventPropagation()
1855 EventTester *a = new EventTester;
1856 EventTester *b = new EventTester;
1857 EventTester *c = new EventTester;
1858 EventTester *d = new EventTester;
1859 b->setParentItem(a);
1860 c->setParentItem(b);
1861 d->setParentItem(c);
1863 a->setFlag(QGraphicsItem::ItemIsMovable);
1864 b->setFlag(QGraphicsItem::ItemIsMovable);
1865 c->setFlag(QGraphicsItem::ItemIsMovable);
1866 d->setFlag(QGraphicsItem::ItemIsMovable);
1873 // scene -> a -> b -> c -> d
1874 QGraphicsScene scene;
1875 QEvent activate(QEvent::WindowActivate);
1876 QApplication::sendEvent(&scene, &activate);
1880 // Prepare some events
1881 QGraphicsSceneMouseEvent pressEvent(QEvent::GraphicsSceneMousePress);
1882 pressEvent.setButton(Qt::LeftButton);
1883 pressEvent.setScenePos(QPointF(0, 0));
1884 QGraphicsSceneMouseEvent moveEvent(QEvent::GraphicsSceneMouseMove);
1885 moveEvent.setButton(Qt::LeftButton);
1886 moveEvent.setScenePos(QPointF(0, 0));
1887 QGraphicsSceneMouseEvent releaseEvent(QEvent::GraphicsSceneMouseRelease);
1888 releaseEvent.setButton(Qt::LeftButton);
1889 releaseEvent.setScenePos(QPointF(0, 0));
1892 QApplication::sendEvent(&scene, &pressEvent);
1893 QCOMPARE(d->eventTypes.size(), 2);
1894 QCOMPARE(d->eventTypes.at(0), QEvent::GrabMouse);
1895 QCOMPARE(d->eventTypes.at(1), QEvent::GraphicsSceneMousePress);
1896 QCOMPARE(c->eventTypes.size(), 0);
1897 QCOMPARE(b->eventTypes.size(), 0);
1898 QCOMPARE(a->eventTypes.size(), 0);
1899 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)d);
1902 QApplication::sendEvent(&scene, &moveEvent);
1903 QCOMPARE(d->eventTypes.size(), 3);
1904 QCOMPARE(d->eventTypes.at(2), QEvent::GraphicsSceneMouseMove);
1905 QCOMPARE(c->eventTypes.size(), 0);
1906 QCOMPARE(b->eventTypes.size(), 0);
1907 QCOMPARE(a->eventTypes.size(), 0);
1908 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)d);
1911 QApplication::sendEvent(&scene, &releaseEvent);
1912 QCOMPARE(d->eventTypes.size(), 5);
1913 QCOMPARE(d->eventTypes.at(3), QEvent::GraphicsSceneMouseRelease);
1914 QCOMPARE(d->eventTypes.at(4), QEvent::UngrabMouse);
1915 QCOMPARE(c->eventTypes.size(), 0);
1916 QCOMPARE(b->eventTypes.size(), 0);
1917 QCOMPARE(a->eventTypes.size(), 0);
1918 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
1920 d->setAcceptedMouseButtons(Qt::RightButton);
1923 QApplication::sendEvent(&scene, &pressEvent);
1924 QCOMPARE(d->eventTypes.size(), 5);
1925 QCOMPARE(c->eventTypes.size(), 2);
1926 QCOMPARE(c->eventTypes.at(0), QEvent::GrabMouse);
1927 QCOMPARE(c->eventTypes.at(1), QEvent::GraphicsSceneMousePress);
1928 QCOMPARE(b->eventTypes.size(), 0);
1929 QCOMPARE(a->eventTypes.size(), 0);
1930 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)c);
1932 // Send another press, with a button that isn't actually accepted
1933 QApplication::sendEvent(&scene, &pressEvent);
1934 pressEvent.setButton(Qt::RightButton);
1935 QCOMPARE(d->eventTypes.size(), 5);
1936 QCOMPARE(c->eventTypes.size(), 3);
1937 QCOMPARE(c->eventTypes.at(2), QEvent::GraphicsSceneMousePress);
1938 QCOMPARE(b->eventTypes.size(), 0);
1939 QCOMPARE(a->eventTypes.size(), 0);
1940 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)c);
1943 QApplication::sendEvent(&scene, &moveEvent);
1944 QCOMPARE(d->eventTypes.size(), 5);
1945 QCOMPARE(c->eventTypes.size(), 4);
1946 QCOMPARE(c->eventTypes.at(3), QEvent::GraphicsSceneMouseMove);
1947 QCOMPARE(b->eventTypes.size(), 0);
1948 QCOMPARE(a->eventTypes.size(), 0);
1949 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)c);
1952 QApplication::sendEvent(&scene, &releaseEvent);
1953 QCOMPARE(d->eventTypes.size(), 5);
1954 QCOMPARE(c->eventTypes.size(), 6);
1955 QCOMPARE(c->eventTypes.at(4), QEvent::GraphicsSceneMouseRelease);
1956 QCOMPARE(c->eventTypes.at(5), QEvent::UngrabMouse);
1957 QCOMPARE(b->eventTypes.size(), 0);
1958 QCOMPARE(a->eventTypes.size(), 0);
1959 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
1961 // Disabled items eat events. c should not get this.
1962 d->setEnabled(false);
1963 d->setAcceptedMouseButtons(Qt::RightButton);
1965 // Send a right press. This disappears in d.
1966 QApplication::sendEvent(&scene, &pressEvent);
1967 QCOMPARE(d->eventTypes.size(), 5);
1968 QCOMPARE(c->eventTypes.size(), 6);
1969 QCOMPARE(b->eventTypes.size(), 0);
1970 QCOMPARE(a->eventTypes.size(), 0);
1971 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
1973 // Send a left press. This goes to c.
1974 pressEvent.setButton(Qt::LeftButton);
1975 QApplication::sendEvent(&scene, &pressEvent);
1976 QCOMPARE(d->eventTypes.size(), 5);
1977 QCOMPARE(c->eventTypes.size(), 8);
1978 QCOMPARE(c->eventTypes.at(6), QEvent::GrabMouse);
1979 QCOMPARE(c->eventTypes.at(7), QEvent::GraphicsSceneMousePress);
1980 QCOMPARE(b->eventTypes.size(), 0);
1981 QCOMPARE(a->eventTypes.size(), 0);
1982 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)c);
1984 // Clicking outside the items removes the mouse grabber
1987 void tst_QGraphicsScene::mouseEventPropagation_ignore()
1989 EventTester *a = new EventTester;
1990 EventTester *b = new EventTester;
1991 EventTester *c = new EventTester;
1992 EventTester *d = new EventTester;
1993 b->setParentItem(a);
1994 c->setParentItem(b);
1995 d->setParentItem(c);
1997 a->setFlags(QGraphicsItem::ItemIsMovable);
1998 b->setFlags(QGraphicsItem::ItemIsMovable);
1999 c->setFlags(QGraphicsItem::ItemIsMovable);
2000 d->setFlags(QGraphicsItem::ItemIsMovable);
2002 // scene -> a -> b -> c -> d
2003 QGraphicsScene scene;
2006 // Prepare some events
2007 QGraphicsSceneMouseEvent pressEvent(QEvent::GraphicsSceneMousePress);
2008 pressEvent.setButton(Qt::LeftButton);
2009 pressEvent.setScenePos(QPointF(0, 0));
2011 b->ignoreMouse = true;
2012 c->ignoreMouse = true;
2013 d->ignoreMouse = true;
2015 QApplication::sendEvent(&scene, &pressEvent);
2016 QCOMPARE(a->eventTypes.size(), 2);
2017 QCOMPARE(a->eventTypes.at(0), QEvent::GrabMouse);
2018 QCOMPARE(a->eventTypes.at(1), QEvent::GraphicsSceneMousePress);
2019 QCOMPARE(b->eventTypes.size(), 3);
2020 QCOMPARE(b->eventTypes.at(0), QEvent::GrabMouse);
2021 QCOMPARE(b->eventTypes.at(1), QEvent::GraphicsSceneMousePress);
2022 QCOMPARE(b->eventTypes.at(2), QEvent::UngrabMouse);
2023 QCOMPARE(c->eventTypes.size(), 3);
2024 QCOMPARE(c->eventTypes.at(0), QEvent::GrabMouse);
2025 QCOMPARE(c->eventTypes.at(1), QEvent::GraphicsSceneMousePress);
2026 QCOMPARE(c->eventTypes.at(2), QEvent::UngrabMouse);
2027 QCOMPARE(d->eventTypes.size(), 3);
2028 QCOMPARE(d->eventTypes.at(0), QEvent::GrabMouse);
2029 QCOMPARE(d->eventTypes.at(1), QEvent::GraphicsSceneMousePress);
2030 QCOMPARE(d->eventTypes.at(2), QEvent::UngrabMouse);
2031 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)a);
2033 a->ignoreMouse = true;
2035 QApplication::sendEvent(&scene, &pressEvent);
2036 QCOMPARE(a->eventTypes.size(), 3);
2037 QCOMPARE(a->eventTypes.at(2), QEvent::GraphicsSceneMousePress);
2038 QCOMPARE(b->eventTypes.size(), 3);
2039 QCOMPARE(c->eventTypes.size(), 3);
2040 QCOMPARE(d->eventTypes.size(), 3);
2042 QVERIFY(!pressEvent.isAccepted());
2045 void tst_QGraphicsScene::mouseEventPropagation_focus()
2047 EventTester *a = new EventTester;
2048 EventTester *b = new EventTester;
2049 EventTester *c = new EventTester;
2050 EventTester *d = new EventTester;
2051 b->setParentItem(a);
2052 c->setParentItem(b);
2053 d->setParentItem(c);
2055 a->setFlag(QGraphicsItem::ItemIsMovable);
2056 b->setFlag(QGraphicsItem::ItemIsMovable);
2057 c->setFlag(QGraphicsItem::ItemIsMovable);
2058 d->setFlag(QGraphicsItem::ItemIsMovable);
2060 // scene -> a -> b -> c -> d
2061 QGraphicsScene scene;
2062 QEvent activate(QEvent::WindowActivate);
2063 QApplication::sendEvent(&scene, &activate);
2067 // Prepare some events
2068 QGraphicsSceneMouseEvent pressEvent(QEvent::GraphicsSceneMousePress);
2069 pressEvent.setButton(Qt::LeftButton);
2070 pressEvent.setScenePos(QPointF(0, 0));
2072 a->setFlag(QGraphicsItem::ItemIsFocusable);
2073 QVERIFY(!a->hasFocus());
2075 QApplication::sendEvent(&scene, &pressEvent);
2077 QVERIFY(a->hasFocus());
2078 QCOMPARE(a->eventTypes.size(), 1);
2079 QCOMPARE(a->eventTypes.first(), QEvent::FocusIn);
2080 QCOMPARE(d->eventTypes.size(), 2);
2081 QCOMPARE(d->eventTypes.at(0), QEvent::GrabMouse);
2082 QCOMPARE(d->eventTypes.at(1), QEvent::GraphicsSceneMousePress);
2085 void tst_QGraphicsScene::mouseEventPropagation_doubleclick()
2087 EventTester *a = new EventTester;
2088 EventTester *b = new EventTester;
2089 a->setFlags(QGraphicsItem::ItemIsMovable);
2090 b->setFlags(QGraphicsItem::ItemIsMovable);
2095 QGraphicsScene scene;
2099 // Prepare some events
2100 QGraphicsSceneMouseEvent pressEvent(QEvent::GraphicsSceneMousePress);
2101 pressEvent.setButton(Qt::LeftButton);
2102 pressEvent.setScenePos(QPointF(0, 0));
2103 QGraphicsSceneMouseEvent doubleClickEvent(QEvent::GraphicsSceneMouseDoubleClick);
2104 doubleClickEvent.setButton(Qt::LeftButton);
2105 doubleClickEvent.setScenePos(QPointF(0, 0));
2106 QGraphicsSceneMouseEvent releaseEvent(QEvent::GraphicsSceneMouseRelease);
2107 releaseEvent.setButton(Qt::LeftButton);
2108 releaseEvent.setScenePos(QPointF(0, 0));
2111 pressEvent.setScenePos(a->mapToScene(0, 0));
2112 QApplication::sendEvent(&scene, &pressEvent);
2113 QCOMPARE(a->eventTypes.size(), 2);
2114 QCOMPARE(a->eventTypes.at(0), QEvent::GrabMouse);
2115 QCOMPARE(a->eventTypes.at(1), QEvent::GraphicsSceneMousePress);
2117 // Send release to A
2118 releaseEvent.setScenePos(a->mapToScene(0, 0));
2119 QApplication::sendEvent(&scene, &releaseEvent);
2120 QCOMPARE(a->eventTypes.size(), 4);
2121 QCOMPARE(a->eventTypes.at(2), QEvent::GraphicsSceneMouseRelease);
2122 QCOMPARE(a->eventTypes.at(3), QEvent::UngrabMouse);
2124 // Send doubleclick to B
2125 doubleClickEvent.setScenePos(b->mapToScene(0, 0));
2126 QApplication::sendEvent(&scene, &doubleClickEvent);
2127 QCOMPARE(a->eventTypes.size(), 4);
2128 QCOMPARE(b->eventTypes.size(), 2);
2129 QCOMPARE(b->eventTypes.at(0), QEvent::GrabMouse);
2130 QCOMPARE(b->eventTypes.at(1), QEvent::GraphicsSceneMousePress);
2132 // Send release to B
2133 releaseEvent.setScenePos(b->mapToScene(0, 0));
2134 QApplication::sendEvent(&scene, &releaseEvent);
2135 QCOMPARE(a->eventTypes.size(), 4);
2136 QCOMPARE(b->eventTypes.size(), 4);
2137 QCOMPARE(b->eventTypes.at(2), QEvent::GraphicsSceneMouseRelease);
2138 QCOMPARE(b->eventTypes.at(3), QEvent::UngrabMouse);
2141 class Scene : public QGraphicsScene
2144 QVector<QPointF> mouseMovePoints;
2147 void mouseMoveEvent(QGraphicsSceneMouseEvent *event)
2149 mouseMovePoints << event->scenePos();
2153 void tst_QGraphicsScene::mouseEventPropagation_mouseMove()
2156 scene.addRect(QRectF(5, 0, 12, 12));
2157 scene.addRect(QRectF(15, 0, 12, 12))->setAcceptsHoverEvents(true);
2158 for (int i = 0; i < 30; ++i) {
2159 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseMove);
2160 event.setScenePos(QPointF(i, 5));
2161 QApplication::sendEvent(&scene, &event);
2164 QCOMPARE(scene.mouseMovePoints.size(), 30);
2165 for (int i = 0; i < 30; ++i)
2166 QCOMPARE(scene.mouseMovePoints.at(i), QPointF(i, 5));
2169 class DndTester : public QGraphicsEllipseItem
2172 DndTester(const QRectF &rect)
2173 : QGraphicsEllipseItem(rect), lastEvent(0),
2174 ignoresDragEnter(false), ignoresDragMove(false)
2184 QGraphicsSceneDragDropEvent *lastEvent;
2185 QList<QEvent::Type> eventList;
2186 bool ignoresDragEnter;
2187 bool ignoresDragMove;
2190 void dragEnterEvent(QGraphicsSceneDragDropEvent *event)
2192 storeLastEvent(event);
2193 event->setAccepted(!ignoresDragEnter);
2194 if (!ignoresDragEnter)
2195 event->setDropAction(Qt::IgnoreAction);
2196 eventList << event->type();
2199 void dragMoveEvent(QGraphicsSceneDragDropEvent *event)
2201 storeLastEvent(event);
2202 event->setAccepted(!ignoresDragMove);
2203 eventList << event->type();
2206 void dragLeaveEvent(QGraphicsSceneDragDropEvent *event)
2208 storeLastEvent(event);
2209 eventList << event->type();
2212 void dropEvent(QGraphicsSceneDragDropEvent *event)
2214 storeLastEvent(event);
2215 eventList << event->type();
2219 void storeLastEvent(QGraphicsSceneDragDropEvent *event)
2222 lastEvent = new QGraphicsSceneDragDropEvent(event->type());
2223 lastEvent->setScenePos(event->scenePos());
2224 lastEvent->setScreenPos(event->screenPos());
2225 lastEvent->setButtons(event->buttons());
2226 lastEvent->setModifiers(event->modifiers());
2227 lastEvent->setPossibleActions(event->possibleActions());
2228 lastEvent->setProposedAction(event->proposedAction());
2229 lastEvent->setDropAction(event->dropAction());
2230 lastEvent->setMimeData(event->mimeData());
2231 lastEvent->setWidget(event->widget());
2232 lastEvent->setSource(event->source());
2236 #ifndef QT_NO_DRAGANDDROP
2237 void tst_QGraphicsScene::dragAndDrop_simple()
2239 DndTester *item = new DndTester(QRectF(-10, -10, 20, 20));
2241 QGraphicsScene scene;
2242 scene.addItem(item);
2244 QGraphicsView view(&scene);
2245 view.setFixedSize(100, 100);
2249 // Initial drag enter for the scene
2250 QDragEnterEvent dragEnter(QPoint(0, 0), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
2251 QApplication::sendEvent(view.viewport(), &dragEnter);
2252 QVERIFY(dragEnter.isAccepted());
2253 QCOMPARE(dragEnter.dropAction(), Qt::CopyAction);
2256 // Move outside the item
2257 QDragMoveEvent dragMove(QPoint(0, 0), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
2258 QApplication::sendEvent(view.viewport(), &dragMove);
2259 QVERIFY(!dragMove.isAccepted());
2260 QCOMPARE(dragMove.dropAction(), Qt::CopyAction);
2263 // Move inside the item without setAcceptDrops
2264 QDragMoveEvent dragMove(view.mapFromScene(item->scenePos()), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
2265 QApplication::sendEvent(view.viewport(), &dragMove);
2266 QVERIFY(!dragMove.isAccepted());
2267 QCOMPARE(dragMove.dropAction(), Qt::CopyAction);
2268 QCOMPARE(item->eventList.size(), 0);
2270 item->setAcceptDrops(true);
2272 // Move inside the item with setAcceptDrops
2273 QDragMoveEvent dragMove(view.mapFromScene(item->scenePos()), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
2274 QApplication::sendEvent(view.viewport(), &dragMove);
2275 QVERIFY(dragMove.isAccepted());
2276 QCOMPARE(dragMove.dropAction(), Qt::IgnoreAction);
2277 QCOMPARE(item->eventList.size(), 2);
2278 QCOMPARE(item->eventList.at(0), QEvent::GraphicsSceneDragEnter);
2279 QCOMPARE(item->eventList.at(1), QEvent::GraphicsSceneDragMove);
2280 QCOMPARE(item->lastEvent->screenPos(), view.mapToGlobal(dragMove.pos()));
2281 QCOMPARE(item->lastEvent->scenePos(), view.mapToScene(dragMove.pos()));
2282 QVERIFY(item->lastEvent->isAccepted());
2283 QCOMPARE(item->lastEvent->dropAction(), Qt::IgnoreAction);
2286 // Another move inside the item
2287 QDragMoveEvent dragMove(view.mapFromScene(item->mapToScene(5, 5)), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
2288 QApplication::sendEvent(view.viewport(), &dragMove);
2289 QVERIFY(dragMove.isAccepted());
2290 QCOMPARE(dragMove.dropAction(), Qt::IgnoreAction);
2291 QCOMPARE(item->eventList.size(), 3);
2292 QCOMPARE(item->eventList.at(2), QEvent::GraphicsSceneDragMove);
2293 QCOMPARE(item->lastEvent->screenPos(), view.mapToGlobal(dragMove.pos()));
2294 QCOMPARE(item->lastEvent->scenePos(), view.mapToScene(dragMove.pos()));
2295 QVERIFY(item->lastEvent->isAccepted());
2296 QCOMPARE(item->lastEvent->dropAction(), Qt::IgnoreAction);
2299 // Move outside the item
2300 QDragMoveEvent dragMove(QPoint(0, 0), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
2301 QApplication::sendEvent(view.viewport(), &dragMove);
2302 QVERIFY(!dragMove.isAccepted());
2303 QCOMPARE(dragMove.dropAction(), Qt::CopyAction);
2304 QCOMPARE(item->eventList.size(), 4);
2305 QCOMPARE(item->eventList.at(3), QEvent::GraphicsSceneDragLeave);
2306 QCOMPARE(item->lastEvent->screenPos(), view.mapToGlobal(dragMove.pos()));
2307 QCOMPARE(item->lastEvent->scenePos(), view.mapToScene(dragMove.pos()));
2308 QVERIFY(item->lastEvent->isAccepted());
2309 QCOMPARE(item->lastEvent->dropAction(), Qt::CopyAction);
2312 // Move inside the item again
2313 QDragMoveEvent dragMove(view.mapFromScene(item->scenePos()), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
2314 QApplication::sendEvent(view.viewport(), &dragMove);
2315 QVERIFY(dragMove.isAccepted());
2316 QCOMPARE(dragMove.dropAction(), Qt::IgnoreAction);
2317 QCOMPARE(item->eventList.size(), 6);
2318 QCOMPARE(item->eventList.at(4), QEvent::GraphicsSceneDragEnter);
2319 QCOMPARE(item->eventList.at(5), QEvent::GraphicsSceneDragMove);
2320 QCOMPARE(item->lastEvent->screenPos(), view.mapToGlobal(dragMove.pos()));
2321 QCOMPARE(item->lastEvent->scenePos(), view.mapToScene(dragMove.pos()));
2322 QVERIFY(item->lastEvent->isAccepted());
2323 QCOMPARE(item->lastEvent->dropAction(), Qt::IgnoreAction);
2326 // Drop inside the item
2327 QDropEvent drop(view.mapFromScene(item->scenePos()), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
2328 QApplication::sendEvent(view.viewport(), &drop);
2329 QVERIFY(drop.isAccepted());
2330 QCOMPARE(drop.dropAction(), Qt::CopyAction);
2331 QCOMPARE(item->eventList.size(), 7);
2332 QCOMPARE(item->eventList.at(6), QEvent::GraphicsSceneDrop);
2333 QCOMPARE(item->lastEvent->screenPos(), view.mapToGlobal(drop.pos()));
2334 QCOMPARE(item->lastEvent->scenePos(), view.mapToScene(drop.pos()));
2335 QVERIFY(item->lastEvent->isAccepted());
2336 QCOMPARE(item->lastEvent->dropAction(), Qt::CopyAction);
2340 void tst_QGraphicsScene::dragAndDrop_disabledOrInvisible()
2342 DndTester *item = new DndTester(QRectF(-10, -10, 20, 20));
2343 item->setAcceptDrops(true);
2345 QGraphicsScene scene;
2346 scene.addItem(item);
2348 QGraphicsView view(&scene);
2349 view.setFixedSize(100, 100);
2353 // Initial drag enter for the scene
2354 QDragEnterEvent dragEnter(QPoint(0, 0), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
2355 QApplication::sendEvent(view.viewport(), &dragEnter);
2356 QVERIFY(dragEnter.isAccepted());
2357 QCOMPARE(dragEnter.dropAction(), Qt::CopyAction);
2359 // Move inside the item
2360 QDragMoveEvent dragMove(view.mapFromScene(item->scenePos()), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
2361 QApplication::sendEvent(view.viewport(), &dragMove);
2362 QVERIFY(dragMove.isAccepted());
2363 QCOMPARE(dragMove.dropAction(), Qt::IgnoreAction);
2364 QCOMPARE(item->eventList.size(), 2);
2365 QCOMPARE(item->eventList.at(0), QEvent::GraphicsSceneDragEnter);
2366 QCOMPARE(item->eventList.at(1), QEvent::GraphicsSceneDragMove);
2369 // Move outside the item
2370 QDragMoveEvent dragMove(QPoint(0, 0), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
2371 QApplication::sendEvent(view.viewport(), &dragMove);
2372 QVERIFY(!dragMove.isAccepted());
2373 QCOMPARE(dragMove.dropAction(), Qt::CopyAction);
2374 QCOMPARE(item->eventList.size(), 3);
2375 QCOMPARE(item->eventList.at(2), QEvent::GraphicsSceneDragLeave);
2378 // Now disable the item
2379 item->setEnabled(false);
2380 QVERIFY(!item->isEnabled());
2381 QVERIFY(item->isVisible());
2384 // Move inside the item
2385 QDragMoveEvent dragMove(view.mapFromScene(item->scenePos()), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
2386 QApplication::sendEvent(view.viewport(), &dragMove);
2387 QVERIFY(!dragMove.isAccepted());
2388 QCOMPARE(dragMove.dropAction(), Qt::CopyAction);
2389 QCOMPARE(item->eventList.size(), 3);
2390 QCOMPARE(item->eventList.at(2), QEvent::GraphicsSceneDragLeave);
2393 // Reenable it, and make it invisible
2394 item->setEnabled(true);
2395 item->setVisible(false);
2396 QVERIFY(item->isEnabled());
2397 QVERIFY(!item->isVisible());
2400 // Move inside the item
2401 QDragMoveEvent dragMove(view.mapFromScene(item->scenePos()), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
2402 QApplication::sendEvent(view.viewport(), &dragMove);
2403 QVERIFY(!dragMove.isAccepted());
2404 QCOMPARE(dragMove.dropAction(), Qt::CopyAction);
2405 QCOMPARE(item->eventList.size(), 3);
2406 QCOMPARE(item->eventList.at(2), QEvent::GraphicsSceneDragLeave);
2409 // Dummy drop event to keep the Mac from crashing.
2410 QDropEvent dropEvent(QPoint(0, 0), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
2411 QApplication::sendEvent(view.viewport(), &dropEvent);
2414 void tst_QGraphicsScene::dragAndDrop_propagate()
2416 DndTester *item1 = new DndTester(QRectF(-10, -10, 20, 20));
2417 DndTester *item2 = new DndTester(QRectF(0, 0, 20, 20));
2418 item1->setAcceptDrops(true);
2419 item2->setAcceptDrops(true);
2420 item2->ignoresDragMove = true;
2421 item2->ignoresDragEnter = false;
2422 item2->setZValue(1);
2424 item1->setData(0, "item1");
2425 item2->setData(0, "item2");
2427 QGraphicsScene scene;
2428 scene.addItem(item1);
2429 scene.addItem(item2);
2431 QGraphicsView view(&scene);
2432 view.setFixedSize(100, 100);
2436 // Initial drag enter for the scene
2437 QDragEnterEvent dragEnter(QPoint(0, 0), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
2438 QApplication::sendEvent(view.viewport(), &dragEnter);
2439 QVERIFY(dragEnter.isAccepted());
2440 QCOMPARE(dragEnter.dropAction(), Qt::CopyAction);
2443 // Move outside the items
2444 QDragMoveEvent dragMove(QPoint(0, 0), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
2445 QApplication::sendEvent(view.viewport(), &dragMove);
2446 QVERIFY(!dragMove.isAccepted());
2447 QCOMPARE(dragMove.dropAction(), Qt::CopyAction);
2448 QVERIFY(item1->eventList.isEmpty());
2449 QVERIFY(item2->eventList.isEmpty());
2452 // Move inside item1
2453 QDragMoveEvent dragMove(view.mapFromScene(-5, -5), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
2454 QApplication::sendEvent(view.viewport(), &dragMove);
2455 QVERIFY(dragMove.isAccepted());
2456 QCOMPARE(dragMove.dropAction(), Qt::IgnoreAction);
2457 QCOMPARE(item1->eventList.size(), 2);
2458 QCOMPARE(item1->eventList.at(0), QEvent::GraphicsSceneDragEnter);
2459 QCOMPARE(item1->eventList.at(1), QEvent::GraphicsSceneDragMove);
2463 // Move into the intersection item1-item2
2464 QDragMoveEvent dragMove(view.mapFromScene(5, 5), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
2465 QApplication::sendEvent(view.viewport(), &dragMove);
2466 QVERIFY(!dragMove.isAccepted()); // move does not propagate, (ignoresDragMove = true)
2467 QCOMPARE(item1->eventList.size(), 3);
2468 QCOMPARE(item1->eventList.at(2), QEvent::GraphicsSceneDragLeave);
2469 QCOMPARE(item2->eventList.size(), 2);
2470 QCOMPARE(item2->eventList.at(0), QEvent::GraphicsSceneDragEnter);
2471 QCOMPARE(item2->eventList.at(1), QEvent::GraphicsSceneDragMove);
2474 // Move into the item2
2475 QDragMoveEvent dragMove(view.mapFromScene(15, 15), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
2476 QApplication::sendEvent(view.viewport(), &dragMove);
2477 QVERIFY(!dragMove.isAccepted());
2478 QCOMPARE(dragMove.dropAction(), Qt::CopyAction);
2479 QCOMPARE(item1->eventList.size(), 3);
2480 QCOMPARE(item2->eventList.size(), 3);
2481 QCOMPARE(item2->eventList.at(2), QEvent::GraphicsSceneDragMove);
2484 // Move inside item1
2485 QDragMoveEvent dragMove(view.mapFromScene(-5, -5), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
2486 QApplication::sendEvent(view.viewport(), &dragMove);
2487 QVERIFY(dragMove.isAccepted());
2488 QCOMPARE(dragMove.dropAction(), Qt::IgnoreAction);
2489 QCOMPARE(item1->eventList.size(), 5);
2490 QCOMPARE(item1->eventList.at(3), QEvent::GraphicsSceneDragEnter);
2491 QCOMPARE(item1->eventList.at(4), QEvent::GraphicsSceneDragMove);
2492 QCOMPARE(item2->eventList.size(), 4);
2493 QCOMPARE(item2->eventList.at(3), QEvent::GraphicsSceneDragLeave);
2497 item2->ignoresDragEnter = true;
2498 // Move into the intersection item1-item2
2499 QDragMoveEvent dragMove(view.mapFromScene(5, 5), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
2500 QApplication::sendEvent(view.viewport(), &dragMove);
2501 QVERIFY(dragMove.isAccepted()); // dragEnter propagates down to item1, which then accepts the move event.
2502 QCOMPARE(dragMove.dropAction(), Qt::IgnoreAction);
2503 QCOMPARE(item1->eventList.size(), 6);
2504 QCOMPARE(item1->eventList.at(5), QEvent::GraphicsSceneDragMove);
2505 QCOMPARE(item2->eventList.size(), 5);
2506 QCOMPARE(item2->eventList.at(4), QEvent::GraphicsSceneDragEnter);
2510 item2->ignoresDragEnter = false;
2511 // Drop on the intersection item1-item2
2512 QDropEvent drop(view.mapFromScene(5, 5), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
2513 QApplication::sendEvent(view.viewport(), &drop);
2514 QVERIFY(drop.isAccepted());
2515 QCOMPARE(drop.dropAction(), Qt::CopyAction);
2517 QCOMPARE(item1->eventList.size(), 7);
2518 QCOMPARE(item1->eventList.at(6), QEvent::GraphicsSceneDrop);
2519 QCOMPARE(item2->eventList.size(), 5);
2522 // Dummy drop event to keep the Mac from crashing.
2523 QDropEvent dropEvent(QPoint(0, 0), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
2524 QApplication::sendEvent(view.viewport(), &dropEvent);
2528 void tst_QGraphicsScene::render_data()
2530 QTest::addColumn<QRectF>("targetRect");
2531 QTest::addColumn<QRectF>("sourceRect");
2532 QTest::addColumn<Qt::AspectRatioMode>("aspectRatioMode");
2533 QTest::addColumn<QMatrix>("matrix");
2534 QTest::addColumn<QPainterPath>("clip");
2536 QPainterPath clip_rect;
2537 clip_rect.addRect(50, 100, 200, 150);
2539 QPainterPath clip_ellipse;
2540 clip_ellipse.addEllipse(100,50,150,200);
2542 QTest::newRow("all-all-untransformed") << QRectF() << QRectF()
2543 << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
2544 QTest::newRow("all-topleft-untransformed") << QRectF(0, 0, 150, 150)
2545 << QRectF() << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
2546 QTest::newRow("all-topright-untransformed") << QRectF(150, 0, 150, 150)
2547 << QRectF() << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
2548 QTest::newRow("all-bottomleft-untransformed") << QRectF(0, 150, 150, 150)
2549 << QRectF() << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
2550 QTest::newRow("all-bottomright-untransformed") << QRectF(150, 150, 150, 150)
2551 << QRectF() << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
2552 QTest::newRow("topleft-all-untransformed") << QRectF() << QRectF(-10, -10, 10, 10)
2553 << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
2554 QTest::newRow("topright-all-untransformed") << QRectF() << QRectF(0, -10, 10, 10)
2555 << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
2556 QTest::newRow("bottomleft-all-untransformed") << QRectF() << QRectF(-10, 0, 10, 10)
2557 << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
2558 QTest::newRow("bottomright-all-untransformed") << QRectF() << QRectF(0, 0, 10, 10)
2559 << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
2560 QTest::newRow("topleft-topleft-untransformed") << QRectF(0, 0, 150, 150) << QRectF(-10, -10, 10, 10)
2561 << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
2562 QTest::newRow("topright-topleft-untransformed") << QRectF(150, 0, 150, 150) << QRectF(-10, -10, 10, 10)
2563 << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
2564 QTest::newRow("bottomleft-topleft-untransformed") << QRectF(0, 150, 150, 150) << QRectF(-10, -10, 10, 10)
2565 << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
2566 QTest::newRow("bottomright-topleft-untransformed") << QRectF(150, 150, 150, 150) << QRectF(-10, -10, 10, 10)
2567 << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
2568 QTest::newRow("top-topleft-untransformed") << QRectF(0, 0, 300, 150) << QRectF(-10, -10, 10, 10)
2569 << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
2570 QTest::newRow("bottom-topleft-untransformed") << QRectF(0, 150, 300, 150) << QRectF(-10, -10, 10, 10)
2571 << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
2572 QTest::newRow("left-topleft-untransformed") << QRectF(0, 0, 150, 300) << QRectF(-10, -10, 10, 10)
2573 << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
2574 QTest::newRow("right-topleft-untransformed") << QRectF(150, 0, 150, 300) << QRectF(-10, -10, 10, 10)
2575 << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
2576 QTest::newRow("top-bottomright-untransformed") << QRectF(0, 0, 300, 150) << QRectF(0, 0, 10, 10)
2577 << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
2578 QTest::newRow("bottom-bottomright-untransformed") << QRectF(0, 150, 300, 150) << QRectF(0, 0, 10, 10)
2579 << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
2580 QTest::newRow("left-bottomright-untransformed") << QRectF(0, 0, 150, 300) << QRectF(0, 0, 10, 10)
2581 << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
2582 QTest::newRow("right-bottomright-untransformed") << QRectF(150, 0, 150, 300) << QRectF(0, 0, 10, 10)
2583 << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
2584 QTest::newRow("all-all-45-deg-right") << QRectF() << QRectF()
2585 << Qt::IgnoreAspectRatio << QMatrix().rotate(-45) << QPainterPath();
2586 QTest::newRow("all-all-45-deg-left") << QRectF() << QRectF()
2587 << Qt::IgnoreAspectRatio << QMatrix().rotate(45) << QPainterPath();
2588 QTest::newRow("all-all-scale-2x") << QRectF() << QRectF()
2589 << Qt::IgnoreAspectRatio << QMatrix().scale(2, 2) << QPainterPath();
2590 QTest::newRow("all-all-translate-50-0") << QRectF() << QRectF()
2591 << Qt::IgnoreAspectRatio << QMatrix().translate(50, 0) << QPainterPath();
2592 QTest::newRow("all-all-translate-0-50") << QRectF() << QRectF()
2593 << Qt::IgnoreAspectRatio << QMatrix().translate(0, 50) << QPainterPath();
2594 QTest::newRow("all-all-untransformed-clip-rect") << QRectF() << QRectF()
2595 << Qt::IgnoreAspectRatio << QMatrix() << clip_rect;
2596 QTest::newRow("all-all-untransformed-clip-ellipse") << QRectF() << QRectF()
2597 << Qt::IgnoreAspectRatio << QMatrix() << clip_ellipse;
2600 void tst_QGraphicsScene::render()
2602 QFETCH(QRectF, targetRect);
2603 QFETCH(QRectF, sourceRect);
2604 QFETCH(Qt::AspectRatioMode, aspectRatioMode);
2605 QFETCH(QMatrix, matrix);
2606 QFETCH(QPainterPath, clip);
2608 QPixmap pix(30, 30);
2612 QGraphicsScene scene(&view);
2613 scene.addEllipse(QRectF(-10, -10, 20, 20), QPen(Qt::black), QBrush(Qt::white));
2614 scene.addEllipse(QRectF(-2, -7, 4, 4), QPen(Qt::black), QBrush(Qt::yellow))->setZValue(1);
2615 QGraphicsPixmapItem *item = scene.addPixmap(pix);
2617 item->setOffset(QPointF(3, 3));
2620 scene.setSceneRect(scene.itemsBoundingRect());
2622 QImage bigImage(300, 300, QImage::Format_RGB32);
2624 QPainter painter(&bigImage);
2625 painter.setPen(Qt::lightGray);
2626 for (int i = 0; i <= 300; i += 25) {
2627 painter.drawLine(0, i, 300, i);
2628 painter.drawLine(i, 0, i, 300);
2630 painter.setPen(QPen(Qt::darkGray, 2));
2631 painter.drawLine(0, 150, 300, 150);
2632 painter.drawLine(150, 0, 150, 300);
2633 painter.setMatrix(matrix);
2634 if (!clip.isEmpty()) painter.setClipPath(clip);
2635 scene.render(&painter, targetRect, sourceRect, aspectRatioMode);
2638 const QString renderPath = QLatin1String(SRCDIR) + "/testData/render";
2639 QString fileName = renderPath + QString("/%1.png").arg(QTest::currentDataTag());
2640 QImage original(fileName);
2641 QVERIFY(!original.isNull());
2644 int wrongPixels = 0;
2645 for (int y = 0; y < original.height(); ++y) {
2646 for (int x = 0; x < original.width(); ++x) {
2647 if (bigImage.pixel(x, y) != original.pixel(x, y))
2652 // This is a pixmap compare test - because of rounding errors on diverse
2653 // platforms, and especially because tests are compiled in release mode,
2654 // we set a 95% acceptance threshold for comparing images. This number may
2655 // have to be adjusted if this test fails.
2656 qreal threshold = 0.95;
2657 qreal similarity = (1 - (wrongPixels / qreal(original.width() * original.height())));
2658 if (similarity < threshold) {
2661 QLabel *expectedLabel = new QLabel;
2662 expectedLabel->setPixmap(QPixmap::fromImage(original));
2664 QLabel *newLabel = new QLabel;
2665 newLabel->setPixmap(QPixmap::fromImage(bigImage));
2667 QGridLayout *gridLayout = new QGridLayout;
2668 gridLayout->addWidget(new QLabel(tr("MISMATCH: %1").arg(QTest::currentDataTag())), 0, 0, 1, 2);
2669 gridLayout->addWidget(new QLabel(tr("Current")), 1, 0);
2670 gridLayout->addWidget(new QLabel(tr("Expected")), 1, 1);
2671 gridLayout->addWidget(expectedLabel, 2, 1);
2672 gridLayout->addWidget(newLabel, 2, 0);
2675 widget.setLayout(gridLayout);
2678 QTestEventLoop::instance().enterLoop(1);
2680 QFAIL("Images are not identical.");
2683 qDebug() << "Updating" << QTest::currentDataTag() << ":" << bigImage.save(fileName, "png");
2688 void tst_QGraphicsScene::renderItemsWithNegativeWidthOrHeight()
2690 QGraphicsScene scene(0, 0, 150, 150);
2692 // Add item with negative width.
2693 QGraphicsRectItem *item1 = new QGraphicsRectItem(0, 0, -150, 50);
2694 item1->setBrush(Qt::red);
2695 item1->setPos(150, 50);
2696 scene.addItem(item1);
2698 // Add item with negative height.
2699 QGraphicsRectItem *item2 = new QGraphicsRectItem(0, 0, 50, -150);
2700 item2->setBrush(Qt::blue);
2701 item2->setPos(50, 150);
2702 scene.addItem(item2);
2704 QGraphicsView view(&scene);
2705 view.setFrameStyle(QFrame::NoFrame);
2706 view.resize(150, 150);
2708 QCOMPARE(view.viewport()->size(), QSize(150, 150));
2710 QImage expected(view.viewport()->size(), QImage::Format_RGB32);
2711 view.viewport()->render(&expected);
2713 // Make sure the scene background is the same as the viewport background.
2714 scene.setBackgroundBrush(view.viewport()->palette().brush(view.viewport()->backgroundRole()));
2715 QImage actual(150, 150, QImage::Format_RGB32);
2716 QPainter painter(&actual);
2717 scene.render(&painter);
2720 QCOMPARE(actual, expected);
2723 void tst_QGraphicsScene::contextMenuEvent()
2725 QGraphicsScene scene;
2726 QEvent activate(QEvent::WindowActivate);
2727 QApplication::sendEvent(&scene, &activate);
2729 EventTester *item = new EventTester;
2730 scene.addItem(item);
2731 item->setFlag(QGraphicsItem::ItemIsFocusable);
2734 QVERIFY(item->hasFocus());
2735 QVERIFY(scene.hasFocus());
2737 QGraphicsView view(&scene);
2739 view.activateWindow();
2740 QVERIFY(QTest::qWaitForWindowActive(&view));
2741 view.centerOn(item);
2744 QContextMenuEvent event(QContextMenuEvent::Keyboard, view.viewport()->rect().center(),
2745 view.mapToGlobal(view.viewport()->rect().center()));
2746 QApplication::sendEvent(view.viewport(), &event);
2747 QCOMPARE(item->eventTypes.last(), QEvent::GraphicsSceneContextMenu);
2751 class ContextMenuItem : public QGraphicsRectItem
2754 ContextMenuItem() : QGraphicsRectItem(0, 0, 100, 100)
2755 { setBrush(Qt::red); }
2758 void contextMenuEvent(QGraphicsSceneContextMenuEvent *)
2759 { /* just accept */ }
2762 void tst_QGraphicsScene::contextMenuEvent_ItemIgnoresTransformations()
2764 QGraphicsScene scene(0, 0, 200, 200);
2765 ContextMenuItem *item = new ContextMenuItem;
2766 item->setFlag(QGraphicsItem::ItemIgnoresTransformations);
2767 scene.addItem(item);
2770 QGraphicsView view(&scene, &topLevel);
2771 view.resize(200, 200);
2773 QVERIFY(QTest::qWaitForWindowExposed(&topLevel));
2777 QContextMenuEvent event(QContextMenuEvent::Keyboard, pos, view.viewport()->mapToGlobal(pos));
2779 QApplication::sendEvent(view.viewport(), &event);
2780 QVERIFY(event.isAccepted());
2783 QPoint pos(150, 150);
2784 QContextMenuEvent event(QContextMenuEvent::Keyboard, pos, view.viewport()->mapToGlobal(pos));
2786 QApplication::sendEvent(view.viewport(), &event);
2787 QVERIFY(!event.isAccepted());
2789 view.scale(1.5, 1.5);
2792 QContextMenuEvent event(QContextMenuEvent::Keyboard, pos, view.viewport()->mapToGlobal(pos));
2794 QApplication::sendEvent(view.viewport(), &event);
2795 QVERIFY(event.isAccepted());
2799 QContextMenuEvent event(QContextMenuEvent::Keyboard, pos, view.viewport()->mapToGlobal(pos));
2801 QApplication::sendEvent(view.viewport(), &event);
2802 QVERIFY(!event.isAccepted());
2806 void tst_QGraphicsScene::update()
2808 QGraphicsScene scene;
2810 QGraphicsRectItem *rect = new QGraphicsRectItem(0, 0, 100, 100);
2811 scene.addItem(rect);
2812 qApp->processEvents();
2813 rect->setPos(-100, -100);
2815 // This function forces indexing
2818 qRegisterMetaType<QList<QRectF> >("QList<QRectF>");
2819 QSignalSpy spy(&scene, SIGNAL(changed(QList<QRectF>)));
2821 // We update the scene.
2824 // This function forces a purge, which will post an update signal
2827 // This will process the pending update
2828 QApplication::instance()->processEvents();
2830 // Check that the update region is correct
2831 QCOMPARE(spy.count(), 1);
2833 foreach (QRectF rectF, qvariant_cast<QList<QRectF> >(spy.at(0).at(0)))
2835 QCOMPARE(region, QRectF(-100, -100, 200, 200));
2838 void tst_QGraphicsScene::update2()
2840 QGraphicsScene scene;
2841 scene.setSceneRect(-200, -200, 200, 200);
2843 view.setScene(&scene);
2845 qApp->setActiveWindow(&view);
2846 QVERIFY(QTest::qWaitForWindowActive(&view));
2847 QTRY_VERIFY(view.repaints >= 1);
2850 // Make sure QGraphicsScene::update only requires one event-loop iteration
2851 // before the view is updated.
2853 qApp->processEvents();
2854 QTRY_COMPARE(view.repaints, 1);
2857 // The same for partial scene updates.
2858 scene.update(QRectF(-100, -100, 100, 100));
2859 qApp->processEvents();
2860 QCOMPARE(view.repaints, 1);
2863 void tst_QGraphicsScene::views()
2865 QGraphicsScene scene;
2866 QGraphicsView view(&scene);
2868 QCOMPARE(scene.views().size(), 1);
2869 QCOMPARE(scene.views().at(0), &view);
2871 QGraphicsView view1(&scene);
2872 QCOMPARE(scene.views().size(), 2);
2873 QVERIFY(scene.views().contains(&view1));
2876 QCOMPARE(scene.views().size(), 1);
2877 QCOMPARE(scene.views().at(0), &view1);
2879 QGraphicsView *view2 = new QGraphicsView(&scene);
2880 QCOMPARE(scene.views().size(), 2);
2881 QCOMPARE(scene.views().at(0), &view1);
2882 QCOMPARE(scene.views().at(1), view2);
2886 QCOMPARE(scene.views().size(), 1);
2887 QCOMPARE(scene.views().at(0), &view1);
2890 class CustomScene : public QGraphicsScene
2893 CustomScene() : gotTimerEvent(false)
2898 void timerEvent(QTimerEvent *)
2900 gotTimerEvent = true;
2904 void tst_QGraphicsScene::event()
2906 // Test that QGraphicsScene properly propagates events to QObject.
2908 QTestEventLoop::instance().enterLoop(1);
2909 QVERIFY(scene.gotTimerEvent);
2912 class DisabledItemTester : public QGraphicsRectItem
2915 DisabledItemTester(const QRectF &rect, QGraphicsItem *parent = 0)
2916 : QGraphicsRectItem(rect, parent)
2919 QList<QEvent::Type> receivedSceneEvents;
2920 QList<QEvent::Type> receivedSceneEventFilters;
2923 bool sceneEventFilter(QGraphicsItem *watched, QEvent *event)
2925 receivedSceneEventFilters << event->type();
2926 return QGraphicsRectItem::sceneEventFilter(watched, event);
2929 bool sceneEvent(QEvent *event)
2931 receivedSceneEvents << event->type();
2932 return QGraphicsRectItem::sceneEvent(event);
2936 void tst_QGraphicsScene::eventsToDisabledItems()
2938 QGraphicsScene scene;
2940 DisabledItemTester *item1 = new DisabledItemTester(QRectF(-50, -50, 100, 100));
2941 DisabledItemTester *item2 = new DisabledItemTester(QRectF(-50, -50, 100, 100));
2942 item1->setZValue(1); // on top
2944 scene.addItem(item1);
2945 scene.addItem(item2);
2947 item1->installSceneEventFilter(item2);
2949 QVERIFY(item1->receivedSceneEvents.isEmpty());
2950 QVERIFY(item2->receivedSceneEvents.isEmpty());
2951 QVERIFY(item1->receivedSceneEventFilters.isEmpty());
2952 QVERIFY(item2->receivedSceneEventFilters.isEmpty());
2954 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
2955 event.setButton(Qt::LeftButton);
2956 QApplication::sendEvent(&scene, &event);
2958 // First item2 receives a scene event filter. Then item1 receives the
2959 // actual event. Finally the event propagates to item2. So both items
2960 // should have received the event, and item1 also got the filter.
2961 QCOMPARE(item1->receivedSceneEvents.size(), 3);
2962 QCOMPARE(item2->receivedSceneEvents.size(), 3);
2963 QCOMPARE(item1->receivedSceneEventFilters.size(), 0);
2964 QCOMPARE(item2->receivedSceneEventFilters.size(), 3);
2966 item1->receivedSceneEvents.clear();
2967 item1->receivedSceneEventFilters.clear();
2968 item2->receivedSceneEvents.clear();
2969 item2->receivedSceneEventFilters.clear();
2971 item1->setEnabled(false); // disable the topmost item, eat mouse events
2973 event.setButton(Qt::LeftButton);
2974 event.setAccepted(false);
2975 QApplication::sendEvent(&scene, &event);
2977 // Check that only item1 received anything - it only got the filter.
2978 QCOMPARE(item1->receivedSceneEvents.size(), 0);
2979 QCOMPARE(item2->receivedSceneEvents.size(), 0);
2980 QCOMPARE(item1->receivedSceneEventFilters.size(), 0);
2981 QCOMPARE(item2->receivedSceneEventFilters.size(), 3);
2984 class ExposedPixmapItem : public QGraphicsPixmapItem
2987 ExposedPixmapItem(QGraphicsItem *item = 0)
2988 : QGraphicsPixmapItem(item)
2991 void paint(QPainter *, const QStyleOptionGraphicsItem *option, QWidget *)
2993 exposed = option->exposedRect;
2999 void tst_QGraphicsScene::exposedRect()
3001 ExposedPixmapItem *item = new ExposedPixmapItem;
3002 item->setPixmap(QPixmap(":/Ash_European.jpg"));
3003 QGraphicsScene scene;
3004 scene.addItem(item);
3006 QCOMPARE(item->exposed, QRectF());
3008 QImage image(100, 100, QImage::Format_ARGB32_Premultiplied);
3009 QPainter painter(&image);
3011 scene.render(&painter);
3012 QCOMPARE(item->exposed, item->boundingRect());
3014 painter.rotate(180);
3015 painter.translate(100, 100);
3017 scene.render(&painter);
3018 QCOMPARE(item->exposed, item->boundingRect());
3021 void tst_QGraphicsScene::tabFocus_emptyScene()
3023 QGraphicsScene scene;
3024 QDial *dial1 = new QDial;
3025 QGraphicsView *view = new QGraphicsView(&scene);
3026 QDial *dial2 = new QDial;
3028 QHBoxLayout *layout = new QHBoxLayout;
3029 layout->addWidget(dial1);
3030 layout->addWidget(view);
3031 layout->addWidget(dial2);
3034 widget.setLayout(layout);
3036 qApp->setActiveWindow(&widget);
3037 widget.activateWindow();
3038 QVERIFY(QTest::qWaitForWindowActive(&widget));
3041 QVERIFY(dial1->hasFocus());
3042 QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
3043 QVERIFY(!dial1->hasFocus());
3044 QVERIFY(view->hasFocus());
3045 QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
3046 QVERIFY(!view->hasFocus());
3047 QVERIFY(dial2->hasFocus());
3048 QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
3049 QVERIFY(!dial2->hasFocus());
3050 QVERIFY(view->hasFocus());
3051 QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
3052 QVERIFY(dial1->hasFocus());
3053 QVERIFY(!dial2->hasFocus());
3056 void tst_QGraphicsScene::tabFocus_sceneWithFocusableItems()
3058 QGraphicsScene scene;
3059 QGraphicsTextItem *item = scene.addText("Qt rocks!");
3060 item->setTabChangesFocus(true);
3061 item->setTextInteractionFlags(Qt::TextEditorInteraction);
3062 QVERIFY(item->flags() & QGraphicsItem::ItemIsFocusable);
3066 QGraphicsTextItem *item2 = scene.addText("Qt rocks!");
3067 item2->setTabChangesFocus(true);
3068 item2->setTextInteractionFlags(Qt::TextEditorInteraction);
3069 item2->setPos(0, item->boundingRect().bottom());
3070 QVERIFY(item2->flags() & QGraphicsItem::ItemIsFocusable);
3072 QDial *dial1 = new QDial;
3073 QGraphicsView *view = new QGraphicsView(&scene);
3074 QDial *dial2 = new QDial;
3076 QHBoxLayout *layout = new QHBoxLayout;
3077 layout->addWidget(dial1);
3078 layout->addWidget(view);
3079 layout->addWidget(dial2);
3082 widget.setLayout(layout);
3084 qApp->setActiveWindow(&widget);
3085 widget.activateWindow();
3086 QVERIFY(QTest::qWaitForWindowActive(&widget));
3089 QTRY_VERIFY(dial1->hasFocus());
3090 QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
3091 QApplication::processEvents();
3092 QTRY_VERIFY(view->hasFocus());
3093 QVERIFY(view->viewport()->hasFocus());
3094 QVERIFY(scene.hasFocus());
3095 QVERIFY(item->hasFocus());
3097 QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
3098 QApplication::processEvents();
3099 QTRY_VERIFY(dial2->hasFocus());
3101 QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
3102 QApplication::processEvents();
3103 QTRY_VERIFY(view->hasFocus());
3104 QTRY_VERIFY(view->viewport()->hasFocus());
3105 QTRY_VERIFY(scene.hasFocus());
3106 QTRY_VERIFY(item->hasFocus());
3108 QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
3109 QApplication::processEvents();
3110 QTRY_VERIFY(dial1->hasFocus());
3112 // If the item requests input focus, it can only ensure that the scene
3113 // sets focus on itself, but the scene cannot request focus from any view.
3115 QApplication::processEvents();
3116 QTRY_VERIFY(!view->hasFocus());
3117 QVERIFY(!view->viewport()->hasFocus());
3118 QTRY_VERIFY(scene.hasFocus());
3119 QVERIFY(item->hasFocus());
3122 QApplication::processEvents();
3123 QTRY_VERIFY(view->hasFocus());
3124 QTRY_VERIFY(view->viewport()->hasFocus());
3125 QTRY_VERIFY(scene.hasFocus());
3126 QTRY_VERIFY(item->hasFocus());
3128 // Check that everyone loses focus when the widget is hidden.
3131 QTRY_VERIFY(!view->hasFocus());
3132 QVERIFY(!view->viewport()->hasFocus());
3133 QVERIFY(!scene.hasFocus());
3134 QVERIFY(!item->hasFocus());
3135 QCOMPARE(scene.focusItem(), static_cast<QGraphicsItem *>(item));
3137 // Check that the correct item regains focus.
3139 qApp->setActiveWindow(&widget);
3140 widget.activateWindow();
3141 QVERIFY(QTest::qWaitForWindowActive(&widget));
3142 QVERIFY(view->hasFocus());
3143 QTRY_VERIFY(scene.isActive());
3144 QVERIFY(view->viewport()->hasFocus());
3145 QVERIFY(scene.hasFocus());
3146 QCOMPARE(scene.focusItem(), static_cast<QGraphicsItem *>(item));
3147 QVERIFY(item->hasFocus());
3150 class FocusWidget : public QGraphicsWidget
3154 FocusWidget(QGraphicsItem *parent = 0)
3155 : QGraphicsWidget(parent), tabs(0), backTabs(0)
3157 setFocusPolicy(Qt::StrongFocus);
3161 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *)
3163 if (option->state & QStyle::State_HasFocus) {
3164 painter->fillRect(rect(), Qt::blue);
3166 painter->setBrush(Qt::green);
3167 painter->drawEllipse(rect());
3168 if (option->state & QStyle::State_HasFocus) {
3169 painter->setPen(QPen(Qt::black, 1, Qt::DashLine));
3170 painter->setBrush(Qt::NoBrush);
3171 painter->drawEllipse(rect().adjusted(5, 5, -5, -5));
3179 bool sceneEvent(QEvent *event)
3181 if (event->type() == QEvent::KeyPress) {
3182 QKeyEvent *k = static_cast<QKeyEvent *>(event);
3183 if (k->key() == Qt::Key_Tab)
3185 if (k->key() == Qt::Key_Backtab)
3188 return QGraphicsWidget::sceneEvent(event);
3191 void focusInEvent(QFocusEvent *)
3193 void focusOutEvent(QFocusEvent *)
3197 void tst_QGraphicsScene::tabFocus_sceneWithFocusWidgets()
3199 QGraphicsScene scene;
3201 FocusWidget *widget1 = new FocusWidget;
3202 FocusWidget *widget2 = new FocusWidget;
3203 widget2->setPos(widget1->boundingRect().right(), 0);
3204 scene.addItem(widget1);
3205 scene.addItem(widget2);
3207 QDial *dial1 = new QDial;
3208 QGraphicsView *view = new QGraphicsView(&scene);
3209 view->setRenderHint(QPainter::Antialiasing);
3210 QDial *dial2 = new QDial;
3212 QHBoxLayout *layout = new QHBoxLayout;
3213 layout->addWidget(dial1);
3214 layout->addWidget(view);
3215 layout->addWidget(dial2);
3218 widget.setLayout(layout);
3220 qApp->setActiveWindow(&widget);
3221 widget.activateWindow();
3222 QVERIFY(QTest::qWaitForWindowActive(&widget));
3225 QTRY_VERIFY(dial1->hasFocus());
3227 QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
3228 QApplication::processEvents();
3229 QTRY_VERIFY(view->hasFocus());
3230 QTRY_VERIFY(view->viewport()->hasFocus());
3231 QTRY_VERIFY(scene.hasFocus());
3232 QCOMPARE(widget1->tabs, 0);
3233 QVERIFY(widget1->hasFocus());
3234 QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
3235 QApplication::processEvents();
3236 QTRY_COMPARE(widget1->tabs, 1);
3237 QTRY_VERIFY(widget2->hasFocus());
3238 QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
3239 QApplication::processEvents();
3240 QTRY_COMPARE(widget2->tabs, 1);
3241 QTRY_VERIFY(dial2->hasFocus());
3242 QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
3243 QApplication::processEvents();
3244 QTRY_VERIFY(widget2->hasFocus());
3245 QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
3246 QApplication::processEvents();
3247 QTRY_COMPARE(widget2->backTabs, 1);
3248 QTRY_VERIFY(widget1->hasFocus());
3249 QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
3250 QApplication::processEvents();
3251 QTRY_COMPARE(widget1->backTabs, 1);
3252 QTRY_VERIFY(dial1->hasFocus());
3254 widget1->setFocus();
3255 view->viewport()->setFocus();
3259 qApp->setActiveWindow(&widget);
3260 widget.activateWindow();
3261 QVERIFY(QTest::qWaitForWindowActive(&widget));
3262 QTRY_VERIFY(widget1->hasFocus());
3265 void tst_QGraphicsScene::tabFocus_sceneWithNestedFocusWidgets()
3267 QGraphicsScene scene;
3269 FocusWidget *widget1 = new FocusWidget;
3270 FocusWidget *widget1_1 = new FocusWidget;
3271 FocusWidget *widget1_2 = new FocusWidget;
3272 widget1_1->setParentItem(widget1);
3273 widget1_1->scale(0.5, 0.5);
3274 widget1_1->setPos(0, widget1->boundingRect().height() / 2);
3275 widget1_2->setParentItem(widget1);
3276 widget1_2->scale(0.5, 0.5);
3277 widget1_2->setPos(widget1->boundingRect().width() / 2, widget1->boundingRect().height() / 2);
3279 FocusWidget *widget2 = new FocusWidget;
3280 widget2->setPos(widget1->boundingRect().right(), 0);
3282 widget1->setData(0, "widget1");
3283 widget1_1->setData(0, "widget1_1");
3284 widget1_2->setData(0, "widget1_2");
3285 widget2->setData(0, "widget2");
3287 scene.addItem(widget1);
3288 scene.addItem(widget2);
3290 QDial *dial1 = new QDial;
3291 QGraphicsView *view = new QGraphicsView(&scene);
3292 view->setRenderHint(QPainter::Antialiasing);
3293 QDial *dial2 = new QDial;
3295 QHBoxLayout *layout = new QHBoxLayout;
3296 layout->addWidget(dial1);
3297 layout->addWidget(view);
3298 layout->addWidget(dial2);
3301 widget.setLayout(layout);
3303 qApp->setActiveWindow(&widget);
3304 widget.activateWindow();
3305 QVERIFY(QTest::qWaitForWindowActive(&widget));
3308 QTRY_VERIFY(dial1->hasFocus());
3310 EventSpy focusInSpy_1(widget1, QEvent::FocusIn);
3311 EventSpy focusOutSpy_1(widget1, QEvent::FocusOut);
3312 EventSpy focusInSpy_1_1(widget1_1, QEvent::FocusIn);
3313 EventSpy focusOutSpy_1_1(widget1_1, QEvent::FocusOut);
3314 EventSpy focusInSpy_1_2(widget1_2, QEvent::FocusIn);
3315 EventSpy focusOutSpy_1_2(widget1_2, QEvent::FocusOut);
3316 EventSpy focusInSpy_2(widget2, QEvent::FocusIn);
3317 EventSpy focusOutSpy_2(widget2, QEvent::FocusOut);
3319 QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
3320 QApplication::processEvents();
3321 QTRY_VERIFY(widget1->hasFocus());
3322 QCOMPARE(focusInSpy_1.count(), 1);
3324 QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
3325 QApplication::processEvents();
3326 QTRY_VERIFY(!widget1->hasFocus());
3327 QVERIFY(widget1_1->hasFocus());
3328 QCOMPARE(focusOutSpy_1.count(), 1);
3329 QCOMPARE(focusInSpy_1_1.count(), 1);
3331 QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
3332 QApplication::processEvents();
3333 QTRY_VERIFY(!widget1_1->hasFocus());
3334 QVERIFY(widget1_2->hasFocus());
3335 QCOMPARE(focusOutSpy_1_1.count(), 1);
3336 QCOMPARE(focusInSpy_1_2.count(), 1);
3338 QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
3339 QApplication::processEvents();
3340 QTRY_VERIFY(!widget1_2->hasFocus());
3341 QVERIFY(widget2->hasFocus());
3342 QCOMPARE(focusOutSpy_1_2.count(), 1);
3343 QCOMPARE(focusInSpy_2.count(), 1);
3345 QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
3346 QApplication::processEvents();
3347 QTRY_VERIFY(!widget2->hasFocus());
3348 QVERIFY(dial2->hasFocus());
3349 QCOMPARE(focusOutSpy_2.count(), 1);
3351 QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
3352 QApplication::processEvents();
3353 QTRY_VERIFY(widget2->hasFocus());
3354 QCOMPARE(focusInSpy_2.count(), 2);
3356 QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
3357 QApplication::processEvents();
3358 QTRY_VERIFY(!widget2->hasFocus());
3359 QTRY_VERIFY(widget1_2->hasFocus());
3360 QCOMPARE(focusOutSpy_2.count(), 2);
3361 QCOMPARE(focusInSpy_1_2.count(), 2);
3363 QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
3364 QApplication::processEvents();
3365 QTRY_VERIFY(!widget1_2->hasFocus());
3366 QTRY_VERIFY(widget1_1->hasFocus());
3367 QCOMPARE(focusOutSpy_1_2.count(), 2);
3368 QCOMPARE(focusInSpy_1_1.count(), 2);
3370 QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
3371 QApplication::processEvents();
3372 QTRY_VERIFY(!widget1_1->hasFocus());
3373 QTRY_VERIFY(widget1->hasFocus());
3374 QCOMPARE(focusOutSpy_1_1.count(), 2);
3375 QCOMPARE(focusInSpy_1.count(), 2);
3377 QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
3378 QApplication::processEvents();
3379 QTRY_VERIFY(!widget1->hasFocus());
3380 QTRY_VERIFY(dial1->hasFocus());
3381 QCOMPARE(focusOutSpy_1.count(), 2);
3383 widget1->setFocus();
3384 view->viewport()->setFocus();
3388 qApp->setActiveWindow(&widget);
3389 widget.activateWindow();
3390 QVERIFY(QTest::qWaitForWindowActive(&widget));
3391 QTRY_VERIFY(widget1->hasFocus());
3394 void tst_QGraphicsScene::style()
3396 QPointer<QWindowsStyle> windowsStyle = new QWindowsStyle;
3398 QGraphicsScene scene;
3399 QLineEdit *edit = new QLineEdit;
3400 QGraphicsProxyWidget *proxy = scene.addWidget(edit);
3402 EventSpy sceneSpy(&scene, QEvent::StyleChange);
3403 EventSpy proxySpy(proxy, QEvent::StyleChange);
3404 EventSpy editSpy(edit, QEvent::StyleChange);
3406 QCOMPARE(scene.style(), QApplication::style());
3408 scene.setStyle(windowsStyle);
3409 QCOMPARE(sceneSpy.count(), 1);
3410 QCOMPARE(proxySpy.count(), 1);
3411 QCOMPARE(editSpy.count(), 1);
3412 QCOMPARE(scene.style(), (QStyle *)windowsStyle);
3413 QCOMPARE(proxy->style(), (QStyle *)windowsStyle);
3414 QCOMPARE(edit->style(), (QStyle *)windowsStyle);
3417 QCOMPARE(sceneSpy.count(), 2);
3418 QCOMPARE(proxySpy.count(), 2);
3419 QCOMPARE(editSpy.count(), 2);
3420 QCOMPARE(scene.style(), QApplication::style());
3421 QCOMPARE(proxy->style(), QApplication::style());
3422 QCOMPARE(edit->style(), QApplication::style());
3423 QVERIFY(!windowsStyle); // deleted
3426 void tst_QGraphicsScene::task139710_bspTreeCrash()
3428 // create a scene with 2000 items
3429 QGraphicsScene scene(0, 0, 1000, 1000);
3431 for (int i = 0; i < 2; ++i) {
3432 // trigger delayed item indexing
3433 qApp->processEvents();
3434 scene.setSceneRect(0, 0, 10000, 10000);
3436 // delete all items in the scene - pointers are now likely to be recycled
3437 foreach (QGraphicsItem *item, scene.items()) {
3438 scene.removeItem(item);
3442 // add 1000 more items - the BSP tree is now resized
3443 for (int i = 0; i < 1000; ++i) {
3444 QGraphicsRectItem *item = scene.addRect(QRectF(0, 0, 200, 200));
3445 item->setPos(qrand() % 10000, qrand() % 10000);
3448 // trigger delayed item indexing for the first 1000 items
3449 qApp->processEvents();
3451 // add 1000 more items - the BSP tree is now resized
3452 for (int i = 0; i < 1000; ++i) {
3453 QGraphicsRectItem *item = scene.addRect(QRectF(0, 0, 200, 200));
3454 item->setPos(qrand() % 10000, qrand() % 10000);
3457 // get items from the BSP tree and use them. there was junk in the tree
3458 // the second time this happened.
3459 foreach (QGraphicsItem *item, scene.items(QRectF(0, 0, 1000, 1000)))
3464 void tst_QGraphicsScene::task139782_containsItemBoundingRect()
3466 // The item in question has a scene bounding rect of (10, 10, 50, 50)
3467 QGraphicsScene scene(0.0, 0.0, 200.0, 200.0);
3468 QGraphicsRectItem *item = new QGraphicsRectItem(0.0, 0.0, 50.0, 50.0, 0);
3469 scene.addItem(item);
3470 item->setPos(10.0, 10.0);
3472 // The (0, 0, 50, 50) scene rect should not include the item's bounding rect
3473 QVERIFY(!scene.items(QRectF(0.0, 0.0, 50.0, 50.0), Qt::ContainsItemBoundingRect).contains(item));
3475 // The (9, 9, 500, 500) scene rect _should_ include the item's bounding rect
3476 QVERIFY(scene.items(QRectF(9.0, 9.0, 500.0, 500.0), Qt::ContainsItemBoundingRect).contains(item));
3478 // The (25, 25, 5, 5) scene rect should not include the item's bounding rect
3479 QVERIFY(!scene.items(QRectF(25.0, 25.0, 5.0, 5.0), Qt::ContainsItemBoundingRect).contains(item));
3482 void tst_QGraphicsScene::task176178_itemIndexMethodBreaksSceneRect()
3484 QGraphicsScene scene;
3485 scene.setItemIndexMethod(QGraphicsScene::NoIndex);
3486 QGraphicsRectItem *rect = new QGraphicsRectItem;
3487 rect->setRect(0,0,100,100);
3488 scene.addItem(rect);
3489 QCOMPARE(scene.sceneRect(), rect->rect());
3492 void tst_QGraphicsScene::task160653_selectionChanged()
3494 QGraphicsScene scene(0, 0, 100, 100);
3495 scene.addItem(new QGraphicsRectItem(0, 0, 20, 20));
3496 scene.addItem(new QGraphicsRectItem(30, 30, 20, 20));
3497 foreach (QGraphicsItem *item, scene.items()) {
3499 item->flags() | QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemIsMovable);
3500 item->setSelected(true);
3502 QVERIFY(scene.items().size() > 1);
3503 QCOMPARE(scene.items().size(), scene.selectedItems().size());
3505 QSignalSpy spy(&scene, SIGNAL(selectionChanged()));
3506 QGraphicsView view(&scene);
3508 view.viewport(), Qt::LeftButton, 0, view.mapFromScene(scene.items().first()->scenePos()));
3509 QCOMPARE(spy.count(), 1);
3512 void tst_QGraphicsScene::task250680_childClip()
3514 QGraphicsRectItem *clipper = new QGraphicsRectItem;
3515 clipper->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
3516 clipper->setPen(QPen(Qt::green));
3517 clipper->setRect(200, 200, 640, 480);
3519 QGraphicsRectItem *rect = new QGraphicsRectItem(clipper);
3520 rect->setPen(QPen(Qt::red));
3521 rect->setBrush(QBrush(QColor(255, 0, 0, 75)));
3522 rect->setPos(320, 240);
3523 rect->setRect(-25, -25, 50, 50);
3525 QGraphicsScene scene;
3526 scene.addItem(clipper);
3529 path.addRect(-25, -25, 50, 50);
3530 QVERIFY(QPathCompare::comparePaths(rect->clipPath().simplified(), path));
3532 QCOMPARE(scene.items(QRectF(320, 240, 5, 5)).size(), 2);
3534 QCOMPARE(scene.items(QRectF(320, 240, 5, 5)).size(), 2);
3537 void tst_QGraphicsScene::sorting_data()
3539 QTest::addColumn<bool>("cache");
3541 QTest::newRow("Normal sorting") << false;
3542 QTest::newRow("Cached sorting") << true;
3545 void tst_QGraphicsScene::sorting()
3547 QFETCH(bool, cache);
3549 QGraphicsScene scene;
3550 scene.setSortCacheEnabled(cache);
3552 QGraphicsRectItem *t_1 = new QGraphicsRectItem(0, 0, 50, 50);
3553 QGraphicsRectItem *c_1 = new QGraphicsRectItem(0, 0, 40, 40, t_1);
3554 QGraphicsRectItem *c_1_1 = new QGraphicsRectItem(0, 0, 30, 30, c_1);
3555 QGraphicsRectItem *c_1_1_1 = new QGraphicsRectItem(0, 0, 20, 20, c_1_1);
3556 QGraphicsRectItem *c_1_2 = new QGraphicsRectItem(0, 0, 30, 30, c_1);
3557 QGraphicsRectItem *c_2 = new QGraphicsRectItem(0, 0, 40, 40, t_1);
3558 QGraphicsRectItem *c_2_1 = new QGraphicsRectItem(0, 0, 30, 30, c_2);
3559 QGraphicsRectItem *c_2_1_1 = new QGraphicsRectItem(0, 0, 20, 20, c_2_1);
3560 QGraphicsRectItem *c_2_2 = new QGraphicsRectItem(0, 0, 30, 30, c_2);
3561 t_1->setBrush(QColor(qrand() % 256, qrand() % 256, qrand() % 256));
3562 c_1->setBrush(QColor(qrand() % 256, qrand() % 256, qrand() % 256));
3563 c_1_1->setBrush(QColor(qrand() % 256, qrand() % 256, qrand() % 256));
3564 c_1_1_1->setBrush(QColor(qrand() % 256, qrand() % 256, qrand() % 256));
3565 c_1_2->setBrush(QColor(qrand() % 256, qrand() % 256, qrand() % 256));
3566 c_2->setBrush(QColor(qrand() % 256, qrand() % 256, qrand() % 256));
3567 c_2_1->setBrush(QColor(qrand() % 256, qrand() % 256, qrand() % 256));
3568 c_2_1_1->setBrush(QColor(qrand() % 256, qrand() % 256, qrand() % 256));
3569 c_2_2->setBrush(QColor(qrand() % 256, qrand() % 256, qrand() % 256));
3571 c_1->setPos(23, 18);
3572 c_1_1->setPos(24, 28);
3573 c_1_1_1->setPos(-16, 16);
3574 c_1_2->setPos(-16, 28);
3575 c_1_2->setZValue(1);
3576 c_2->setPos(-23, 18);
3578 c_2_1->setPos(24, 28);
3579 c_2_1_1->setPos(-16, 16);
3580 c_2_2->setPos(-16, 28);
3581 c_2_2->setZValue(1);
3583 c_1->setFlag(QGraphicsItem::ItemIsMovable);
3584 c_1_1->setFlag(QGraphicsItem::ItemIsMovable);
3585 c_1_1_1->setFlag(QGraphicsItem::ItemIsMovable);
3586 c_1_2->setFlag(QGraphicsItem::ItemIsMovable);
3587 c_2->setFlag(QGraphicsItem::ItemIsMovable);
3588 c_2_1->setFlag(QGraphicsItem::ItemIsMovable);
3589 c_2_1_1->setFlag(QGraphicsItem::ItemIsMovable);
3590 c_2_2->setFlag(QGraphicsItem::ItemIsMovable);
3592 t_1->setData(0, "t_1");
3593 c_1->setData(0, "c_1");
3594 c_1_1->setData(0, "c_1_1");
3595 c_1_1_1->setData(0, "c_1_1_1");
3596 c_1_2->setData(0, "c_1_2");
3597 c_2->setData(0, "c_2");
3598 c_2_1->setData(0, "c_2_1");
3599 c_2_1_1->setData(0, "c_2_1_1");
3600 c_2_2->setData(0, "c_2_2");
3604 foreach (QGraphicsItem *item, scene.items())
3605 item->setFlag(QGraphicsItem::ItemIsSelectable);
3607 // QGraphicsView view(&scene);
3608 // view.setDragMode(QGraphicsView::RubberBandDrag);
3611 qDebug() << "items: {";
3612 foreach (QGraphicsItem *item, scene.items(32, 31, 4, 55))
3613 qDebug() << "\t" << item->data(0).toString();
3616 QCOMPARE(scene.items(32, 31, 4, 55),
3617 QList<QGraphicsItem *>()
3618 << c_1_2 << c_1_1_1 << c_1 << t_1);
3619 QCOMPARE(scene.items(-53, 47, 136, 3),
3620 QList<QGraphicsItem *>()
3621 << c_2_2 << c_2_1 << c_2 << c_1_2 << c_1_1 << c_1 << t_1);
3622 QCOMPARE(scene.items(-23, 79, 104, 3),
3623 QList<QGraphicsItem *>()
3624 << c_2_1_1 << c_1_1_1);
3625 QCOMPARE(scene.items(-26, -3, 92, 79),
3626 QList<QGraphicsItem *>()
3627 << c_2_2 << c_2_1_1 << c_2_1 << c_2
3628 << c_1_2 << c_1_1_1 << c_1_1 << c_1
3632 class ChangedListener : public QObject
3636 QList<QList<QRectF> > changes;
3639 void changed(const QList<QRectF> &dirty)
3645 void tst_QGraphicsScene::changedSignal_data()
3647 QTest::addColumn<bool>("withView");
3649 QTest::newRow("without view") << false;
3650 QTest::newRow("with view") << true;
3653 void tst_QGraphicsScene::changedSignal()
3655 QFETCH(bool, withView);
3656 QGraphicsScene scene;
3658 connect(&scene, SIGNAL(changed(QList<QRectF>)), &cl, SLOT(changed(QList<QRectF>)));
3660 QGraphicsView *view = 0;
3662 view = new QGraphicsView(&scene);
3664 QGraphicsRectItem *rect = new QGraphicsRectItem(0, 0, 10, 10);
3665 scene.addItem(rect);
3667 QCOMPARE(cl.changes.size(), 0);
3668 QTRY_COMPARE(cl.changes.size(), 1);
3669 QCOMPARE(cl.changes.at(0).size(), 1);
3670 QCOMPARE(cl.changes.at(0).first(), QRectF(0, 0, 10, 10));
3672 rect->setPos(20, 0);
3674 QCOMPARE(cl.changes.size(), 1);
3675 qApp->processEvents();
3676 QCOMPARE(cl.changes.size(), 2);
3677 QCOMPARE(cl.changes.at(1).size(), 2);
3678 QCOMPARE(cl.changes.at(1).first(), QRectF(0, 0, 10, 10));
3679 QCOMPARE(cl.changes.at(1).last(), QRectF(20, 0, 10, 10));
3681 QCOMPARE(scene.sceneRect(), QRectF(0, 0, 30, 10));
3687 void tst_QGraphicsScene::stickyFocus_data()
3689 QTest::addColumn<bool>("sticky");
3690 QTest::newRow("sticky") << true;
3691 QTest::newRow("not sticky") << false;
3694 void tst_QGraphicsScene::stickyFocus()
3696 QFETCH(bool, sticky);
3698 QGraphicsScene scene;
3699 QEvent activate(QEvent::WindowActivate);
3700 QApplication::sendEvent(&scene, &activate);
3702 QGraphicsTextItem *text = scene.addText("Hei");
3703 text->setTextInteractionFlags(Qt::TextEditorInteraction);
3706 scene.setStickyFocus(sticky);
3708 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
3709 event.setScenePos(QPointF(-10, -10)); // outside item
3710 event.setButton(Qt::LeftButton);
3711 qApp->sendEvent(&scene, &event);
3713 QCOMPARE(text->hasFocus(), sticky);
3716 void tst_QGraphicsScene::sendEvent()
3718 QGraphicsScene scene;
3719 QGraphicsTextItem *item = scene.addText(QString());
3720 EventSpy *spy = new EventSpy(&scene, item, QEvent::User);
3721 QCOMPARE(spy->count(), 0);
3722 QEvent event(QEvent::User);
3723 scene.sendEvent(item, &event);
3724 QCOMPARE(spy->count(), 1);
3727 void tst_QGraphicsScene::inputMethod_data()
3729 QTest::addColumn<int>("flags");
3730 QTest::addColumn<bool>("callFocusItem");
3731 QTest::newRow("0") << 0 << false;
3732 QTest::newRow("1") << (int)QGraphicsItem::ItemAcceptsInputMethod << false;
3733 QTest::newRow("2") << (int)QGraphicsItem::ItemIsFocusable << false;
3734 QTest::newRow("3") <<
3735 (int)(QGraphicsItem::ItemAcceptsInputMethod|QGraphicsItem::ItemIsFocusable) << true;
3738 class InputMethodTester : public QGraphicsRectItem
3740 void inputMethodEvent(QInputMethodEvent *) { ++eventCalls; }
3741 QVariant inputMethodQuery(Qt::InputMethodQuery) const { ++queryCalls; return QVariant(); }
3744 mutable int queryCalls;
3747 void tst_QGraphicsScene::inputMethod()
3749 PlatformInputContext inputContext;
3750 QInputMethodPrivate *inputMethodPrivate = QInputMethodPrivate::get(qApp->inputMethod());
3751 inputMethodPrivate->testContext = &inputContext;
3754 QFETCH(bool, callFocusItem);
3756 InputMethodTester *item = new InputMethodTester;
3757 item->setFlags((QGraphicsItem::GraphicsItemFlags)flags);
3759 QGraphicsScene scene;
3760 QGraphicsView view(&scene);
3762 QApplication::setActiveWindow(&view);
3764 QVERIFY(QTest::qWaitForWindowActive(&view));
3765 QCOMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
3767 inputContext.m_resetCallCount = 0;
3768 inputContext.m_commitCallCount = 0;
3769 scene.addItem(item);
3770 QInputMethodEvent event;
3772 scene.setFocusItem(item);
3773 QCOMPARE(!!(item->flags() & QGraphicsItem::ItemIsFocusable), scene.focusItem() == item);
3774 QCOMPARE(inputContext.m_resetCallCount, 0);
3776 item->eventCalls = 0;
3777 qApp->sendEvent(&scene, &event);
3778 QCOMPARE(item->eventCalls, callFocusItem ? 1 : 0);
3780 item->queryCalls = 0;
3781 scene.inputMethodQuery((Qt::InputMethodQuery)0);
3782 QCOMPARE(item->queryCalls, callFocusItem ? 1 : 0);
3784 scene.setFocusItem(0);
3785 // the input context is reset twice, once because an item has lost focus and again because
3786 // the Qt::WA_InputMethodEnabled flag is cleared because no item has focus.
3787 QCOMPARE(inputContext.m_resetCallCount + inputContext.m_commitCallCount, callFocusItem ? 2 : 0);
3788 QCOMPARE(item->queryCalls, callFocusItem ? 1 : 0); // verify that value is unaffected
3790 item->eventCalls = 0;
3791 qApp->sendEvent(&scene, &event);
3792 QCOMPARE(item->eventCalls, 0);
3794 item->queryCalls = 0;
3795 scene.inputMethodQuery((Qt::InputMethodQuery)0);
3796 QCOMPARE(item->queryCalls, 0);
3799 void tst_QGraphicsScene::dispatchHoverOnPress()
3801 QGraphicsScene scene;
3802 EventTester *tester1 = new EventTester;
3803 tester1->setAcceptHoverEvents(true);
3804 EventTester *tester2 = new EventTester;
3805 tester2->setAcceptHoverEvents(true);
3806 tester2->setPos(30, 30);
3807 scene.addItem(tester1);
3808 scene.addItem(tester2);
3810 tester1->eventTypes.clear();
3811 tester2->eventTypes.clear();
3814 QGraphicsSceneMouseEvent me(QEvent::GraphicsSceneMousePress);
3815 me.setButton(Qt::LeftButton);
3816 me.setButtons(Qt::LeftButton);
3817 QGraphicsSceneMouseEvent me2(QEvent::GraphicsSceneMouseRelease);
3818 me2.setButton(Qt::LeftButton);
3819 qApp->sendEvent(&scene, &me);
3820 qApp->sendEvent(&scene, &me2);
3821 QCOMPARE(tester1->eventTypes, QList<QEvent::Type>()
3822 << QEvent::GraphicsSceneHoverEnter
3823 << QEvent::GraphicsSceneHoverMove
3824 << QEvent::GrabMouse
3825 << QEvent::GraphicsSceneMousePress
3826 << QEvent::UngrabMouse);
3827 tester1->eventTypes.clear();
3828 qApp->sendEvent(&scene, &me);
3829 qApp->sendEvent(&scene, &me2);
3830 QCOMPARE(tester1->eventTypes, QList<QEvent::Type>()
3831 << QEvent::GraphicsSceneHoverMove
3832 << QEvent::GrabMouse
3833 << QEvent::GraphicsSceneMousePress
3834 << QEvent::UngrabMouse);
3837 QGraphicsSceneMouseEvent me(QEvent::GraphicsSceneMousePress);
3838 me.setScenePos(QPointF(30, 30));
3839 me.setButton(Qt::LeftButton);
3840 me.setButtons(Qt::LeftButton);
3841 QGraphicsSceneMouseEvent me2(QEvent::GraphicsSceneMouseRelease);
3842 me2.setScenePos(QPointF(30, 30));
3843 me2.setButton(Qt::LeftButton);
3844 tester1->eventTypes.clear();
3845 qApp->sendEvent(&scene, &me);
3846 qApp->sendEvent(&scene, &me2);
3847 qDebug() << tester1->eventTypes;
3848 QCOMPARE(tester1->eventTypes, QList<QEvent::Type>()
3849 << QEvent::GraphicsSceneHoverLeave);
3850 QCOMPARE(tester2->eventTypes, QList<QEvent::Type>()
3851 << QEvent::GraphicsSceneHoverEnter
3852 << QEvent::GraphicsSceneHoverMove
3853 << QEvent::GrabMouse
3854 << QEvent::GraphicsSceneMousePress
3855 << QEvent::UngrabMouse);
3856 tester2->eventTypes.clear();
3857 qApp->sendEvent(&scene, &me);
3858 qApp->sendEvent(&scene, &me2);
3859 QCOMPARE(tester2->eventTypes, QList<QEvent::Type>()
3860 << QEvent::GraphicsSceneHoverMove
3861 << QEvent::GrabMouse
3862 << QEvent::GraphicsSceneMousePress
3863 << QEvent::UngrabMouse);
3867 void tst_QGraphicsScene::initialFocus_data()
3869 QTest::addColumn<bool>("activeScene");
3870 QTest::addColumn<bool>("explicitSetFocus");
3871 QTest::addColumn<bool>("isPanel");
3872 QTest::addColumn<bool>("shouldHaveFocus");
3874 QTest::newRow("inactive scene, normal item") << false << false << false << false;
3875 QTest::newRow("inactive scene, panel item") << false << false << true << false;
3876 QTest::newRow("inactive scene, normal item, explicit focus") << false << true << false << true;
3877 QTest::newRow("inactive scene, panel, explicit focus") << false << true << true << true;
3878 QTest::newRow("active scene, normal item") << true << false << false << false;
3879 QTest::newRow("active scene, panel item") << true << false << true << false;
3880 QTest::newRow("active scene, normal item, explicit focus") << true << true << false << true;
3881 QTest::newRow("active scene, panel, explicit focus") << true << true << true << true;
3884 void tst_QGraphicsScene::initialFocus()
3886 QFETCH(bool, activeScene);
3887 QFETCH(bool, explicitSetFocus);
3888 QFETCH(bool, isPanel);
3889 QFETCH(bool, shouldHaveFocus);
3891 QGraphicsRectItem *rect = new QGraphicsRectItem;
3892 rect->setFlag(QGraphicsItem::ItemIsFocusable);
3893 QVERIFY(!rect->hasFocus());
3896 rect->setFlag(QGraphicsItem::ItemIsPanel);
3898 // Setting focus on an item before adding to the scene will ensure
3899 // it gets focus when the scene is activated.
3900 if (explicitSetFocus)
3903 QGraphicsScene scene;
3904 QVERIFY(!scene.isActive());
3907 QEvent windowActivate(QEvent::WindowActivate);
3908 qApp->sendEvent(&scene, &windowActivate);
3912 scene.addItem(rect);
3915 QEvent windowActivate(QEvent::WindowActivate);
3916 qApp->sendEvent(&scene, &windowActivate);
3920 QCOMPARE(rect->hasFocus(), shouldHaveFocus);
3923 class PolishItem : public QGraphicsTextItem
3926 PolishItem(QGraphicsItem *parent = 0)
3927 : QGraphicsTextItem(parent), polished(false), deleteChildrenInPolish(true), addChildrenInPolish(false) { }
3930 bool deleteChildrenInPolish;
3931 bool addChildrenInPolish;
3933 QVariant itemChange(GraphicsItemChange change, const QVariant& value)
3935 if (change == ItemVisibleChange) {
3937 if (deleteChildrenInPolish)
3938 qDeleteAll(childItems());
3939 if (addChildrenInPolish) {
3940 for (int i = 0; i < 10; ++i)
3941 new PolishItem(this);
3944 return QGraphicsItem::itemChange(change, value);
3948 void tst_QGraphicsScene::polishItems()
3950 QGraphicsScene scene;
3951 PolishItem *parent = new PolishItem;
3952 scene.addItem(parent);
3953 PolishItem *child = new PolishItem(parent);
3955 // test that QGraphicsScenePrivate::_q_polishItems() doesn't crash
3956 QMetaObject::invokeMethod(&scene,"_q_polishItems");
3959 void tst_QGraphicsScene::polishItems2()
3961 QGraphicsScene scene;
3962 PolishItem *item = new PolishItem;
3963 item->addChildrenInPolish = true;
3964 item->deleteChildrenInPolish = true;
3965 // These children should be deleted in the polish.
3966 for (int i = 0; i < 20; ++i)
3967 new PolishItem(item);
3968 scene.addItem(item);
3970 // Wait for the polish event to be delivered.
3971 QVERIFY(!item->polished);
3972 QApplication::sendPostedEvents(&scene, QEvent::MetaCall);
3973 QVERIFY(item->polished);
3975 // We deleted the children we added above, but we also
3976 // added 10 new children. These should be polished in the next
3977 // event loop iteration.
3978 QList<QGraphicsItem *> children = item->childItems();
3979 QCOMPARE(children.count(), 10);
3980 foreach (QGraphicsItem *child, children)
3981 QVERIFY(!static_cast<PolishItem *>(child)->polished);
3983 QApplication::sendPostedEvents(&scene, QEvent::MetaCall);
3984 foreach (QGraphicsItem *child, children)
3985 QVERIFY(static_cast<PolishItem *>(child)->polished);
3988 void tst_QGraphicsScene::isActive()
3990 QGraphicsScene scene1;
3991 QVERIFY(!scene1.isActive());
3992 QGraphicsScene scene2;
3993 QVERIFY(!scene2.isActive());
3997 QHBoxLayout *layout = new QHBoxLayout;
3998 toplevel1.setLayout(layout);
3999 QGraphicsView *view1 = new QGraphicsView(&scene1);
4000 QGraphicsView *view2 = new QGraphicsView(&scene2);
4001 layout->addWidget(view1);
4002 layout->addWidget(view2);
4004 QVERIFY(!scene1.isActive());
4005 QVERIFY(!scene2.isActive());
4007 view1->setVisible(false);
4010 QApplication::setActiveWindow(&toplevel1);
4011 QVERIFY(QTest::qWaitForWindowActive(&toplevel1));
4012 QCOMPARE(QApplication::activeWindow(), &toplevel1);
4014 QVERIFY(!scene1.isActive()); //it is hidden;
4015 QVERIFY(scene2.isActive());
4016 QVERIFY(!scene1.hasFocus());
4017 QVERIFY(scene2.hasFocus());
4020 QVERIFY(scene1.isActive());
4021 QVERIFY(scene2.isActive());
4022 QVERIFY(!scene1.hasFocus());
4023 QVERIFY(scene2.hasFocus());
4027 QVERIFY(scene1.isActive());
4028 QVERIFY(!scene2.isActive());
4029 QVERIFY(scene1.hasFocus());
4030 QVERIFY(!scene2.hasFocus());
4034 QTRY_VERIFY(!scene1.isActive());
4035 QTRY_VERIFY(!scene2.isActive());
4036 QVERIFY(!scene1.hasFocus());
4037 QVERIFY(!scene2.hasFocus());
4040 QApplication::setActiveWindow(&toplevel1);
4041 QVERIFY(QTest::qWaitForWindowActive(&toplevel1));
4042 QCOMPARE(QApplication::activeWindow(), &toplevel1);
4044 QTRY_VERIFY(scene1.isActive());
4045 QTRY_VERIFY(!scene2.isActive());
4046 QVERIFY(scene1.hasFocus());
4047 QVERIFY(!scene2.hasFocus());
4050 QVERIFY(scene1.isActive());
4051 QVERIFY(scene2.isActive());
4052 QVERIFY(scene1.hasFocus());
4053 QVERIFY(!scene2.hasFocus());
4056 QVERIFY(!scene1.isActive());
4057 QVERIFY(!scene2.isActive());
4058 QVERIFY(!scene1.hasFocus());
4059 QVERIFY(!scene2.hasFocus());
4064 QHBoxLayout *layout = new QHBoxLayout;
4065 toplevel2.setLayout(layout);
4066 QGraphicsView *view1 = new QGraphicsView(&scene1);
4067 QGraphicsView *view2 = new QGraphicsView();
4068 layout->addWidget(view1);
4069 layout->addWidget(view2);
4071 QVERIFY(!scene1.isActive());
4072 QVERIFY(!scene2.isActive());
4073 QVERIFY(!scene1.hasFocus());
4074 QVERIFY(!scene2.hasFocus());
4077 QApplication::setActiveWindow(&toplevel2);
4078 QVERIFY(QTest::qWaitForWindowActive(&toplevel2));
4079 QCOMPARE(QApplication::activeWindow(), &toplevel2);
4081 QVERIFY(scene1.isActive());
4082 QVERIFY(!scene2.isActive());
4083 QVERIFY(scene1.hasFocus());
4084 QVERIFY(!scene2.hasFocus());
4086 view2->setScene(&scene2);
4088 QVERIFY(scene1.isActive());
4089 QVERIFY(scene2.isActive());
4090 QVERIFY(scene1.hasFocus());
4091 QVERIFY(!scene2.hasFocus());
4093 view1->setScene(&scene2);
4094 QVERIFY(!scene1.isActive());
4095 QVERIFY(scene2.isActive());
4096 QVERIFY(!scene1.hasFocus());
4097 QVERIFY(scene2.hasFocus());
4100 QVERIFY(!scene1.isActive());
4101 QVERIFY(scene2.isActive());
4102 QVERIFY(!scene1.hasFocus());
4103 QVERIFY(scene2.hasFocus());
4105 view1->setScene(&scene1);
4106 QVERIFY(!scene1.isActive());
4107 QVERIFY(scene2.isActive());
4108 QVERIFY(!scene1.hasFocus());
4109 QVERIFY(scene2.hasFocus());
4112 QVERIFY(scene1.isActive());
4113 QVERIFY(scene2.isActive());
4114 QVERIFY(!scene1.hasFocus());
4115 QVERIFY(scene2.hasFocus());
4118 QVERIFY(scene1.isActive());
4119 QVERIFY(!scene2.isActive());
4120 QVERIFY(scene1.hasFocus());
4121 QVERIFY(!scene2.hasFocus());
4123 QGraphicsView topLevelView;
4124 topLevelView.show();
4125 QApplication::setActiveWindow(&topLevelView);
4126 topLevelView.setFocus();
4127 QVERIFY(QTest::qWaitForWindowActive(&topLevelView));
4128 QCOMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&topLevelView));
4130 QVERIFY(!scene1.isActive());
4131 QVERIFY(!scene2.isActive());
4132 QVERIFY(!scene1.hasFocus());
4133 QVERIFY(!scene2.hasFocus());
4135 topLevelView.setScene(&scene1);
4136 QVERIFY(scene1.isActive());
4137 QVERIFY(!scene2.isActive());
4138 QVERIFY(scene1.hasFocus());
4139 QVERIFY(!scene2.hasFocus());
4142 QVERIFY(scene1.isActive());
4143 QVERIFY(!scene2.isActive());
4144 QVERIFY(scene1.hasFocus());
4145 QVERIFY(!scene2.hasFocus());
4148 QVERIFY(scene1.isActive());
4149 QVERIFY(!scene2.isActive());
4150 QVERIFY(scene1.hasFocus());
4151 QVERIFY(!scene2.hasFocus());
4153 QApplication::setActiveWindow(&toplevel2);
4154 QVERIFY(QTest::qWaitForWindowActive(&toplevel2));
4156 QVERIFY(!scene1.isActive());
4157 QVERIFY(scene2.isActive());
4158 QVERIFY(!scene1.hasFocus());
4159 QVERIFY(scene2.hasFocus());
4162 QVERIFY(!scene1.isActive());
4163 QVERIFY(!scene2.isActive());
4164 QVERIFY(!scene1.hasFocus());
4165 QVERIFY(!scene2.hasFocus());
4169 QHBoxLayout *layout = new QHBoxLayout;
4170 toplevel3.setLayout(layout);
4171 QGraphicsView *view1 = new QGraphicsView(&scene1);
4172 QGraphicsView *view2 = new QGraphicsView(&scene2);
4173 layout->addWidget(view1);
4175 QVERIFY(!scene1.isActive());
4176 QVERIFY(!scene2.isActive());
4177 QVERIFY(!scene1.hasFocus());
4178 QVERIFY(!scene2.hasFocus());
4182 QApplication::setActiveWindow(&toplevel3);
4183 QVERIFY(QTest::qWaitForWindowActive(&toplevel3));
4184 QCOMPARE(QApplication::activeWindow(), &toplevel3);
4186 QVERIFY(scene1.isActive());
4187 QVERIFY(!scene2.isActive());
4188 QVERIFY(scene1.hasFocus());
4189 QVERIFY(!scene2.hasFocus());
4191 layout->addWidget(view2);
4192 QApplication::processEvents();
4193 QVERIFY(scene1.isActive());
4194 QVERIFY(scene2.isActive());
4195 QVERIFY(scene1.hasFocus());
4196 QVERIFY(!scene2.hasFocus());
4198 view1->setParent(0);
4199 QVERIFY(!scene1.isActive());
4200 QVERIFY(scene2.isActive());
4201 QVERIFY(!scene1.hasFocus());
4202 QVERIFY(scene2.hasFocus());
4206 QVERIFY(!scene1.isActive());
4207 QVERIFY(!scene2.isActive());
4208 QVERIFY(!scene1.hasFocus());
4209 QVERIFY(!scene2.hasFocus());
4213 void tst_QGraphicsScene::siblingIndexAlwaysValid()
4215 QGraphicsScene scene;
4217 QGraphicsWidget *parent = new QGraphicsWidget;
4218 parent->setZValue(350);
4219 parent->setGeometry(0, 0, 100, 100);
4220 QGraphicsWidget *parent2 = new QGraphicsWidget;
4221 parent2->setGeometry(10, 10, 50, 50);
4222 QGraphicsWidget *child = new QGraphicsWidget(parent2);
4223 child->setGeometry(15, 15, 25, 25);
4224 child->setZValue(150);
4225 //Both are top level
4226 scene.addItem(parent);
4227 scene.addItem(parent2);
4229 //Then we make the child a top level
4230 child->setParentItem(0);
4232 //This is trigerred by a repaint...
4233 QGraphicsScenePrivate::get(&scene)->index->estimateTopLevelItems(QRectF(), Qt::AscendingOrder);
4237 //If there are in the list that's bad, we crash...
4238 QVERIFY(!QGraphicsScenePrivate::get(&scene)->topLevelItems.contains(static_cast<QGraphicsItem *>(child)));
4241 QGraphicsScene scene2;
4242 // works with bsp tree index
4243 scene2.setItemIndexMethod(QGraphicsScene::NoIndex);
4245 QGraphicsView view2(&scene2);
4247 // first add the blue rect
4248 QGraphicsRectItem* const item1 = new QGraphicsRectItem(QRect( 10, 10, 10, 10 ));
4249 item1->setPen(QColor(Qt::blue));
4250 item1->setBrush(Qt::blue);
4251 scene2.addItem(item1);
4253 // then add the red rect
4254 QGraphicsRectItem* const item2 = new QGraphicsRectItem(5, 5, 10, 10);
4255 item2->setPen(QColor(Qt::red));
4256 item2->setBrush(Qt::red);
4257 scene2.addItem(item2);
4259 // now the blue one is visible on top of the red one -> swap them (important for the bug)
4260 item1->setZValue(1.0);
4261 item2->setZValue(0.0);
4265 // handle events as a real life app would do
4266 QApplication::processEvents();
4268 // now delete the red rect
4271 // handle events as a real life app would do
4272 QApplication::processEvents();
4274 //We should not crash
4278 void tst_QGraphicsScene::removeFullyTransparentItem()
4280 QGraphicsScene scene;
4282 QGraphicsItem *parent = scene.addRect(0, 0, 100, 100);
4283 parent->setFlag(QGraphicsItem::ItemHasNoContents);
4285 QGraphicsItem *child = scene.addRect(0, 0, 100, 100);
4286 child->setParentItem(parent);
4289 view.setScene(&scene);
4291 qApp->setActiveWindow(&view);
4292 QVERIFY(QTest::qWaitForWindowActive(&view));
4294 // NB! The parent has the ItemHasNoContents flag set, which means
4295 // the parent itself doesn't generate any update requests, only the
4296 // child can possibly trigger an update. Also note that the child
4297 // is removed before processing events.
4299 parent->setOpacity(0);
4300 QVERIFY(qFuzzyIsNull(child->effectiveOpacity()));
4301 scene.removeItem(child);
4302 QVERIFY(!scene.items().contains(child));
4303 QTRY_VERIFY(view.repaints > 0);
4305 // Re-add child. There's nothing new to display (child is still
4306 // effectively hidden), so it shouldn't trigger an update.
4308 child->setParentItem(parent);
4309 QVERIFY(scene.items().contains(child));
4310 QVERIFY(qFuzzyIsNull(child->effectiveOpacity()));
4311 QApplication::processEvents();
4312 QCOMPARE(view.repaints, 0);
4314 // Nothing is visible on the screen, removing child item shouldn't trigger an update.
4315 scene.removeItem(child);
4316 QApplication::processEvents();
4317 QCOMPARE(view.repaints, 0);
4321 void tst_QGraphicsScene::taskQTBUG_5904_crashWithDeviceCoordinateCache()
4323 QGraphicsScene scene;
4324 QGraphicsRectItem *rectItem = scene.addRect(QRectF(0, 0, 100, 200), QPen(Qt::black), QBrush(Qt::green));
4326 rectItem->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
4328 QPixmap pixmap(100,200);
4329 QPainter painter(&pixmap);
4330 painter.setRenderHint(QPainter::Antialiasing);
4331 scene.render(&painter);
4333 // No crash, then it passed!
4336 void tst_QGraphicsScene::taskQT657_paintIntoCacheWithTransparentParts()
4338 // Test using DeviceCoordinateCache and opaque item
4339 QWidget *w = new QWidget();
4340 w->setPalette(QColor(0, 0, 255));
4341 w->setGeometry(0, 0, 50, 50);
4343 QGraphicsScene *scene = new QGraphicsScene();
4344 CustomView *view = new CustomView;
4345 view->setScene(scene);
4347 QGraphicsProxyWidget *proxy = scene->addWidget(w);
4348 proxy->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
4352 QVERIFY(QTest::qWaitForWindowExposed(view));
4354 proxy->update(10, 10, 10, 10);
4356 QTRY_VERIFY(view->repaints > 0);
4359 QGraphicsItemPrivate* itemp = QGraphicsItemPrivate::get(proxy);
4360 QTRY_VERIFY(QPixmapCache::find(itemp->extraItemCache()->deviceData.value(view->viewport()).key, &pix));
4362 QTransform t = proxy->sceneTransform();
4363 // Map from scene coordinates to pixmap coordinates.
4364 // X origin in the pixmap is the most-left point
4365 // of the item's boundingRect in the scene.
4366 qreal adjust = t.mapRect(proxy->boundingRect().toRect()).left();
4367 QRect rect = t.mapRect(QRect(10, 10, 10, 10)).adjusted(-adjust, 0, -adjust + 1, 1);
4368 QPixmap subpix = pix.copy(rect);
4370 QImage im = subpix.toImage();
4371 for(int i = 0; i < im.width(); i++) {
4372 for(int j = 0; j < im.height(); j++)
4373 QCOMPARE(qAlpha(im.pixel(i, j)), 255);
4379 void tst_QGraphicsScene::taskQTBUG_7863_paintIntoCacheWithTransparentParts()
4381 // Test using DeviceCoordinateCache and semi-transparent item
4383 QGraphicsRectItem *backItem = new QGraphicsRectItem(0, 0, 100, 100);
4384 backItem->setBrush(QColor(255, 255, 0));
4385 QGraphicsRectItem *rectItem = new QGraphicsRectItem(0, 0, 50, 50);
4386 rectItem->setBrush(QColor(0, 0, 255, 125));
4387 rectItem->setParentItem(backItem);
4389 QGraphicsScene *scene = new QGraphicsScene();
4390 CustomView *view = new CustomView;
4391 view->setScene(scene);
4393 scene->addItem(backItem);
4394 rectItem->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
4395 backItem->rotate(15);
4398 QVERIFY(QTest::qWaitForWindowExposed(view));
4400 rectItem->update(10, 10, 10, 10);
4402 QTRY_VERIFY(view->repaints > 0);
4405 QGraphicsItemPrivate* itemp = QGraphicsItemPrivate::get(rectItem);
4406 QTRY_VERIFY(QPixmapCache::find(itemp->extraItemCache()->deviceData.value(view->viewport()).key, &pix));
4408 QTransform t = rectItem->sceneTransform();
4409 // Map from scene coordinates to pixmap coordinates.
4410 // X origin in the pixmap is the most-left point
4411 // of the item's boundingRect in the scene.
4412 qreal adjust = t.mapRect(rectItem->boundingRect().toRect()).left();
4413 QRect rect = t.mapRect(QRect(10, 10, 10, 10)).adjusted(-adjust, 0, -adjust + 1, 1);
4414 QPixmap subpix = pix.copy(rect);
4416 QImage im = subpix.toImage();
4417 for(int i = 0; i < im.width(); i++) {
4418 for(int j = 0; j < im.height(); j++) {
4419 QCOMPARE(qAlpha(im.pixel(i, j)), 125);
4426 // Test using ItemCoordinateCache and opaque item
4428 QGraphicsRectItem *rectItem = new QGraphicsRectItem(0, 0, 50, 50);
4429 rectItem->setBrush(QColor(0, 0, 255));
4431 QGraphicsScene *scene = new QGraphicsScene();
4432 CustomView *view = new CustomView;
4433 view->setScene(scene);
4435 scene->addItem(rectItem);
4436 rectItem->setCacheMode(QGraphicsItem::ItemCoordinateCache);
4437 rectItem->rotate(15);
4440 QVERIFY(QTest::qWaitForWindowExposed(view));
4442 rectItem->update(10, 10, 10, 10);
4444 QTRY_VERIFY(view->repaints > 0);
4447 QGraphicsItemPrivate* itemp = QGraphicsItemPrivate::get(rectItem);
4448 QTRY_VERIFY(QPixmapCache::find(itemp->extraItemCache()->key, &pix));
4450 QTransform t = rectItem->sceneTransform();
4451 // Map from scene coordinates to pixmap coordinates.
4452 // X origin in the pixmap is the most-left point
4453 // of the item's boundingRect in the scene.
4454 qreal adjust = t.mapRect(rectItem->boundingRect().toRect()).left();
4455 QRect rect = t.mapRect(QRect(10, 10, 10, 10)).adjusted(-adjust, 0, -adjust + 1, 1);
4456 QPixmap subpix = pix.copy(rect);
4458 QImage im = subpix.toImage();
4459 for(int i = 0; i < im.width(); i++) {
4460 for(int j = 0; j < im.height(); j++)
4461 QCOMPARE(qAlpha(im.pixel(i, j)), 255);
4467 // Test using ItemCoordinateCache and semi-transparent item
4469 QGraphicsRectItem *rectItem = new QGraphicsRectItem(0, 0, 50, 50);
4470 rectItem->setBrush(QColor(0, 0, 255, 125));
4472 QGraphicsScene *scene = new QGraphicsScene();
4473 CustomView *view = new CustomView;
4474 view->setScene(scene);
4476 scene->addItem(rectItem);
4477 rectItem->setCacheMode(QGraphicsItem::ItemCoordinateCache);
4478 rectItem->rotate(15);
4481 QVERIFY(QTest::qWaitForWindowExposed(view));
4483 rectItem->update(10, 10, 10, 10);
4485 QTRY_VERIFY(view->repaints > 0);
4488 QGraphicsItemPrivate* itemp = QGraphicsItemPrivate::get(rectItem);
4489 QTRY_VERIFY(QPixmapCache::find(itemp->extraItemCache()->key, &pix));
4491 QTransform t = rectItem->sceneTransform();
4492 // Map from scene coordinates to pixmap coordinates.
4493 // X origin in the pixmap is the most-left point
4494 // of the item's boundingRect in the scene.
4495 qreal adjust = t.mapRect(rectItem->boundingRect().toRect()).left();
4496 QRect rect = t.mapRect(QRect(10, 10, 10, 10)).adjusted(-adjust, 0, -adjust + 1, 1);
4497 QPixmap subpix = pix.copy(rect);
4499 QImage im = subpix.toImage();
4500 for(int i = 0; i < im.width(); i++) {
4501 for(int j = 0; j < im.height(); j++)
4502 QCOMPARE(qAlpha(im.pixel(i, j)), 125);
4509 void tst_QGraphicsScene::taskQT_3674_doNotCrash()
4511 QGraphicsScene scene;
4513 QGraphicsView view(&scene);
4514 view.resize(200, 200);
4516 QPixmap pixmap(view.size());
4517 QPainter painter(&pixmap);
4518 view.render(&painter);
4521 scene.addItem(new QGraphicsWidget);
4522 scene.setBackgroundBrush(Qt::green);
4524 QApplication::processEvents();
4525 QApplication::processEvents();
4528 void tst_QGraphicsScene::zeroScale()
4531 QGraphicsScene scene;
4532 scene.setSceneRect(-100, -100, 100, 100);
4533 QGraphicsView view(&scene);
4536 connect(&scene, SIGNAL(changed(QList<QRectF>)), &cl, SLOT(changed(QList<QRectF>)));
4538 QGraphicsRectItem *rect1 = new QGraphicsRectItem(0, 0, 0.0000001, 0.00000001);
4539 scene.addItem(rect1);
4540 rect1->setRotation(82);
4541 rect1->setScale(0.00000001);
4543 QApplication::processEvents();
4544 QTRY_COMPARE(cl.changes.count(), 1);
4545 QGraphicsRectItem *rect2 = new QGraphicsRectItem(-0.0000001, -0.0000001, 0.0000001, 0.0000001);
4546 rect2->setScale(0.00000001);
4547 scene.addItem(rect2);
4548 rect1->setPos(20,20);
4549 QApplication::processEvents();
4550 QTRY_COMPARE(cl.changes.count(), 2);
4553 void tst_QGraphicsScene::taskQTBUG_15977_renderWithDeviceCoordinateCache()
4555 QGraphicsScene scene;
4556 scene.setSceneRect(0, 0, 100, 100);
4557 QGraphicsRectItem *rect = scene.addRect(0, 0, 100, 100);
4558 rect->setPen(Qt::NoPen);
4559 rect->setBrush(Qt::red);
4560 rect->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
4562 QImage image(100, 100, QImage::Format_RGB32);
4567 QImage expected(100, 100, QImage::Format_RGB32);
4569 p.fillRect(expected.rect(), Qt::red);
4572 QCOMPARE(image, expected);
4575 void tst_QGraphicsScene::taskQTBUG_16401_focusItem()
4577 QGraphicsScene scene;
4578 QGraphicsView view(&scene);
4579 QGraphicsRectItem *rect = scene.addRect(0, 0, 100, 100);
4580 rect->setFlag(QGraphicsItem::ItemIsFocusable);
4583 QApplication::setActiveWindow(&view);
4584 QVERIFY(QTest::qWaitForWindowActive(&view));
4586 QVERIFY(!scene.focusItem());
4589 QCOMPARE(scene.focusItem(), rect);
4590 QFocusEvent focusOut(QEvent::FocusOut);
4591 QApplication::sendEvent(&view, &focusOut);
4592 QVERIFY(!scene.focusItem());
4593 QFocusEvent focusIn(QEvent::FocusIn);
4594 QApplication::sendEvent(&view, &focusIn);
4595 QCOMPARE(scene.focusItem(), rect);
4598 QVERIFY(!scene.focusItem());
4599 QApplication::sendEvent(&view, &focusOut);
4600 QVERIFY(!scene.focusItem());
4601 QApplication::sendEvent(&view, &focusIn);
4602 QVERIFY(!scene.focusItem());
4605 QTEST_MAIN(tst_QGraphicsScene)
4606 #include "tst_qgraphicsscene.moc"