90d21d6d958aa8489b71bbbc5fa083262e738081
[profile/ivi/qtbase.git] / tests / auto / widgets / graphicsview / qgraphicsscene / tst_qgraphicsscene.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the test suite of the Qt Toolkit.
7 **
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.
16 **
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.
24 **
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.
28 **
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.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42
43 #include <QtTest/QtTest>
44 #if defined(Q_OS_WINCE)
45 #include <ceconfig.h>
46 #endif
47
48 #include <QtGui>
49 #include <QtWidgets>
50 #include <private/qgraphicsscene_p.h>
51 #include <private/qgraphicssceneindex_p.h>
52 #include <math.h>
53 #include "../../../gui/painting/qpathclipper/pathcompare.h"
54 #include "../../../shared/platforminputcontext.h"
55 #include <private/qinputmethod_p.h>
56
57 #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
58 #include <windows.h>
59 #define Q_CHECK_PAINTEVENTS \
60     if (::SwitchDesktop(::GetThreadDesktop(::GetCurrentThreadId())) == 0) \
61         QSKIP("The Graphics View doesn't get the paint events");
62 #else
63 #define Q_CHECK_PAINTEVENTS
64 #endif
65
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)
74
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};
96
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};
117
118 class HoverItem : public QGraphicsRectItem
119 {
120 public:
121     HoverItem()
122         : QGraphicsRectItem(QRectF(-10, -10, 20, 20)), isHovered(false)
123     { setAcceptsHoverEvents(true); }
124
125     bool isHovered;
126
127 protected:
128     void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *)
129     {
130         isHovered = (option->state & QStyle::State_MouseOver);
131
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);
137         if (isHovered) {
138             painter->setBrush(QColor(Qt::blue).light(120));
139         } else {
140             painter->setBrush(Qt::gray);
141         }
142         painter->drawRoundRect(boundingRect().adjusted(0, 0, -5, -5));
143     }
144 };
145
146 class EventSpy : public QGraphicsWidget
147 {
148     Q_OBJECT
149 public:
150     EventSpy(QObject *watched, QEvent::Type type)
151         : _count(0), spied(type)
152     {
153         watched->installEventFilter(this);
154     }
155
156     EventSpy(QGraphicsScene *scene, QGraphicsItem *watched, QEvent::Type type)
157         : _count(0), spied(type)
158     {
159         scene->addItem(this);
160         watched->installSceneEventFilter(this);
161     }
162
163     int count() const { return _count; }
164
165 protected:
166     bool eventFilter(QObject *watched, QEvent *event)
167     {
168         Q_UNUSED(watched);
169         if (event->type() == spied)
170             ++_count;
171         return false;
172     }
173
174     bool sceneEventFilter(QGraphicsItem *watched, QEvent *event)
175     {
176         Q_UNUSED(watched);
177         if (event->type() == spied)
178             ++_count;
179         return false;
180     }
181
182     int _count;
183     QEvent::Type spied;
184 };
185
186 class tst_QGraphicsScene : public QObject
187 {
188     Q_OBJECT
189 public slots:
190     void initTestCase();
191     void cleanup();
192
193 private slots:
194     void construction();
195     void sceneRect();
196     void itemIndexMethod();
197     void bspTreeDepth();
198     void itemsBoundingRect_data();
199     void itemsBoundingRect();
200     void items();
201     void items_QPointF_data();
202     void items_QPointF();
203     void items_QRectF();
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();
212     void addItem();
213     void addEllipse();
214     void addLine();
215     void addPath();
216     void addPixmap();
217     void addRect();
218     void addText();
219     void removeItem();
220     void clear();
221     void focusItem();
222     void focusItemLostFocus();
223     void setFocusItem();
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();
238 #endif
239     void render_data();
240     void render();
241     void renderItemsWithNegativeWidthOrHeight();
242     void contextMenuEvent();
243     void contextMenuEvent_ItemIgnoresTransformations();
244     void update();
245     void update2();
246     void views();
247     void event();
248     void eventsToDisabledItems();
249     void exposedRect();
250     void tabFocus_emptyScene();
251     void tabFocus_sceneWithFocusableItems();
252     void tabFocus_sceneWithFocusWidgets();
253     void tabFocus_sceneWithNestedFocusWidgets();
254     void style();
255     void sorting_data();
256     void sorting();
257     void changedSignal_data();
258     void changedSignal();
259     void stickyFocus_data();
260     void stickyFocus();
261     void sendEvent();
262     void inputMethod_data();
263     void inputMethod();
264     void dispatchHoverOnPress();
265     void initialFocus_data();
266     void initialFocus();
267     void polishItems();
268     void polishItems2();
269     void isActive();
270     void siblingIndexAlwaysValid();
271     void removeFullyTransparentItem();
272     void zeroScale();
273
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();
286 };
287
288 void tst_QGraphicsScene::initTestCase()
289 {
290 #ifdef Q_OS_WINCE //disable magic for WindowsCE
291     qApp->setAutoMaximizeThreshold(-1);
292 #endif
293 }
294
295 void tst_QGraphicsScene::cleanup()
296 {
297     // ensure not even skipped tests with custom input context leave it dangling
298     QInputMethodPrivate *inputMethodPrivate = QInputMethodPrivate::get(qApp->inputMethod());
299     inputMethodPrivate->testContext = 0;
300 }
301
302 void tst_QGraphicsScene::construction()
303 {
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());
316 }
317
318 void tst_QGraphicsScene::sceneRect()
319 {
320     QGraphicsScene scene;
321     QSignalSpy sceneRectChanged(&scene, SIGNAL(sceneRectChanged(QRectF)));
322     QCOMPARE(scene.sceneRect(), QRectF());
323     QCOMPARE(sceneRectChanged.count(), 0);
324
325     QGraphicsItem *item = scene.addRect(QRectF(0, 0, 10, 10));
326     item->setPos(-5, -5);
327     QCOMPARE(sceneRectChanged.count(), 0);
328
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());
335
336     item->setPos(0, 0);
337     QCOMPARE(scene.sceneRect(), QRectF(-5, -5, 15, 15));
338     QCOMPARE(sceneRectChanged.count(), 2);
339     QCOMPARE(sceneRectChanged.last().at(0).toRectF(), scene.sceneRect());
340
341     scene.setSceneRect(-100, -100, 10, 10);
342     QCOMPARE(sceneRectChanged.count(), 3);
343     QCOMPARE(sceneRectChanged.last().at(0).toRectF(), scene.sceneRect());
344
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());
352
353     scene.setSceneRect(QRectF());
354
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());
361 }
362
363 void tst_QGraphicsScene::itemIndexMethod()
364 {
365     QGraphicsScene scene;
366     QCOMPARE(scene.itemIndexMethod(), QGraphicsScene::BspTreeIndex);
367
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;
373 #else
374     const int minY = -1000;
375     const int maxY = 2000;
376     const int minX = -1000;
377     const int maxX = 2000;
378 #endif
379
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));
384             item->setPos(x, y);
385             QCOMPARE(scene.itemAt(x, y), item);
386             items << item;
387         }
388     }
389
390     int n = 0;
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++));
394     }
395
396     scene.setItemIndexMethod(QGraphicsScene::NoIndex);
397     QCOMPARE(scene.itemIndexMethod(), QGraphicsScene::NoIndex);
398
399     n = 0;
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++));
403     }
404
405     scene.setItemIndexMethod(QGraphicsScene::BspTreeIndex);
406     QCOMPARE(scene.itemIndexMethod(), QGraphicsScene::BspTreeIndex);
407
408     n = 0;
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++));
412     }
413 }
414
415 void tst_QGraphicsScene::bspTreeDepth()
416 {
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);
425 }
426
427 void tst_QGraphicsScene::items()
428 {
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;
434 #else
435     const int minY = -1000;
436     const int maxY = 2000;
437     const int minX = -1000;
438     const int maxX = 2000;
439 #endif
440
441     {
442         QGraphicsScene scene;
443
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));
448         }
449         QCOMPARE(scene.items().size(), items.size());
450         scene.itemAt(0, 0); // trigger indexing
451
452         scene.removeItem(items.at(5));
453         delete items.at(5);
454         QVERIFY(!scene.items().contains(0));
455         delete items.at(7);
456         QVERIFY(!scene.items().contains(0));
457     }
458     {
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;
465         items<<l1<<l2;
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));
469     }
470 }
471
472 void tst_QGraphicsScene::itemsBoundingRect_data()
473 {
474     QTest::addColumn<QList<QRectF> >("rects");
475     QTest::addColumn<QMatrix>("matrix");
476     QTest::addColumn<QRectF>("boundingRect");
477
478     QMatrix transformationMatrix;
479     transformationMatrix.translate(50, -50);
480     transformationMatrix.scale(2, 2);
481     transformationMatrix.rotate(90);
482
483     QTest::newRow("none")
484         << QList<QRectF>()
485         << QMatrix()
486         << QRectF();
487     QTest::newRow("{{0, 0, 10, 10}}")
488         << (QList<QRectF>() << QRectF(0, 0, 10, 10))
489         << QMatrix()
490         << QRectF(0, 0, 10, 10);
491     QTest::newRow("{{-10, -10, 10, 10}}")
492         << (QList<QRectF>() << QRectF(-10, -10, 10, 10))
493         << QMatrix()
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))
497         << QMatrix()
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);
511
512     QList<QRectF> all;
513     for (int i = 0; i < 256; ++i)
514         all << QRectF(randomX[i], randomY[i], 10, 10);
515     QTest::newRow("all")
516         << all
517         << QMatrix()
518         << QRectF(-980, -994, 1988, 1983);
519     QTest::newRow("transformed all")
520         << all
521         << transformationMatrix
522         << QRectF(-1928, -2010, 3966, 3976);
523 }
524
525 void tst_QGraphicsScene::itemsBoundingRect()
526 {
527     QFETCH(QList<QRectF>, rects);
528     QFETCH(QMatrix, matrix);
529     QFETCH(QRectF, boundingRect);
530
531     QGraphicsScene scene;
532
533     foreach (QRectF rect, rects) {
534         QPainterPath path;
535         path.addRect(rect);
536         scene.addPath(path)->setMatrix(matrix);
537     }
538
539     QCOMPARE(scene.itemsBoundingRect(), boundingRect);
540 }
541
542 void tst_QGraphicsScene::items_QPointF_data()
543 {
544     QTest::addColumn<QList<QRectF> >("items");
545     QTest::addColumn<QPointF>("point");
546     QTest::addColumn<QList<int> >("itemsAtPoint");
547
548     QTest::newRow("empty")
549         << QList<QRectF>()
550         << QPointF()
551         << QList<int>();
552     QTest::newRow("1")
553         << (QList<QRectF>() << QRectF(0, 0, 10, 10))
554         << QPointF(0, 0)
555         << (QList<int>() << 0);
556     QTest::newRow("2")
557         << (QList<QRectF>() << QRectF(0, 0, 10, 10))
558         << QPointF(5, 5)
559         << (QList<int>() << 0);
560     QTest::newRow("3")
561         << (QList<QRectF>() << QRectF(0, 0, 10, 10))
562         << QPointF(9.9, 9.9)
563         << (QList<int>() << 0);
564     QTest::newRow("3.5")
565         << (QList<QRectF>() << QRectF(0, 0, 10, 10))
566         << QPointF(10, 10)
567         << QList<int>();
568     QTest::newRow("4")
569         << (QList<QRectF>() << QRectF(0, 0, 10, 10) << QRectF(9.9, 9.9, 10, 10))
570         << QPointF(9.9, 9.9)
571         << (QList<int>() << 1 << 0);
572     QTest::newRow("4.5")
573         << (QList<QRectF>() << QRectF(0, 0, 10, 10) << QRectF(10, 10, 10, 10))
574         << QPointF(10, 10)
575         << (QList<int>() << 1);
576     QTest::newRow("5")
577         << (QList<QRectF>() << QRectF(5, 5, 10, 10) << QRectF(10, 10, 10, 10))
578         << QPointF(10, 10)
579         << (QList<int>() << 1 << 0);
580     QTest::newRow("6")
581         << (QList<QRectF>() << QRectF(5, 5, 10, 10) << QRectF(10, 10, 10, 10) << QRectF(0, 0, 20, 30))
582         << QPointF(10, 10)
583         << (QList<int>() << 2 << 1 << 0);
584 }
585
586 void tst_QGraphicsScene::items_QPointF()
587 {
588     QFETCH(QList<QRectF>, items);
589     QFETCH(QPointF, point);
590     QFETCH(QList<int>, itemsAtPoint);
591
592     QGraphicsScene scene;
593
594     int n = 0;
595     QList<QGraphicsItem *> addedItems;
596     foreach(QRectF rect, items) {
597         QPainterPath path;
598         path.addRect(0, 0, rect.width(), rect.height());
599
600         QGraphicsItem *item = scene.addPath(path);
601         item->setZValue(n++);
602         item->setPos(rect.topLeft());
603         addedItems << item;
604     }
605
606     QList<int> itemIndexes;
607     foreach (QGraphicsItem *item, scene.items(point))
608         itemIndexes << addedItems.indexOf(item);
609
610     QCOMPARE(itemIndexes, itemsAtPoint);
611 }
612
613 void tst_QGraphicsScene::items_QRectF()
614 {
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));
620
621     item1->setZValue(0);
622     item2->setZValue(1);
623     item3->setZValue(2);
624     item4->setZValue(3);
625
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);
634
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);
637
638     item1->setZValue(3);
639     item2->setZValue(2);
640     item3->setZValue(1);
641     item4->setZValue(0);
642
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);
645 }
646
647 void tst_QGraphicsScene::items_QRectF_2_data()
648 {
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");
654
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;
679
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;
682
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;
693
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;
697
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;
701
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;
708
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;
714 }
715
716 void tst_QGraphicsScene::items_QRectF_2()
717 {
718     QFETCH(QRectF, ellipseRect);
719     QFETCH(QRectF, sceneRect);
720     QFETCH(Qt::ItemSelectionMode, selectionMode);
721     QFETCH(bool, contained);
722     QFETCH(bool, containedRotated);
723
724     QGraphicsScene scene;
725     QGraphicsItem *item = scene.addEllipse(ellipseRect);
726
727     QCOMPARE(!scene.items(sceneRect, selectionMode).isEmpty(), contained);
728     item->rotate(45);
729     QCOMPARE(!scene.items(sceneRect, selectionMode).isEmpty(), containedRotated);
730 }
731
732 void tst_QGraphicsScene::items_QPolygonF()
733 {
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));
739
740     item1->setZValue(0);
741     item2->setZValue(1);
742     item3->setZValue(2);
743     item4->setZValue(3);
744
745     QPolygonF poly1(item1->boundingRect());
746     QPolygonF poly2(item2->boundingRect());
747     QPolygonF poly3(item3->boundingRect());
748     QPolygonF poly4(item4->boundingRect());
749
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);
754
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));
759
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);
764
765     poly1 = QPolygonF(QRectF(-10, -10, 40, 10));
766     poly2 = QPolygonF(QRectF(-10, 10, 40, 10));
767
768     QCOMPARE(scene.items(poly1), QList<QGraphicsItem *>() << item2 << item1);
769     QCOMPARE(scene.items(poly2), QList<QGraphicsItem *>() << item4 << item3);
770
771     item1->setZValue(3);
772     item2->setZValue(2);
773     item3->setZValue(1);
774     item4->setZValue(0);
775
776     QCOMPARE(scene.items(poly1), QList<QGraphicsItem *>() << item1 << item2);
777     QCOMPARE(scene.items(poly2), QList<QGraphicsItem *>() << item3 << item4);
778 }
779
780 void tst_QGraphicsScene::items_QPolygonF_2()
781 {
782     QGraphicsScene scene;
783     QGraphicsItem *ellipse = scene.addEllipse(QRectF(0, 0, 100, 100));
784
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());
794
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);
805
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());
809
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);
813
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);
820 }
821
822 void tst_QGraphicsScene::items_QPainterPath()
823 {
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));
829
830     item1->setZValue(0);
831     item2->setZValue(1);
832     item3->setZValue(2);
833     item4->setZValue(3);
834
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());
839
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);
844
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));
849
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);
854
855     path1 = QPainterPath(); path1.addRect(QRectF(-10, -10, 40, 10));
856     path2 = QPainterPath(); path2.addRect(QRectF(-10, 10, 40, 10));
857
858     QCOMPARE(scene.items(path1), QList<QGraphicsItem *>() << item2 << item1);
859     QCOMPARE(scene.items(path2), QList<QGraphicsItem *>() << item4 << item3);
860
861     item1->setZValue(3);
862     item2->setZValue(2);
863     item3->setZValue(1);
864     item4->setZValue(0);
865
866     QCOMPARE(scene.items(path1), QList<QGraphicsItem *>() << item1 << item2);
867     QCOMPARE(scene.items(path2), QList<QGraphicsItem *>() << item3 << item4);
868 }
869
870 void tst_QGraphicsScene::items_QPainterPath_2()
871 {
872     QGraphicsScene scene;
873     QGraphicsItem *ellipse = scene.addEllipse(QRectF(0, 0, 100, 100));
874
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));
879
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());
889
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);
900
901     QPainterPath p5;
902     p5.addRect(QRectF(5, 5, 90, 90));
903
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());
907
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);
911
912     QPainterPath p6;
913     p6.addRect(QRectF(-5, -5, 110, 110));
914
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);
921 }
922
923 class CustomView : public QGraphicsView
924 {
925 public:
926     CustomView() : repaints(0)
927     { }
928
929     int repaints;
930 protected:
931     void paintEvent(QPaintEvent *event)
932     {
933         ++repaints;
934         QGraphicsView::paintEvent(event);
935     }
936 };
937
938 void tst_QGraphicsScene::selectionChanged()
939 {
940     QGraphicsScene scene(0, 0, 1000, 1000);
941     QSignalSpy spy(&scene, SIGNAL(selectionChanged()));
942     QCOMPARE(spy.count(), 0);
943
944     QPainterPath path;
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());
951
952     QGraphicsItem *rect = scene.addRect(QRectF(0, 0, 100, 100));
953     QCOMPARE(spy.count(), 0); // selection didn't change
954
955     rect->setSelected(true);
956     QVERIFY(!rect->isSelected());
957     QCOMPARE(spy.count(), 0); // selection didn't change, item isn't selectable
958
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);
964
965     rect->setSelected(false);
966     QVERIFY(!rect->isSelected());
967     QCOMPARE(spy.count(), 2); // selection changed
968     QVERIFY(scene.selectedItems().isEmpty());
969
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);
978
979     QCOMPARE(spy.count(), 3); // the grandchild was added, so the selection changed once
980
981     scene.removeItem(parentItem);
982     QCOMPARE(spy.count(), 4); // the grandchild was removed, so the selection changed
983
984     rect->setSelected(true);
985     QCOMPARE(spy.count(), 5); // the rect was reselected, so the selection changed
986
987     scene.clearSelection();
988     QCOMPARE(spy.count(), 6); // the scene selection was cleared
989
990     rect->setSelected(true);
991     QCOMPARE(spy.count(), 7); // the rect was reselected, so the selection changed
992
993     rect->setFlag(QGraphicsItem::ItemIsSelectable, false);
994     QCOMPARE(spy.count(), 8); // the rect was unselected, so the selection changed
995
996     rect->setSelected(true);
997     QCOMPARE(spy.count(), 8); // the rect is not longer selectable, so the selection does not change
998
999
1000     rect->setFlag(QGraphicsItem::ItemIsSelectable, true);
1001     rect->setSelected(true);
1002     QCOMPARE(spy.count(), 9); // the rect is again selectable, so the selection changed
1003
1004     delete rect;
1005     QCOMPARE(spy.count(), 10); // a selected item was deleted; selection changed
1006 }
1007
1008 void tst_QGraphicsScene::selectionChanged2()
1009 {
1010     QGraphicsScene scene;
1011     QSignalSpy spy(&scene, SIGNAL(selectionChanged()));
1012
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);
1017
1018     QCOMPARE(spy.count(), 0);
1019     {
1020         QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
1021         event.setScenePos(QPointF(50, 50));
1022         event.setButton(Qt::LeftButton);
1023         qApp->sendEvent(&scene, &event);
1024     }
1025     {
1026         QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseRelease);
1027         event.setScenePos(QPointF(50, 50));
1028         event.setButton(Qt::LeftButton);
1029         qApp->sendEvent(&scene, &event);
1030     }
1031     QVERIFY(item1->isSelected());
1032     QVERIFY(!item2->isSelected());
1033     QCOMPARE(spy.count(), 1);
1034     {
1035         QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
1036         event.setScenePos(QPointF(150, 150));
1037         event.setButton(Qt::LeftButton);
1038         qApp->sendEvent(&scene, &event);
1039     }
1040     {
1041         QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseRelease);
1042         event.setScenePos(QPointF(150, 150));
1043         event.setButton(Qt::LeftButton);
1044         qApp->sendEvent(&scene, &event);
1045     }
1046     QVERIFY(!item1->isSelected());
1047     QVERIFY(item2->isSelected());
1048     QCOMPARE(spy.count(), 2);
1049     {
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);
1055     }
1056     QVERIFY(!item1->isSelected());
1057     QVERIFY(item2->isSelected());
1058     QCOMPARE(spy.count(), 2);
1059     {
1060         QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseRelease);
1061         event.setScenePos(QPointF(50, 50));
1062         event.setButton(Qt::LeftButton);
1063         qApp->sendEvent(&scene, &event);
1064     }
1065     QVERIFY(item1->isSelected());
1066     QVERIFY(!item2->isSelected());
1067     QCOMPARE(spy.count(), 3);
1068 }
1069
1070 void tst_QGraphicsScene::addItem()
1071 {
1072     Q_CHECK_PAINTEVENTS
1073     {
1074         // 1) Create item, then scene, then add item
1075         QGraphicsItem *path = new QGraphicsEllipseItem(QRectF(-10, -10, 20, 20));
1076         QGraphicsScene scene;
1077
1078         CustomView view;
1079         view.setScene(&scene);
1080         view.show();
1081         QVERIFY(QTest::qWaitForWindowExposed(&view));
1082         qApp->processEvents();
1083         view.repaints = 0;
1084
1085         scene.addItem(path);
1086
1087         // Adding an item should always issue a repaint.
1088         QTRY_VERIFY(view.repaints > 0);
1089         view.repaints = 0;
1090
1091         QCOMPARE(scene.itemAt(0, 0), path);
1092
1093         QGraphicsItem *path2 = new QGraphicsEllipseItem(QRectF(-10, -10, 20, 20));
1094         path2->setPos(100, 100);
1095
1096         QCOMPARE(scene.itemAt(0, 0), path);
1097         QCOMPARE(scene.itemAt(100, 100), (QGraphicsItem *)0);
1098         scene.addItem(path2);
1099
1100         // Adding an item should always issue a repaint.
1101         QTRY_VERIFY(view.repaints > 0);
1102
1103         QCOMPARE(scene.itemAt(100, 100), path2);
1104     }
1105     {
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);
1110
1111         QGraphicsItem *path2 = new QGraphicsEllipseItem(QRectF(-10, -10, 20, 20));
1112         path2->setPos(100, 100);
1113         scene.addItem(path2);
1114
1115         QCOMPARE(scene.itemAt(0, 0), path);
1116         QCOMPARE(scene.itemAt(100, 100), path2);
1117     }
1118 }
1119
1120 void tst_QGraphicsScene::addEllipse()
1121 {
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);
1138 }
1139
1140 void tst_QGraphicsScene::addLine()
1141 {
1142     QGraphicsScene scene;
1143     QPen pen(Qt::red);
1144     pen.setWidthF(1.0);
1145     QGraphicsLineItem *line = scene.addLine(QLineF(-10, -10, 20, 20),
1146                                             pen);
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);
1159 }
1160
1161 void tst_QGraphicsScene::addPath()
1162 {
1163     QGraphicsScene scene;
1164     QPainterPath p;
1165     p.addEllipse(QRectF(-10, -10, 20, 20));
1166     p.addEllipse(QRectF(-10, 20, 20, 20));
1167
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");
1191 else
1192     QCOMPARE(scene.itemAt(-10, 30), (QGraphicsItem *)0);
1193     QCOMPARE(scene.itemAt(10.1, 30), (QGraphicsItem *)0);
1194 }
1195
1196 void tst_QGraphicsScene::addPixmap()
1197 {
1198     QGraphicsScene scene;
1199     QPixmap pix(":/Ash_European.jpg");
1200     QGraphicsPixmapItem *pixmap = scene.addPixmap(pix);
1201
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);
1214 }
1215
1216 void tst_QGraphicsScene::addRect()
1217 {
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);
1234 }
1235
1236 void tst_QGraphicsScene::addText()
1237 {
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());
1243 }
1244
1245 void tst_QGraphicsScene::removeItem()
1246 {
1247 #if defined(Q_OS_WINCE) && !defined(GWES_ICONCURS)
1248     QSKIP("No mouse cursor support");
1249 #endif
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);
1255     delete item;
1256
1257     QGraphicsItem *item2 = scene.addRect(QRectF(0, 0, 10, 10));
1258     item2->setFlag(QGraphicsItem::ItemIsSelectable);
1259     QCOMPARE(scene.itemAt(0, 0), item2);
1260
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());
1267
1268     // Check that we are in a state that can receive paint events
1269     // (i.e., not logged out on Windows).
1270     Q_CHECK_PAINTEVENTS
1271
1272     // Removing a hovered item
1273     HoverItem *hoverItem = new HoverItem;
1274     scene.addItem(hoverItem);
1275     scene.setSceneRect(-50, -50, 100, 100);
1276
1277     QGraphicsView view(&scene);
1278     view.setFixedSize(150, 150);
1279     view.show();
1280     QApplication::setActiveWindow(&view);
1281     QVERIFY(QTest::qWaitForWindowActive(&view));
1282     QTest::mouseMove(view.viewport(), QPoint(-1, -1));
1283     {
1284         QMouseEvent moveEvent(QEvent::MouseMove, view.mapFromScene(hoverItem->scenePos() + QPointF(20, 20)), Qt::NoButton, 0, 0);
1285         QApplication::sendEvent(view.viewport(), &moveEvent);
1286     }
1287     qApp->processEvents(); // update
1288     qApp->processEvents(); // draw
1289     QVERIFY(!hoverItem->isHovered);
1290
1291     {
1292         QTest::qWait(250);
1293         QTest::mouseMove(view.viewport(), view.mapFromScene(hoverItem->scenePos()), Qt::NoButton);
1294         QTest::qWait(10);
1295         QMouseEvent moveEvent(QEvent::MouseMove, view.mapFromScene(hoverItem->scenePos()), Qt::NoButton, 0, 0);
1296         QApplication::sendEvent(view.viewport(), &moveEvent);
1297     }
1298     qApp->processEvents(); // update
1299     qApp->processEvents(); // draw
1300     QVERIFY(hoverItem->isHovered);
1301
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);
1309 }
1310
1311 void tst_QGraphicsScene::focusItem()
1312 {
1313     QGraphicsScene scene;
1314     QEvent activate(QEvent::WindowActivate);
1315     QApplication::sendEvent(&scene, &activate);
1316
1317     QVERIFY(!scene.focusItem());
1318     QGraphicsItem *item = scene.addText("Qt");
1319     QVERIFY(!scene.focusItem());
1320     item->setFocus();
1321     QVERIFY(!scene.focusItem());
1322     item->setFlag(QGraphicsItem::ItemIsFocusable);
1323     QVERIFY(!scene.focusItem());
1324     item->setFocus();
1325     QCOMPARE(scene.focusItem(), item);
1326
1327     QFocusEvent focusOut(QEvent::FocusOut);
1328     QApplication::sendEvent(&scene, &focusOut);
1329
1330     QVERIFY(!scene.focusItem());
1331
1332     QFocusEvent focusIn(QEvent::FocusIn);
1333     QApplication::sendEvent(&scene, &focusIn);
1334     QCOMPARE(scene.focusItem(), item);
1335
1336     QGraphicsItem *item2 = scene.addText("Qt");
1337     item2->setFlag(QGraphicsItem::ItemIsFocusable);
1338     QCOMPARE(scene.focusItem(), item);
1339
1340     item2->setFocus();
1341     QCOMPARE(scene.focusItem(), item2);
1342     item->setFocus();
1343     QCOMPARE(scene.focusItem(), item);
1344
1345     item2->setFocus();
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);
1352
1353     QApplication::sendEvent(&scene, &focusOut);
1354
1355     QVERIFY(!scene.focusItem());
1356     scene.removeItem(item2);
1357     delete item2;
1358
1359     QApplication::sendEvent(&scene, &focusIn);
1360     QVERIFY(!scene.focusItem());
1361 }
1362
1363 class FocusItem : public QGraphicsTextItem
1364 {
1365 protected:
1366     void focusOutEvent(QFocusEvent *)
1367     {
1368         QVERIFY(!scene()->focusItem());
1369     }
1370 };
1371
1372 void tst_QGraphicsScene::focusItemLostFocus()
1373 {
1374     QGraphicsScene scene;
1375     QEvent activate(QEvent::WindowActivate);
1376     QApplication::sendEvent(&scene, &activate);
1377
1378     FocusItem *item = new FocusItem;
1379     item->setTextInteractionFlags(Qt::TextEditorInteraction);
1380     scene.addItem(item);
1381
1382     item->setFocus();
1383     QCOMPARE(scene.focusItem(), (QGraphicsItem *)item);
1384     item->clearFocus();
1385 }
1386
1387 class ClearTestItem : public QGraphicsRectItem
1388 {
1389 public:
1390     ClearTestItem(QGraphicsItem *parent = 0) : QGraphicsRectItem(parent) {}
1391     ~ClearTestItem() { qDeleteAll(items); }
1392     QList<QGraphicsItem *> items;
1393 };
1394
1395 void tst_QGraphicsScene::clear()
1396 {
1397     QGraphicsScene scene;
1398     scene.clear();
1399     QVERIFY(scene.items().isEmpty());
1400     scene.addRect(0, 0, 100, 100);
1401     QCOMPARE(scene.sceneRect(), QRectF(0, 0, 100, 100));
1402     scene.clear();
1403     QVERIFY(scene.items().isEmpty());
1404     QCOMPARE(scene.sceneRect(), QRectF(0, 0, 100, 100));
1405
1406     ClearTestItem *firstItem = new ClearTestItem;
1407     QGraphicsItem *secondItem = new QGraphicsRectItem;
1408     firstItem->items += secondItem;
1409
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);
1415
1416     ClearTestItem *thirdItem = new ClearTestItem(firstItem);
1417     QGraphicsItem *forthItem = new QGraphicsRectItem(firstItem);
1418     thirdItem->items += forthItem;
1419
1420     // must not crash even if firstItem deletes secondItem
1421     scene.clear();
1422     QVERIFY(scene.items().isEmpty());
1423 }
1424
1425 void tst_QGraphicsScene::setFocusItem()
1426 {
1427     QGraphicsScene scene;
1428     QEvent activate(QEvent::WindowActivate);
1429     QApplication::sendEvent(&scene, &activate);
1430
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);
1438
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());
1444     }
1445
1446     QGraphicsItem *item2 = scene.addText("Qt");
1447     item2->setFlag(QGraphicsItem::ItemIsFocusable);
1448
1449     scene.setFocusItem(item2);
1450     QVERIFY(!item->hasFocus());
1451     QVERIFY(item2->hasFocus());
1452
1453     scene.setFocusItem(item);
1454     QVERIFY(item->hasFocus());
1455     QVERIFY(!item2->hasFocus());
1456
1457     scene.clearFocus();
1458     QVERIFY(!item->hasFocus());
1459     QVERIFY(!item2->hasFocus());
1460
1461     scene.setFocus();
1462     QVERIFY(item->hasFocus());
1463     QVERIFY(!item2->hasFocus());
1464
1465     scene.setFocusItem(0);
1466     QVERIFY(!item->hasFocus());
1467     QVERIFY(!item2->hasFocus());
1468
1469     scene.setFocus();
1470     QVERIFY(!item->hasFocus());
1471     QVERIFY(!item2->hasFocus());
1472 }
1473
1474 void tst_QGraphicsScene::setFocusItem_inactive()
1475 {
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);
1484
1485     for (int i = 0; i < 3; ++i) {
1486         scene.setFocusItem(item);
1487         QCOMPARE(scene.focusItem(), item);
1488         QVERIFY(!item->hasFocus());
1489     }
1490
1491 }
1492
1493
1494 void tst_QGraphicsScene::mouseGrabberItem()
1495 {
1496     QGraphicsScene scene;
1497     QVERIFY(!scene.mouseGrabberItem());
1498
1499     QGraphicsItem *item = scene.addRect(QRectF(-10, -10, 20, 20));
1500     item->setFlag(QGraphicsItem::ItemIsMovable);
1501     item->setZValue(1);
1502
1503     QGraphicsItem *item2 = scene.addRect(QRectF(-10, -10, 20, 20));
1504     item2->setFlag(QGraphicsItem::ItemIsMovable);
1505     item2->setZValue(0);
1506
1507     for (int i = 0; i < 3; ++i) {
1508         item->setPos(0, 0);
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;
1513
1514         QGraphicsSceneMouseEvent pressEvent(QEvent::GraphicsSceneMousePress);
1515         pressEvent.setButton(Qt::LeftButton);
1516         pressEvent.setScenePos(QPointF(0, 0));
1517         pressEvent.setScreenPos(QPoint(100, 100));
1518
1519         QApplication::sendEvent(&scene, &pressEvent);
1520         QCOMPARE(scene.mouseGrabberItem(), topMostItem);
1521
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);
1529
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);
1535         }
1536
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());
1542     }
1543
1544     // Structural change: deleting the mouse grabber
1545     item->setPos(0, 0);
1546     item->setZValue(1);
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));
1553
1554     QGraphicsSceneMouseEvent moveEvent(QEvent::GraphicsSceneMouseMove);
1555     moveEvent.setButtons(Qt::LeftButton);
1556     moveEvent.setScenePos(QPointF(0, 0));
1557     moveEvent.setScreenPos(QPoint(100, 100));
1558
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);
1577     delete item2;
1578     QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
1579 }
1580
1581 void tst_QGraphicsScene::hoverEvents_siblings()
1582 {
1583     Q_CHECK_PAINTEVENTS
1584
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;
1592         if (lastItem) {
1593             item->setPos(lastItem->pos() + QPointF(sin(i / 3.0) * 17, cos(i / 3.0) * 17));
1594         }
1595         item->setZValue(i);
1596         lastItem = item;
1597     }
1598
1599     QGraphicsView view(&scene);
1600     view.setRenderHint(QPainter::Antialiasing, true);
1601 #if defined(Q_OS_WINCE)
1602     view.setMinimumSize(230, 200);
1603 #else
1604     view.setMinimumSize(400, 300);
1605 #endif
1606     view.rotate(10);
1607     view.scale(1.7, 1.7);
1608     view.show();
1609     qApp->setActiveWindow(&view);
1610     view.activateWindow();
1611     QVERIFY(QTest::qWaitForWindowActive(&view));
1612
1613     QCursor::setPos(view.mapToGlobal(QPoint(-5, -5)));
1614
1615     QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMouseMove);
1616     mouseEvent.setScenePos(QPointF(-1000, -1000));
1617     QApplication::sendEvent(&scene, &mouseEvent);
1618
1619     QTest::qWait(50);
1620
1621     for (int j = 1; j >= 0; --j) {
1622         int i = j ? 0 : 14;
1623         forever {
1624             if (j)
1625                 QVERIFY(!items.at(i)->isHovered);
1626             else
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);
1631
1632             qApp->processEvents(); // this posts updates from the scene to the view
1633             qApp->processEvents(); // which trigger a repaint here
1634
1635             QTRY_VERIFY(items.at(i)->isHovered);
1636             if (j && i > 0)
1637                 QVERIFY(!items.at(i - 1)->isHovered);
1638             if (!j && i < 14)
1639                 QVERIFY(!items.at(i + 1)->isHovered);
1640             i += j ? 1 : -1;
1641             if ((j && i == 15) || (!j && i == -1))
1642                 break;
1643         }
1644
1645         QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMouseMove);
1646         mouseEvent.setScenePos(QPointF(-1000, -1000));
1647         QApplication::sendEvent(&scene, &mouseEvent);
1648
1649         qApp->processEvents(); // this posts updates from the scene to the view
1650         qApp->processEvents(); // which trigger a repaint here
1651     }
1652 }
1653
1654 void tst_QGraphicsScene::hoverEvents_parentChild()
1655 {
1656     Q_CHECK_PAINTEVENTS
1657
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;
1665         if (lastItem) {
1666             item->setParentItem(lastItem);
1667             item->setPos(sin(i / 3.0) * 17, cos(i / 3.0) * 17);
1668         }
1669         lastItem = item;
1670     }
1671
1672     QGraphicsView view(&scene);
1673     view.setRenderHint(QPainter::Antialiasing, true);
1674 #if defined(Q_OS_WINCE)
1675     view.setMinimumSize(230, 200);
1676 #else
1677     view.setMinimumSize(400, 300);
1678 #endif
1679     view.rotate(10);
1680     view.scale(1.7, 1.7);
1681     view.show();
1682     qApp->setActiveWindow(&view);
1683     QVERIFY(QTest::qWaitForWindowActive(&view));
1684
1685     QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMouseMove);
1686     mouseEvent.setScenePos(QPointF(-1000, -1000));
1687     QApplication::sendEvent(&scene, &mouseEvent);
1688
1689     for (int j = 1; j >= 0; --j) {
1690         int i = j ? 0 : 14;
1691         forever {
1692             if (j) {
1693                 QVERIFY(!items.at(i)->isHovered);
1694             } else {
1695                 if (i == 14)
1696                     QVERIFY(!items.at(13)->isHovered);
1697             }
1698             mouseEvent.setScenePos(items.at(i)->mapToScene(0, 0));
1699             QApplication::sendEvent(&scene, &mouseEvent);
1700
1701             qApp->processEvents(); // this posts updates from the scene to the view
1702             qApp->processEvents(); // which trigger a repaint here
1703
1704             QTRY_VERIFY(items.at(i)->isHovered);
1705             if (i < 14)
1706                 QVERIFY(!items.at(i + 1)->isHovered);
1707             i += j ? 1 : -1;
1708             if ((j && i == 15) || (!j && i == -1))
1709                 break;
1710         }
1711
1712         mouseEvent.setScenePos(QPointF(-1000, -1000));
1713         QApplication::sendEvent(&scene, &mouseEvent);
1714
1715         qApp->processEvents(); // this posts updates from the scene to the view
1716         qApp->processEvents(); // which trigger a repaint here
1717     }
1718 }
1719
1720 void tst_QGraphicsScene::createItemGroup()
1721 {
1722     QGraphicsScene scene;
1723
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));
1729
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));
1735
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));
1741
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);
1746
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);
1757
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);
1762
1763     // Now make parent2 a child of parent1, so all children2 are also children
1764     // of parent1.
1765     parent2->setParentItem(parent1);
1766
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);
1773
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);
1782
1783     // Fixup the parent-child chain
1784     foreach (QGraphicsItem *item, children2)
1785         item->setParentItem(parent2);
1786
1787     // These share no common parent
1788     group = scene.createItemGroup(children3);
1789     QCOMPARE(group->parentItem(), (QGraphicsItem *)0);
1790     scene.destroyItemGroup(group);
1791
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);
1796
1797     // These should have parent3 as a parent
1798     group = scene.createItemGroup(children3);
1799     QCOMPARE(group->parentItem(), parent3);
1800     scene.destroyItemGroup(group);
1801
1802     // Now make them all children of parent1
1803     parent3->setParentItem(parent1);
1804
1805     group = scene.createItemGroup(children3);
1806     QCOMPARE(group->parentItem(), parent3);
1807     scene.destroyItemGroup(group);
1808
1809     group = scene.createItemGroup(children2);
1810     QCOMPARE(group->parentItem(), parent2);
1811     scene.destroyItemGroup(group);
1812
1813     group = scene.createItemGroup(children1);
1814     QCOMPARE(group->parentItem(), parent1);
1815     scene.destroyItemGroup(group);
1816
1817     QGraphicsItemGroup *emptyGroup = scene.createItemGroup(QList<QGraphicsItem *>());
1818     QCOMPARE(emptyGroup->children(), QList<QGraphicsItem *>());
1819     QVERIFY(!emptyGroup->parentItem());
1820     QCOMPARE(emptyGroup->scene(), &scene);
1821 }
1822
1823 class EventTester : public QGraphicsEllipseItem
1824 {
1825 public:
1826     EventTester()
1827         : QGraphicsEllipseItem(QRectF(-10, -10, 20, 20)), ignoreMouse(false)
1828     { }
1829
1830     bool ignoreMouse;
1831     QList<QEvent::Type> eventTypes;
1832
1833 protected:
1834     bool sceneEvent(QEvent *event)
1835     {
1836         eventTypes << QEvent::Type(event->type());
1837         switch (event->type()) {
1838         case QEvent::GraphicsSceneMousePress:
1839         case QEvent::GraphicsSceneMouseMove:
1840         case QEvent::GraphicsSceneMouseRelease:
1841             if (ignoreMouse) {
1842                 event->ignore();
1843                 return true;
1844             }
1845         default:
1846             break;
1847         }
1848
1849         return QGraphicsEllipseItem::sceneEvent(event);
1850     }
1851 };
1852
1853 void tst_QGraphicsScene::mouseEventPropagation()
1854 {
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);
1862
1863     a->setFlag(QGraphicsItem::ItemIsMovable);
1864     b->setFlag(QGraphicsItem::ItemIsMovable);
1865     c->setFlag(QGraphicsItem::ItemIsMovable);
1866     d->setFlag(QGraphicsItem::ItemIsMovable);
1867
1868     a->setData(0, "A");
1869     b->setData(0, "B");
1870     c->setData(0, "C");
1871     d->setData(0, "D");
1872
1873     // scene -> a -> b -> c -> d
1874     QGraphicsScene scene;
1875     QEvent activate(QEvent::WindowActivate);
1876     QApplication::sendEvent(&scene, &activate);
1877
1878     scene.addItem(a);
1879
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));
1890
1891     // Send a press
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);
1900
1901     // Send a move
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);
1909
1910     // Send a release
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);
1919
1920     d->setAcceptedMouseButtons(Qt::RightButton);
1921
1922     // Send a press
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);
1931
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);
1941
1942     // Send a move
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);
1950
1951     // Send a release
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);
1960
1961     // Disabled items eat events. c should not get this.
1962     d->setEnabled(false);
1963     d->setAcceptedMouseButtons(Qt::RightButton);
1964
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);
1972
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);
1983
1984     // Clicking outside the items removes the mouse grabber
1985 }
1986
1987 void tst_QGraphicsScene::mouseEventPropagation_ignore()
1988 {
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);
1996
1997     a->setFlags(QGraphicsItem::ItemIsMovable);
1998     b->setFlags(QGraphicsItem::ItemIsMovable);
1999     c->setFlags(QGraphicsItem::ItemIsMovable);
2000     d->setFlags(QGraphicsItem::ItemIsMovable);
2001
2002     // scene -> a -> b -> c -> d
2003     QGraphicsScene scene;
2004     scene.addItem(a);
2005
2006     // Prepare some events
2007     QGraphicsSceneMouseEvent pressEvent(QEvent::GraphicsSceneMousePress);
2008     pressEvent.setButton(Qt::LeftButton);
2009     pressEvent.setScenePos(QPointF(0, 0));
2010
2011     b->ignoreMouse = true;
2012     c->ignoreMouse = true;
2013     d->ignoreMouse = true;
2014
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);
2032
2033     a->ignoreMouse = true;
2034
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);
2041
2042     QVERIFY(!pressEvent.isAccepted());
2043 }
2044
2045 void tst_QGraphicsScene::mouseEventPropagation_focus()
2046 {
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);
2054
2055     a->setFlag(QGraphicsItem::ItemIsMovable);
2056     b->setFlag(QGraphicsItem::ItemIsMovable);
2057     c->setFlag(QGraphicsItem::ItemIsMovable);
2058     d->setFlag(QGraphicsItem::ItemIsMovable);
2059
2060     // scene -> a -> b -> c -> d
2061     QGraphicsScene scene;
2062     QEvent activate(QEvent::WindowActivate);
2063     QApplication::sendEvent(&scene, &activate);
2064
2065     scene.addItem(a);
2066
2067     // Prepare some events
2068     QGraphicsSceneMouseEvent pressEvent(QEvent::GraphicsSceneMousePress);
2069     pressEvent.setButton(Qt::LeftButton);
2070     pressEvent.setScenePos(QPointF(0, 0));
2071
2072     a->setFlag(QGraphicsItem::ItemIsFocusable);
2073     QVERIFY(!a->hasFocus());
2074
2075     QApplication::sendEvent(&scene, &pressEvent);
2076
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);
2083 }
2084
2085 void tst_QGraphicsScene::mouseEventPropagation_doubleclick()
2086 {
2087     EventTester *a = new EventTester;
2088     EventTester *b = new EventTester;
2089     a->setFlags(QGraphicsItem::ItemIsMovable);
2090     b->setFlags(QGraphicsItem::ItemIsMovable);
2091
2092     a->setPos(-50, 0);
2093     b->setPos(50, 0);
2094
2095     QGraphicsScene scene;
2096     scene.addItem(a);
2097     scene.addItem(b);
2098
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));
2109
2110     // Send press to A
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);
2116
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);
2123
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);
2131
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);
2139 }
2140
2141 class Scene : public QGraphicsScene
2142 {
2143 public:
2144     QVector<QPointF> mouseMovePoints;
2145
2146 protected:
2147     void mouseMoveEvent(QGraphicsSceneMouseEvent *event)
2148     {
2149         mouseMovePoints << event->scenePos();
2150     }
2151 };
2152
2153 void tst_QGraphicsScene::mouseEventPropagation_mouseMove()
2154 {
2155     Scene scene;
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);
2162     }
2163
2164     QCOMPARE(scene.mouseMovePoints.size(), 30);
2165     for (int i = 0; i < 30; ++i)
2166         QCOMPARE(scene.mouseMovePoints.at(i), QPointF(i, 5));
2167 }
2168
2169 class DndTester : public QGraphicsEllipseItem
2170 {
2171 public:
2172     DndTester(const QRectF &rect)
2173         : QGraphicsEllipseItem(rect), lastEvent(0),
2174           ignoresDragEnter(false), ignoresDragMove(false)
2175
2176     {
2177     }
2178
2179     ~DndTester()
2180     {
2181         delete lastEvent;
2182     }
2183
2184     QGraphicsSceneDragDropEvent *lastEvent;
2185     QList<QEvent::Type> eventList;
2186     bool ignoresDragEnter;
2187     bool ignoresDragMove;
2188
2189 protected:
2190     void dragEnterEvent(QGraphicsSceneDragDropEvent *event)
2191     {
2192         storeLastEvent(event);
2193         event->setAccepted(!ignoresDragEnter);
2194         if (!ignoresDragEnter)
2195             event->setDropAction(Qt::IgnoreAction);
2196         eventList << event->type();
2197     }
2198
2199     void dragMoveEvent(QGraphicsSceneDragDropEvent *event)
2200     {
2201         storeLastEvent(event);
2202         event->setAccepted(!ignoresDragMove);
2203         eventList << event->type();
2204     }
2205
2206     void dragLeaveEvent(QGraphicsSceneDragDropEvent *event)
2207     {
2208         storeLastEvent(event);
2209         eventList << event->type();
2210     }
2211
2212     void dropEvent(QGraphicsSceneDragDropEvent *event)
2213     {
2214         storeLastEvent(event);
2215         eventList << event->type();
2216     }
2217
2218 private:
2219     void storeLastEvent(QGraphicsSceneDragDropEvent *event)
2220     {
2221         delete lastEvent;
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());
2233     }
2234 };
2235
2236 #ifndef QT_NO_DRAGANDDROP
2237 void tst_QGraphicsScene::dragAndDrop_simple()
2238 {
2239     DndTester *item = new DndTester(QRectF(-10, -10, 20, 20));
2240
2241     QGraphicsScene scene;
2242     scene.addItem(item);
2243
2244     QGraphicsView view(&scene);
2245     view.setFixedSize(100, 100);
2246
2247     QMimeData mimeData;
2248
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);
2254
2255     {
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);
2261     }
2262     {
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);
2269     }
2270     item->setAcceptDrops(true);
2271     {
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);
2284     }
2285     {
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);
2297     }
2298     {
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);
2310     }
2311     {
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);
2324     }
2325     {
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);
2337     }
2338 }
2339
2340 void tst_QGraphicsScene::dragAndDrop_disabledOrInvisible()
2341 {
2342     DndTester *item = new DndTester(QRectF(-10, -10, 20, 20));
2343     item->setAcceptDrops(true);
2344
2345     QGraphicsScene scene;
2346     scene.addItem(item);
2347
2348     QGraphicsView view(&scene);
2349     view.setFixedSize(100, 100);
2350
2351     QMimeData mimeData;
2352
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);
2358     {
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);
2367     }
2368     {
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);
2376     }
2377
2378     // Now disable the item
2379     item->setEnabled(false);
2380     QVERIFY(!item->isEnabled());
2381     QVERIFY(item->isVisible());
2382
2383     {
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);
2391     }
2392
2393     // Reenable it, and make it invisible
2394     item->setEnabled(true);
2395     item->setVisible(false);
2396     QVERIFY(item->isEnabled());
2397     QVERIFY(!item->isVisible());
2398
2399     {
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);
2407     }
2408
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);
2412 }
2413
2414 void tst_QGraphicsScene::dragAndDrop_propagate()
2415 {
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);
2423
2424     item1->setData(0, "item1");
2425     item2->setData(0, "item2");
2426
2427     QGraphicsScene scene;
2428     scene.addItem(item1);
2429     scene.addItem(item2);
2430
2431     QGraphicsView view(&scene);
2432     view.setFixedSize(100, 100);
2433
2434     QMimeData mimeData;
2435
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);
2441
2442     {
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());
2450     }
2451     {
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);
2460     }
2461
2462     {
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);
2472     }
2473     {
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);
2482     }
2483     {
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);
2494     }
2495
2496     {
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);
2507     }
2508
2509     {
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);
2516
2517         QCOMPARE(item1->eventList.size(), 7);
2518         QCOMPARE(item1->eventList.at(6), QEvent::GraphicsSceneDrop);
2519         QCOMPARE(item2->eventList.size(), 5);
2520     }
2521
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);
2525 }
2526 #endif
2527
2528 void tst_QGraphicsScene::render_data()
2529 {
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");
2535
2536     QPainterPath clip_rect;
2537     clip_rect.addRect(50, 100, 200, 150);
2538
2539     QPainterPath clip_ellipse;
2540     clip_ellipse.addEllipse(100,50,150,200);
2541
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;
2598 }
2599
2600 void tst_QGraphicsScene::render()
2601 {
2602     QFETCH(QRectF, targetRect);
2603     QFETCH(QRectF, sourceRect);
2604     QFETCH(Qt::AspectRatioMode, aspectRatioMode);
2605     QFETCH(QMatrix, matrix);
2606     QFETCH(QPainterPath, clip);
2607
2608     QPixmap pix(30, 30);
2609     pix.fill(Qt::blue);
2610
2611     QGraphicsView view;
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);
2616     item->setZValue(2);
2617     item->setOffset(QPointF(3, 3));
2618     view.show();
2619
2620     scene.setSceneRect(scene.itemsBoundingRect());
2621
2622     QImage bigImage(300, 300, QImage::Format_RGB32);
2623     bigImage.fill(0);
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);
2629     }
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);
2636     painter.end();
2637
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());
2642
2643     // Compare
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))
2648                 ++wrongPixels;
2649         }
2650     }
2651
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) {
2659 #if 1
2660         // fail
2661         QLabel *expectedLabel = new QLabel;
2662         expectedLabel->setPixmap(QPixmap::fromImage(original));
2663
2664         QLabel *newLabel = new QLabel;
2665         newLabel->setPixmap(QPixmap::fromImage(bigImage));
2666
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);
2673
2674         QWidget widget;
2675         widget.setLayout(gridLayout);
2676         widget.show();
2677
2678         QTestEventLoop::instance().enterLoop(1);
2679
2680         QFAIL("Images are not identical.");
2681 #else
2682         // generate
2683         qDebug() << "Updating" << QTest::currentDataTag() << ":" << bigImage.save(fileName, "png");
2684 #endif
2685     }
2686 }
2687
2688 void tst_QGraphicsScene::renderItemsWithNegativeWidthOrHeight()
2689 {
2690     QGraphicsScene scene(0, 0, 150, 150);
2691
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);
2697
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);
2703
2704     QGraphicsView view(&scene);
2705     view.setFrameStyle(QFrame::NoFrame);
2706     view.resize(150, 150);
2707     view.show();
2708     QCOMPARE(view.viewport()->size(), QSize(150, 150));
2709
2710     QImage expected(view.viewport()->size(), QImage::Format_RGB32);
2711     view.viewport()->render(&expected);
2712
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);
2718     painter.end();
2719
2720     QCOMPARE(actual, expected);
2721 }
2722
2723 void tst_QGraphicsScene::contextMenuEvent()
2724 {
2725     QGraphicsScene scene;
2726     QEvent activate(QEvent::WindowActivate);
2727     QApplication::sendEvent(&scene, &activate);
2728
2729     EventTester *item = new EventTester;
2730     scene.addItem(item);
2731     item->setFlag(QGraphicsItem::ItemIsFocusable);
2732     item->setFocus();
2733
2734     QVERIFY(item->hasFocus());
2735     QVERIFY(scene.hasFocus());
2736
2737     QGraphicsView view(&scene);
2738     view.show();
2739     view.activateWindow();
2740     QVERIFY(QTest::qWaitForWindowActive(&view));
2741     view.centerOn(item);
2742
2743     {
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);
2748     }
2749 }
2750
2751 class ContextMenuItem : public QGraphicsRectItem
2752 {
2753 public:
2754     ContextMenuItem() : QGraphicsRectItem(0, 0, 100, 100)
2755     { setBrush(Qt::red); }
2756
2757 protected:
2758     void contextMenuEvent(QGraphicsSceneContextMenuEvent *)
2759     { /* just accept */ }
2760 };
2761
2762 void tst_QGraphicsScene::contextMenuEvent_ItemIgnoresTransformations()
2763 {
2764     QGraphicsScene scene(0, 0, 200, 200);
2765     ContextMenuItem *item = new ContextMenuItem;
2766     item->setFlag(QGraphicsItem::ItemIgnoresTransformations);
2767     scene.addItem(item);
2768
2769     QWidget topLevel;
2770     QGraphicsView view(&scene, &topLevel);
2771     view.resize(200, 200);
2772     topLevel.show();
2773     QVERIFY(QTest::qWaitForWindowExposed(&topLevel));
2774
2775     {
2776         QPoint pos(50, 50);
2777         QContextMenuEvent event(QContextMenuEvent::Keyboard, pos, view.viewport()->mapToGlobal(pos));
2778         event.ignore();
2779         QApplication::sendEvent(view.viewport(), &event);
2780         QVERIFY(event.isAccepted());
2781     }
2782     {
2783         QPoint pos(150, 150);
2784         QContextMenuEvent event(QContextMenuEvent::Keyboard, pos, view.viewport()->mapToGlobal(pos));
2785         event.ignore();
2786         QApplication::sendEvent(view.viewport(), &event);
2787         QVERIFY(!event.isAccepted());
2788     }
2789     view.scale(1.5, 1.5);
2790     {
2791         QPoint pos(25, 25);
2792         QContextMenuEvent event(QContextMenuEvent::Keyboard, pos, view.viewport()->mapToGlobal(pos));
2793         event.ignore();
2794         QApplication::sendEvent(view.viewport(), &event);
2795         QVERIFY(event.isAccepted());
2796     }
2797     {
2798         QPoint pos(55, 55);
2799         QContextMenuEvent event(QContextMenuEvent::Keyboard, pos, view.viewport()->mapToGlobal(pos));
2800         event.ignore();
2801         QApplication::sendEvent(view.viewport(), &event);
2802         QVERIFY(!event.isAccepted());
2803     }
2804 }
2805
2806 void tst_QGraphicsScene::update()
2807 {
2808     QGraphicsScene scene;
2809
2810     QGraphicsRectItem *rect = new QGraphicsRectItem(0, 0, 100, 100);
2811     scene.addItem(rect);
2812     qApp->processEvents();
2813     rect->setPos(-100, -100);
2814
2815     // This function forces indexing
2816     scene.itemAt(0, 0);
2817
2818     qRegisterMetaType<QList<QRectF> >("QList<QRectF>");
2819     QSignalSpy spy(&scene, SIGNAL(changed(QList<QRectF>)));
2820
2821     // We update the scene.
2822     scene.update();
2823
2824     // This function forces a purge, which will post an update signal
2825     scene.itemAt(0, 0);
2826
2827     // This will process the pending update
2828     QApplication::instance()->processEvents();
2829
2830     // Check that the update region is correct
2831     QCOMPARE(spy.count(), 1);
2832     QRectF region;
2833     foreach (QRectF rectF, qvariant_cast<QList<QRectF> >(spy.at(0).at(0)))
2834         region |= rectF;
2835     QCOMPARE(region, QRectF(-100, -100, 200, 200));
2836 }
2837
2838 void tst_QGraphicsScene::update2()
2839 {
2840     QGraphicsScene scene;
2841     scene.setSceneRect(-200, -200, 200, 200);
2842     CustomView view;
2843     view.setScene(&scene);
2844     view.show();
2845     qApp->setActiveWindow(&view);
2846     QVERIFY(QTest::qWaitForWindowActive(&view));
2847     QTRY_VERIFY(view.repaints >= 1);
2848     view.repaints = 0;
2849
2850     // Make sure QGraphicsScene::update only requires one event-loop iteration
2851     // before the view is updated.
2852     scene.update();
2853     qApp->processEvents();
2854     QTRY_COMPARE(view.repaints, 1);
2855     view.repaints = 0;
2856
2857     // The same for partial scene updates.
2858     scene.update(QRectF(-100, -100, 100, 100));
2859     qApp->processEvents();
2860     QCOMPARE(view.repaints, 1);
2861 }
2862
2863 void tst_QGraphicsScene::views()
2864 {
2865     QGraphicsScene scene;
2866     QGraphicsView view(&scene);
2867
2868     QCOMPARE(scene.views().size(), 1);
2869     QCOMPARE(scene.views().at(0), &view);
2870
2871     QGraphicsView view1(&scene);
2872     QCOMPARE(scene.views().size(), 2);
2873     QVERIFY(scene.views().contains(&view1));
2874
2875     view.setScene(0);
2876     QCOMPARE(scene.views().size(), 1);
2877     QCOMPARE(scene.views().at(0), &view1);
2878
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);
2883
2884     delete view2;
2885
2886     QCOMPARE(scene.views().size(), 1);
2887     QCOMPARE(scene.views().at(0), &view1);
2888 }
2889
2890 class CustomScene : public QGraphicsScene
2891 {
2892 public:
2893     CustomScene() : gotTimerEvent(false)
2894     { startTimer(10); }
2895
2896     bool gotTimerEvent;
2897 protected:
2898     void timerEvent(QTimerEvent *)
2899     {
2900         gotTimerEvent = true;
2901     }
2902 };
2903
2904 void tst_QGraphicsScene::event()
2905 {
2906     // Test that QGraphicsScene properly propagates events to QObject.
2907     CustomScene scene;
2908     QTestEventLoop::instance().enterLoop(1);
2909     QVERIFY(scene.gotTimerEvent);
2910 }
2911
2912 class DisabledItemTester : public QGraphicsRectItem
2913 {
2914 public:
2915     DisabledItemTester(const QRectF &rect, QGraphicsItem *parent = 0)
2916         : QGraphicsRectItem(rect, parent)
2917     { }
2918
2919     QList<QEvent::Type> receivedSceneEvents;
2920     QList<QEvent::Type> receivedSceneEventFilters;
2921
2922 protected:
2923     bool sceneEventFilter(QGraphicsItem *watched, QEvent *event)
2924     {
2925         receivedSceneEventFilters << event->type();
2926         return QGraphicsRectItem::sceneEventFilter(watched, event);
2927     }
2928
2929     bool sceneEvent(QEvent *event)
2930     {
2931         receivedSceneEvents << event->type();
2932         return QGraphicsRectItem::sceneEvent(event);
2933     }
2934 };
2935
2936 void tst_QGraphicsScene::eventsToDisabledItems()
2937 {
2938     QGraphicsScene scene;
2939
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
2943
2944     scene.addItem(item1);
2945     scene.addItem(item2);
2946
2947     item1->installSceneEventFilter(item2);
2948
2949     QVERIFY(item1->receivedSceneEvents.isEmpty());
2950     QVERIFY(item2->receivedSceneEvents.isEmpty());
2951     QVERIFY(item1->receivedSceneEventFilters.isEmpty());
2952     QVERIFY(item2->receivedSceneEventFilters.isEmpty());
2953
2954     QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
2955     event.setButton(Qt::LeftButton);
2956     QApplication::sendEvent(&scene, &event);
2957
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);
2965
2966     item1->receivedSceneEvents.clear();
2967     item1->receivedSceneEventFilters.clear();
2968     item2->receivedSceneEvents.clear();
2969     item2->receivedSceneEventFilters.clear();
2970
2971     item1->setEnabled(false); // disable the topmost item, eat mouse events
2972
2973     event.setButton(Qt::LeftButton);
2974     event.setAccepted(false);
2975     QApplication::sendEvent(&scene, &event);
2976
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);
2982 }
2983
2984 class ExposedPixmapItem : public QGraphicsPixmapItem
2985 {
2986 public:
2987     ExposedPixmapItem(QGraphicsItem *item = 0)
2988         : QGraphicsPixmapItem(item)
2989     { }
2990
2991     void paint(QPainter *, const QStyleOptionGraphicsItem *option, QWidget *)
2992     {
2993         exposed = option->exposedRect;
2994     }
2995
2996     QRectF exposed;
2997 };
2998
2999 void tst_QGraphicsScene::exposedRect()
3000 {
3001     ExposedPixmapItem *item = new ExposedPixmapItem;
3002     item->setPixmap(QPixmap(":/Ash_European.jpg"));
3003     QGraphicsScene scene;
3004     scene.addItem(item);
3005
3006     QCOMPARE(item->exposed, QRectF());
3007
3008     QImage image(100, 100, QImage::Format_ARGB32_Premultiplied);
3009     QPainter painter(&image);
3010
3011     scene.render(&painter);
3012     QCOMPARE(item->exposed, item->boundingRect());
3013
3014     painter.rotate(180);
3015     painter.translate(100, 100);
3016
3017     scene.render(&painter);
3018     QCOMPARE(item->exposed, item->boundingRect());
3019 }
3020
3021 void tst_QGraphicsScene::tabFocus_emptyScene()
3022 {
3023     QGraphicsScene scene;
3024     QDial *dial1 = new QDial;
3025     QGraphicsView *view = new QGraphicsView(&scene);
3026     QDial *dial2 = new QDial;
3027
3028     QHBoxLayout *layout = new QHBoxLayout;
3029     layout->addWidget(dial1);
3030     layout->addWidget(view);
3031     layout->addWidget(dial2);
3032
3033     QWidget widget;
3034     widget.setLayout(layout);
3035     widget.show();
3036     qApp->setActiveWindow(&widget);
3037     widget.activateWindow();
3038     QVERIFY(QTest::qWaitForWindowActive(&widget));
3039
3040     dial1->setFocus();
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());
3054 }
3055
3056 void tst_QGraphicsScene::tabFocus_sceneWithFocusableItems()
3057 {
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);
3063     item->setFocus();
3064     item->clearFocus();
3065
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);
3071
3072     QDial *dial1 = new QDial;
3073     QGraphicsView *view = new QGraphicsView(&scene);
3074     QDial *dial2 = new QDial;
3075
3076     QHBoxLayout *layout = new QHBoxLayout;
3077     layout->addWidget(dial1);
3078     layout->addWidget(view);
3079     layout->addWidget(dial2);
3080
3081     QWidget widget;
3082     widget.setLayout(layout);
3083     widget.show();
3084     qApp->setActiveWindow(&widget);
3085     widget.activateWindow();
3086     QVERIFY(QTest::qWaitForWindowActive(&widget));
3087
3088     dial1->setFocus();
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());
3096
3097     QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
3098     QApplication::processEvents();
3099     QTRY_VERIFY(dial2->hasFocus());
3100
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());
3107
3108     QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
3109     QApplication::processEvents();
3110     QTRY_VERIFY(dial1->hasFocus());
3111
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.
3114     item->setFocus();
3115     QApplication::processEvents();
3116     QTRY_VERIFY(!view->hasFocus());
3117     QVERIFY(!view->viewport()->hasFocus());
3118     QTRY_VERIFY(scene.hasFocus());
3119     QVERIFY(item->hasFocus());
3120
3121     view->setFocus();
3122     QApplication::processEvents();
3123     QTRY_VERIFY(view->hasFocus());
3124     QTRY_VERIFY(view->viewport()->hasFocus());
3125     QTRY_VERIFY(scene.hasFocus());
3126     QTRY_VERIFY(item->hasFocus());
3127
3128     // Check that everyone loses focus when the widget is hidden.
3129     widget.hide();
3130     QTest::qWait(15);
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));
3136
3137     // Check that the correct item regains focus.
3138     widget.show();
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());
3148 }
3149
3150 class FocusWidget : public QGraphicsWidget
3151 {
3152     Q_OBJECT
3153 public:
3154     FocusWidget(QGraphicsItem *parent = 0)
3155         : QGraphicsWidget(parent), tabs(0), backTabs(0)
3156     {
3157         setFocusPolicy(Qt::StrongFocus);
3158         resize(100, 100);
3159     }
3160
3161     void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *)
3162     {
3163         if (option->state & QStyle::State_HasFocus) {
3164             painter->fillRect(rect(), Qt::blue);
3165         }
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));
3172         }
3173     }
3174
3175     int tabs;
3176     int backTabs;
3177
3178 protected:
3179     bool sceneEvent(QEvent *event)
3180     {
3181         if (event->type() == QEvent::KeyPress) {
3182             QKeyEvent *k = static_cast<QKeyEvent *>(event);
3183             if (k->key() == Qt::Key_Tab)
3184                 ++tabs;
3185             if (k->key() == Qt::Key_Backtab)
3186                 ++backTabs;
3187         }
3188         return QGraphicsWidget::sceneEvent(event);
3189     }
3190
3191     void focusInEvent(QFocusEvent *)
3192     { update(); }
3193     void focusOutEvent(QFocusEvent *)
3194     { update(); }
3195 };
3196
3197 void tst_QGraphicsScene::tabFocus_sceneWithFocusWidgets()
3198 {
3199     QGraphicsScene scene;
3200
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);
3206
3207     QDial *dial1 = new QDial;
3208     QGraphicsView *view = new QGraphicsView(&scene);
3209     view->setRenderHint(QPainter::Antialiasing);
3210     QDial *dial2 = new QDial;
3211
3212     QHBoxLayout *layout = new QHBoxLayout;
3213     layout->addWidget(dial1);
3214     layout->addWidget(view);
3215     layout->addWidget(dial2);
3216
3217     QWidget widget;
3218     widget.setLayout(layout);
3219     widget.show();
3220     qApp->setActiveWindow(&widget);
3221     widget.activateWindow();
3222     QVERIFY(QTest::qWaitForWindowActive(&widget));
3223
3224     dial1->setFocus();
3225     QTRY_VERIFY(dial1->hasFocus());
3226
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());
3253
3254     widget1->setFocus();
3255     view->viewport()->setFocus();
3256     widget.hide();
3257     QTest::qWait(15);
3258     widget.show();
3259     qApp->setActiveWindow(&widget);
3260     widget.activateWindow();
3261     QVERIFY(QTest::qWaitForWindowActive(&widget));
3262     QTRY_VERIFY(widget1->hasFocus());
3263 }
3264
3265 void tst_QGraphicsScene::tabFocus_sceneWithNestedFocusWidgets()
3266 {
3267     QGraphicsScene scene;
3268
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);
3278
3279     FocusWidget *widget2 = new FocusWidget;
3280     widget2->setPos(widget1->boundingRect().right(), 0);
3281
3282     widget1->setData(0, "widget1");
3283     widget1_1->setData(0, "widget1_1");
3284     widget1_2->setData(0, "widget1_2");
3285     widget2->setData(0, "widget2");
3286
3287     scene.addItem(widget1);
3288     scene.addItem(widget2);
3289
3290     QDial *dial1 = new QDial;
3291     QGraphicsView *view = new QGraphicsView(&scene);
3292     view->setRenderHint(QPainter::Antialiasing);
3293     QDial *dial2 = new QDial;
3294
3295     QHBoxLayout *layout = new QHBoxLayout;
3296     layout->addWidget(dial1);
3297     layout->addWidget(view);
3298     layout->addWidget(dial2);
3299
3300     QWidget widget;
3301     widget.setLayout(layout);
3302     widget.show();
3303     qApp->setActiveWindow(&widget);
3304     widget.activateWindow();
3305     QVERIFY(QTest::qWaitForWindowActive(&widget));
3306
3307     dial1->setFocus();
3308     QTRY_VERIFY(dial1->hasFocus());
3309
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);
3318
3319     QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
3320     QApplication::processEvents();
3321     QTRY_VERIFY(widget1->hasFocus());
3322     QCOMPARE(focusInSpy_1.count(), 1);
3323
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);
3330
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);
3337
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);
3344
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);
3350
3351     QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
3352     QApplication::processEvents();
3353     QTRY_VERIFY(widget2->hasFocus());
3354     QCOMPARE(focusInSpy_2.count(), 2);
3355
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);
3362
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);
3369
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);
3376
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);
3382
3383     widget1->setFocus();
3384     view->viewport()->setFocus();
3385     widget.hide();
3386     QTest::qWait(12);
3387     widget.show();
3388     qApp->setActiveWindow(&widget);
3389     widget.activateWindow();
3390     QVERIFY(QTest::qWaitForWindowActive(&widget));
3391     QTRY_VERIFY(widget1->hasFocus());
3392 }
3393
3394 void tst_QGraphicsScene::style()
3395 {
3396     QPointer<QWindowsStyle> windowsStyle = new QWindowsStyle;
3397
3398     QGraphicsScene scene;
3399     QLineEdit *edit = new QLineEdit;
3400     QGraphicsProxyWidget *proxy = scene.addWidget(edit);
3401
3402     EventSpy sceneSpy(&scene, QEvent::StyleChange);
3403     EventSpy proxySpy(proxy, QEvent::StyleChange);
3404     EventSpy editSpy(edit, QEvent::StyleChange);
3405
3406     QCOMPARE(scene.style(), QApplication::style());
3407
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);
3415
3416     scene.setStyle(0);
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
3424 }
3425
3426 void tst_QGraphicsScene::task139710_bspTreeCrash()
3427 {
3428     // create a scene with 2000 items
3429     QGraphicsScene scene(0, 0, 1000, 1000);
3430
3431     for (int i = 0; i < 2; ++i) {
3432         // trigger delayed item indexing
3433         qApp->processEvents();
3434         scene.setSceneRect(0, 0, 10000, 10000);
3435
3436         // delete all items in the scene - pointers are now likely to be recycled
3437         foreach (QGraphicsItem *item, scene.items()) {
3438             scene.removeItem(item);
3439             delete item;
3440         }
3441
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);
3446         }
3447
3448         // trigger delayed item indexing for the first 1000 items
3449         qApp->processEvents();
3450
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);
3455         }
3456
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)))
3460             item->moveBy(0, 0);
3461     }
3462 }
3463
3464 void tst_QGraphicsScene::task139782_containsItemBoundingRect()
3465 {
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);
3471
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));
3474
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));
3477
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));
3480 }
3481
3482 void tst_QGraphicsScene::task176178_itemIndexMethodBreaksSceneRect()
3483 {
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());
3490 }
3491
3492 void tst_QGraphicsScene::task160653_selectionChanged()
3493 {
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()) {
3498         item->setFlags(
3499             item->flags() | QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemIsMovable);
3500         item->setSelected(true);
3501     }
3502     QVERIFY(scene.items().size() > 1);
3503     QCOMPARE(scene.items().size(), scene.selectedItems().size());
3504
3505     QSignalSpy spy(&scene, SIGNAL(selectionChanged()));
3506     QGraphicsView view(&scene);
3507     QTest::mouseClick(
3508         view.viewport(), Qt::LeftButton, 0, view.mapFromScene(scene.items().first()->scenePos()));
3509     QCOMPARE(spy.count(), 1);
3510 }
3511
3512 void tst_QGraphicsScene::task250680_childClip()
3513 {
3514     QGraphicsRectItem *clipper = new QGraphicsRectItem;
3515     clipper->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
3516     clipper->setPen(QPen(Qt::green));
3517     clipper->setRect(200, 200, 640, 480);
3518
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);
3524
3525     QGraphicsScene scene;
3526     scene.addItem(clipper);
3527
3528     QPainterPath path;
3529     path.addRect(-25, -25, 50, 50);
3530     QVERIFY(QPathCompare::comparePaths(rect->clipPath().simplified(), path));
3531
3532     QCOMPARE(scene.items(QRectF(320, 240, 5, 5)).size(), 2);
3533     rect->rotate(45);
3534     QCOMPARE(scene.items(QRectF(320, 240, 5, 5)).size(), 2);
3535 }
3536
3537 void tst_QGraphicsScene::sorting_data()
3538 {
3539     QTest::addColumn<bool>("cache");
3540
3541     QTest::newRow("Normal sorting") << false;
3542     QTest::newRow("Cached sorting") << true;
3543 }
3544
3545 void tst_QGraphicsScene::sorting()
3546 {
3547     QFETCH(bool, cache);
3548
3549     QGraphicsScene scene;
3550     scene.setSortCacheEnabled(cache);
3551
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));
3570
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);
3577     c_2->setZValue(1);
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);
3582
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);
3591
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");
3601
3602     scene.addItem(t_1);
3603
3604     foreach (QGraphicsItem *item, scene.items())
3605         item->setFlag(QGraphicsItem::ItemIsSelectable);
3606
3607     // QGraphicsView view(&scene);
3608     // view.setDragMode(QGraphicsView::RubberBandDrag);
3609     // view.show();
3610
3611     qDebug() << "items: {";
3612     foreach (QGraphicsItem *item, scene.items(32, 31, 4, 55))
3613         qDebug() << "\t" << item->data(0).toString();
3614     qDebug() << "}";
3615
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
3629              << t_1);
3630 }
3631
3632 class ChangedListener : public QObject
3633 {
3634     Q_OBJECT
3635 public:
3636     QList<QList<QRectF> > changes;
3637
3638 public slots:
3639     void changed(const QList<QRectF> &dirty)
3640     {
3641         changes << dirty;
3642     }
3643 };
3644
3645 void tst_QGraphicsScene::changedSignal_data()
3646 {
3647     QTest::addColumn<bool>("withView");
3648
3649     QTest::newRow("without view") << false;
3650     QTest::newRow("with view") << true;
3651 }
3652
3653 void tst_QGraphicsScene::changedSignal()
3654 {
3655     QFETCH(bool, withView);
3656     QGraphicsScene scene;
3657     ChangedListener cl;
3658     connect(&scene, SIGNAL(changed(QList<QRectF>)), &cl, SLOT(changed(QList<QRectF>)));
3659
3660     QGraphicsView *view = 0;
3661     if (withView)
3662         view = new QGraphicsView(&scene);
3663
3664     QGraphicsRectItem *rect = new QGraphicsRectItem(0, 0, 10, 10);
3665     scene.addItem(rect);
3666
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));
3671
3672     rect->setPos(20, 0);
3673
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));
3680
3681     QCOMPARE(scene.sceneRect(), QRectF(0, 0, 30, 10));
3682
3683     if (withView)
3684         delete view;
3685 }
3686
3687 void tst_QGraphicsScene::stickyFocus_data()
3688 {
3689     QTest::addColumn<bool>("sticky");
3690     QTest::newRow("sticky") << true;
3691     QTest::newRow("not sticky") << false;
3692 }
3693
3694 void tst_QGraphicsScene::stickyFocus()
3695 {
3696     QFETCH(bool, sticky);
3697
3698     QGraphicsScene scene;
3699     QEvent activate(QEvent::WindowActivate);
3700     QApplication::sendEvent(&scene, &activate);
3701
3702     QGraphicsTextItem *text = scene.addText("Hei");
3703     text->setTextInteractionFlags(Qt::TextEditorInteraction);
3704     text->setFocus();
3705
3706     scene.setStickyFocus(sticky);
3707
3708     QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
3709     event.setScenePos(QPointF(-10, -10)); // outside item
3710     event.setButton(Qt::LeftButton);
3711     qApp->sendEvent(&scene, &event);
3712
3713     QCOMPARE(text->hasFocus(), sticky);
3714 }
3715
3716 void tst_QGraphicsScene::sendEvent()
3717 {
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);
3725 }
3726
3727 void tst_QGraphicsScene::inputMethod_data()
3728 {
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;
3736 }
3737
3738 class InputMethodTester : public QGraphicsRectItem
3739 {
3740     void inputMethodEvent(QInputMethodEvent *) { ++eventCalls; }
3741     QVariant inputMethodQuery(Qt::InputMethodQuery) const { ++queryCalls; return QVariant(); }
3742 public:
3743     int eventCalls;
3744     mutable int queryCalls;
3745 };
3746
3747 void tst_QGraphicsScene::inputMethod()
3748 {
3749     PlatformInputContext inputContext;
3750     QInputMethodPrivate *inputMethodPrivate = QInputMethodPrivate::get(qApp->inputMethod());
3751     inputMethodPrivate->testContext = &inputContext;
3752
3753     QFETCH(int, flags);
3754     QFETCH(bool, callFocusItem);
3755
3756     InputMethodTester *item = new InputMethodTester;
3757     item->setFlags((QGraphicsItem::GraphicsItemFlags)flags);
3758
3759     QGraphicsScene scene;
3760     QGraphicsView view(&scene);
3761     view.show();
3762     QApplication::setActiveWindow(&view);
3763     view.setFocus();
3764     QVERIFY(QTest::qWaitForWindowActive(&view));
3765     QCOMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
3766
3767     inputContext.m_resetCallCount = 0;
3768     inputContext.m_commitCallCount = 0;
3769     scene.addItem(item);
3770     QInputMethodEvent event;
3771
3772     scene.setFocusItem(item);
3773     QCOMPARE(!!(item->flags() & QGraphicsItem::ItemIsFocusable), scene.focusItem() == item);
3774     QCOMPARE(inputContext.m_resetCallCount, 0);
3775
3776     item->eventCalls = 0;
3777     qApp->sendEvent(&scene, &event);
3778     QCOMPARE(item->eventCalls, callFocusItem ? 1 : 0);
3779
3780     item->queryCalls = 0;
3781     scene.inputMethodQuery((Qt::InputMethodQuery)0);
3782     QCOMPARE(item->queryCalls, callFocusItem ? 1 : 0);
3783
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
3789
3790     item->eventCalls = 0;
3791     qApp->sendEvent(&scene, &event);
3792     QCOMPARE(item->eventCalls, 0);
3793
3794     item->queryCalls = 0;
3795     scene.inputMethodQuery((Qt::InputMethodQuery)0);
3796     QCOMPARE(item->queryCalls, 0);
3797 }
3798
3799 void tst_QGraphicsScene::dispatchHoverOnPress()
3800 {
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);
3809
3810     tester1->eventTypes.clear();
3811     tester2->eventTypes.clear();
3812
3813     {
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);
3835     }
3836     {
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);
3864     }
3865 }
3866
3867 void tst_QGraphicsScene::initialFocus_data()
3868 {
3869     QTest::addColumn<bool>("activeScene");
3870     QTest::addColumn<bool>("explicitSetFocus");
3871     QTest::addColumn<bool>("isPanel");
3872     QTest::addColumn<bool>("shouldHaveFocus");
3873
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;
3882 }
3883
3884 void tst_QGraphicsScene::initialFocus()
3885 {
3886     QFETCH(bool, activeScene);
3887     QFETCH(bool, explicitSetFocus);
3888     QFETCH(bool, isPanel);
3889     QFETCH(bool, shouldHaveFocus);
3890
3891     QGraphicsRectItem *rect = new QGraphicsRectItem;
3892     rect->setFlag(QGraphicsItem::ItemIsFocusable);
3893     QVERIFY(!rect->hasFocus());
3894
3895     if (isPanel)
3896         rect->setFlag(QGraphicsItem::ItemIsPanel);
3897
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)
3901         rect->setFocus();
3902
3903     QGraphicsScene scene;
3904     QVERIFY(!scene.isActive());
3905
3906     if (activeScene) {
3907         QEvent windowActivate(QEvent::WindowActivate);
3908         qApp->sendEvent(&scene, &windowActivate);
3909         scene.setFocus();
3910     }
3911
3912     scene.addItem(rect);
3913
3914     if (!activeScene) {
3915         QEvent windowActivate(QEvent::WindowActivate);
3916         qApp->sendEvent(&scene, &windowActivate);
3917         scene.setFocus();
3918     }
3919
3920     QCOMPARE(rect->hasFocus(), shouldHaveFocus);
3921 }
3922
3923 class PolishItem : public QGraphicsTextItem
3924 {
3925 public:
3926     PolishItem(QGraphicsItem *parent = 0)
3927         : QGraphicsTextItem(parent), polished(false), deleteChildrenInPolish(true), addChildrenInPolish(false) { }
3928
3929     bool polished;
3930     bool deleteChildrenInPolish;
3931     bool addChildrenInPolish;
3932 protected:
3933     QVariant itemChange(GraphicsItemChange change, const QVariant& value)
3934     {
3935         if (change == ItemVisibleChange) {
3936             polished = true;
3937             if (deleteChildrenInPolish)
3938                 qDeleteAll(childItems());
3939             if (addChildrenInPolish) {
3940                 for (int i = 0; i < 10; ++i)
3941                     new PolishItem(this);
3942             }
3943         }
3944         return QGraphicsItem::itemChange(change, value);
3945     }
3946 };
3947
3948 void tst_QGraphicsScene::polishItems()
3949 {
3950     QGraphicsScene scene;
3951     PolishItem *parent = new PolishItem;
3952     scene.addItem(parent);
3953     PolishItem *child = new PolishItem(parent);
3954     Q_UNUSED(child)
3955     // test that QGraphicsScenePrivate::_q_polishItems() doesn't crash
3956     QMetaObject::invokeMethod(&scene,"_q_polishItems");
3957 }
3958
3959 void tst_QGraphicsScene::polishItems2()
3960 {
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);
3969
3970     // Wait for the polish event to be delivered.
3971     QVERIFY(!item->polished);
3972     QApplication::sendPostedEvents(&scene, QEvent::MetaCall);
3973     QVERIFY(item->polished);
3974
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);
3982
3983     QApplication::sendPostedEvents(&scene, QEvent::MetaCall);
3984     foreach (QGraphicsItem *child, children)
3985         QVERIFY(static_cast<PolishItem *>(child)->polished);
3986 }
3987
3988 void tst_QGraphicsScene::isActive()
3989 {
3990     QGraphicsScene scene1;
3991     QVERIFY(!scene1.isActive());
3992     QGraphicsScene scene2;
3993     QVERIFY(!scene2.isActive());
3994
3995     {
3996         QWidget toplevel1;
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);
4003
4004         QVERIFY(!scene1.isActive());
4005         QVERIFY(!scene2.isActive());
4006
4007         view1->setVisible(false);
4008
4009         toplevel1.show();
4010         QApplication::setActiveWindow(&toplevel1);
4011         QVERIFY(QTest::qWaitForWindowActive(&toplevel1));
4012         QCOMPARE(QApplication::activeWindow(), &toplevel1);
4013
4014         QVERIFY(!scene1.isActive()); //it is hidden;
4015         QVERIFY(scene2.isActive());
4016         QVERIFY(!scene1.hasFocus());
4017         QVERIFY(scene2.hasFocus());
4018
4019         view1->show();
4020         QVERIFY(scene1.isActive());
4021         QVERIFY(scene2.isActive());
4022         QVERIFY(!scene1.hasFocus());
4023         QVERIFY(scene2.hasFocus());
4024
4025         view2->hide();
4026
4027         QVERIFY(scene1.isActive());
4028         QVERIFY(!scene2.isActive());
4029         QVERIFY(scene1.hasFocus());
4030         QVERIFY(!scene2.hasFocus());
4031
4032         toplevel1.hide();
4033         QTest::qWait(50);
4034         QTRY_VERIFY(!scene1.isActive());
4035         QTRY_VERIFY(!scene2.isActive());
4036         QVERIFY(!scene1.hasFocus());
4037         QVERIFY(!scene2.hasFocus());
4038
4039         toplevel1.show();
4040         QApplication::setActiveWindow(&toplevel1);
4041         QVERIFY(QTest::qWaitForWindowActive(&toplevel1));
4042         QCOMPARE(QApplication::activeWindow(), &toplevel1);
4043
4044         QTRY_VERIFY(scene1.isActive());
4045         QTRY_VERIFY(!scene2.isActive());
4046         QVERIFY(scene1.hasFocus());
4047         QVERIFY(!scene2.hasFocus());
4048
4049         view2->show();
4050         QVERIFY(scene1.isActive());
4051         QVERIFY(scene2.isActive());
4052         QVERIFY(scene1.hasFocus());
4053         QVERIFY(!scene2.hasFocus());
4054     }
4055
4056     QVERIFY(!scene1.isActive());
4057     QVERIFY(!scene2.isActive());
4058     QVERIFY(!scene1.hasFocus());
4059     QVERIFY(!scene2.hasFocus());
4060
4061
4062     {
4063         QWidget toplevel2;
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);
4070
4071         QVERIFY(!scene1.isActive());
4072         QVERIFY(!scene2.isActive());
4073         QVERIFY(!scene1.hasFocus());
4074         QVERIFY(!scene2.hasFocus());
4075
4076         toplevel2.show();
4077         QApplication::setActiveWindow(&toplevel2);
4078         QVERIFY(QTest::qWaitForWindowActive(&toplevel2));
4079         QCOMPARE(QApplication::activeWindow(), &toplevel2);
4080
4081         QVERIFY(scene1.isActive());
4082         QVERIFY(!scene2.isActive());
4083         QVERIFY(scene1.hasFocus());
4084         QVERIFY(!scene2.hasFocus());
4085
4086         view2->setScene(&scene2);
4087
4088         QVERIFY(scene1.isActive());
4089         QVERIFY(scene2.isActive());
4090         QVERIFY(scene1.hasFocus());
4091         QVERIFY(!scene2.hasFocus());
4092
4093         view1->setScene(&scene2);
4094         QVERIFY(!scene1.isActive());
4095         QVERIFY(scene2.isActive());
4096         QVERIFY(!scene1.hasFocus());
4097         QVERIFY(scene2.hasFocus());
4098
4099         view1->hide();
4100         QVERIFY(!scene1.isActive());
4101         QVERIFY(scene2.isActive());
4102         QVERIFY(!scene1.hasFocus());
4103         QVERIFY(scene2.hasFocus());
4104
4105         view1->setScene(&scene1);
4106         QVERIFY(!scene1.isActive());
4107         QVERIFY(scene2.isActive());
4108         QVERIFY(!scene1.hasFocus());
4109         QVERIFY(scene2.hasFocus());
4110
4111         view1->show();
4112         QVERIFY(scene1.isActive());
4113         QVERIFY(scene2.isActive());
4114         QVERIFY(!scene1.hasFocus());
4115         QVERIFY(scene2.hasFocus());
4116
4117         view2->hide();
4118         QVERIFY(scene1.isActive());
4119         QVERIFY(!scene2.isActive());
4120         QVERIFY(scene1.hasFocus());
4121         QVERIFY(!scene2.hasFocus());
4122
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));
4129
4130         QVERIFY(!scene1.isActive());
4131         QVERIFY(!scene2.isActive());
4132         QVERIFY(!scene1.hasFocus());
4133         QVERIFY(!scene2.hasFocus());
4134
4135         topLevelView.setScene(&scene1);
4136         QVERIFY(scene1.isActive());
4137         QVERIFY(!scene2.isActive());
4138         QVERIFY(scene1.hasFocus());
4139         QVERIFY(!scene2.hasFocus());
4140
4141         view2->show();
4142         QVERIFY(scene1.isActive());
4143         QVERIFY(!scene2.isActive());
4144         QVERIFY(scene1.hasFocus());
4145         QVERIFY(!scene2.hasFocus());
4146
4147         view1->hide();
4148         QVERIFY(scene1.isActive());
4149         QVERIFY(!scene2.isActive());
4150         QVERIFY(scene1.hasFocus());
4151         QVERIFY(!scene2.hasFocus());
4152
4153         QApplication::setActiveWindow(&toplevel2);
4154         QVERIFY(QTest::qWaitForWindowActive(&toplevel2));
4155
4156         QVERIFY(!scene1.isActive());
4157         QVERIFY(scene2.isActive());
4158         QVERIFY(!scene1.hasFocus());
4159         QVERIFY(scene2.hasFocus());
4160     }
4161
4162     QVERIFY(!scene1.isActive());
4163     QVERIFY(!scene2.isActive());
4164     QVERIFY(!scene1.hasFocus());
4165     QVERIFY(!scene2.hasFocus());
4166
4167     {
4168         QWidget toplevel3;
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);
4174
4175         QVERIFY(!scene1.isActive());
4176         QVERIFY(!scene2.isActive());
4177         QVERIFY(!scene1.hasFocus());
4178         QVERIFY(!scene2.hasFocus());
4179
4180
4181         toplevel3.show();
4182         QApplication::setActiveWindow(&toplevel3);
4183         QVERIFY(QTest::qWaitForWindowActive(&toplevel3));
4184         QCOMPARE(QApplication::activeWindow(), &toplevel3);
4185
4186         QVERIFY(scene1.isActive());
4187         QVERIFY(!scene2.isActive());
4188         QVERIFY(scene1.hasFocus());
4189         QVERIFY(!scene2.hasFocus());
4190
4191         layout->addWidget(view2);
4192         QApplication::processEvents();
4193         QVERIFY(scene1.isActive());
4194         QVERIFY(scene2.isActive());
4195         QVERIFY(scene1.hasFocus());
4196         QVERIFY(!scene2.hasFocus());
4197
4198         view1->setParent(0);
4199         QVERIFY(!scene1.isActive());
4200         QVERIFY(scene2.isActive());
4201         QVERIFY(!scene1.hasFocus());
4202         QVERIFY(scene2.hasFocus());
4203         delete view1;
4204     }
4205
4206     QVERIFY(!scene1.isActive());
4207     QVERIFY(!scene2.isActive());
4208     QVERIFY(!scene1.hasFocus());
4209     QVERIFY(!scene2.hasFocus());
4210
4211 }
4212
4213 void tst_QGraphicsScene::siblingIndexAlwaysValid()
4214 {
4215     QGraphicsScene scene;
4216
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);
4228
4229     //Then we make the child a top level
4230     child->setParentItem(0);
4231
4232     //This is trigerred by a repaint...
4233     QGraphicsScenePrivate::get(&scene)->index->estimateTopLevelItems(QRectF(), Qt::AscendingOrder);
4234
4235     delete child;
4236
4237     //If there are in the list that's bad, we crash...
4238     QVERIFY(!QGraphicsScenePrivate::get(&scene)->topLevelItems.contains(static_cast<QGraphicsItem *>(child)));
4239
4240     //Other case
4241     QGraphicsScene scene2;
4242     // works with bsp tree index
4243     scene2.setItemIndexMethod(QGraphicsScene::NoIndex);
4244
4245     QGraphicsView view2(&scene2);
4246
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);
4252
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);
4258
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);
4262
4263     view2.show();
4264
4265     // handle events as a real life app would do
4266     QApplication::processEvents();
4267
4268     // now delete the red rect
4269     delete item2;
4270
4271     // handle events as a real life app would do
4272      QApplication::processEvents();
4273
4274      //We should not crash
4275
4276 }
4277
4278 void tst_QGraphicsScene::removeFullyTransparentItem()
4279 {
4280     QGraphicsScene scene;
4281
4282     QGraphicsItem *parent = scene.addRect(0, 0, 100, 100);
4283     parent->setFlag(QGraphicsItem::ItemHasNoContents);
4284
4285     QGraphicsItem *child = scene.addRect(0, 0, 100, 100);
4286     child->setParentItem(parent);
4287
4288     CustomView view;
4289     view.setScene(&scene);
4290     view.show();
4291     qApp->setActiveWindow(&view);
4292     QVERIFY(QTest::qWaitForWindowActive(&view));
4293
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.
4298     view.repaints = 0;
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);
4304
4305     // Re-add child. There's nothing new to display (child is still
4306     // effectively hidden), so it shouldn't trigger an update.
4307     view.repaints = 0;
4308     child->setParentItem(parent);
4309     QVERIFY(scene.items().contains(child));
4310     QVERIFY(qFuzzyIsNull(child->effectiveOpacity()));
4311     QApplication::processEvents();
4312     QCOMPARE(view.repaints, 0);
4313
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);
4318     delete child;
4319 }
4320
4321 void tst_QGraphicsScene::taskQTBUG_5904_crashWithDeviceCoordinateCache()
4322 {
4323     QGraphicsScene scene;
4324     QGraphicsRectItem *rectItem = scene.addRect(QRectF(0, 0, 100, 200), QPen(Qt::black), QBrush(Qt::green));
4325
4326     rectItem->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
4327
4328     QPixmap pixmap(100,200);
4329     QPainter painter(&pixmap);
4330     painter.setRenderHint(QPainter::Antialiasing);
4331     scene.render(&painter);
4332     painter.end();
4333     // No crash, then it passed!
4334 }
4335
4336 void tst_QGraphicsScene::taskQT657_paintIntoCacheWithTransparentParts()
4337 {
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);
4342
4343     QGraphicsScene *scene = new QGraphicsScene();
4344     CustomView *view = new CustomView;
4345     view->setScene(scene);
4346
4347     QGraphicsProxyWidget *proxy = scene->addWidget(w);
4348     proxy->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
4349     proxy->rotate(15);
4350
4351     view->show();
4352     QVERIFY(QTest::qWaitForWindowExposed(view));
4353     view->repaints = 0;
4354     proxy->update(10, 10, 10, 10);
4355     QTest::qWait(50);
4356     QTRY_VERIFY(view->repaints > 0);
4357
4358     QPixmap pix;
4359     QGraphicsItemPrivate* itemp = QGraphicsItemPrivate::get(proxy);
4360     QTRY_VERIFY(QPixmapCache::find(itemp->extraItemCache()->deviceData.value(view->viewport()).key, &pix));
4361
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);
4369
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);
4374     }
4375
4376     delete w;
4377 }
4378
4379 void tst_QGraphicsScene::taskQTBUG_7863_paintIntoCacheWithTransparentParts()
4380 {
4381     // Test using DeviceCoordinateCache and semi-transparent item
4382     {
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);
4388
4389         QGraphicsScene *scene = new QGraphicsScene();
4390         CustomView *view = new CustomView;
4391         view->setScene(scene);
4392
4393         scene->addItem(backItem);
4394         rectItem->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
4395         backItem->rotate(15);
4396
4397         view->show();
4398         QVERIFY(QTest::qWaitForWindowExposed(view));
4399         view->repaints = 0;
4400         rectItem->update(10, 10, 10, 10);
4401         QTest::qWait(50);
4402         QTRY_VERIFY(view->repaints > 0);
4403
4404         QPixmap pix;
4405         QGraphicsItemPrivate* itemp = QGraphicsItemPrivate::get(rectItem);
4406         QTRY_VERIFY(QPixmapCache::find(itemp->extraItemCache()->deviceData.value(view->viewport()).key, &pix));
4407
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);
4415
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);
4420             }
4421         }
4422
4423         delete view;
4424     }
4425
4426     // Test using ItemCoordinateCache and opaque item
4427     {
4428         QGraphicsRectItem *rectItem = new QGraphicsRectItem(0, 0, 50, 50);
4429         rectItem->setBrush(QColor(0, 0, 255));
4430
4431         QGraphicsScene *scene = new QGraphicsScene();
4432         CustomView *view = new CustomView;
4433         view->setScene(scene);
4434
4435         scene->addItem(rectItem);
4436         rectItem->setCacheMode(QGraphicsItem::ItemCoordinateCache);
4437         rectItem->rotate(15);
4438
4439         view->show();
4440         QVERIFY(QTest::qWaitForWindowExposed(view));
4441         view->repaints = 0;
4442         rectItem->update(10, 10, 10, 10);
4443         QTest::qWait(50);
4444         QTRY_VERIFY(view->repaints > 0);
4445
4446         QPixmap pix;
4447         QGraphicsItemPrivate* itemp = QGraphicsItemPrivate::get(rectItem);
4448         QTRY_VERIFY(QPixmapCache::find(itemp->extraItemCache()->key, &pix));
4449
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);
4457
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);
4462         }
4463
4464         delete view;
4465     }
4466
4467     // Test using ItemCoordinateCache and semi-transparent item
4468     {
4469         QGraphicsRectItem *rectItem = new QGraphicsRectItem(0, 0, 50, 50);
4470         rectItem->setBrush(QColor(0, 0, 255, 125));
4471
4472         QGraphicsScene *scene = new QGraphicsScene();
4473         CustomView *view = new CustomView;
4474         view->setScene(scene);
4475
4476         scene->addItem(rectItem);
4477         rectItem->setCacheMode(QGraphicsItem::ItemCoordinateCache);
4478         rectItem->rotate(15);
4479
4480         view->show();
4481         QVERIFY(QTest::qWaitForWindowExposed(view));
4482         view->repaints = 0;
4483         rectItem->update(10, 10, 10, 10);
4484         QTest::qWait(50);
4485         QTRY_VERIFY(view->repaints > 0);
4486
4487         QPixmap pix;
4488         QGraphicsItemPrivate* itemp = QGraphicsItemPrivate::get(rectItem);
4489         QTRY_VERIFY(QPixmapCache::find(itemp->extraItemCache()->key, &pix));
4490
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);
4498
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);
4503         }
4504
4505         delete view;
4506     }
4507 }
4508
4509 void tst_QGraphicsScene::taskQT_3674_doNotCrash()
4510 {
4511     QGraphicsScene scene;
4512
4513     QGraphicsView view(&scene);
4514     view.resize(200, 200);
4515
4516     QPixmap pixmap(view.size());
4517     QPainter painter(&pixmap);
4518     view.render(&painter);
4519     painter.end();
4520
4521     scene.addItem(new QGraphicsWidget);
4522     scene.setBackgroundBrush(Qt::green);
4523
4524     QApplication::processEvents();
4525     QApplication::processEvents();
4526 }
4527
4528 void tst_QGraphicsScene::zeroScale()
4529 {
4530     //should not crash
4531     QGraphicsScene scene;
4532     scene.setSceneRect(-100, -100, 100, 100);
4533     QGraphicsView view(&scene);
4534
4535     ChangedListener cl;
4536     connect(&scene, SIGNAL(changed(QList<QRectF>)), &cl, SLOT(changed(QList<QRectF>)));
4537
4538     QGraphicsRectItem *rect1 = new QGraphicsRectItem(0, 0, 0.0000001, 0.00000001);
4539     scene.addItem(rect1);
4540     rect1->setRotation(82);
4541     rect1->setScale(0.00000001);
4542
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);
4551 }
4552
4553 void tst_QGraphicsScene::taskQTBUG_15977_renderWithDeviceCoordinateCache()
4554 {
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);
4561
4562     QImage image(100, 100, QImage::Format_RGB32);
4563     QPainter p(&image);
4564     scene.render(&p);
4565     p.end();
4566
4567     QImage expected(100, 100, QImage::Format_RGB32);
4568     p.begin(&expected);
4569     p.fillRect(expected.rect(), Qt::red);
4570     p.end();
4571
4572     QCOMPARE(image, expected);
4573 }
4574
4575 void tst_QGraphicsScene::taskQTBUG_16401_focusItem()
4576 {
4577     QGraphicsScene scene;
4578     QGraphicsView view(&scene);
4579     QGraphicsRectItem *rect = scene.addRect(0, 0, 100, 100);
4580     rect->setFlag(QGraphicsItem::ItemIsFocusable);
4581
4582     view.show();
4583     QApplication::setActiveWindow(&view);
4584     QVERIFY(QTest::qWaitForWindowActive(&view));
4585
4586     QVERIFY(!scene.focusItem());
4587
4588     rect->setFocus();
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);
4596
4597     rect->clearFocus();
4598     QVERIFY(!scene.focusItem());
4599     QApplication::sendEvent(&view, &focusOut);
4600     QVERIFY(!scene.focusItem());
4601     QApplication::sendEvent(&view, &focusIn);
4602     QVERIFY(!scene.focusItem());
4603 }
4604
4605 QTEST_MAIN(tst_QGraphicsScene)
4606 #include "tst_qgraphicsscene.moc"