1 /****************************************************************************
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
6 ** This file is part of the test suite of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
40 ****************************************************************************/
43 #include <QtTest/QtTest>
45 #include <private/qgraphicsitem_p.h>
46 #include <private/qgraphicsview_p.h>
47 #include <private/qgraphicsscene_p.h>
48 #include <QStyleOptionGraphicsItem>
49 #include <QAbstractTextDocumentLayout>
54 #include <QGraphicsItem>
55 #include <QGraphicsScene>
56 #include <QGraphicsSceneEvent>
57 #include <QGraphicsView>
58 #include <QGraphicsWidget>
59 #include <QGraphicsProxyWidget>
62 #include <QVBoxLayout>
63 #include <QGraphicsEffect>
64 #include <QPushButton>
66 #include <QGraphicsLinearLayout>
68 #include <QStyleHints>
70 Q_DECLARE_METATYPE(QList<int>)
71 Q_DECLARE_METATYPE(QList<QRectF>)
72 Q_DECLARE_METATYPE(QPainterPath)
73 Q_DECLARE_METATYPE(QPointF)
74 Q_DECLARE_METATYPE(QRectF)
76 #include "../../../qtest-config.h"
78 #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
80 #define Q_CHECK_PAINTEVENTS \
81 if (::SwitchDesktop(::GetThreadDesktop(::GetCurrentThreadId())) == 0) \
82 QSKIP("The Graphics View doesn't get the paint events");
84 #define Q_CHECK_PAINTEVENTS
88 // On mac (cocoa) we always get full update.
89 // So check that the expected region is contained inside the actual
90 #define COMPARE_REGIONS(ACTUAL, EXPECTED) QVERIFY((EXPECTED).subtracted(ACTUAL).isEmpty())
92 #define COMPARE_REGIONS QTRY_COMPARE
95 static QGraphicsRectItem staticItem; //QTBUG-7629, we should not crash at exit.
97 static void sendMousePress(QGraphicsScene *scene, const QPointF &point, Qt::MouseButton button = Qt::LeftButton)
99 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
100 event.setScenePos(point);
101 event.setButton(button);
102 event.setButtons(button);
103 QApplication::sendEvent(scene, &event);
106 static void sendMouseMove(QGraphicsScene *scene, const QPointF &point,
107 Qt::MouseButton button = Qt::NoButton, Qt::MouseButtons /* buttons */ = 0)
109 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseMove);
110 event.setScenePos(point);
111 event.setButton(button);
112 event.setButtons(button);
113 QApplication::sendEvent(scene, &event);
116 static void sendMouseRelease(QGraphicsScene *scene, const QPointF &point, Qt::MouseButton button = Qt::LeftButton)
118 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseRelease);
119 event.setScenePos(point);
120 event.setButton(button);
121 QApplication::sendEvent(scene, &event);
124 static void sendMouseClick(QGraphicsScene *scene, const QPointF &point, Qt::MouseButton button = Qt::LeftButton)
126 sendMousePress(scene, point, button);
127 sendMouseRelease(scene, point, button);
130 static void sendKeyPress(QGraphicsScene *scene, Qt::Key key)
132 QKeyEvent keyEvent(QEvent::KeyPress, key, Qt::NoModifier);
133 QApplication::sendEvent(scene, &keyEvent);
136 static void sendKeyRelease(QGraphicsScene *scene, Qt::Key key)
138 QKeyEvent keyEvent(QEvent::KeyRelease, key, Qt::NoModifier);
139 QApplication::sendEvent(scene, &keyEvent);
142 static void sendKeyClick(QGraphicsScene *scene, Qt::Key key)
144 sendKeyPress(scene, key);
145 sendKeyRelease(scene, key);
148 class EventSpy : public QGraphicsWidget
152 EventSpy(QObject *watched, QEvent::Type type)
153 : _count(0), spied(type)
155 watched->installEventFilter(this);
158 EventSpy(QGraphicsScene *scene, QGraphicsItem *watched, QEvent::Type type)
159 : _count(0), spied(type)
161 scene->addItem(this);
162 watched->installSceneEventFilter(this);
165 int count() const { return _count; }
168 bool eventFilter(QObject *watched, QEvent *event)
171 if (event->type() == spied)
176 bool sceneEventFilter(QGraphicsItem *watched, QEvent *event)
179 if (event->type() == spied)
188 class EventSpy2 : public QGraphicsWidget
192 EventSpy2(QObject *watched)
194 watched->installEventFilter(this);
197 EventSpy2(QGraphicsScene *scene, QGraphicsItem *watched)
199 scene->addItem(this);
200 watched->installSceneEventFilter(this);
203 QMap<QEvent::Type, int> counts;
206 bool eventFilter(QObject *watched, QEvent *event)
209 ++counts[event->type()];
213 bool sceneEventFilter(QGraphicsItem *watched, QEvent *event)
216 ++counts[event->type()];
221 class EventTester : public QGraphicsItem
224 EventTester(QGraphicsItem *parent = 0) : QGraphicsItem(parent), repaints(0)
225 { br = QRectF(-10, -10, 20, 20); }
227 void setGeometry(const QRectF &rect)
229 prepareGeometryChange();
234 QRectF boundingRect() const
237 void paint(QPainter *painter, const QStyleOptionGraphicsItem *o, QWidget *)
239 hints = painter->renderHints();
240 painter->setBrush(brush);
241 painter->drawRect(boundingRect());
242 lastExposedRect = o->exposedRect;
246 bool sceneEvent(QEvent *event)
248 events << event->type();
249 return QGraphicsItem::sceneEvent(event);
255 hints = QPainter::RenderHints(0);
257 lastExposedRect = QRectF();
260 QList<QEvent::Type> events;
261 QPainter::RenderHints hints;
264 QRectF lastExposedRect;
268 class MyGraphicsView : public QGraphicsView
272 QRegion paintedRegion;
273 MyGraphicsView(QGraphicsScene *scene, QWidget *parent=0) : QGraphicsView(scene,parent), repaints(0) {}
274 void paintEvent(QPaintEvent *e)
276 paintedRegion += e->region();
278 QGraphicsView::paintEvent(e);
280 void reset() { repaints = 0; paintedRegion = QRegion(); }
283 class tst_QGraphicsItem : public QObject
292 void constructionWithParent();
294 void deleteChildItem();
297 void setParentItem();
300 void inputMethodHints();
304 void explicitlyVisible();
306 void explicitlyEnabled();
309 void selected_group();
310 void selected_textItem();
311 void selected_multi();
312 void acceptedMouseButtons();
313 void acceptsHoverEvents();
314 void childAcceptsHoverEvents();
324 void collidesWith_item();
325 void collidesWith_path_data();
326 void collidesWith_path();
327 void collidesWithItemWithClip();
330 void mapFromToParent();
331 void mapFromToScene();
332 void mapFromToItem();
333 void mapRectFromToParent_data();
334 void mapRectFromToParent();
336 void commonAncestorItem();
339 void graphicsitem_cast();
340 void hoverEventsGenerateRepaints();
341 void boundingRects_data();
342 void boundingRects();
343 void boundingRects2();
344 void sceneBoundingRect();
345 void childrenBoundingRect();
346 void childrenBoundingRectTransformed();
347 void childrenBoundingRect2();
348 void childrenBoundingRect3();
349 void childrenBoundingRect4();
350 void childrenBoundingRect5();
355 void warpChildrenIntoGroup();
356 void removeFromGroup();
357 void handlesChildEvents();
358 void handlesChildEvents2();
359 void handlesChildEvents3();
360 void filtersChildEvents();
361 void filtersChildEvents2();
362 void ensureVisible();
363 #ifndef QTEST_NO_CURSOR
366 //void textControlGetterSetter();
367 void defaultItemTest_QGraphicsLineItem();
368 void defaultItemTest_QGraphicsPixmapItem();
369 void defaultItemTest_QGraphicsTextItem();
370 void defaultItemTest_QGraphicsEllipseItem();
372 void sceneEventFilter();
373 void prepareGeometryChange();
375 void deleteItemInEventHandlers();
376 void itemClipsToShape();
377 void itemClipsChildrenToShape();
378 void itemClipsChildrenToShape2();
379 void itemClipsChildrenToShape3();
380 void itemClipsChildrenToShape4();
381 void itemClipsChildrenToShape5();
382 void itemClipsTextChildToShape();
383 void itemClippingDiscovery();
384 void ancestorFlags();
385 void untransformable();
386 void contextMenuEventPropagation();
387 void itemIsMovable();
388 void boundingRegion_data();
389 void boundingRegion();
390 void itemTransform_parentChild();
391 void itemTransform_siblings();
392 void itemTransform_unrelated();
396 void opacityZeroUpdates();
397 void itemStacksBehindParent();
398 void nestedClipping();
399 void nestedClippingTransforms();
400 void sceneTransformCache();
401 void tabChangesFocus();
402 void tabChangesFocus_data();
405 void updateCachedItemAfterMove();
406 void deviceTransform_data();
407 void deviceTransform();
409 void setTransformProperties_data();
410 void setTransformProperties();
411 void itemUsesExtendedStyleOption();
412 void itemSendsGeometryChanges();
417 void itemHasNoContents();
418 void hitTestUntransformableItem();
419 void hitTestGraphicsEffectItem();
422 void focusProxyDeletion();
423 void negativeZStacksBehindParent();
424 void setGraphicsEffect();
426 void addPanelToActiveScene();
427 void panelWithFocusItem();
429 void setActivePanelOnInactiveScene();
430 void activationOnShowHide();
431 void moveWhileDeleting();
432 void ensureDirtySceneTransform();
436 void sceneModality();
437 void panelModality();
438 void mixedModality();
439 void modality_hover();
440 void modality_mouseGrabber();
441 void modality_clickFocus();
442 void modality_keyEvents();
443 void itemIsInFront();
444 void scenePosChange();
445 void textItem_shortcuts();
447 void focusHandling_data();
448 void focusHandling();
449 void touchEventPropagation_data();
450 void touchEventPropagation();
451 void deviceCoordinateCache_simpleRotations();
453 // task specific tests below me
454 void task141694_textItemEnsureVisible();
455 void task128696_textItemEnsureMovable();
456 void ensureUpdateOnTextItem();
457 void task177918_lineItemUndetected();
458 void task240400_clickOnTextItem_data();
459 void task240400_clickOnTextItem();
460 void task243707_addChildBeforeParent();
461 void task197802_childrenVisibility();
462 void QTBUG_4233_updateCachedWithSceneRect();
463 void QTBUG_5418_textItemSetDefaultColor();
464 void QTBUG_6738_missingUpdateWithSetParent();
465 void QTBUG_7714_fullUpdateDiscardingOpacityUpdate2();
466 void QT_2653_fullUpdateDiscardingOpacityUpdate();
467 void QT_2649_focusScope();
468 void sortItemsWhileAdding();
469 void doNotMarkFullUpdateIfNotInScene();
470 void itemDiesDuringDraggingOperation();
471 void QTBUG_12112_focusItem();
472 void QTBUG_13473_sceneposchange();
473 void QTBUG_16374_crashInDestructor();
474 void QTBUG_20699_focusScopeCrash();
477 QList<QGraphicsItem *> paintedItems;
480 void tst_QGraphicsItem::init()
482 #ifdef Q_OS_WINCE //disable magic for WindowsCE
483 qApp->setAutoMaximizeThreshold(-1);
487 void tst_QGraphicsItem::construction()
489 for (int i = 0; i < 7; ++i) {
493 item = new QGraphicsEllipseItem;
494 QCOMPARE(int(item->type()), int(QGraphicsEllipseItem::Type));
495 QCOMPARE(qgraphicsitem_cast<QGraphicsEllipseItem *>(item), (QGraphicsEllipseItem *)item);
496 QCOMPARE(qgraphicsitem_cast<QGraphicsRectItem *>(item), (QGraphicsRectItem *)0);
497 QCOMPARE(item->flags(), 0);
500 item = new QGraphicsLineItem;
501 QCOMPARE(int(item->type()), int(QGraphicsLineItem::Type));
502 QCOMPARE(qgraphicsitem_cast<QGraphicsLineItem *>(item), (QGraphicsLineItem *)item);
503 QCOMPARE(qgraphicsitem_cast<QGraphicsRectItem *>(item), (QGraphicsRectItem *)0);
504 QCOMPARE(item->flags(), 0);
507 item = new QGraphicsPathItem;
508 QCOMPARE(int(item->type()), int(QGraphicsPathItem::Type));
509 QCOMPARE(qgraphicsitem_cast<QGraphicsPathItem *>(item), (QGraphicsPathItem *)item);
510 QCOMPARE(qgraphicsitem_cast<QGraphicsRectItem *>(item), (QGraphicsRectItem *)0);
511 QCOMPARE(item->flags(), 0);
514 item = new QGraphicsPixmapItem;
515 QCOMPARE(int(item->type()), int(QGraphicsPixmapItem::Type));
516 QCOMPARE(qgraphicsitem_cast<QGraphicsPixmapItem *>(item), (QGraphicsPixmapItem *)item);
517 QCOMPARE(qgraphicsitem_cast<QGraphicsRectItem *>(item), (QGraphicsRectItem *)0);
518 QCOMPARE(item->flags(), 0);
521 item = new QGraphicsPolygonItem;
522 QCOMPARE(int(item->type()), int(QGraphicsPolygonItem::Type));
523 QCOMPARE(qgraphicsitem_cast<QGraphicsPolygonItem *>(item), (QGraphicsPolygonItem *)item);
524 QCOMPARE(qgraphicsitem_cast<QGraphicsRectItem *>(item), (QGraphicsRectItem *)0);
525 QCOMPARE(item->flags(), 0);
528 item = new QGraphicsRectItem;
529 QCOMPARE(int(item->type()), int(QGraphicsRectItem::Type));
530 QCOMPARE(qgraphicsitem_cast<QGraphicsRectItem *>(item), (QGraphicsRectItem *)item);
531 QCOMPARE(qgraphicsitem_cast<QGraphicsLineItem *>(item), (QGraphicsLineItem *)0);
532 QCOMPARE(item->flags(), 0);
535 item = new QGraphicsTextItem;
536 QCOMPARE(int(item->type()), int(QGraphicsTextItem::Type));
537 QCOMPARE(qgraphicsitem_cast<QGraphicsTextItem *>(item), (QGraphicsTextItem *)item);
538 QCOMPARE(qgraphicsitem_cast<QGraphicsRectItem *>(item), (QGraphicsRectItem *)0);
539 // This is the only item that uses an extended style option.
540 QCOMPARE(item->flags(), QGraphicsItem::GraphicsItemFlags(QGraphicsItem::ItemUsesExtendedStyleOption));
543 qFatal("You broke the logic, please fix!");
547 QCOMPARE(item->scene(), (QGraphicsScene *)0);
548 QCOMPARE(item->parentItem(), (QGraphicsItem *)0);
549 QVERIFY(item->children().isEmpty());
550 QVERIFY(item->isVisible());
551 QVERIFY(item->isEnabled());
552 QVERIFY(!item->isSelected());
553 QCOMPARE(item->acceptedMouseButtons(), Qt::MouseButtons(0x1f));
554 if (item->type() == QGraphicsTextItem::Type)
555 QVERIFY(item->acceptsHoverEvents());
557 QVERIFY(!item->acceptsHoverEvents());
558 QVERIFY(!item->hasFocus());
559 QCOMPARE(item->pos(), QPointF());
560 QCOMPARE(item->matrix(), QMatrix());
561 QCOMPARE(item->sceneMatrix(), QMatrix());
562 QCOMPARE(item->zValue(), qreal(0));
563 QCOMPARE(item->sceneBoundingRect(), QRectF());
564 QCOMPARE(item->shape(), QPainterPath());
565 QVERIFY(!item->contains(QPointF(0, 0)));
566 QVERIFY(!item->collidesWithItem(0));
567 QVERIFY(item->collidesWithItem(item));
568 QVERIFY(!item->collidesWithPath(QPainterPath()));
569 QVERIFY(!item->isAncestorOf(0));
570 QVERIFY(!item->isAncestorOf(item));
571 QCOMPARE(item->data(0), QVariant());
576 class BoundingRectItem : public QGraphicsRectItem
579 BoundingRectItem(QGraphicsItem *parent = 0)
580 : QGraphicsRectItem(0, 0, parent ? 200 : 100, parent ? 200 : 100,
584 QRectF boundingRect() const
586 QRectF tmp = QGraphicsRectItem::boundingRect();
587 foreach (QGraphicsItem *child, children())
588 tmp |= child->boundingRect(); // <- might be pure virtual
593 void tst_QGraphicsItem::constructionWithParent()
595 // This test causes a crash if item1 calls item2's pure virtuals before the
596 // object has been constructed.
597 QGraphicsItem *item0 = new BoundingRectItem;
598 QGraphicsItem *item1 = new BoundingRectItem;
599 QGraphicsScene scene;
600 scene.addItem(item0);
601 scene.addItem(item1);
602 QGraphicsItem *item2 = new BoundingRectItem(item1);
603 QCOMPARE(item1->children(), QList<QGraphicsItem *>() << item2);
604 QCOMPARE(item1->boundingRect(), QRectF(0, 0, 200, 200));
606 item2->setParentItem(item0);
607 QCOMPARE(item0->children(), QList<QGraphicsItem *>() << item2);
608 QCOMPARE(item0->boundingRect(), QRectF(0, 0, 200, 200));
611 static int itemDeleted = 0;
612 class Item : public QGraphicsRectItem
619 void tst_QGraphicsItem::destruction()
621 QCOMPARE(itemDeleted, 0);
623 QGraphicsItem *parent = new QGraphicsRectItem;
624 Item *child = new Item;
625 child->setParentItem(parent);
626 QCOMPARE(child->parentItem(), parent);
628 QCOMPARE(itemDeleted, 1);
631 QGraphicsItem *parent = new QGraphicsRectItem;
632 Item *child = new Item;
633 child->setParentItem(parent);
634 QCOMPARE(parent->children().size(), 1);
636 QCOMPARE(parent->children().size(), 0);
638 QCOMPARE(itemDeleted, 2);
641 QGraphicsScene scene;
642 QGraphicsItem *parent = new QGraphicsRectItem;
643 Item *child = new Item;
644 QCOMPARE(child->parentItem(), (QGraphicsItem *)0);
645 child->setParentItem(parent);
646 QCOMPARE(child->parentItem(), parent);
647 scene.addItem(parent);
648 QCOMPARE(child->parentItem(), parent);
650 QCOMPARE(itemDeleted, 3);
653 QGraphicsScene scene;
654 QGraphicsItem *parent = new QGraphicsRectItem;
655 Item *child = new Item;
656 child->setParentItem(parent);
657 scene.addItem(parent);
658 QCOMPARE(child->scene(), &scene);
659 QCOMPARE(parent->children().size(), 1);
661 QCOMPARE(parent->children().size(), 0);
663 QCOMPARE(itemDeleted, 4);
666 QGraphicsScene scene;
667 QGraphicsItem *parent = new QGraphicsRectItem;
668 Item *child = new Item;
669 child->setParentItem(parent);
670 scene.addItem(parent);
671 QCOMPARE(child->scene(), &scene);
672 scene.removeItem(parent);
673 QCOMPARE(child->scene(), (QGraphicsScene *)0);
675 QCOMPARE(itemDeleted, 5);
678 QGraphicsScene scene;
679 QGraphicsItem *parent = new QGraphicsRectItem;
680 Item *child = new Item;
681 child->setParentItem(parent);
682 QCOMPARE(child->scene(), (QGraphicsScene *)0);
683 QCOMPARE(parent->scene(), (QGraphicsScene *)0);
684 scene.addItem(parent);
685 QCOMPARE(child->scene(), &scene);
686 scene.removeItem(child);
687 QCOMPARE(child->scene(), (QGraphicsScene *)0);
688 QCOMPARE(parent->scene(), &scene);
689 QCOMPARE(child->parentItem(), (QGraphicsItem *)0);
690 QVERIFY(parent->children().isEmpty());
692 QCOMPARE(itemDeleted, 5);
694 QCOMPARE(itemDeleted, 6);
697 QGraphicsScene scene;
698 QGraphicsItem *parent = new QGraphicsRectItem;
699 Item *child = new Item;
700 child->setParentItem(parent);
701 scene.addItem(parent);
702 scene.removeItem(child);
703 scene.removeItem(parent);
706 QCOMPARE(itemDeleted, 7);
709 QGraphicsScene scene;
710 QGraphicsItem *parent = new QGraphicsRectItem;
711 Item *child = new Item;
712 child->setParentItem(parent);
713 scene.addItem(parent);
714 QGraphicsScene scene2;
715 scene2.addItem(parent);
717 QCOMPARE(itemDeleted, 8);
720 QGraphicsScene scene;
721 QGraphicsItem *parent = new QGraphicsRectItem;
722 Item *child = new Item;
723 child->setParentItem(parent);
724 scene.addItem(parent);
725 QCOMPARE(child->scene(), &scene);
726 QGraphicsScene scene2;
727 scene2.addItem(parent);
728 QCOMPARE(child->scene(), &scene2);
729 scene.addItem(parent);
730 QCOMPARE(child->scene(), &scene);
731 scene2.addItem(parent);
732 QCOMPARE(child->scene(), &scene2);
734 QCOMPARE(itemDeleted, 9);
737 QGraphicsScene scene;
738 QGraphicsItem *parent = new QGraphicsRectItem;
739 Item *child = new Item;
740 child->setParentItem(parent);
741 scene.addItem(parent);
742 QCOMPARE(child->scene(), &scene);
743 QGraphicsScene scene2;
744 scene2.addItem(child);
745 QCOMPARE(child->scene(), &scene2);
747 QCOMPARE(itemDeleted, 9);
749 QCOMPARE(itemDeleted, 10);
752 QGraphicsScene scene;
753 QGraphicsItem *root = new QGraphicsRectItem;
754 QGraphicsItem *parent = root;
755 QGraphicsItem *middleItem = 0;
756 for (int i = 0; i < 99; ++i) {
757 Item *child = new Item;
758 child->setParentItem(parent);
765 QCOMPARE(scene.items().size(), 100);
767 QGraphicsScene scene2;
768 scene2.addItem(middleItem);
771 QCOMPARE(itemDeleted, 59);
773 QCOMPARE(itemDeleted, 109);
775 QGraphicsScene *scene = new QGraphicsScene;
776 QGraphicsRectItem *parent = new QGraphicsRectItem;
777 Item *child = new Item;
778 child->setParentItem(parent);
779 parent->setVisible(false);
780 scene->addItem(parent);
781 QCOMPARE(child->parentItem(), static_cast<QGraphicsItem*>(parent));
783 QCOMPARE(itemDeleted, 110);
787 void tst_QGraphicsItem::deleteChildItem()
789 QGraphicsScene scene;
790 QGraphicsItem *rect = scene.addRect(QRectF());
791 QGraphicsItem *child1 = new QGraphicsRectItem(rect);
792 QGraphicsItem *child2 = new QGraphicsRectItem(rect);
793 QGraphicsItem *child3 = new QGraphicsRectItem(rect);
796 child2->setParentItem(0);
800 void tst_QGraphicsItem::scene()
802 QGraphicsRectItem *item = new QGraphicsRectItem;
803 QCOMPARE(item->scene(), (QGraphicsScene *)0);
805 QGraphicsScene scene;
807 QCOMPARE(item->scene(), (QGraphicsScene *)&scene);
809 QGraphicsScene scene2;
810 scene2.addItem(item);
811 QCOMPARE(item->scene(), (QGraphicsScene *)&scene2);
813 scene2.removeItem(item);
814 QCOMPARE(item->scene(), (QGraphicsScene *)0);
819 void tst_QGraphicsItem::parentItem()
821 QGraphicsRectItem item;
822 QCOMPARE(item.parentItem(), (QGraphicsItem *)0);
824 QGraphicsRectItem *item2 = new QGraphicsRectItem(QRectF(), &item);
825 QCOMPARE(item2->parentItem(), (QGraphicsItem *)&item);
826 item2->setParentItem(&item);
827 QCOMPARE(item2->parentItem(), (QGraphicsItem *)&item);
828 item2->setParentItem(0);
829 QCOMPARE(item2->parentItem(), (QGraphicsItem *)0);
834 void tst_QGraphicsItem::setParentItem()
836 QGraphicsScene scene;
837 QGraphicsItem *item = scene.addRect(QRectF(0, 0, 10, 10));
838 QCOMPARE(item->scene(), &scene);
840 QGraphicsRectItem *child = new QGraphicsRectItem;
841 QCOMPARE(child->scene(), (QGraphicsScene *)0);
843 // This implicitly adds the item to the parent's scene
844 child->setParentItem(item);
845 QCOMPARE(child->scene(), &scene);
847 // This just makes it a toplevel
848 child->setParentItem(0);
849 QCOMPARE(child->scene(), &scene);
851 // Add the child back to the parent, then remove the parent from the scene
852 child->setParentItem(item);
853 scene.removeItem(item);
854 QCOMPARE(child->scene(), (QGraphicsScene *)0);
857 void tst_QGraphicsItem::children()
859 QGraphicsRectItem item;
860 QVERIFY(item.children().isEmpty());
862 QGraphicsRectItem *item2 = new QGraphicsRectItem(QRectF(), &item);
863 QCOMPARE(item.children().size(), 1);
864 QCOMPARE(item.children().first(), (QGraphicsItem *)item2);
865 QVERIFY(item2->children().isEmpty());
868 QVERIFY(item.children().isEmpty());
871 void tst_QGraphicsItem::flags()
873 QGraphicsRectItem *item = new QGraphicsRectItem(QRectF(-10, -10, 20, 20));
874 QCOMPARE(item->flags(), 0);
876 QGraphicsScene scene;
877 QEvent activate(QEvent::WindowActivate);
878 QApplication::sendEvent(&scene, &activate);
884 item->setFlag(QGraphicsItem::ItemIsFocusable, false);
885 QVERIFY(!item->hasFocus());
887 QVERIFY(!item->hasFocus());
889 item->setFlag(QGraphicsItem::ItemIsFocusable, true);
890 QVERIFY(!item->hasFocus());
892 QVERIFY(item->hasFocus());
893 QVERIFY(scene.hasFocus());
895 item->setFlag(QGraphicsItem::ItemIsFocusable, false);
896 QVERIFY(!item->hasFocus());
897 QVERIFY(scene.hasFocus());
901 item->setFlag(QGraphicsItem::ItemIsSelectable, false);
902 QVERIFY(!item->isSelected());
903 item->setSelected(true);
904 QVERIFY(!item->isSelected());
906 item->setFlag(QGraphicsItem::ItemIsSelectable, true);
907 QVERIFY(!item->isSelected());
908 item->setSelected(true);
909 QVERIFY(item->isSelected());
910 item->setFlag(QGraphicsItem::ItemIsSelectable, false);
911 QVERIFY(!item->isSelected());
915 item->setFlag(QGraphicsItem::ItemIsMovable, false);
916 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
917 event.setScenePos(QPointF(0, 0));
918 event.setButton(Qt::LeftButton);
919 event.setButtons(Qt::LeftButton);
920 QApplication::sendEvent(&scene, &event);
921 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0); // mouse grabber is reset
923 QGraphicsSceneMouseEvent event2(QEvent::GraphicsSceneMouseMove);
924 event2.setScenePos(QPointF(10, 10));
925 event2.setButton(Qt::LeftButton);
926 event2.setButtons(Qt::LeftButton);
927 QApplication::sendEvent(&scene, &event2);
928 QCOMPARE(item->pos(), QPointF());
930 QGraphicsSceneMouseEvent event3(QEvent::GraphicsSceneMouseRelease);
931 event3.setScenePos(QPointF(10, 10));
932 event3.setButtons(0);
933 QApplication::sendEvent(&scene, &event3);
934 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
936 item->setFlag(QGraphicsItem::ItemIsMovable, true);
937 QGraphicsSceneMouseEvent event4(QEvent::GraphicsSceneMousePress);
938 event4.setScenePos(QPointF(0, 0));
939 event4.setButton(Qt::LeftButton);
940 event4.setButtons(Qt::LeftButton);
941 QApplication::sendEvent(&scene, &event4);
942 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)item);
943 QGraphicsSceneMouseEvent event5(QEvent::GraphicsSceneMouseMove);
944 event5.setScenePos(QPointF(10, 10));
945 event5.setButton(Qt::LeftButton);
946 event5.setButtons(Qt::LeftButton);
947 QApplication::sendEvent(&scene, &event5);
948 QCOMPARE(item->pos(), QPointF(10, 10));
951 QGraphicsItem* clippingParent = new QGraphicsRectItem;
952 clippingParent->setFlag(QGraphicsItem::ItemClipsChildrenToShape, true);
954 QGraphicsItem* nonClippingParent = new QGraphicsRectItem;
955 nonClippingParent->setFlag(QGraphicsItem::ItemClipsChildrenToShape, false);
957 QGraphicsItem* child = new QGraphicsRectItem(nonClippingParent);
958 QVERIFY(!child->isClipped());
960 child->setParentItem(clippingParent);
961 QVERIFY(child->isClipped());
963 child->setParentItem(nonClippingParent);
964 QVERIFY(!child->isClipped());
968 class ImhTester : public QGraphicsItem
970 QRectF boundingRect() const { return QRectF(); }
971 void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *) {}
974 void tst_QGraphicsItem::inputMethodHints()
976 ImhTester *item = new ImhTester;
977 item->setFlag(QGraphicsItem::ItemAcceptsInputMethod, true);
978 item->setFlag(QGraphicsItem::ItemIsFocusable, true);
979 QCOMPARE(item->inputMethodHints(), Qt::ImhNone);
980 ImhTester *item2 = new ImhTester;
981 item2->setFlag(QGraphicsItem::ItemAcceptsInputMethod, true);
982 item2->setFlag(QGraphicsItem::ItemIsFocusable, true);
983 Qt::InputMethodHints imHints = item2->inputMethodHints();
984 imHints |= Qt::ImhHiddenText;
985 item2->setInputMethodHints(imHints);
986 QGraphicsScene scene;
988 scene.addItem(item2);
989 QGraphicsView view(&scene);
990 QApplication::setActiveWindow(&view);
992 QVERIFY(QTest::qWaitForWindowActive(&view));
994 QTRY_VERIFY(item->hasFocus());
995 QCOMPARE(view.inputMethodHints(), item->inputMethodHints());
997 QTRY_VERIFY(item2->hasFocus());
998 QCOMPARE(view.inputMethodHints(), item2->inputMethodHints());
999 item->setFlag(QGraphicsItem::ItemAcceptsInputMethod, false);
1001 QTRY_VERIFY(item->hasFocus());
1002 //Focus has changed but the new item doesn't accept input method, no hints.
1003 QCOMPARE(view.inputMethodHints(), 0);
1005 QTRY_VERIFY(item2->hasFocus());
1006 QCOMPARE(view.inputMethodHints(), item2->inputMethodHints());
1007 imHints = item2->inputMethodHints();
1008 imHints |= (Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText);
1009 item2->setInputMethodHints(imHints);
1010 QCOMPARE(view.inputMethodHints(), item2->inputMethodHints());
1011 QGraphicsProxyWidget *widget = new QGraphicsProxyWidget;
1012 QLineEdit *edit = new QLineEdit;
1013 edit->setEchoMode(QLineEdit::Password);
1014 scene.addItem(widget);
1016 QTRY_VERIFY(widget->hasFocus());
1017 //No widget on the proxy, so no hints
1018 QCOMPARE(view.inputMethodHints(), 0);
1019 widget->setWidget(edit);
1020 //View should match with the line edit
1021 QCOMPARE(view.inputMethodHints(), edit->inputMethodHints());
1024 void tst_QGraphicsItem::toolTip()
1026 QString toolTip = "Qt rocks!";
1028 QGraphicsRectItem *item = new QGraphicsRectItem(QRectF(0, 0, 100, 100));
1029 item->setPen(QPen(Qt::red, 1));
1030 item->setBrush(QBrush(Qt::blue));
1031 QVERIFY(item->toolTip().isEmpty());
1032 item->setToolTip(toolTip);
1033 QCOMPARE(item->toolTip(), toolTip);
1035 QGraphicsScene scene;
1036 scene.addItem(item);
1038 QGraphicsView view(&scene);
1039 view.setFixedSize(200, 200);
1041 QApplication::setActiveWindow(&view);
1042 QVERIFY(QTest::qWaitForWindowActive(&view));
1044 QHelpEvent helpEvent(QEvent::ToolTip, view.viewport()->rect().topLeft(),
1045 view.viewport()->mapToGlobal(view.viewport()->rect().topLeft()));
1046 QApplication::sendEvent(view.viewport(), &helpEvent);
1049 bool foundView = false;
1050 bool foundTipLabel = false;
1051 foreach (QWidget *widget, QApplication::topLevelWidgets()) {
1052 if (widget == &view)
1054 if (widget->inherits("QTipLabel"))
1055 foundTipLabel = true;
1058 QVERIFY(!foundTipLabel);
1062 QHelpEvent helpEvent(QEvent::ToolTip, view.viewport()->rect().center(),
1063 view.viewport()->mapToGlobal(view.viewport()->rect().center()));
1064 QApplication::sendEvent(view.viewport(), &helpEvent);
1067 bool foundView = false;
1068 bool foundTipLabel = false;
1069 foreach (QWidget *widget, QApplication::topLevelWidgets()) {
1070 if (widget == &view)
1072 if (widget->inherits("QTipLabel"))
1073 foundTipLabel = true;
1076 QVERIFY(foundTipLabel);
1080 QHelpEvent helpEvent(QEvent::ToolTip, view.viewport()->rect().topLeft(),
1081 view.viewport()->mapToGlobal(view.viewport()->rect().topLeft()));
1082 QApplication::sendEvent(view.viewport(), &helpEvent);
1085 bool foundView = false;
1086 bool foundTipLabel = false;
1087 foreach (QWidget *widget, QApplication::topLevelWidgets()) {
1088 if (widget == &view)
1090 if (widget->inherits("QTipLabel") && widget->isVisible())
1091 foundTipLabel = true;
1094 QVERIFY(!foundTipLabel);
1098 void tst_QGraphicsItem::visible()
1100 QGraphicsItem *item = new QGraphicsRectItem(QRectF(-10, -10, 20, 20));
1101 item->setFlag(QGraphicsItem::ItemIsMovable);
1102 QVERIFY(item->isVisible());
1103 item->setVisible(false);
1104 QVERIFY(!item->isVisible());
1105 item->setVisible(true);
1106 QVERIFY(item->isVisible());
1108 QGraphicsScene scene;
1109 QEvent activate(QEvent::WindowActivate);
1110 QApplication::sendEvent(&scene, &activate);
1112 scene.addItem(item);
1113 QVERIFY(item->isVisible());
1114 QCOMPARE(scene.itemAt(0, 0), item);
1115 item->setVisible(false);
1116 QCOMPARE(scene.itemAt(0, 0), (QGraphicsItem *)0);
1117 item->setVisible(true);
1118 QCOMPARE(scene.itemAt(0, 0), item);
1120 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
1121 event.setButton(Qt::LeftButton);
1122 event.setScenePos(QPointF(0, 0));
1123 QApplication::sendEvent(&scene, &event);
1124 QCOMPARE(scene.mouseGrabberItem(), item);
1125 item->setVisible(false);
1126 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
1127 item->setVisible(true);
1128 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
1130 item->setFlag(QGraphicsItem::ItemIsFocusable);
1132 QVERIFY(item->hasFocus());
1133 item->setVisible(false);
1134 QVERIFY(!item->hasFocus());
1135 item->setVisible(true);
1136 QVERIFY(!item->hasFocus());
1139 void tst_QGraphicsItem::isVisibleTo()
1141 QGraphicsScene scene;
1142 QGraphicsItem *parent = scene.addRect(QRectF(0, 0, 100, 100));
1143 QGraphicsItem *child = scene.addRect(QRectF(25, 25, 50, 50));
1144 QGraphicsItem *grandChild = scene.addRect(QRectF(50, 50, 50, 50));
1145 QGraphicsItem *stranger = scene.addRect(100, 100, 100, 100);
1147 child->setParentItem(parent);
1148 grandChild->setParentItem(child);
1150 QVERIFY(grandChild->isVisible());
1151 QVERIFY(grandChild->isVisibleTo(grandChild));
1152 QVERIFY(grandChild->isVisibleTo(child));
1153 QVERIFY(grandChild->isVisibleTo(parent));
1154 QVERIFY(grandChild->isVisibleTo(0));
1155 QVERIFY(child->isVisible());
1156 QVERIFY(child->isVisibleTo(child));
1157 QVERIFY(child->isVisibleTo(parent));
1158 QVERIFY(child->isVisibleTo(0));
1159 QVERIFY(parent->isVisible());
1160 QVERIFY(parent->isVisibleTo(parent));
1161 QVERIFY(parent->isVisibleTo(0));
1162 QVERIFY(!parent->isVisibleTo(child));
1163 QVERIFY(!child->isVisibleTo(grandChild));
1164 QVERIFY(!grandChild->isVisibleTo(stranger));
1165 QVERIFY(!child->isVisibleTo(stranger));
1166 QVERIFY(!parent->isVisibleTo(stranger));
1167 QVERIFY(!stranger->isVisibleTo(grandChild));
1168 QVERIFY(!stranger->isVisibleTo(child));
1169 QVERIFY(!stranger->isVisibleTo(parent));
1171 // Case 1: only parent is explicitly hidden
1174 QVERIFY(!grandChild->isVisible());
1175 QVERIFY(grandChild->isVisibleTo(grandChild));
1176 QVERIFY(grandChild->isVisibleTo(child));
1177 QVERIFY(grandChild->isVisibleTo(parent));
1178 QVERIFY(!grandChild->isVisibleTo(0));
1179 QVERIFY(!child->isVisible());
1180 QVERIFY(child->isVisibleTo(child));
1181 QVERIFY(child->isVisibleTo(parent));
1182 QVERIFY(!child->isVisibleTo(0));
1183 QVERIFY(!parent->isVisible());
1184 QVERIFY(!parent->isVisibleTo(parent));
1185 QVERIFY(!parent->isVisibleTo(0));
1186 QVERIFY(!parent->isVisibleTo(child));
1187 QVERIFY(!child->isVisibleTo(grandChild));
1188 QVERIFY(!grandChild->isVisibleTo(stranger));
1189 QVERIFY(!child->isVisibleTo(stranger));
1190 QVERIFY(!parent->isVisibleTo(stranger));
1191 QVERIFY(!stranger->isVisibleTo(grandChild));
1192 QVERIFY(!stranger->isVisibleTo(child));
1193 QVERIFY(!stranger->isVisibleTo(parent));
1195 // Case 2: only child is hidden
1199 QVERIFY(!grandChild->isVisible());
1200 QVERIFY(grandChild->isVisibleTo(grandChild));
1201 QVERIFY(grandChild->isVisibleTo(child));
1202 QVERIFY(!grandChild->isVisibleTo(parent));
1203 QVERIFY(!grandChild->isVisibleTo(0));
1204 QVERIFY(!child->isVisible());
1205 QVERIFY(!child->isVisibleTo(child));
1206 QVERIFY(!child->isVisibleTo(parent));
1207 QVERIFY(!child->isVisibleTo(0));
1208 QVERIFY(parent->isVisible());
1209 QVERIFY(parent->isVisibleTo(parent));
1210 QVERIFY(parent->isVisibleTo(0));
1211 QVERIFY(!parent->isVisibleTo(child));
1212 QVERIFY(!child->isVisibleTo(grandChild));
1213 QVERIFY(!grandChild->isVisibleTo(stranger));
1214 QVERIFY(!child->isVisibleTo(stranger));
1215 QVERIFY(!parent->isVisibleTo(stranger));
1216 QVERIFY(!stranger->isVisibleTo(grandChild));
1217 QVERIFY(!stranger->isVisibleTo(child));
1218 QVERIFY(!stranger->isVisibleTo(parent));
1220 // Case 3: only grand child is hidden
1224 QVERIFY(!grandChild->isVisible());
1225 QVERIFY(!grandChild->isVisibleTo(grandChild));
1226 QVERIFY(!grandChild->isVisibleTo(child));
1227 QVERIFY(!grandChild->isVisibleTo(parent));
1228 QVERIFY(!grandChild->isVisibleTo(0));
1229 QVERIFY(child->isVisible());
1230 QVERIFY(child->isVisibleTo(child));
1231 QVERIFY(child->isVisibleTo(parent));
1232 QVERIFY(child->isVisibleTo(0));
1233 QVERIFY(parent->isVisible());
1234 QVERIFY(parent->isVisibleTo(parent));
1235 QVERIFY(parent->isVisibleTo(0));
1236 QVERIFY(!parent->isVisibleTo(child));
1237 QVERIFY(!child->isVisibleTo(grandChild));
1238 QVERIFY(!grandChild->isVisibleTo(stranger));
1239 QVERIFY(!child->isVisibleTo(stranger));
1240 QVERIFY(!parent->isVisibleTo(stranger));
1241 QVERIFY(!stranger->isVisibleTo(grandChild));
1242 QVERIFY(!stranger->isVisibleTo(child));
1243 QVERIFY(!stranger->isVisibleTo(parent));
1246 void tst_QGraphicsItem::explicitlyVisible()
1248 QGraphicsScene scene;
1249 QGraphicsItem *parent = scene.addRect(QRectF(0, 0, 100, 100));
1250 QGraphicsItem *child = scene.addRect(QRectF(25, 25, 50, 50));
1251 child->setParentItem(parent);
1253 QVERIFY(parent->isVisible());
1254 QVERIFY(child->isVisible());
1258 QVERIFY(!parent->isVisible());
1259 QVERIFY(!child->isVisible());
1264 QVERIFY(parent->isVisible());
1265 QVERIFY(!child->isVisible());
1269 QVERIFY(!parent->isVisible());
1270 QVERIFY(!child->isVisible());
1274 QVERIFY(parent->isVisible());
1275 QVERIFY(!child->isVisible()); // <- explicitly hidden
1279 QVERIFY(child->isVisible());
1283 QVERIFY(!parent->isVisible());
1284 QVERIFY(!child->isVisible()); // <- explicit show doesn't work
1288 QVERIFY(parent->isVisible());
1289 QVERIFY(child->isVisible()); // <- no longer explicitly hidden
1291 // ------------------- Reparenting ------------------------------
1293 QGraphicsItem *parent2 = scene.addRect(-50, -50, 200, 200);
1294 QVERIFY(parent2->isVisible());
1296 // Reparent implicitly hidden item to a visible parent.
1298 QVERIFY(!parent->isVisible());
1299 QVERIFY(!child->isVisible());
1300 child->setParentItem(parent2);
1301 QVERIFY(parent2->isVisible());
1302 QVERIFY(child->isVisible());
1304 // Reparent implicitly hidden item to a hidden parent.
1305 child->setParentItem(parent);
1307 child->setParentItem(parent2);
1308 QVERIFY(!parent2->isVisible());
1309 QVERIFY(!child->isVisible());
1311 // Reparent explicitly hidden item to a visible parent.
1314 child->setParentItem(parent);
1315 QVERIFY(parent->isVisible());
1316 QVERIFY(!child->isVisible());
1318 // Reparent explicitly hidden item to a hidden parent.
1319 child->setParentItem(parent2);
1320 QVERIFY(!parent2->isVisible());
1321 QVERIFY(!child->isVisible());
1323 // Reparent explicitly hidden item to a visible parent.
1325 child->setParentItem(parent);
1326 QVERIFY(parent->isVisible());
1327 QVERIFY(!child->isVisible());
1329 // Reparent visible item to a hidden parent.
1332 child->setParentItem(parent2);
1333 QVERIFY(!parent2->isVisible());
1334 QVERIFY(!child->isVisible());
1336 QVERIFY(parent2->isVisible());
1337 QVERIFY(child->isVisible());
1339 // Reparent implicitly hidden child to root.
1341 QVERIFY(!child->isVisible());
1342 child->setParentItem(0);
1343 QVERIFY(child->isVisible());
1345 // Reparent an explicitly hidden child to root.
1347 child->setParentItem(parent2);
1349 QVERIFY(!child->isVisible());
1350 child->setParentItem(0);
1351 QVERIFY(!child->isVisible());
1354 void tst_QGraphicsItem::enabled()
1356 QGraphicsRectItem *item = new QGraphicsRectItem(QRectF(-10, -10, 20, 20));
1357 item->setFlag(QGraphicsItem::ItemIsMovable);
1358 QVERIFY(item->isEnabled());
1359 item->setEnabled(false);
1360 QVERIFY(!item->isEnabled());
1361 item->setEnabled(true);
1362 QVERIFY(item->isEnabled());
1363 item->setEnabled(false);
1364 item->setFlag(QGraphicsItem::ItemIsFocusable);
1365 QGraphicsScene scene;
1366 QEvent activate(QEvent::WindowActivate);
1367 QApplication::sendEvent(&scene, &activate);
1369 scene.addItem(item);
1371 QVERIFY(!item->hasFocus());
1372 item->setEnabled(true);
1374 QVERIFY(item->hasFocus());
1375 item->setEnabled(false);
1376 QVERIFY(!item->hasFocus());
1378 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
1379 event.setButton(Qt::LeftButton);
1380 event.setScenePos(QPointF(0, 0));
1381 QApplication::sendEvent(&scene, &event);
1382 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
1383 item->setEnabled(true);
1384 QApplication::sendEvent(&scene, &event);
1385 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)item);
1386 item->setEnabled(false);
1387 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
1390 void tst_QGraphicsItem::explicitlyEnabled()
1392 QGraphicsScene scene;
1393 QGraphicsItem *parent = scene.addRect(QRectF(0, 0, 100, 100));
1394 QGraphicsItem *child = scene.addRect(QRectF(25, 25, 50, 50));
1395 child->setParentItem(parent);
1397 QVERIFY(parent->isEnabled());
1398 QVERIFY(child->isEnabled());
1400 parent->setEnabled(false);
1402 QVERIFY(!parent->isEnabled());
1403 QVERIFY(!child->isEnabled());
1405 parent->setEnabled(true);
1406 child->setEnabled(false);
1408 QVERIFY(parent->isEnabled());
1409 QVERIFY(!child->isEnabled());
1411 parent->setEnabled(false);
1413 QVERIFY(!parent->isEnabled());
1414 QVERIFY(!child->isEnabled());
1416 parent->setEnabled(true);
1418 QVERIFY(parent->isEnabled());
1419 QVERIFY(!child->isEnabled()); // <- explicitly disabled
1421 child->setEnabled(true);
1423 QVERIFY(child->isEnabled());
1425 parent->setEnabled(false);
1427 QVERIFY(!parent->isEnabled());
1428 QVERIFY(!child->isEnabled()); // <- explicit enabled doesn't work
1430 parent->setEnabled(true);
1432 QVERIFY(parent->isEnabled());
1433 QVERIFY(child->isEnabled()); // <- no longer explicitly disabled
1435 // ------------------- Reparenting ------------------------------
1437 QGraphicsItem *parent2 = scene.addRect(-50, -50, 200, 200);
1438 QVERIFY(parent2->isEnabled());
1440 // Reparent implicitly hidden item to a enabled parent.
1441 parent->setEnabled(false);
1442 QVERIFY(!parent->isEnabled());
1443 QVERIFY(!child->isEnabled());
1444 child->setParentItem(parent2);
1445 QVERIFY(parent2->isEnabled());
1446 QVERIFY(child->isEnabled());
1448 // Reparent implicitly hidden item to a hidden parent.
1449 child->setParentItem(parent);
1450 parent2->setEnabled(false);
1451 child->setParentItem(parent2);
1452 QVERIFY(!parent2->isEnabled());
1453 QVERIFY(!child->isEnabled());
1455 // Reparent explicitly hidden item to a enabled parent.
1456 child->setEnabled(false);
1457 parent->setEnabled(true);
1458 child->setParentItem(parent);
1459 QVERIFY(parent->isEnabled());
1460 QVERIFY(!child->isEnabled());
1462 // Reparent explicitly hidden item to a hidden parent.
1463 child->setParentItem(parent2);
1464 QVERIFY(!parent2->isEnabled());
1465 QVERIFY(!child->isEnabled());
1467 // Reparent explicitly hidden item to a enabled parent.
1468 parent->setEnabled(true);
1469 child->setParentItem(parent);
1470 QVERIFY(parent->isEnabled());
1471 QVERIFY(!child->isEnabled());
1473 // Reparent enabled item to a hidden parent.
1474 child->setEnabled(true);
1475 parent2->setEnabled(false);
1476 child->setParentItem(parent2);
1477 QVERIFY(!parent2->isEnabled());
1478 QVERIFY(!child->isEnabled());
1479 parent2->setEnabled(true);
1480 QVERIFY(parent2->isEnabled());
1481 QVERIFY(child->isEnabled());
1483 // Reparent implicitly hidden child to root.
1484 parent2->setEnabled(false);
1485 QVERIFY(!child->isEnabled());
1486 child->setParentItem(0);
1487 QVERIFY(child->isEnabled());
1489 // Reparent an explicitly hidden child to root.
1490 child->setEnabled(false);
1491 child->setParentItem(parent2);
1492 parent2->setEnabled(true);
1493 QVERIFY(!child->isEnabled());
1494 child->setParentItem(0);
1495 QVERIFY(!child->isEnabled());
1498 class SelectChangeItem : public QGraphicsRectItem
1501 SelectChangeItem() : QGraphicsRectItem(-50, -50, 100, 100) { setBrush(Qt::blue); }
1505 QVariant itemChange(GraphicsItemChange change, const QVariant &value)
1507 if (change == ItemSelectedChange)
1508 values << value.toBool();
1509 return QGraphicsRectItem::itemChange(change, value);
1513 void tst_QGraphicsItem::selected()
1515 SelectChangeItem *item = new SelectChangeItem;
1516 item->setFlag(QGraphicsItem::ItemIsSelectable);
1517 QVERIFY(!item->isSelected());
1518 QVERIFY(item->values.isEmpty());
1519 item->setSelected(true);
1520 QCOMPARE(item->values.size(), 1);
1521 QCOMPARE(item->values.last(), true);
1522 QVERIFY(item->isSelected());
1523 item->setSelected(false);
1524 QCOMPARE(item->values.size(), 2);
1525 QCOMPARE(item->values.last(), false);
1526 QVERIFY(!item->isSelected());
1527 item->setSelected(true);
1528 QCOMPARE(item->values.size(), 3);
1529 item->setEnabled(false);
1530 QCOMPARE(item->values.size(), 4);
1531 QCOMPARE(item->values.last(), false);
1532 QVERIFY(!item->isSelected());
1533 item->setEnabled(true);
1534 QCOMPARE(item->values.size(), 4);
1535 item->setSelected(true);
1536 QCOMPARE(item->values.size(), 5);
1537 QCOMPARE(item->values.last(), true);
1538 QVERIFY(item->isSelected());
1539 item->setVisible(false);
1540 QCOMPARE(item->values.size(), 6);
1541 QCOMPARE(item->values.last(), false);
1542 QVERIFY(!item->isSelected());
1543 item->setVisible(true);
1544 QCOMPARE(item->values.size(), 6);
1545 item->setSelected(true);
1546 QCOMPARE(item->values.size(), 7);
1547 QCOMPARE(item->values.last(), true);
1548 QVERIFY(item->isSelected());
1550 QGraphicsScene scene(-100, -100, 200, 200);
1551 scene.addItem(item);
1552 QCOMPARE(scene.selectedItems(), QList<QGraphicsItem *>() << item);
1553 item->setSelected(false);
1554 QVERIFY(scene.selectedItems().isEmpty());
1555 item->setSelected(true);
1556 QCOMPARE(scene.selectedItems(), QList<QGraphicsItem *>() << item);
1557 item->setSelected(false);
1558 QVERIFY(scene.selectedItems().isEmpty());
1560 // Interactive selection
1561 QGraphicsView view(&scene);
1562 view.setFixedSize(250, 250);
1565 QVERIFY(QTest::qWaitForWindowExposed(&view));
1566 qApp->processEvents();
1567 qApp->processEvents();
1569 scene.clearSelection();
1570 QCOMPARE(item->values.size(), 10);
1571 QCOMPARE(item->values.last(), false);
1572 QVERIFY(!item->isSelected());
1574 // Click inside and check that it's selected
1575 QTest::mouseMove(view.viewport());
1576 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item->scenePos()));
1577 QCOMPARE(item->values.size(), 11);
1578 QCOMPARE(item->values.last(), true);
1579 QVERIFY(item->isSelected());
1581 // Click outside and check that it's not selected
1582 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item->scenePos() + QPointF(item->boundingRect().width(), item->boundingRect().height())));
1583 QCOMPARE(item->values.size(), 12);
1584 QCOMPARE(item->values.last(), false);
1585 QVERIFY(!item->isSelected());
1587 SelectChangeItem *item2 = new SelectChangeItem;
1588 item2->setFlag(QGraphicsItem::ItemIsSelectable);
1589 item2->setPos(100, 0);
1590 scene.addItem(item2);
1592 // Click inside and check that it's selected
1593 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item->scenePos()));
1594 QCOMPARE(item->values.size(), 13);
1595 QCOMPARE(item->values.last(), true);
1596 QVERIFY(item->isSelected());
1598 // Click inside item2 and check that it's selected, and item is not
1599 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item2->scenePos()));
1600 QCOMPARE(item->values.size(), 14);
1601 QCOMPARE(item->values.last(), false);
1602 QVERIFY(!item->isSelected());
1603 QCOMPARE(item2->values.size(), 1);
1604 QCOMPARE(item2->values.last(), true);
1605 QVERIFY(item2->isSelected());
1608 void tst_QGraphicsItem::selected2()
1610 // Selecting an item, then moving another previously caused a crash.
1611 QGraphicsScene scene;
1612 QGraphicsItem *line1 = scene.addRect(QRectF(0, 0, 100, 100));
1613 line1->setPos(-105, 0);
1614 line1->setFlag(QGraphicsItem::ItemIsSelectable);
1616 QGraphicsItem *line2 = scene.addRect(QRectF(0, 0, 100, 100));
1617 line2->setFlag(QGraphicsItem::ItemIsMovable);
1619 line1->setSelected(true);
1622 QGraphicsSceneMouseEvent mousePress(QEvent::GraphicsSceneMousePress);
1623 mousePress.setScenePos(QPointF(50, 50));
1624 mousePress.setButton(Qt::LeftButton);
1625 QApplication::sendEvent(&scene, &mousePress);
1626 QVERIFY(mousePress.isAccepted());
1629 QGraphicsSceneMouseEvent mouseMove(QEvent::GraphicsSceneMouseMove);
1630 mouseMove.setScenePos(QPointF(60, 60));
1631 mouseMove.setButton(Qt::LeftButton);
1632 mouseMove.setButtons(Qt::LeftButton);
1633 QApplication::sendEvent(&scene, &mouseMove);
1634 QVERIFY(mouseMove.isAccepted());
1638 void tst_QGraphicsItem::selected_group()
1640 QGraphicsScene scene;
1641 QGraphicsItem *item1 = scene.addRect(QRectF());
1642 QGraphicsItem *item2 = scene.addRect(QRectF());
1643 item1->setFlag(QGraphicsItem::ItemIsSelectable);
1644 item2->setFlag(QGraphicsItem::ItemIsSelectable);
1645 scene.addRect(QRectF())->setParentItem(item1);
1646 QGraphicsItem *leaf = scene.addRect(QRectF());
1647 leaf->setFlag(QGraphicsItem::ItemIsSelectable);
1648 leaf->setParentItem(item2);
1650 QGraphicsItemGroup *group = scene.createItemGroup(QList<QGraphicsItem *>() << item1 << item2);
1651 QCOMPARE(group->scene(), &scene);
1652 group->setFlag(QGraphicsItem::ItemIsSelectable);
1653 foreach (QGraphicsItem *item, scene.items()) {
1655 QVERIFY(!item->group());
1657 QCOMPARE(item->group(), group);
1660 QVERIFY(group->handlesChildEvents());
1661 QVERIFY(!group->isSelected());
1662 group->setSelected(false);
1663 QVERIFY(!group->isSelected());
1664 group->setSelected(true);
1665 QVERIFY(group->isSelected());
1666 foreach (QGraphicsItem *item, scene.items())
1667 QVERIFY(item->isSelected());
1668 group->setSelected(false);
1669 QVERIFY(!group->isSelected());
1670 foreach (QGraphicsItem *item, scene.items())
1671 QVERIFY(!item->isSelected());
1672 leaf->setSelected(true);
1673 foreach (QGraphicsItem *item, scene.items())
1674 QVERIFY(item->isSelected());
1675 leaf->setSelected(false);
1676 foreach (QGraphicsItem *item, scene.items())
1677 QVERIFY(!item->isSelected());
1679 leaf->setSelected(true);
1680 QGraphicsScene scene2;
1681 scene2.addItem(item1);
1682 QVERIFY(!item1->isSelected());
1683 QVERIFY(item2->isSelected());
1686 void tst_QGraphicsItem::selected_textItem()
1688 QGraphicsScene scene;
1689 QGraphicsTextItem *text = scene.addText(QLatin1String("Text"));
1690 text->setFlag(QGraphicsItem::ItemIsSelectable);
1692 QGraphicsView view(&scene);
1694 QVERIFY(QTest::qWaitForWindowExposed(&view));
1697 QTRY_VERIFY(!text->isSelected());
1698 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0,
1699 view.mapFromScene(text->mapToScene(0, 0)));
1700 QTRY_VERIFY(text->isSelected());
1702 text->setSelected(false);
1703 text->setTextInteractionFlags(Qt::TextEditorInteraction);
1705 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0,
1706 view.mapFromScene(text->mapToScene(0, 0)));
1707 QTRY_VERIFY(text->isSelected());
1710 void tst_QGraphicsItem::selected_multi()
1712 // Test multiselection behavior
1713 QGraphicsScene scene;
1715 // Create two disjoint items
1716 QGraphicsItem *item1 = scene.addRect(QRectF(-10, -10, 20, 20));
1717 QGraphicsItem *item2 = scene.addRect(QRectF(-10, -10, 20, 20));
1718 item1->setPos(-15, 0);
1719 item2->setPos(15, 20);
1721 // Make both items selectable
1722 item1->setFlag(QGraphicsItem::ItemIsSelectable);
1723 item2->setFlag(QGraphicsItem::ItemIsSelectable);
1725 // Create and show a view
1726 QGraphicsView view(&scene);
1728 view.fitInView(scene.sceneRect());
1729 qApp->processEvents();
1731 QVERIFY(!item1->isSelected());
1732 QVERIFY(!item2->isSelected());
1738 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item1->scenePos()));
1740 QVERIFY(item1->isSelected());
1741 QVERIFY(!item2->isSelected());
1744 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item2->scenePos()));
1746 QVERIFY(item2->isSelected());
1747 QVERIFY(!item1->isSelected());
1749 // Ctrl-click on item1
1750 QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(item1->scenePos()));
1752 QVERIFY(item2->isSelected());
1753 QVERIFY(item1->isSelected());
1755 // Ctrl-click on item1 again
1756 QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(item1->scenePos()));
1758 QVERIFY(item2->isSelected());
1759 QVERIFY(!item1->isSelected());
1761 // Ctrl-click on item2
1762 QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(item2->scenePos()));
1764 QVERIFY(!item2->isSelected());
1765 QVERIFY(!item1->isSelected());
1768 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item1->scenePos()));
1770 QVERIFY(item1->isSelected());
1771 QVERIFY(!item2->isSelected());
1774 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(0, 0));
1776 QVERIFY(!item1->isSelected());
1777 QVERIFY(!item2->isSelected());
1780 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item1->scenePos()));
1782 QVERIFY(item1->isSelected());
1783 QVERIFY(!item2->isSelected());
1785 // Ctrl-click on scene
1786 QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(0, 0));
1788 QVERIFY(!item1->isSelected());
1789 QVERIFY(!item2->isSelected());
1792 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item1->scenePos()));
1794 QVERIFY(item1->isSelected());
1795 QVERIFY(!item2->isSelected());
1798 QTest::mousePress(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item2->scenePos()));
1800 QVERIFY(!item1->isSelected());
1801 QVERIFY(item2->isSelected());
1804 QTest::mouseRelease(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item2->scenePos()));
1806 QVERIFY(!item1->isSelected());
1807 QVERIFY(item2->isSelected());
1810 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item1->scenePos()));
1812 QVERIFY(item1->isSelected());
1813 QVERIFY(!item2->isSelected());
1815 // Ctrl-click on item1
1816 QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(item1->scenePos()));
1818 QVERIFY(!item1->isSelected());
1819 QVERIFY(!item2->isSelected());
1821 // Ctrl-press on item1
1822 QTest::mousePress(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(item1->scenePos()));
1824 QVERIFY(!item1->isSelected());
1825 QVERIFY(!item2->isSelected());
1828 // Ctrl-move on item1
1829 QMouseEvent event(QEvent::MouseMove, view.mapFromScene(item1->scenePos()) + QPoint(1, 0), Qt::LeftButton, Qt::LeftButton, Qt::ControlModifier);
1830 QApplication::sendEvent(view.viewport(), &event);
1832 QVERIFY(!item1->isSelected());
1833 QVERIFY(!item2->isSelected());
1837 QTest::mouseRelease(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(item1->scenePos()));
1839 QVERIFY(item1->isSelected());
1840 QVERIFY(!item2->isSelected());
1842 item1->setFlag(QGraphicsItem::ItemIsMovable);
1843 item1->setSelected(false);
1845 // Ctrl-press on item1
1846 QTest::mousePress(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(item1->scenePos()));
1848 QVERIFY(!item1->isSelected());
1849 QVERIFY(!item2->isSelected());
1852 // Ctrl-move on item1
1853 QMouseEvent event(QEvent::MouseMove, view.mapFromScene(item1->scenePos()) + QPoint(1, 0), Qt::LeftButton, Qt::LeftButton, Qt::ControlModifier);
1854 QApplication::sendEvent(view.viewport(), &event);
1856 QVERIFY(item1->isSelected());
1857 QVERIFY(!item2->isSelected());
1861 QTest::mouseRelease(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(item1->scenePos()));
1863 QVERIFY(item1->isSelected());
1864 QVERIFY(!item2->isSelected());
1867 void tst_QGraphicsItem::acceptedMouseButtons()
1869 QGraphicsScene scene;
1870 QGraphicsRectItem *item1 = scene.addRect(QRectF(-10, -10, 20, 20));
1871 QGraphicsRectItem *item2 = scene.addRect(QRectF(-10, -10, 20, 20));
1872 item2->setZValue(1);
1874 item1->setFlag(QGraphicsItem::ItemIsMovable);
1875 item2->setFlag(QGraphicsItem::ItemIsMovable);
1877 QCOMPARE(item1->acceptedMouseButtons(), Qt::MouseButtons(0x1f));
1878 QCOMPARE(item2->acceptedMouseButtons(), Qt::MouseButtons(0x1f));
1880 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
1881 event.setButton(Qt::LeftButton);
1882 event.setScenePos(QPointF(0, 0));
1883 QApplication::sendEvent(&scene, &event);
1884 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)item2);
1885 item2->setAcceptedMouseButtons(0);
1886 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
1887 QApplication::sendEvent(&scene, &event);
1888 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)item1);
1891 class HoverItem : public QGraphicsRectItem
1894 HoverItem(const QRectF &rect)
1895 : QGraphicsRectItem(rect), hoverInCount(0),
1896 hoverMoveCount(0), hoverOutCount(0)
1903 void hoverEnterEvent(QGraphicsSceneHoverEvent *)
1906 void hoverMoveEvent(QGraphicsSceneHoverEvent *)
1907 { ++hoverMoveCount; }
1909 void hoverLeaveEvent(QGraphicsSceneHoverEvent *)
1910 { ++hoverOutCount; }
1913 void tst_QGraphicsItem::acceptsHoverEvents()
1915 QGraphicsScene scene;
1916 HoverItem *item1 = new HoverItem(QRectF(-10, -10, 20, 20));
1917 HoverItem *item2 = new HoverItem(QRectF(-5, -5, 10, 10));
1918 scene.addItem(item1);
1919 scene.addItem(item2);
1920 item2->setZValue(1);
1922 QVERIFY(!item1->acceptsHoverEvents());
1923 QVERIFY(!item2->acceptsHoverEvents());
1924 item1->setAcceptsHoverEvents(true);
1925 item2->setAcceptsHoverEvents(true);
1927 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseMove);
1928 event.setScenePos(QPointF(-100, -100));
1929 QApplication::sendEvent(&scene, &event);
1930 event.setScenePos(QPointF(-2.5, -2.5));
1931 QApplication::sendEvent(&scene, &event);
1933 QCOMPARE(item1->hoverInCount, 0);
1934 QCOMPARE(item2->hoverInCount, 1);
1936 item1->setAcceptsHoverEvents(false);
1937 item2->setAcceptsHoverEvents(false);
1939 event.setScenePos(QPointF(-100, -100));
1940 QApplication::sendEvent(&scene, &event);
1941 event.setScenePos(QPointF(-2.5, -2.5));
1942 QApplication::sendEvent(&scene, &event);
1944 QCOMPARE(item1->hoverInCount, 0);
1945 QCOMPARE(item2->hoverInCount, 1);
1947 item1->setAcceptsHoverEvents(true);
1948 item2->setAcceptsHoverEvents(false);
1950 event.setScenePos(QPointF(-100, -100));
1951 QApplication::sendEvent(&scene, &event);
1952 event.setScenePos(QPointF(-2.5, -2.5));
1953 QApplication::sendEvent(&scene, &event);
1955 QCOMPARE(item1->hoverInCount, 1);
1956 QCOMPARE(item2->hoverInCount, 1);
1959 void tst_QGraphicsItem::childAcceptsHoverEvents()
1961 QGraphicsScene scene;
1962 HoverItem *item1 = new HoverItem(QRectF(-10, -10, 20, 20));
1963 HoverItem *item2 = new HoverItem(QRectF(-5, -5, 10, 10));
1965 scene.addItem(item1);
1966 scene.addItem(item2);
1967 item2->setParentItem(item1);
1968 item2->setAcceptHoverEvents(true);
1970 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseMove);
1971 event.setScenePos(QPointF(-100, -100));
1972 QApplication::sendEvent(&scene, &event);
1973 QCOMPARE(item2->hoverInCount, 0);
1974 QCOMPARE(item2->hoverMoveCount, 0);
1975 QCOMPARE(item2->hoverOutCount, 0);
1976 QCOMPARE(item1->hoverInCount, 0);
1977 QCOMPARE(item1->hoverMoveCount, 0);
1978 QCOMPARE(item1->hoverOutCount, 0);
1980 event.setScenePos(QPointF(-2.5, -2.5));
1981 QApplication::sendEvent(&scene, &event);
1983 QCOMPARE(item2->hoverInCount, 1);
1984 QCOMPARE(item2->hoverMoveCount, 1);
1985 QCOMPARE(item2->hoverOutCount, 0);
1986 QCOMPARE(item1->hoverInCount, 0);
1987 QCOMPARE(item1->hoverMoveCount, 0);
1988 QCOMPARE(item1->hoverOutCount, 0);
1990 event.setScenePos(QPointF(0, 0));
1991 QApplication::sendEvent(&scene, &event);
1993 QCOMPARE(item2->hoverInCount, 1);
1994 QCOMPARE(item2->hoverMoveCount, 2);
1995 QCOMPARE(item2->hoverOutCount, 0);
1996 QCOMPARE(item1->hoverInCount, 0);
1997 QCOMPARE(item1->hoverMoveCount, 0);
1998 QCOMPARE(item1->hoverOutCount, 0);
2000 event.setScenePos(QPointF(-7, -7));
2001 QApplication::sendEvent(&scene, &event);
2003 QCOMPARE(item2->hoverInCount, 1);
2004 QCOMPARE(item2->hoverMoveCount, 2);
2005 QCOMPARE(item2->hoverOutCount, 1);
2006 QCOMPARE(item1->hoverInCount, 0);
2007 QCOMPARE(item1->hoverMoveCount, 0);
2008 QCOMPARE(item1->hoverOutCount, 0);
2010 event.setScenePos(QPointF(0, 0));
2011 QApplication::sendEvent(&scene, &event);
2013 QCOMPARE(item2->hoverInCount, 2);
2014 QCOMPARE(item2->hoverMoveCount, 3);
2015 QCOMPARE(item2->hoverOutCount, 1);
2016 QCOMPARE(item1->hoverInCount, 0);
2017 QCOMPARE(item1->hoverMoveCount, 0);
2018 QCOMPARE(item1->hoverOutCount, 0);
2020 HoverItem *item0 = new HoverItem(QRectF(-20, -20, 20, 20));
2021 scene.addItem(item0);
2022 item1->setParentItem(item0);
2023 item0->setAcceptHoverEvents(true);
2025 event.setScenePos(QPointF(-100, -100));
2026 QApplication::sendEvent(&scene, &event);
2028 event.setScenePos(QPointF(-15, -15));
2029 QApplication::sendEvent(&scene, &event);
2031 QCOMPARE(item2->hoverInCount, 2);
2032 QCOMPARE(item2->hoverMoveCount, 3);
2033 QCOMPARE(item2->hoverOutCount, 2);
2034 QCOMPARE(item1->hoverInCount, 0);
2035 QCOMPARE(item1->hoverMoveCount, 0);
2036 QCOMPARE(item1->hoverOutCount, 0);
2037 QCOMPARE(item0->hoverInCount, 1);
2038 QCOMPARE(item0->hoverMoveCount, 1);
2039 QCOMPARE(item0->hoverOutCount, 0);
2042 void tst_QGraphicsItem::hasFocus()
2044 QGraphicsLineItem *line = new QGraphicsLineItem;
2045 QVERIFY(!line->hasFocus());
2047 QVERIFY(!line->hasFocus());
2049 QGraphicsScene scene;
2050 QEvent activate(QEvent::WindowActivate);
2051 QApplication::sendEvent(&scene, &activate);
2053 scene.addItem(line);
2056 QVERIFY(!line->hasFocus());
2057 line->setFlag(QGraphicsItem::ItemIsFocusable);
2059 QVERIFY(line->hasFocus());
2061 QGraphicsScene scene2;
2062 QApplication::sendEvent(&scene2, &activate);
2064 scene2.addItem(line);
2065 QVERIFY(!line->hasFocus());
2067 QCOMPARE(scene.focusItem(), (QGraphicsItem *)0);
2068 QCOMPARE(scene2.focusItem(), (QGraphicsItem *)0);
2071 QVERIFY(line->hasFocus());
2073 QVERIFY(!line->hasFocus());
2075 QGraphicsLineItem *line2 = new QGraphicsLineItem;
2076 line2->setFlag(QGraphicsItem::ItemIsFocusable);
2077 scene2.addItem(line2);
2080 QVERIFY(!line->hasFocus());
2081 QVERIFY(line2->hasFocus());
2083 QVERIFY(line->hasFocus());
2084 QVERIFY(!line2->hasFocus());
2087 void tst_QGraphicsItem::pos()
2089 QGraphicsItem *child = new QGraphicsLineItem;
2090 QGraphicsItem *parent = new QGraphicsLineItem;
2092 QCOMPARE(child->pos(), QPointF());
2093 QCOMPARE(parent->pos(), QPointF());
2095 child->setParentItem(parent);
2096 child->setPos(10, 10);
2098 QCOMPARE(child->pos(), QPointF(10, 10));
2100 parent->setPos(10, 10);
2102 QCOMPARE(parent->pos(), QPointF(10, 10));
2103 QCOMPARE(child->pos(), QPointF(10, 10));
2109 void tst_QGraphicsItem::scenePos()
2111 QGraphicsItem *child = new QGraphicsLineItem;
2112 QGraphicsItem *parent = new QGraphicsLineItem;
2114 QCOMPARE(child->scenePos(), QPointF());
2115 QCOMPARE(parent->scenePos(), QPointF());
2117 child->setParentItem(parent);
2118 child->setPos(10, 10);
2120 QCOMPARE(child->scenePos(), QPointF(10, 10));
2122 parent->setPos(10, 10);
2124 QCOMPARE(parent->scenePos(), QPointF(10, 10));
2125 QCOMPARE(child->scenePos(), QPointF(20, 20));
2127 parent->setPos(20, 20);
2129 QCOMPARE(parent->scenePos(), QPointF(20, 20));
2130 QCOMPARE(child->scenePos(), QPointF(30, 30));
2136 void tst_QGraphicsItem::matrix()
2138 QGraphicsLineItem line;
2139 QCOMPARE(line.matrix(), QMatrix());
2140 line.setMatrix(QMatrix().rotate(90));
2141 QCOMPARE(line.matrix(), QMatrix().rotate(90));
2142 line.setMatrix(QMatrix().rotate(90));
2143 QCOMPARE(line.matrix(), QMatrix().rotate(90));
2144 line.setMatrix(QMatrix().rotate(90), true);
2145 QCOMPARE(line.matrix(), QMatrix().rotate(180));
2146 line.setMatrix(QMatrix().rotate(-90), true);
2147 QCOMPARE(line.matrix(), QMatrix().rotate(90));
2149 QCOMPARE(line.matrix(), QMatrix());
2152 QCOMPARE(line.matrix(), QMatrix().rotate(90));
2154 QCOMPARE(line.matrix(), QMatrix().rotate(90).rotate(90));
2158 QCOMPARE(line.matrix(), QMatrix().scale(2, 4));
2160 QCOMPARE(line.matrix(), QMatrix().scale(2, 4).scale(2, 4));
2164 QCOMPARE(line.matrix(), QMatrix().shear(2, 4));
2166 QCOMPARE(line.matrix(), QMatrix().shear(2, 4).shear(2, 4));
2169 line.translate(10, 10);
2170 QCOMPARE(line.matrix(), QMatrix().translate(10, 10));
2171 line.translate(10, 10);
2172 QCOMPARE(line.matrix(), QMatrix().translate(10, 10).translate(10, 10));
2176 void tst_QGraphicsItem::sceneMatrix()
2178 QGraphicsLineItem *parent = new QGraphicsLineItem;
2179 QGraphicsLineItem *child = new QGraphicsLineItem(QLineF(), parent);
2181 QCOMPARE(parent->sceneMatrix(), QMatrix());
2182 QCOMPARE(child->sceneMatrix(), QMatrix());
2184 parent->translate(10, 10);
2185 QCOMPARE(parent->sceneMatrix(), QMatrix().translate(10, 10));
2186 QCOMPARE(child->sceneMatrix(), QMatrix().translate(10, 10));
2188 child->translate(10, 10);
2189 QCOMPARE(parent->sceneMatrix(), QMatrix().translate(10, 10));
2190 QCOMPARE(child->sceneMatrix(), QMatrix().translate(20, 20));
2193 QCOMPARE(parent->sceneMatrix(), QMatrix().translate(10, 10).rotate(90));
2194 QCOMPARE(child->sceneMatrix(), QMatrix().translate(10, 10).rotate(90).translate(10, 10));
2200 void tst_QGraphicsItem::setMatrix()
2202 QGraphicsScene scene;
2203 qRegisterMetaType<QList<QRectF> >("QList<QRectF>");
2204 QSignalSpy spy(&scene, SIGNAL(changed(QList<QRectF>)));
2205 QRectF unrotatedRect(-12, -34, 56, 78);
2206 QGraphicsRectItem item(unrotatedRect, 0);
2207 scene.addItem(&item);
2208 scene.update(scene.sceneRect());
2209 QApplication::instance()->processEvents();
2211 QCOMPARE(spy.count(), 1);
2213 item.setMatrix(QMatrix().rotate(qreal(12.34)));
2214 QRectF rotatedRect = scene.sceneRect();
2215 QVERIFY(unrotatedRect != rotatedRect);
2216 scene.update(scene.sceneRect());
2217 QApplication::instance()->processEvents();
2219 QCOMPARE(spy.count(), 2);
2221 item.setMatrix(QMatrix());
2223 scene.update(scene.sceneRect());
2224 QApplication::instance()->processEvents();
2226 QCOMPARE(spy.count(), 3);
2227 QList<QRectF> rlist = qvariant_cast<QList<QRectF> >(spy.last().at(0));
2229 QCOMPARE(rlist.size(), 3);
2230 QCOMPARE(rlist.at(0), rotatedRect); // From item.setMatrix() (clearing rotated rect)
2231 QCOMPARE(rlist.at(1), rotatedRect); // From scene.update() (updating scene rect)
2232 QCOMPARE(rlist.at(2), unrotatedRect); // From post-update (update current state)
2235 static QList<QGraphicsItem *> _paintedItems;
2236 class PainterItem : public QGraphicsItem
2239 QRectF boundingRect() const
2240 { return QRectF(-10, -10, 20, 20); }
2242 void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
2243 { _paintedItems << this; painter->fillRect(boundingRect(), Qt::red); }
2246 void tst_QGraphicsItem::zValue()
2250 QGraphicsScene scene;
2252 QGraphicsItem *item1 = new PainterItem;
2253 QGraphicsItem *item2 = new PainterItem;
2254 QGraphicsItem *item3 = new PainterItem;
2255 QGraphicsItem *item4 = new PainterItem;
2256 scene.addItem(item1);
2257 scene.addItem(item2);
2258 scene.addItem(item3);
2259 scene.addItem(item4);
2260 item2->setZValue(-3);
2261 item4->setZValue(-2);
2262 item1->setZValue(-1);
2263 item3->setZValue(0);
2265 QGraphicsView view(&scene);
2267 QVERIFY(QTest::qWaitForWindowExposed(&view));
2269 QApplication::processEvents();
2271 QTRY_VERIFY(!_paintedItems.isEmpty());
2272 QVERIFY((_paintedItems.size() % 4) == 0);
2273 for (int i = 0; i < 3; ++i)
2274 QVERIFY(_paintedItems.at(i)->zValue() < _paintedItems.at(i + 1)->zValue());
2277 void tst_QGraphicsItem::shape()
2279 QGraphicsLineItem line(QLineF(-10, -10, 20, 20));
2281 // We unfortunately need this hack as QPainterPathStroker will set a width of 1.0
2282 // if we pass a value of 0.0 to QPainterPathStroker::setWidth()
2283 const qreal penWidthZero = qreal(0.00000001);
2285 QPainterPathStroker ps;
2286 ps.setWidth(penWidthZero);
2288 QPainterPath path(line.line().p1());
2289 path.lineTo(line.line().p2());
2290 QPainterPath p = ps.createStroke(path);
2292 QCOMPARE(line.shape(), p);
2295 linePen.setWidthF(5.0);
2296 linePen.setCapStyle(Qt::RoundCap);
2297 line.setPen(linePen);
2299 ps.setCapStyle(line.pen().capStyle());
2300 ps.setWidth(line.pen().widthF());
2301 p = ps.createStroke(path);
2303 QCOMPARE(line.shape(), p);
2305 linePen.setCapStyle(Qt::FlatCap);
2306 line.setPen(linePen);
2307 ps.setCapStyle(line.pen().capStyle());
2308 p = ps.createStroke(path);
2310 QCOMPARE(line.shape(), p);
2312 linePen.setCapStyle(Qt::SquareCap);
2313 line.setPen(linePen);
2314 ps.setCapStyle(line.pen().capStyle());
2315 p = ps.createStroke(path);
2317 QCOMPARE(line.shape(), p);
2319 QGraphicsRectItem rect(QRectF(-10, -10, 20, 20));
2320 QPainterPathStroker ps1;
2321 ps1.setWidth(penWidthZero);
2322 path = QPainterPath();
2323 path.addRect(rect.rect());
2324 p = ps1.createStroke(path);
2326 QCOMPARE(rect.shape(), p);
2328 QGraphicsEllipseItem ellipse(QRectF(-10, -10, 20, 20));
2329 QPainterPathStroker ps2;
2330 ps2.setWidth(ellipse.pen().widthF() <= 0.0 ? penWidthZero : ellipse.pen().widthF());
2331 path = QPainterPath();
2332 path.addEllipse(ellipse.rect());
2333 p = ps2.createStroke(path);
2335 QCOMPARE(ellipse.shape(), p);
2337 QPainterPathStroker ps3;
2338 ps3.setWidth(penWidthZero);
2339 p = ps3.createStroke(path);
2341 QGraphicsPathItem pathItem(path);
2342 QCOMPARE(pathItem.shape(), p);
2344 QRegion region(QRect(0, 0, 300, 200));
2345 region = region.subtracted(QRect(50, 50, 200, 100));
2347 QImage image(300, 200, QImage::Format_ARGB32_Premultiplied);
2349 QPainter painter(&image);
2350 painter.setClipRegion(region);
2351 painter.fillRect(0, 0, 300, 200, Qt::green);
2353 QPixmap pixmap = QPixmap::fromImage(image);
2355 QGraphicsPixmapItem pixmapItem(pixmap);
2356 path = QPainterPath();
2357 path.addRegion(region);
2360 QBitmap bitmap(300, 200);
2362 QPainter painter(&bitmap);
2363 painter.setClipRegion(region);
2364 painter.fillRect(0, 0, 300, 200, Qt::color1);
2367 QBitmap bitmap2(300, 200);
2369 painter.begin(&bitmap2);
2370 painter.setClipPath(pixmapItem.shape());
2371 painter.fillRect(0, 0, 300, 200, Qt::color1);
2374 QCOMPARE(bitmap.toImage(), bitmap2.toImage());
2378 poly << QPointF(0, 0) << QPointF(10, 0) << QPointF(0, 10);
2379 QGraphicsPolygonItem polygon(poly);
2380 path = QPainterPath();
2381 path.addPolygon(poly);
2383 QPainterPathStroker ps4;
2384 ps4.setWidth(penWidthZero);
2385 p = ps4.createStroke(path);
2387 QCOMPARE(polygon.shape(), p);
2390 void tst_QGraphicsItem::contains()
2392 if (sizeof(qreal) != sizeof(double))
2393 QSKIP("Skipped due to rounding errors");
2396 QGraphicsRectItem rect(QRectF(-10, -10, 20, 20));
2397 QVERIFY(!rect.contains(QPointF(-11, -10)));
2398 QVERIFY(rect.contains(QPointF(-10, -10)));
2399 QVERIFY(!rect.contains(QPointF(-11, 0)));
2400 QVERIFY(rect.contains(QPointF(-10, 0)));
2401 QVERIFY(rect.contains(QPointF(0, -10)));
2402 QVERIFY(rect.contains(QPointF(0, 0)));
2403 QVERIFY(rect.contains(QPointF(9, 9)));
2406 QGraphicsEllipseItem ellipse(QRectF(-10, -10, 20, 20));
2407 QVERIFY(!ellipse.contains(QPointF(-10, -10)));
2408 QVERIFY(ellipse.contains(QPointF(-9, 0)));
2409 QVERIFY(ellipse.contains(QPointF(0, -9)));
2410 QVERIFY(ellipse.contains(QPointF(0, 0)));
2411 QVERIFY(!ellipse.contains(QPointF(9, 9)));
2414 QGraphicsLineItem line(QLineF(-10, -10, 20, 20));
2415 QVERIFY(!line.contains(QPointF(-10, 0)));
2416 QVERIFY(!line.contains(QPointF(0, -10)));
2417 QVERIFY(!line.contains(QPointF(10, 0)));
2418 QVERIFY(!line.contains(QPointF(0, 10)));
2419 QVERIFY(line.contains(QPointF(0, 0)));
2420 QVERIFY(line.contains(QPointF(-9, -9)));
2421 QVERIFY(line.contains(QPointF(9, 9)));
2424 QGraphicsPolygonItem polygon(QPolygonF()
2428 QVERIFY(polygon.contains(QPointF(1, 1)));
2429 QVERIFY(polygon.contains(QPointF(4, 4)));
2430 QVERIFY(polygon.contains(QPointF(1, 4)));
2431 QVERIFY(polygon.contains(QPointF(4, 1)));
2432 QVERIFY(!polygon.contains(QPointF(8, 8)));
2433 QVERIFY(polygon.contains(QPointF(1, 8)));
2434 QVERIFY(polygon.contains(QPointF(8, 1)));
2437 void tst_QGraphicsItem::collidesWith_item()
2440 QGraphicsRectItem rect(QRectF(-10, -10, 20, 20));
2441 QGraphicsRectItem rect2(QRectF(-10, -10, 20, 20));
2442 QVERIFY(rect.collidesWithItem(&rect2));
2443 QVERIFY(rect2.collidesWithItem(&rect));
2444 rect2.setPos(21, 21);
2445 QVERIFY(!rect.collidesWithItem(&rect2));
2446 QVERIFY(!rect2.collidesWithItem(&rect));
2447 rect2.setPos(-21, -21);
2448 QVERIFY(!rect.collidesWithItem(&rect2));
2449 QVERIFY(!rect2.collidesWithItem(&rect));
2450 rect2.setPos(-17, -17);
2451 QVERIFY(rect.collidesWithItem(&rect2));
2452 QVERIFY(rect2.collidesWithItem(&rect));
2454 QGraphicsEllipseItem ellipse(QRectF(-10, -10, 20, 20));
2455 QGraphicsEllipseItem ellipse2(QRectF(-10, -10, 20, 20));
2456 QVERIFY(ellipse.collidesWithItem(&ellipse2));
2457 QVERIFY(ellipse2.collidesWithItem(&ellipse));
2458 ellipse2.setPos(21, 21);
2459 QVERIFY(!ellipse.collidesWithItem(&ellipse2));
2460 QVERIFY(!ellipse2.collidesWithItem(&ellipse));
2461 ellipse2.setPos(-21, -21);
2462 QVERIFY(!ellipse.collidesWithItem(&ellipse2));
2463 QVERIFY(!ellipse2.collidesWithItem(&ellipse));
2465 ellipse2.setPos(-17, -17);
2466 QVERIFY(!ellipse.collidesWithItem(&ellipse2));
2467 QVERIFY(!ellipse2.collidesWithItem(&ellipse));
2470 QGraphicsScene scene;
2471 QGraphicsRectItem rect(20, 20, 100, 100, 0);
2472 scene.addItem(&rect);
2473 QGraphicsRectItem rect2(40, 40, 50, 50, 0);
2474 scene.addItem(&rect2);
2476 QGraphicsLineItem line(0, 0, 200, 200, 0);
2477 scene.addItem(&line);
2480 QCOMPARE(scene.items().size(), 3);
2482 QList<QGraphicsItem *> col1 = rect.collidingItems();
2483 QCOMPARE(col1.size(), 2);
2484 QCOMPARE(col1.first(), static_cast<QGraphicsItem *>(&line));
2485 QCOMPARE(col1.last(), static_cast<QGraphicsItem *>(&rect2));
2487 QList<QGraphicsItem *> col2 = rect2.collidingItems();
2488 QCOMPARE(col2.size(), 2);
2489 QCOMPARE(col2.first(), static_cast<QGraphicsItem *>(&line));
2490 QCOMPARE(col2.last(), static_cast<QGraphicsItem *>(&rect));
2492 QList<QGraphicsItem *> col3 = line.collidingItems();
2493 QCOMPARE(col3.size(), 2);
2494 QCOMPARE(col3.first(), static_cast<QGraphicsItem *>(&rect2));
2495 QCOMPARE(col3.last(), static_cast<QGraphicsItem *>(&rect));
2499 void tst_QGraphicsItem::collidesWith_path_data()
2501 QTest::addColumn<QPointF>("pos");
2502 QTest::addColumn<QMatrix>("matrix");
2503 QTest::addColumn<QPainterPath>("shape");
2504 QTest::addColumn<bool>("rectCollides");
2505 QTest::addColumn<bool>("ellipseCollides");
2507 QTest::newRow("nothing") << QPointF(0, 0) << QMatrix() << QPainterPath() << false << false;
2510 rect.addRect(0, 0, 20, 20);
2512 QTest::newRow("rect1") << QPointF(0, 0) << QMatrix() << rect << true << true;
2513 QTest::newRow("rect2") << QPointF(0, 0) << QMatrix().translate(21, 21) << rect << false << false;
2514 QTest::newRow("rect3") << QPointF(21, 21) << QMatrix() << rect << false << false;
2517 void tst_QGraphicsItem::collidesWith_path()
2519 QFETCH(QPointF, pos);
2520 QFETCH(QMatrix, matrix);
2521 QFETCH(QPainterPath, shape);
2522 QFETCH(bool, rectCollides);
2523 QFETCH(bool, ellipseCollides);
2525 QGraphicsRectItem rect(QRectF(0, 0, 20, 20));
2526 QGraphicsEllipseItem ellipse(QRectF(0, 0, 20, 20));
2529 rect.setMatrix(matrix);
2531 ellipse.setPos(pos);
2532 ellipse.setMatrix(matrix);
2534 QPainterPath mappedShape = rect.sceneMatrix().inverted().map(shape);
2537 QVERIFY(rect.collidesWithPath(mappedShape));
2539 QVERIFY(!rect.collidesWithPath(mappedShape));
2541 if (ellipseCollides)
2542 QVERIFY(ellipse.collidesWithPath(mappedShape));
2544 QVERIFY(!ellipse.collidesWithPath(mappedShape));
2547 void tst_QGraphicsItem::collidesWithItemWithClip()
2549 QGraphicsScene scene;
2551 QGraphicsEllipseItem *ellipse = scene.addEllipse(0, 0, 100, 100);
2552 ellipse->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
2553 QGraphicsEllipseItem *ellipse2 = scene.addEllipse(0, 0, 10, 10);
2554 ellipse2->setParentItem(ellipse);
2555 QGraphicsEllipseItem *ellipse3 = scene.addEllipse(0, 0, 10, 10);
2556 ellipse3->setParentItem(ellipse);
2557 QGraphicsEllipseItem *ellipse5 = scene.addEllipse(50, 50, 10, 10);
2558 ellipse5->setParentItem(ellipse);
2559 QGraphicsEllipseItem *ellipse4 = scene.addEllipse(0, 0, 10, 10);
2561 QVERIFY(ellipse2->collidesWithItem(ellipse3));
2562 QVERIFY(ellipse3->collidesWithItem(ellipse2));
2563 QVERIFY(!ellipse2->collidesWithItem(ellipse));
2564 QVERIFY(!ellipse->collidesWithItem(ellipse2));
2565 QVERIFY(!ellipse4->collidesWithItem(ellipse));
2566 QVERIFY(!ellipse4->collidesWithItem(ellipse2));
2567 QVERIFY(!ellipse4->collidesWithItem(ellipse3));
2568 QVERIFY(!ellipse->collidesWithItem(ellipse4));
2569 QVERIFY(!ellipse2->collidesWithItem(ellipse4));
2570 QVERIFY(!ellipse3->collidesWithItem(ellipse4));
2571 QVERIFY(ellipse->collidesWithItem(ellipse5));
2572 QVERIFY(ellipse5->collidesWithItem(ellipse));
2575 class MyItem : public QGraphicsEllipseItem
2578 bool isObscuredBy(const QGraphicsItem *item) const
2580 const MyItem *myItem = qgraphicsitem_cast<const MyItem *>(item);
2582 if (item->zValue() > zValue()) {
2584 QPointF topMid = (r.topRight()+r.topLeft())/2;
2585 QPointF botMid = (r.bottomRight()+r.bottomLeft())/2;
2586 QPointF leftMid = (r.topLeft()+r.bottomLeft())/2;
2587 QPointF rightMid = (r.topRight()+r.bottomRight())/2;
2589 QPainterPath mappedShape = item->mapToItem(this, item->opaqueArea());
2591 if (mappedShape.contains(topMid) &&
2592 mappedShape.contains(botMid) &&
2593 mappedShape.contains(leftMid) &&
2594 mappedShape.contains(rightMid))
2602 return QGraphicsItem::isObscuredBy(item);
2605 QPainterPath opaqueArea() const
2613 int type() const { return Type; }
2616 void tst_QGraphicsItem::isObscuredBy()
2618 QGraphicsScene scene;
2620 MyItem myitem1, myitem2;
2622 myitem1.setRect(QRectF(50, 50, 40, 200));
2625 myitem2.setRect(QRectF(25, 25, 20, 20));
2626 myitem2.setZValue(-1.0);
2627 scene.addItem(&myitem1);
2628 scene.addItem(&myitem2);
2630 QVERIFY(!myitem2.isObscuredBy(&myitem1));
2631 QVERIFY(!myitem1.isObscuredBy(&myitem2));
2633 myitem2.setRect(QRectF(-50, 85, 20, 20));
2634 QVERIFY(myitem2.isObscuredBy(&myitem1));
2635 QVERIFY(!myitem1.isObscuredBy(&myitem2));
2637 myitem2.setRect(QRectF(-30, 70, 20, 20));
2638 QVERIFY(!myitem2.isObscuredBy(&myitem1));
2639 QVERIFY(!myitem1.isObscuredBy(&myitem2));
2641 QGraphicsRectItem rect1, rect2;
2643 rect1.setRect(QRectF(-40, -40, 50, 50));
2644 rect1.setBrush(QBrush(Qt::red));
2645 rect2.setRect(QRectF(-30, -20, 20, 20));
2646 rect2.setZValue(-1.0);
2647 rect2.setBrush(QBrush(Qt::blue));
2649 QVERIFY(rect2.isObscuredBy(&rect1));
2650 QVERIFY(!rect1.isObscuredBy(&rect2));
2652 rect2.setPos(QPointF(-20, -25));
2654 QVERIFY(!rect2.isObscuredBy(&rect1));
2655 QVERIFY(!rect1.isObscuredBy(&rect2));
2657 rect2.setPos(QPointF(-100, -100));
2659 QVERIFY(!rect2.isObscuredBy(&rect1));
2660 QVERIFY(!rect1.isObscuredBy(&rect2));
2663 class OpaqueItem : public QGraphicsRectItem
2666 QPainterPath opaqueArea() const
2672 void tst_QGraphicsItem::isObscured()
2674 if (sizeof(qreal) != sizeof(double))
2675 QSKIP("Skipped due to rounding errors");
2677 OpaqueItem *item1 = new OpaqueItem;
2678 item1->setRect(0, 0, 100, 100);
2679 item1->setZValue(0);
2681 OpaqueItem *item2 = new OpaqueItem;
2682 item2->setZValue(1);
2683 item2->setRect(0, 0, 100, 100);
2685 QGraphicsScene scene;
2686 scene.addItem(item1);
2687 scene.addItem(item2);
2689 QVERIFY(item1->isObscured());
2690 QVERIFY(item1->isObscuredBy(item2));
2691 QVERIFY(item1->isObscured(QRectF(0, 0, 50, 50)));
2692 QVERIFY(item1->isObscured(QRectF(50, 0, 50, 50)));
2693 QVERIFY(item1->isObscured(QRectF(50, 50, 50, 50)));
2694 QVERIFY(item1->isObscured(QRectF(0, 50, 50, 50)));
2695 QVERIFY(item1->isObscured(0, 0, 50, 50));
2696 QVERIFY(item1->isObscured(50, 0, 50, 50));
2697 QVERIFY(item1->isObscured(50, 50, 50, 50));
2698 QVERIFY(item1->isObscured(0, 50, 50, 50));
2699 QVERIFY(!item2->isObscured());
2700 QVERIFY(!item2->isObscuredBy(item1));
2701 QVERIFY(!item2->isObscured(QRectF(0, 0, 50, 50)));
2702 QVERIFY(!item2->isObscured(QRectF(50, 0, 50, 50)));
2703 QVERIFY(!item2->isObscured(QRectF(50, 50, 50, 50)));
2704 QVERIFY(!item2->isObscured(QRectF(0, 50, 50, 50)));
2705 QVERIFY(!item2->isObscured(0, 0, 50, 50));
2706 QVERIFY(!item2->isObscured(50, 0, 50, 50));
2707 QVERIFY(!item2->isObscured(50, 50, 50, 50));
2708 QVERIFY(!item2->isObscured(0, 50, 50, 50));
2710 item2->moveBy(50, 0);
2712 QVERIFY(!item1->isObscured());
2713 QVERIFY(!item1->isObscuredBy(item2));
2714 QVERIFY(!item1->isObscured(QRectF(0, 0, 50, 50)));
2715 QVERIFY(item1->isObscured(QRectF(50, 0, 50, 50)));
2716 QVERIFY(item1->isObscured(QRectF(50, 50, 50, 50)));
2717 QVERIFY(!item1->isObscured(QRectF(0, 50, 50, 50)));
2718 QVERIFY(!item1->isObscured(0, 0, 50, 50));
2719 QVERIFY(item1->isObscured(50, 0, 50, 50));
2720 QVERIFY(item1->isObscured(50, 50, 50, 50));
2721 QVERIFY(!item1->isObscured(0, 50, 50, 50));
2722 QVERIFY(!item2->isObscured());
2723 QVERIFY(!item2->isObscuredBy(item1));
2724 QVERIFY(!item2->isObscured(QRectF(0, 0, 50, 50)));
2725 QVERIFY(!item2->isObscured(QRectF(50, 0, 50, 50)));
2726 QVERIFY(!item2->isObscured(QRectF(50, 50, 50, 50)));
2727 QVERIFY(!item2->isObscured(QRectF(0, 50, 50, 50)));
2728 QVERIFY(!item2->isObscured(0, 0, 50, 50));
2729 QVERIFY(!item2->isObscured(50, 0, 50, 50));
2730 QVERIFY(!item2->isObscured(50, 50, 50, 50));
2731 QVERIFY(!item2->isObscured(0, 50, 50, 50));
2734 void tst_QGraphicsItem::mapFromToParent()
2737 path1.addRect(0, 0, 200, 200);
2740 path2.addRect(0, 0, 100, 100);
2743 path3.addRect(0, 0, 50, 50);
2746 path4.addRect(0, 0, 25, 25);
2748 QGraphicsItem *item1 = new QGraphicsPathItem(path1);
2749 QGraphicsItem *item2 = new QGraphicsPathItem(path2, item1);
2750 QGraphicsItem *item3 = new QGraphicsPathItem(path3, item2);
2751 QGraphicsItem *item4 = new QGraphicsPathItem(path4, item3);
2753 item1->setPos(10, 10);
2754 item2->setPos(10, 10);
2755 item3->setPos(10, 10);
2756 item4->setPos(10, 10);
2758 for (int i = 0; i < 4; ++i) {
2760 matrix.rotate(i * 90);
2761 matrix.translate(i * 100, -i * 100);
2763 item1->setMatrix(matrix);
2765 QCOMPARE(item1->mapToParent(QPointF(0, 0)), item1->pos() + matrix.map(QPointF(0, 0)));
2766 QCOMPARE(item2->mapToParent(QPointF(0, 0)), item2->pos());
2767 QCOMPARE(item3->mapToParent(QPointF(0, 0)), item3->pos());
2768 QCOMPARE(item4->mapToParent(QPointF(0, 0)), item4->pos());
2769 QCOMPARE(item1->mapToParent(QPointF(10, -10)), item1->pos() + matrix.map(QPointF(10, -10)));
2770 QCOMPARE(item2->mapToParent(QPointF(10, -10)), item2->pos() + QPointF(10, -10));
2771 QCOMPARE(item3->mapToParent(QPointF(10, -10)), item3->pos() + QPointF(10, -10));
2772 QCOMPARE(item4->mapToParent(QPointF(10, -10)), item4->pos() + QPointF(10, -10));
2773 QCOMPARE(item1->mapToParent(QPointF(-10, 10)), item1->pos() + matrix.map(QPointF(-10, 10)));
2774 QCOMPARE(item2->mapToParent(QPointF(-10, 10)), item2->pos() + QPointF(-10, 10));
2775 QCOMPARE(item3->mapToParent(QPointF(-10, 10)), item3->pos() + QPointF(-10, 10));
2776 QCOMPARE(item4->mapToParent(QPointF(-10, 10)), item4->pos() + QPointF(-10, 10));
2777 QCOMPARE(item1->mapFromParent(item1->pos()), matrix.inverted().map(QPointF(0, 0)));
2778 QCOMPARE(item2->mapFromParent(item2->pos()), QPointF(0, 0));
2779 QCOMPARE(item3->mapFromParent(item3->pos()), QPointF(0, 0));
2780 QCOMPARE(item4->mapFromParent(item4->pos()), QPointF(0, 0));
2781 QCOMPARE(item1->mapFromParent(item1->pos() + QPointF(10, -10)),
2782 matrix.inverted().map(QPointF(10, -10)));
2783 QCOMPARE(item2->mapFromParent(item2->pos() + QPointF(10, -10)), QPointF(10, -10));
2784 QCOMPARE(item3->mapFromParent(item3->pos() + QPointF(10, -10)), QPointF(10, -10));
2785 QCOMPARE(item4->mapFromParent(item4->pos() + QPointF(10, -10)), QPointF(10, -10));
2786 QCOMPARE(item1->mapFromParent(item1->pos() + QPointF(-10, 10)),
2787 matrix.inverted().map(QPointF(-10, 10)));
2788 QCOMPARE(item2->mapFromParent(item2->pos() + QPointF(-10, 10)), QPointF(-10, 10));
2789 QCOMPARE(item3->mapFromParent(item3->pos() + QPointF(-10, 10)), QPointF(-10, 10));
2790 QCOMPARE(item4->mapFromParent(item4->pos() + QPointF(-10, 10)), QPointF(-10, 10));
2796 void tst_QGraphicsItem::mapFromToScene()
2798 QGraphicsItem *item1 = new QGraphicsPathItem(QPainterPath());
2799 QGraphicsItem *item2 = new QGraphicsPathItem(QPainterPath(), item1);
2800 QGraphicsItem *item3 = new QGraphicsPathItem(QPainterPath(), item2);
2801 QGraphicsItem *item4 = new QGraphicsPathItem(QPainterPath(), item3);
2803 item1->setPos(100, 100);
2804 item2->setPos(100, 100);
2805 item3->setPos(100, 100);
2806 item4->setPos(100, 100);
2807 QCOMPARE(item1->pos(), QPointF(100, 100));
2808 QCOMPARE(item2->pos(), QPointF(100, 100));
2809 QCOMPARE(item3->pos(), QPointF(100, 100));
2810 QCOMPARE(item4->pos(), QPointF(100, 100));
2811 QCOMPARE(item1->pos(), item1->mapToParent(0, 0));
2812 QCOMPARE(item2->pos(), item2->mapToParent(0, 0));
2813 QCOMPARE(item3->pos(), item3->mapToParent(0, 0));
2814 QCOMPARE(item4->pos(), item4->mapToParent(0, 0));
2815 QCOMPARE(item1->mapToParent(10, 10), QPointF(110, 110));
2816 QCOMPARE(item2->mapToParent(10, 10), QPointF(110, 110));
2817 QCOMPARE(item3->mapToParent(10, 10), QPointF(110, 110));
2818 QCOMPARE(item4->mapToParent(10, 10), QPointF(110, 110));
2819 QCOMPARE(item1->mapToScene(0, 0), QPointF(100, 100));
2820 QCOMPARE(item2->mapToScene(0, 0), QPointF(200, 200));
2821 QCOMPARE(item3->mapToScene(0, 0), QPointF(300, 300));
2822 QCOMPARE(item4->mapToScene(0, 0), QPointF(400, 400));
2823 QCOMPARE(item1->mapToScene(10, 0), QPointF(110, 100));
2824 QCOMPARE(item2->mapToScene(10, 0), QPointF(210, 200));
2825 QCOMPARE(item3->mapToScene(10, 0), QPointF(310, 300));
2826 QCOMPARE(item4->mapToScene(10, 0), QPointF(410, 400));
2827 QCOMPARE(item1->mapFromScene(100, 100), QPointF(0, 0));
2828 QCOMPARE(item2->mapFromScene(200, 200), QPointF(0, 0));
2829 QCOMPARE(item3->mapFromScene(300, 300), QPointF(0, 0));
2830 QCOMPARE(item4->mapFromScene(400, 400), QPointF(0, 0));
2831 QCOMPARE(item1->mapFromScene(110, 100), QPointF(10, 0));
2832 QCOMPARE(item2->mapFromScene(210, 200), QPointF(10, 0));
2833 QCOMPARE(item3->mapFromScene(310, 300), QPointF(10, 0));
2834 QCOMPARE(item4->mapFromScene(410, 400), QPointF(10, 0));
2836 // Rotate item1 90 degrees clockwise
2837 QMatrix matrix; matrix.rotate(90);
2838 item1->setMatrix(matrix);
2839 QCOMPARE(item1->pos(), item1->mapToParent(0, 0));
2840 QCOMPARE(item2->pos(), item2->mapToParent(0, 0));
2841 QCOMPARE(item3->pos(), item3->mapToParent(0, 0));
2842 QCOMPARE(item4->pos(), item4->mapToParent(0, 0));
2843 QCOMPARE(item1->mapToParent(10, 0), QPointF(100, 110));
2844 QCOMPARE(item2->mapToParent(10, 0), QPointF(110, 100));
2845 QCOMPARE(item3->mapToParent(10, 0), QPointF(110, 100));
2846 QCOMPARE(item4->mapToParent(10, 0), QPointF(110, 100));
2847 QCOMPARE(item1->mapToScene(0, 0), QPointF(100, 100));
2848 QCOMPARE(item2->mapToScene(0, 0), QPointF(0, 200));
2849 QCOMPARE(item3->mapToScene(0, 0), QPointF(-100, 300));
2850 QCOMPARE(item4->mapToScene(0, 0), QPointF(-200, 400));
2851 QCOMPARE(item1->mapToScene(10, 0), QPointF(100, 110));
2852 QCOMPARE(item2->mapToScene(10, 0), QPointF(0, 210));
2853 QCOMPARE(item3->mapToScene(10, 0), QPointF(-100, 310));
2854 QCOMPARE(item4->mapToScene(10, 0), QPointF(-200, 410));
2855 QCOMPARE(item1->mapFromScene(100, 100), QPointF(0, 0));
2856 QCOMPARE(item2->mapFromScene(0, 200), QPointF(0, 0));
2857 QCOMPARE(item3->mapFromScene(-100, 300), QPointF(0, 0));
2858 QCOMPARE(item4->mapFromScene(-200, 400), QPointF(0, 0));
2859 QCOMPARE(item1->mapFromScene(100, 110), QPointF(10, 0));
2860 QCOMPARE(item2->mapFromScene(0, 210), QPointF(10, 0));
2861 QCOMPARE(item3->mapFromScene(-100, 310), QPointF(10, 0));
2862 QCOMPARE(item4->mapFromScene(-200, 410), QPointF(10, 0));
2864 // Rotate item2 90 degrees clockwise
2865 item2->setMatrix(matrix);
2866 QCOMPARE(item1->pos(), item1->mapToParent(0, 0));
2867 QCOMPARE(item2->pos(), item2->mapToParent(0, 0));
2868 QCOMPARE(item3->pos(), item3->mapToParent(0, 0));
2869 QCOMPARE(item4->pos(), item4->mapToParent(0, 0));
2870 QCOMPARE(item1->mapToParent(10, 0), QPointF(100, 110));
2871 QCOMPARE(item2->mapToParent(10, 0), QPointF(100, 110));
2872 QCOMPARE(item3->mapToParent(10, 0), QPointF(110, 100));
2873 QCOMPARE(item4->mapToParent(10, 0), QPointF(110, 100));
2874 QCOMPARE(item1->mapToScene(0, 0), QPointF(100, 100));
2875 QCOMPARE(item2->mapToScene(0, 0), QPointF(0, 200));
2876 QCOMPARE(item3->mapToScene(0, 0), QPointF(-100, 100));
2877 QCOMPARE(item4->mapToScene(0, 0), QPointF(-200, 0));
2878 QCOMPARE(item1->mapToScene(10, 0), QPointF(100, 110));
2879 QCOMPARE(item2->mapToScene(10, 0), QPointF(-10, 200));
2880 QCOMPARE(item3->mapToScene(10, 0), QPointF(-110, 100));
2881 QCOMPARE(item4->mapToScene(10, 0), QPointF(-210, 0));
2882 QCOMPARE(item1->mapFromScene(100, 100), QPointF(0, 0));
2883 QCOMPARE(item2->mapFromScene(0, 200), QPointF(0, 0));
2884 QCOMPARE(item3->mapFromScene(-100, 100), QPointF(0, 0));
2885 QCOMPARE(item4->mapFromScene(-200, 0), QPointF(0, 0));
2886 QCOMPARE(item1->mapFromScene(100, 110), QPointF(10, 0));
2887 QCOMPARE(item2->mapFromScene(-10, 200), QPointF(10, 0));
2888 QCOMPARE(item3->mapFromScene(-110, 100), QPointF(10, 0));
2889 QCOMPARE(item4->mapFromScene(-210, 0), QPointF(10, 0));
2891 // Translate item3 50 points, then rotate 90 degrees counterclockwise
2893 matrix2.translate(50, 0);
2894 matrix2.rotate(-90);
2895 item3->setMatrix(matrix2);
2896 QCOMPARE(item1->pos(), item1->mapToParent(0, 0));
2897 QCOMPARE(item2->pos(), item2->mapToParent(0, 0));
2898 QCOMPARE(item3->pos(), item3->mapToParent(0, 0) - QPointF(50, 0));
2899 QCOMPARE(item4->pos(), item4->mapToParent(0, 0));
2900 QCOMPARE(item1->mapToParent(10, 0), QPointF(100, 110));
2901 QCOMPARE(item2->mapToParent(10, 0), QPointF(100, 110));
2902 QCOMPARE(item3->mapToParent(10, 0), QPointF(150, 90));
2903 QCOMPARE(item4->mapToParent(10, 0), QPointF(110, 100));
2904 QCOMPARE(item1->mapToScene(0, 0), QPointF(100, 100));
2905 QCOMPARE(item2->mapToScene(0, 0), QPointF(0, 200));
2906 QCOMPARE(item3->mapToScene(0, 0), QPointF(-150, 100));
2907 QCOMPARE(item4->mapToScene(0, 0), QPointF(-250, 200));
2908 QCOMPARE(item1->mapToScene(10, 0), QPointF(100, 110));
2909 QCOMPARE(item2->mapToScene(10, 0), QPointF(-10, 200));
2910 QCOMPARE(item3->mapToScene(10, 0), QPointF(-150, 110));
2911 QCOMPARE(item4->mapToScene(10, 0), QPointF(-250, 210));
2912 QCOMPARE(item1->mapFromScene(100, 100), QPointF(0, 0));
2913 QCOMPARE(item2->mapFromScene(0, 200), QPointF(0, 0));
2914 QCOMPARE(item3->mapFromScene(-150, 100), QPointF(0, 0));
2915 QCOMPARE(item4->mapFromScene(-250, 200), QPointF(0, 0));
2916 QCOMPARE(item1->mapFromScene(100, 110), QPointF(10, 0));
2917 QCOMPARE(item2->mapFromScene(-10, 200), QPointF(10, 0));
2918 QCOMPARE(item3->mapFromScene(-150, 110), QPointF(10, 0));
2919 QCOMPARE(item4->mapFromScene(-250, 210), QPointF(10, 0));
2924 void tst_QGraphicsItem::mapFromToItem()
2926 QGraphicsItem *item1 = new QGraphicsPathItem;
2927 QGraphicsItem *item2 = new QGraphicsPathItem;
2928 QGraphicsItem *item3 = new QGraphicsPathItem;
2929 QGraphicsItem *item4 = new QGraphicsPathItem;
2931 item1->setPos(-100, -100);
2932 item2->setPos(100, -100);
2933 item3->setPos(100, 100);
2934 item4->setPos(-100, 100);
2936 QCOMPARE(item1->mapFromItem(item2, 0, 0), QPointF(200, 0));
2937 QCOMPARE(item2->mapFromItem(item3, 0, 0), QPointF(0, 200));
2938 QCOMPARE(item3->mapFromItem(item4, 0, 0), QPointF(-200, 0));
2939 QCOMPARE(item4->mapFromItem(item1, 0, 0), QPointF(0, -200));
2940 QCOMPARE(item1->mapFromItem(item4, 0, 0), QPointF(0, 200));
2941 QCOMPARE(item2->mapFromItem(item1, 0, 0), QPointF(-200, 0));
2942 QCOMPARE(item3->mapFromItem(item2, 0, 0), QPointF(0, -200));
2943 QCOMPARE(item4->mapFromItem(item3, 0, 0), QPointF(200, 0));
2946 matrix.translate(100, 100);
2947 item1->setMatrix(matrix);
2949 QCOMPARE(item1->mapFromItem(item2, 0, 0), QPointF(100, -100));
2950 QCOMPARE(item2->mapFromItem(item3, 0, 0), QPointF(0, 200));
2951 QCOMPARE(item3->mapFromItem(item4, 0, 0), QPointF(-200, 0));
2952 QCOMPARE(item4->mapFromItem(item1, 0, 0), QPointF(100, -100));
2953 QCOMPARE(item1->mapFromItem(item4, 0, 0), QPointF(-100, 100));
2954 QCOMPARE(item2->mapFromItem(item1, 0, 0), QPointF(-100, 100));
2955 QCOMPARE(item3->mapFromItem(item2, 0, 0), QPointF(0, -200));
2956 QCOMPARE(item4->mapFromItem(item3, 0, 0), QPointF(200, 0));
2959 item1->setMatrix(matrix);
2960 item2->setMatrix(matrix);
2961 item3->setMatrix(matrix);
2962 item4->setMatrix(matrix);
2964 QCOMPARE(item1->mapFromItem(item2, 0, 0), QPointF(0, -200));
2965 QCOMPARE(item2->mapFromItem(item3, 0, 0), QPointF(200, 0));
2966 QCOMPARE(item3->mapFromItem(item4, 0, 0), QPointF(0, 200));
2967 QCOMPARE(item4->mapFromItem(item1, 0, 0), QPointF(-200, 0));
2968 QCOMPARE(item1->mapFromItem(item4, 0, 0), QPointF(200, 0));
2969 QCOMPARE(item2->mapFromItem(item1, 0, 0), QPointF(0, 200));
2970 QCOMPARE(item3->mapFromItem(item2, 0, 0), QPointF(-200, 0));
2971 QCOMPARE(item4->mapFromItem(item3, 0, 0), QPointF(0, -200));
2972 QCOMPARE(item1->mapFromItem(item2, 10, -5), QPointF(10, -205));
2973 QCOMPARE(item2->mapFromItem(item3, 10, -5), QPointF(210, -5));
2974 QCOMPARE(item3->mapFromItem(item4, 10, -5), QPointF(10, 195));
2975 QCOMPARE(item4->mapFromItem(item1, 10, -5), QPointF(-190, -5));
2976 QCOMPARE(item1->mapFromItem(item4, 10, -5), QPointF(210, -5));
2977 QCOMPARE(item2->mapFromItem(item1, 10, -5), QPointF(10, 195));
2978 QCOMPARE(item3->mapFromItem(item2, 10, -5), QPointF(-190, -5));
2979 QCOMPARE(item4->mapFromItem(item3, 10, -5), QPointF(10, -205));
2981 QCOMPARE(item1->mapFromItem(0, 10, -5), item1->mapFromScene(10, -5));
2982 QCOMPARE(item2->mapFromItem(0, 10, -5), item2->mapFromScene(10, -5));
2983 QCOMPARE(item3->mapFromItem(0, 10, -5), item3->mapFromScene(10, -5));
2984 QCOMPARE(item4->mapFromItem(0, 10, -5), item4->mapFromScene(10, -5));
2985 QCOMPARE(item1->mapToItem(0, 10, -5), item1->mapToScene(10, -5));
2986 QCOMPARE(item2->mapToItem(0, 10, -5), item2->mapToScene(10, -5));
2987 QCOMPARE(item3->mapToItem(0, 10, -5), item3->mapToScene(10, -5));
2988 QCOMPARE(item4->mapToItem(0, 10, -5), item4->mapToScene(10, -5));
2996 void tst_QGraphicsItem::mapRectFromToParent_data()
2998 QTest::addColumn<bool>("parent");
2999 QTest::addColumn<QPointF>("parentPos");
3000 QTest::addColumn<QTransform>("parentTransform");
3001 QTest::addColumn<QPointF>("pos");
3002 QTest::addColumn<QTransform>("transform");
3003 QTest::addColumn<QRectF>("inputRect");
3004 QTest::addColumn<QRectF>("outputRect");
3006 QTest::newRow("nil") << false << QPointF() << QTransform() << QPointF() << QTransform() << QRectF() << QRectF();
3007 QTest::newRow("simple") << false << QPointF() << QTransform() << QPointF() << QTransform()
3008 << QRectF(0, 0, 10, 10) << QRectF(0, 0, 10, 10);
3009 QTest::newRow("simple w/parent") << true
3010 << QPointF() << QTransform()
3011 << QPointF() << QTransform()
3012 << QRectF(0, 0, 10, 10) << QRectF(0, 0, 10, 10);
3013 QTest::newRow("simple w/parent parentPos") << true
3014 << QPointF(50, 50) << QTransform()
3015 << QPointF() << QTransform()
3016 << QRectF(0, 0, 10, 10) << QRectF(0, 0, 10, 10);
3017 QTest::newRow("simple w/parent parentPos parentRotation") << true
3018 << QPointF(50, 50) << QTransform().rotate(45)
3019 << QPointF() << QTransform()
3020 << QRectF(0, 0, 10, 10) << QRectF(0, 0, 10, 10);
3021 QTest::newRow("pos w/parent") << true
3022 << QPointF() << QTransform()
3023 << QPointF(50, 50) << QTransform()
3024 << QRectF(0, 0, 10, 10) << QRectF(50, 50, 10, 10);
3025 QTest::newRow("rotation w/parent") << true
3026 << QPointF() << QTransform()
3027 << QPointF() << QTransform().rotate(90)
3028 << QRectF(0, 0, 10, 10) << QRectF(-10, 0, 10, 10);
3029 QTest::newRow("pos rotation w/parent") << true
3030 << QPointF() << QTransform()
3031 << QPointF(50, 50) << QTransform().rotate(90)
3032 << QRectF(0, 0, 10, 10) << QRectF(40, 50, 10, 10);
3033 QTest::newRow("pos rotation w/parent parentPos parentRotation") << true
3034 << QPointF(-170, -190) << QTransform().rotate(90)
3035 << QPointF(50, 50) << QTransform().rotate(90)
3036 << QRectF(0, 0, 10, 10) << QRectF(40, 50, 10, 10);
3039 void tst_QGraphicsItem::mapRectFromToParent()
3041 QFETCH(bool, parent);
3042 QFETCH(QPointF, parentPos);
3043 QFETCH(QTransform, parentTransform);
3044 QFETCH(QPointF, pos);
3045 QFETCH(QTransform, transform);
3046 QFETCH(QRectF, inputRect);
3047 QFETCH(QRectF, outputRect);
3049 QGraphicsRectItem *rect = new QGraphicsRectItem;
3051 rect->setTransform(transform);
3054 QGraphicsRectItem *rectParent = new QGraphicsRectItem;
3055 rect->setParentItem(rectParent);
3056 rectParent->setPos(parentPos);
3057 rectParent->setTransform(parentTransform);
3060 // Make sure we use non-destructive transform operations (e.g., 90 degree
3062 QCOMPARE(rect->mapRectToParent(inputRect), outputRect);
3063 QCOMPARE(rect->mapRectFromParent(outputRect), inputRect);
3064 QCOMPARE(rect->itemTransform(rect->parentItem()).mapRect(inputRect), outputRect);
3065 QCOMPARE(rect->mapToParent(inputRect).boundingRect(), outputRect);
3066 QCOMPARE(rect->mapToParent(QPolygonF(inputRect)).boundingRect(), outputRect);
3067 QCOMPARE(rect->mapFromParent(outputRect).boundingRect(), inputRect);
3068 QCOMPARE(rect->mapFromParent(QPolygonF(outputRect)).boundingRect(), inputRect);
3069 QPainterPath inputPath;
3070 inputPath.addRect(inputRect);
3071 QPainterPath outputPath;
3072 outputPath.addRect(outputRect);
3073 QCOMPARE(rect->mapToParent(inputPath).boundingRect(), outputPath.boundingRect());
3074 QCOMPARE(rect->mapFromParent(outputPath).boundingRect(), inputPath.boundingRect());
3077 void tst_QGraphicsItem::isAncestorOf()
3079 QGraphicsItem *grandPa = new QGraphicsRectItem;
3080 QGraphicsItem *parent = new QGraphicsRectItem;
3081 QGraphicsItem *child = new QGraphicsRectItem;
3083 QVERIFY(!parent->isAncestorOf(0));
3084 QVERIFY(!child->isAncestorOf(0));
3085 QVERIFY(!parent->isAncestorOf(child));
3086 QVERIFY(!child->isAncestorOf(parent));
3087 QVERIFY(!parent->isAncestorOf(parent));
3089 child->setParentItem(parent);
3090 parent->setParentItem(grandPa);
3092 QVERIFY(parent->isAncestorOf(child));
3093 QVERIFY(grandPa->isAncestorOf(parent));
3094 QVERIFY(grandPa->isAncestorOf(child));
3095 QVERIFY(!child->isAncestorOf(parent));
3096 QVERIFY(!parent->isAncestorOf(grandPa));
3097 QVERIFY(!child->isAncestorOf(grandPa));
3098 QVERIFY(!child->isAncestorOf(child));
3099 QVERIFY(!parent->isAncestorOf(parent));
3100 QVERIFY(!grandPa->isAncestorOf(grandPa));
3102 parent->setParentItem(0);
3109 void tst_QGraphicsItem::commonAncestorItem()
3111 QGraphicsItem *ancestor = new QGraphicsRectItem;
3112 QGraphicsItem *grandMa = new QGraphicsRectItem;
3113 QGraphicsItem *grandPa = new QGraphicsRectItem;
3114 QGraphicsItem *brotherInLaw = new QGraphicsRectItem;
3115 QGraphicsItem *cousin = new QGraphicsRectItem;
3116 QGraphicsItem *husband = new QGraphicsRectItem;
3117 QGraphicsItem *child = new QGraphicsRectItem;
3118 QGraphicsItem *wife = new QGraphicsRectItem;
3120 child->setParentItem(husband);
3121 husband->setParentItem(grandPa);
3122 brotherInLaw->setParentItem(grandPa);
3123 cousin->setParentItem(brotherInLaw);
3124 wife->setParentItem(grandMa);
3125 grandMa->setParentItem(ancestor);
3126 grandPa->setParentItem(ancestor);
3128 QCOMPARE(grandMa->commonAncestorItem(grandMa), grandMa);
3129 QCOMPARE(grandMa->commonAncestorItem(0), (QGraphicsItem *)0);
3130 QCOMPARE(grandMa->commonAncestorItem(grandPa), ancestor);
3131 QCOMPARE(grandPa->commonAncestorItem(grandMa), ancestor);
3132 QCOMPARE(grandPa->commonAncestorItem(husband), grandPa);
3133 QCOMPARE(grandPa->commonAncestorItem(wife), ancestor);
3134 QCOMPARE(grandMa->commonAncestorItem(husband), ancestor);
3135 QCOMPARE(grandMa->commonAncestorItem(wife), grandMa);
3136 QCOMPARE(wife->commonAncestorItem(grandMa), grandMa);
3137 QCOMPARE(child->commonAncestorItem(cousin), grandPa);
3138 QCOMPARE(cousin->commonAncestorItem(child), grandPa);
3139 QCOMPARE(wife->commonAncestorItem(child), ancestor);
3140 QCOMPARE(child->commonAncestorItem(wife), ancestor);
3143 void tst_QGraphicsItem::data()
3145 QGraphicsTextItem text;
3147 QCOMPARE(text.data(0), QVariant());
3148 text.setData(0, "TextItem");
3149 QCOMPARE(text.data(0), QVariant(QString("TextItem")));
3150 text.setData(0, QVariant());
3151 QCOMPARE(text.data(0), QVariant());
3154 void tst_QGraphicsItem::type()
3156 QCOMPARE(int(QGraphicsItem::Type), 1);
3157 QCOMPARE(int(QGraphicsPathItem::Type), 2);
3158 QCOMPARE(int(QGraphicsRectItem::Type), 3);
3159 QCOMPARE(int(QGraphicsEllipseItem::Type), 4);
3160 QCOMPARE(int(QGraphicsPolygonItem::Type), 5);
3161 QCOMPARE(int(QGraphicsLineItem::Type), 6);
3162 QCOMPARE(int(QGraphicsPixmapItem::Type), 7);
3163 QCOMPARE(int(QGraphicsTextItem::Type), 8);
3165 QCOMPARE(QGraphicsPathItem().type(), 2);
3166 QCOMPARE(QGraphicsRectItem().type(), 3);
3167 QCOMPARE(QGraphicsEllipseItem().type(), 4);
3168 QCOMPARE(QGraphicsPolygonItem().type(), 5);
3169 QCOMPARE(QGraphicsLineItem().type(), 6);
3170 QCOMPARE(QGraphicsPixmapItem().type(), 7);
3171 QCOMPARE(QGraphicsTextItem().type(), 8);
3174 void tst_QGraphicsItem::graphicsitem_cast()
3176 QGraphicsPathItem pathItem;
3177 const QGraphicsPathItem *pPathItem = &pathItem;
3178 QGraphicsRectItem rectItem;
3179 const QGraphicsRectItem *pRectItem = &rectItem;
3180 QGraphicsEllipseItem ellipseItem;
3181 const QGraphicsEllipseItem *pEllipseItem = &ellipseItem;
3182 QGraphicsPolygonItem polygonItem;
3183 const QGraphicsPolygonItem *pPolygonItem = &polygonItem;
3184 QGraphicsLineItem lineItem;
3185 const QGraphicsLineItem *pLineItem = &lineItem;
3186 QGraphicsPixmapItem pixmapItem;
3187 const QGraphicsPixmapItem *pPixmapItem = &pixmapItem;
3188 QGraphicsTextItem textItem;
3189 const QGraphicsTextItem *pTextItem = &textItem;
3191 QVERIFY(qgraphicsitem_cast<QGraphicsPathItem *>(&pathItem));
3192 //QVERIFY(qgraphicsitem_cast<QAbstractGraphicsPathItem *>(&pathItem));
3193 QVERIFY(qgraphicsitem_cast<QGraphicsItem *>(&pathItem));
3194 QVERIFY(qgraphicsitem_cast<const QGraphicsItem *>(pPathItem));
3195 QVERIFY(qgraphicsitem_cast<const QGraphicsPathItem *>(pPathItem));
3197 QVERIFY(qgraphicsitem_cast<QGraphicsRectItem *>(&rectItem));
3198 QVERIFY(qgraphicsitem_cast<QGraphicsItem *>(&rectItem));
3199 QVERIFY(qgraphicsitem_cast<const QGraphicsItem *>(pRectItem));
3200 QVERIFY(qgraphicsitem_cast<const QGraphicsRectItem *>(pRectItem));
3202 QVERIFY(qgraphicsitem_cast<QGraphicsEllipseItem *>(&ellipseItem));
3203 QVERIFY(qgraphicsitem_cast<QGraphicsItem *>(&ellipseItem));
3204 QVERIFY(qgraphicsitem_cast<const QGraphicsItem *>(pEllipseItem));
3205 QVERIFY(qgraphicsitem_cast<const QGraphicsEllipseItem *>(pEllipseItem));
3207 QVERIFY(qgraphicsitem_cast<QGraphicsPolygonItem *>(&polygonItem));
3208 //QVERIFY(qgraphicsitem_cast<QAbstractGraphicsPathItem *>(&polygonItem));
3209 QVERIFY(qgraphicsitem_cast<QGraphicsItem *>(&polygonItem));
3210 QVERIFY(qgraphicsitem_cast<const QGraphicsItem *>(pPolygonItem));
3211 QVERIFY(qgraphicsitem_cast<const QGraphicsPolygonItem *>(pPolygonItem));
3213 QVERIFY(qgraphicsitem_cast<QGraphicsLineItem *>(&lineItem));
3214 QVERIFY(qgraphicsitem_cast<QGraphicsItem *>(&lineItem));
3215 QVERIFY(qgraphicsitem_cast<const QGraphicsItem *>(pLineItem));
3216 QVERIFY(qgraphicsitem_cast<const QGraphicsLineItem *>(pLineItem));
3218 QVERIFY(qgraphicsitem_cast<QGraphicsPixmapItem *>(&pixmapItem));
3219 QVERIFY(qgraphicsitem_cast<QGraphicsItem *>(&pixmapItem));
3220 QVERIFY(qgraphicsitem_cast<const QGraphicsItem *>(pPixmapItem));
3221 QVERIFY(qgraphicsitem_cast<const QGraphicsPixmapItem *>(pPixmapItem));
3223 QVERIFY(qgraphicsitem_cast<QGraphicsTextItem *>(&textItem));
3224 QVERIFY(qgraphicsitem_cast<QGraphicsItem *>(&textItem));
3225 QVERIFY(qgraphicsitem_cast<const QGraphicsItem *>(pTextItem));
3226 QVERIFY(qgraphicsitem_cast<const QGraphicsTextItem *>(pTextItem));
3228 // and some casts that _should_ fail:
3229 QVERIFY(!qgraphicsitem_cast<QGraphicsEllipseItem *>(&pathItem));
3230 QVERIFY(!qgraphicsitem_cast<const QGraphicsTextItem *>(pPolygonItem));
3232 // and this shouldn't crash
3233 QGraphicsItem *ptr = 0;
3234 QVERIFY(!qgraphicsitem_cast<QGraphicsTextItem *>(ptr));
3235 QVERIFY(!qgraphicsitem_cast<QGraphicsItem *>(ptr));
3238 void tst_QGraphicsItem::hoverEventsGenerateRepaints()
3242 QGraphicsScene scene;
3243 QGraphicsView view(&scene);
3245 QVERIFY(QTest::qWaitForWindowActive(&view));
3247 EventTester *tester = new EventTester;
3248 scene.addItem(tester);
3249 tester->setAcceptsHoverEvents(true);
3251 QTRY_COMPARE(tester->repaints, 1);
3253 // Send a hover enter event
3254 QGraphicsSceneHoverEvent hoverEnterEvent(QEvent::GraphicsSceneHoverEnter);
3255 hoverEnterEvent.setScenePos(QPointF(0, 0));
3256 hoverEnterEvent.setPos(QPointF(0, 0));
3257 QApplication::sendEvent(&scene, &hoverEnterEvent);
3259 // Check that we get a repaint
3260 int npaints = tester->repaints;
3261 qApp->processEvents();
3262 qApp->processEvents();
3263 QCOMPARE(tester->events.size(), 2); // enter + move
3264 QCOMPARE(tester->repaints, npaints + 1);
3265 QCOMPARE(tester->events.last(), QEvent::GraphicsSceneHoverMove);
3267 // Send a hover move event
3268 QGraphicsSceneHoverEvent hoverMoveEvent(QEvent::GraphicsSceneHoverMove);
3269 hoverMoveEvent.setScenePos(QPointF(0, 0));
3270 hoverMoveEvent.setPos(QPointF(0, 0));
3271 QApplication::sendEvent(&scene, &hoverMoveEvent);
3273 // Check that we don't get a repaint
3274 qApp->processEvents();
3275 qApp->processEvents();
3277 QCOMPARE(tester->events.size(), 3);
3278 QCOMPARE(tester->repaints, npaints + 1);
3279 QCOMPARE(tester->events.last(), QEvent::GraphicsSceneHoverMove);
3281 // Send a hover leave event
3282 QGraphicsSceneHoverEvent hoverLeaveEvent(QEvent::GraphicsSceneHoverLeave);
3283 hoverLeaveEvent.setScenePos(QPointF(-100, -100));
3284 hoverLeaveEvent.setPos(QPointF(0, 0));
3285 QApplication::sendEvent(&scene, &hoverLeaveEvent);
3287 // Check that we get a repaint
3288 qApp->processEvents();
3289 qApp->processEvents();
3291 QCOMPARE(tester->events.size(), 4);
3292 QCOMPARE(tester->repaints, npaints + 2);
3293 QCOMPARE(tester->events.last(), QEvent::GraphicsSceneHoverLeave);
3296 void tst_QGraphicsItem::boundingRects_data()
3298 QTest::addColumn<QGraphicsItem *>("item");
3299 QTest::addColumn<QRectF>("boundingRect");
3301 QRectF rect(0, 0, 100, 100);
3305 QRectF adjustedRect(-0.5, -0.5, 101, 101);
3307 QTest::newRow("path") << (QGraphicsItem *)new QGraphicsPathItem(path) << adjustedRect;
3308 QTest::newRow("rect") << (QGraphicsItem *)new QGraphicsRectItem(rect) << adjustedRect;
3309 QTest::newRow("ellipse") << (QGraphicsItem *)new QGraphicsEllipseItem(rect) << adjustedRect;
3310 QTest::newRow("polygon") << (QGraphicsItem *)new QGraphicsPolygonItem(rect) << adjustedRect;
3313 void tst_QGraphicsItem::boundingRects()
3315 QFETCH(QGraphicsItem *, item);
3316 QFETCH(QRectF, boundingRect);
3318 ((QAbstractGraphicsShapeItem *)item)->setPen(QPen(Qt::black, 1));
3319 QCOMPARE(item->boundingRect(), boundingRect);
3322 void tst_QGraphicsItem::boundingRects2()
3324 QGraphicsPixmapItem pixmap(QPixmap::fromImage(QImage(100, 100, QImage::Format_ARGB32_Premultiplied)));
3325 QCOMPARE(pixmap.boundingRect(), QRectF(0, 0, 100, 100));
3327 QGraphicsLineItem line(0, 0, 100, 0);
3328 line.setPen(QPen(Qt::black, 1));
3329 QCOMPARE(line.boundingRect(), QRectF(-0.5, -0.5, 101, 1));
3332 void tst_QGraphicsItem::sceneBoundingRect()
3334 QGraphicsScene scene;
3335 QGraphicsRectItem *item = scene.addRect(QRectF(0, 0, 100, 100), QPen(Qt::black, 0));
3336 item->setPos(100, 100);
3338 QCOMPARE(item->boundingRect(), QRectF(0, 0, 100, 100));
3339 QCOMPARE(item->sceneBoundingRect(), QRectF(100, 100, 100, 100));
3343 QCOMPARE(item->boundingRect(), QRectF(0, 0, 100, 100));
3344 QCOMPARE(item->sceneBoundingRect(), QRectF(0, 100, 100, 100));
3347 void tst_QGraphicsItem::childrenBoundingRect()
3349 QGraphicsScene scene;
3350 QGraphicsRectItem *parent = scene.addRect(QRectF(0, 0, 100, 100), QPen(Qt::black, 0));
3351 QGraphicsRectItem *child = scene.addRect(QRectF(0, 0, 100, 100), QPen(Qt::black, 0));
3352 child->setParentItem(parent);
3353 parent->setPos(100, 100);
3354 child->setPos(100, 100);
3356 QCOMPARE(parent->boundingRect(), QRectF(0, 0, 100, 100));
3357 QCOMPARE(child->boundingRect(), QRectF(0, 0, 100, 100));
3358 QCOMPARE(child->childrenBoundingRect(), QRectF());
3359 QCOMPARE(parent->childrenBoundingRect(), QRectF(100, 100, 100, 100));
3361 QGraphicsRectItem *child2 = scene.addRect(QRectF(0, 0, 100, 100), QPen(Qt::black, 0));
3362 child2->setParentItem(parent);
3363 child2->setPos(-100, -100);
3364 QCOMPARE(parent->childrenBoundingRect(), QRectF(-100, -100, 300, 300));
3366 QGraphicsRectItem *childChild = scene.addRect(QRectF(0, 0, 100, 100), QPen(Qt::black, 0));
3367 childChild->setParentItem(child);
3368 childChild->setPos(500, 500);
3371 scene.addPolygon(parent->mapToScene(parent->boundingRect() | parent->childrenBoundingRect()))->setPen(QPen(Qt::red));;
3373 QGraphicsView view(&scene);
3376 QVERIFY(QTest::qWaitForWindowExposed(&view));
3379 QCOMPARE(parent->childrenBoundingRect(), QRectF(-500, -100, 600, 800));
3382 void tst_QGraphicsItem::childrenBoundingRectTransformed()
3384 QGraphicsScene scene;
3386 QGraphicsRectItem *rect = scene.addRect(QRectF(0, 0, 100, 100));
3387 QGraphicsRectItem *rect2 = scene.addRect(QRectF(0, 0, 100, 100));
3388 QGraphicsRectItem *rect3 = scene.addRect(QRectF(0, 0, 100, 100));
3389 QGraphicsRectItem *rect4 = scene.addRect(QRectF(0, 0, 100, 100));
3390 QGraphicsRectItem *rect5 = scene.addRect(QRectF(0, 0, 100, 100));
3391 rect2->setParentItem(rect);
3392 rect3->setParentItem(rect2);
3393 rect4->setParentItem(rect3);
3394 rect5->setParentItem(rect4);
3396 rect2->setTransform(QTransform().translate(50, 50).rotate(45));
3397 rect2->setPos(25, 25);
3398 rect3->setTransform(QTransform().translate(50, 50).rotate(45));
3399 rect3->setPos(25, 25);
3400 rect4->setTransform(QTransform().translate(50, 50).rotate(45));
3401 rect4->setPos(25, 25);
3402 rect5->setTransform(QTransform().translate(50, 50).rotate(45));
3403 rect5->setPos(25, 25);
3405 QRectF subTreeRect = rect->childrenBoundingRect();
3406 QCOMPARE(subTreeRect.left(), qreal(-206.0660171779821));
3407 QCOMPARE(subTreeRect.top(), qreal(75.0));
3408 QCOMPARE(subTreeRect.width(), qreal(351.7766952966369));
3409 QCOMPARE(subTreeRect.height(), qreal(251.7766952966369));
3417 subTreeRect = rect->childrenBoundingRect();
3418 QCOMPARE(rect->childrenBoundingRect(), QRectF(-100, 75, 275, 250));
3421 void tst_QGraphicsItem::childrenBoundingRect2()
3423 QGraphicsItemGroup box;
3424 QGraphicsLineItem l1(0, 0, 100, 0, &box);
3425 QGraphicsLineItem l2(100, 0, 100, 100, &box);
3426 QGraphicsLineItem l3(0, 0, 0, 100, &box);
3427 // Make sure lines (zero with/height) are included in the childrenBoundingRect.
3428 QCOMPARE(box.childrenBoundingRect(), QRectF(0, 0, 100, 100));
3431 void tst_QGraphicsItem::childrenBoundingRect3()
3433 QGraphicsScene scene;
3435 QGraphicsRectItem *rect = scene.addRect(QRectF(0, 0, 100, 100));
3436 QGraphicsRectItem *rect2 = scene.addRect(QRectF(0, 0, 100, 100));
3437 QGraphicsRectItem *rect3 = scene.addRect(QRectF(0, 0, 100, 100));
3438 QGraphicsRectItem *rect4 = scene.addRect(QRectF(0, 0, 100, 100));
3439 QGraphicsRectItem *rect5 = scene.addRect(QRectF(0, 0, 100, 100));
3440 rect2->setParentItem(rect);
3441 rect3->setParentItem(rect2);
3442 rect4->setParentItem(rect3);
3443 rect5->setParentItem(rect4);
3445 rect2->setTransform(QTransform().translate(50, 50).rotate(45));
3446 rect2->setPos(25, 25);
3447 rect3->setTransform(QTransform().translate(50, 50).rotate(45));
3448 rect3->setPos(25, 25);
3449 rect4->setTransform(QTransform().translate(50, 50).rotate(45));
3450 rect4->setPos(25, 25);
3451 rect5->setTransform(QTransform().translate(50, 50).rotate(45));
3452 rect5->setPos(25, 25);
3454 // Try to mess up the cached bounding rect.
3455 (void)rect2->childrenBoundingRect();
3457 QRectF subTreeRect = rect->childrenBoundingRect();
3458 QCOMPARE(subTreeRect.left(), qreal(-206.0660171779821));
3459 QCOMPARE(subTreeRect.top(), qreal(75.0));
3460 QCOMPARE(subTreeRect.width(), qreal(351.7766952966369));
3461 QCOMPARE(subTreeRect.height(), qreal(251.7766952966369));
3464 void tst_QGraphicsItem::childrenBoundingRect4()
3466 QGraphicsScene scene;
3468 QGraphicsRectItem *rect = scene.addRect(QRectF(0, 0, 10, 10));
3469 QGraphicsRectItem *rect2 = scene.addRect(QRectF(0, 0, 20, 20));
3470 QGraphicsRectItem *rect3 = scene.addRect(QRectF(0, 0, 30, 30));
3471 rect2->setParentItem(rect);
3472 rect3->setParentItem(rect);
3474 QGraphicsView view(&scene);
3477 QVERIFY(QTest::qWaitForWindowExposed(&view));
3479 // Try to mess up the cached bounding rect.
3480 rect->childrenBoundingRect();
3481 rect2->childrenBoundingRect();
3483 rect3->setOpacity(0.0);
3484 rect3->setParentItem(rect2);
3486 QCOMPARE(rect->childrenBoundingRect(), rect3->boundingRect());
3487 QCOMPARE(rect2->childrenBoundingRect(), rect3->boundingRect());
3490 void tst_QGraphicsItem::childrenBoundingRect5()
3492 QGraphicsScene scene;
3494 QGraphicsRectItem *parent = scene.addRect(QRectF(0, 0, 100, 100));
3495 QGraphicsRectItem *child = scene.addRect(QRectF(0, 0, 100, 100));
3496 child->setParentItem(parent);
3498 QGraphicsView view(&scene);
3501 QVERIFY(QTest::qWaitForWindowExposed(&view));
3503 // Try to mess up the cached bounding rect.
3504 QRectF expectedChildrenBoundingRect = parent->boundingRect();
3505 QCOMPARE(parent->childrenBoundingRect(), expectedChildrenBoundingRect);
3507 // Apply some effects.
3508 QGraphicsDropShadowEffect *dropShadow = new QGraphicsDropShadowEffect;
3509 dropShadow->setOffset(25, 25);
3510 child->setGraphicsEffect(dropShadow);
3511 parent->setGraphicsEffect(new QGraphicsOpacityEffect);
3513 QVERIFY(parent->childrenBoundingRect() != expectedChildrenBoundingRect);
3514 expectedChildrenBoundingRect |= dropShadow->boundingRect();
3515 QCOMPARE(parent->childrenBoundingRect(), expectedChildrenBoundingRect);
3518 void tst_QGraphicsItem::group()
3520 QGraphicsScene scene;
3521 QGraphicsRectItem *parent = scene.addRect(QRectF(0, 0, 50, 50), QPen(Qt::black, 0), QBrush(Qt::green));
3522 QGraphicsRectItem *child = scene.addRect(QRectF(0, 0, 50, 50), QPen(Qt::black, 0), QBrush(Qt::blue));
3523 QGraphicsRectItem *parent2 = scene.addRect(QRectF(0, 0, 50, 50), QPen(Qt::black, 0), QBrush(Qt::red));
3524 parent2->setPos(-50, 50);
3526 child->setParentItem(parent);
3527 parent->setPos(25, 25);
3528 child->setPos(25, 25);
3530 QCOMPARE(parent->group(), (QGraphicsItemGroup *)0);
3531 QCOMPARE(parent2->group(), (QGraphicsItemGroup *)0);
3532 QCOMPARE(child->group(), (QGraphicsItemGroup *)0);
3534 QGraphicsView view(&scene);
3536 QVERIFY(QTest::qWaitForWindowExposed(&view));
3538 QGraphicsItemGroup *group = new QGraphicsItemGroup;
3539 group->setSelected(true);
3540 scene.addItem(group);
3542 QRectF parentSceneBoundingRect = parent->sceneBoundingRect();
3543 group->addToGroup(parent);
3544 QCOMPARE(parent->group(), group);
3545 QCOMPARE(parent->sceneBoundingRect(), parentSceneBoundingRect);
3547 QCOMPARE(parent->parentItem(), (QGraphicsItem *)group);
3548 QCOMPARE(group->children().size(), 1);
3549 QCOMPARE(scene.items().size(), 4);
3550 QCOMPARE(scene.items(group->sceneBoundingRect()).size(), 3);
3554 QRectF parent2SceneBoundingRect = parent2->sceneBoundingRect();
3555 group->addToGroup(parent2);
3556 QCOMPARE(parent2->group(), group);
3557 QCOMPARE(parent2->sceneBoundingRect(), parent2SceneBoundingRect);
3559 QCOMPARE(parent2->parentItem(), (QGraphicsItem *)group);
3560 QCOMPARE(group->children().size(), 2);
3561 QCOMPARE(scene.items().size(), 4);
3562 QCOMPARE(scene.items(group->sceneBoundingRect()).size(), 4);
3566 QList<QGraphicsItem *> newItems;
3567 for (int i = 0; i < 100; ++i) {
3568 QGraphicsItem *item = scene.addRect(QRectF(-25, -25, 50, 50), QPen(Qt::black, 0),
3569 QBrush(QColor(rand() % 255, rand() % 255,
3570 rand() % 255, rand() % 255)));
3572 item->setPos(-1000 + rand() % 2000,
3573 -1000 + rand() % 2000);
3574 item->rotate(rand() % 90);
3577 view.fitInView(scene.itemsBoundingRect());
3580 foreach (QGraphicsItem *item, newItems) {
3581 group->addToGroup(item);
3582 QCOMPARE(item->group(), group);
3583 if ((n++ % 100) == 0)
3588 void tst_QGraphicsItem::setGroup()
3590 QGraphicsItemGroup group1;
3591 QGraphicsItemGroup group2;
3593 QGraphicsRectItem *rect = new QGraphicsRectItem;
3594 QCOMPARE(rect->group(), (QGraphicsItemGroup *)0);
3595 QCOMPARE(rect->parentItem(), (QGraphicsItem *)0);
3596 rect->setGroup(&group1);
3597 QCOMPARE(rect->group(), &group1);
3598 QCOMPARE(rect->parentItem(), (QGraphicsItem *)&group1);
3599 rect->setGroup(&group2);
3600 QCOMPARE(rect->group(), &group2);
3601 QCOMPARE(rect->parentItem(), (QGraphicsItem *)&group2);
3603 QCOMPARE(rect->group(), (QGraphicsItemGroup *)0);
3604 QCOMPARE(rect->parentItem(), (QGraphicsItem *)0);
3607 void tst_QGraphicsItem::setGroup2()
3609 QGraphicsScene scene;
3610 QGraphicsItemGroup group;
3611 scene.addItem(&group);
3613 QGraphicsRectItem *rect = scene.addRect(50,50,50,50,Qt::NoPen,Qt::black);
3614 rect->setTransformOriginPoint(50,50);
3615 rect->setRotation(45);
3616 rect->setScale(1.5);
3617 rect->translate(20,20);
3618 group.translate(-30,-40);
3619 group.setRotation(180);
3620 group.setScale(0.5);
3622 QTransform oldSceneTransform = rect->sceneTransform();
3623 rect->setGroup(&group);
3624 QCOMPARE(rect->sceneTransform(), oldSceneTransform);
3626 group.setRotation(20);
3628 rect->setRotation(90);
3629 rect->setScale(0.8);
3631 oldSceneTransform = rect->sceneTransform();
3633 QCOMPARE(rect->sceneTransform(), oldSceneTransform);
3636 void tst_QGraphicsItem::nestedGroups()
3638 QGraphicsItemGroup *group1 = new QGraphicsItemGroup;
3639 QGraphicsItemGroup *group2 = new QGraphicsItemGroup;
3641 QGraphicsRectItem *rect = new QGraphicsRectItem;
3642 QGraphicsRectItem *rect2 = new QGraphicsRectItem;
3643 rect2->setParentItem(rect);
3645 group1->addToGroup(rect);
3646 QCOMPARE(rect->group(), group1);
3647 QCOMPARE(rect2->group(), group1);
3649 group2->addToGroup(group1);
3650 QCOMPARE(rect->group(), group1);
3651 QCOMPARE(rect2->group(), group1);
3652 QCOMPARE(group1->group(), group2);
3653 QCOMPARE(group2->group(), (QGraphicsItemGroup *)0);
3655 QGraphicsScene scene;
3656 scene.addItem(group1);
3658 QCOMPARE(rect->group(), group1);
3659 QCOMPARE(rect2->group(), group1);
3660 QCOMPARE(group1->group(), (QGraphicsItemGroup *)0);
3661 QVERIFY(group2->children().isEmpty());
3666 void tst_QGraphicsItem::warpChildrenIntoGroup()
3668 QGraphicsScene scene;
3669 QGraphicsRectItem *parentRectItem = scene.addRect(QRectF(0, 0, 100, 100));
3670 QGraphicsRectItem *childRectItem = scene.addRect(QRectF(0, 0, 100, 100));
3671 parentRectItem->rotate(90);
3672 childRectItem->setPos(-50, -25);
3673 childRectItem->setParentItem(parentRectItem);
3675 QCOMPARE(childRectItem->mapToScene(50, 0), QPointF(25, 0));
3676 QCOMPARE(childRectItem->scenePos(), QPointF(25, -50));
3678 QGraphicsRectItem *parentOfGroup = scene.addRect(QRectF(0, 0, 100, 100));
3679 parentOfGroup->setPos(-200, -200);
3680 parentOfGroup->scale(2, 2);
3682 QGraphicsItemGroup *group = new QGraphicsItemGroup;
3683 group->setPos(50, 50);
3684 group->setParentItem(parentOfGroup);
3686 QCOMPARE(group->scenePos(), QPointF(-100, -100));
3688 group->addToGroup(childRectItem);
3690 QCOMPARE(childRectItem->mapToScene(50, 0), QPointF(25, 0));
3691 QCOMPARE(childRectItem->scenePos(), QPointF(25, -50));
3694 void tst_QGraphicsItem::removeFromGroup()
3696 QGraphicsScene scene;
3697 QGraphicsRectItem *rect1 = scene.addRect(QRectF(-100, -100, 200, 200));
3698 QGraphicsRectItem *rect2 = scene.addRect(QRectF(100, 100, 200, 200));
3699 rect1->setFlag(QGraphicsItem::ItemIsSelectable);
3700 rect2->setFlag(QGraphicsItem::ItemIsSelectable);
3701 rect1->setSelected(true);
3702 rect2->setSelected(true);
3704 QGraphicsView view(&scene);
3707 qApp->processEvents(); // index items
3708 qApp->processEvents(); // emit changed
3710 QGraphicsItemGroup *group = scene.createItemGroup(scene.selectedItems());
3712 QCOMPARE(group->children().size(), 2);
3713 qApp->processEvents(); // index items
3714 qApp->processEvents(); // emit changed
3716 scene.destroyItemGroup(group); // calls removeFromGroup.
3718 qApp->processEvents(); // index items
3719 qApp->processEvents(); // emit changed
3721 QCOMPARE(scene.items().size(), 2);
3722 QVERIFY(!rect1->group());
3723 QVERIFY(!rect2->group());
3726 class ChildEventTester : public QGraphicsRectItem
3729 ChildEventTester(const QRectF &rect, QGraphicsItem *parent = 0)
3730 : QGraphicsRectItem(rect, parent), counter(0)
3736 void focusInEvent(QFocusEvent *event)
3737 { ++counter; QGraphicsRectItem::focusInEvent(event); }
3738 void mousePressEvent(QGraphicsSceneMouseEvent *)
3740 void mouseMoveEvent(QGraphicsSceneMouseEvent *)
3742 void mouseReleaseEvent(QGraphicsSceneMouseEvent *)
3746 void tst_QGraphicsItem::handlesChildEvents()
3748 ChildEventTester *blue = new ChildEventTester(QRectF(0, 0, 100, 100));
3749 ChildEventTester *red = new ChildEventTester(QRectF(0, 0, 50, 50));
3750 ChildEventTester *green = new ChildEventTester(QRectF(0, 0, 25, 25));
3751 ChildEventTester *gray = new ChildEventTester(QRectF(0, 0, 25, 25));
3752 ChildEventTester *yellow = new ChildEventTester(QRectF(0, 0, 50, 50));
3754 blue->setBrush(QBrush(Qt::blue));
3755 red->setBrush(QBrush(Qt::red));
3756 yellow->setBrush(QBrush(Qt::yellow));
3757 green->setBrush(QBrush(Qt::green));
3758 gray->setBrush(QBrush(Qt::gray));
3760 yellow->setPos(50, 50);
3761 green->setPos(25, 0);
3762 gray->setPos(25, 25);
3763 red->setParentItem(blue);
3764 yellow->setParentItem(blue);
3765 green->setParentItem(red);
3766 gray->setParentItem(red);
3768 QGraphicsScene scene;
3769 scene.addItem(blue);
3771 QGraphicsView view(&scene);
3773 QVERIFY(QTest::qWaitForWindowExposed(&view));
3776 // Pull out the items, closest item first
3777 QList<QGraphicsItem *> items = scene.items(scene.itemsBoundingRect());
3778 QCOMPARE(items.at(0), (QGraphicsItem *)yellow);
3779 QCOMPARE(items.at(1), (QGraphicsItem *)gray);
3780 QCOMPARE(items.at(2), (QGraphicsItem *)green);
3781 QCOMPARE(items.at(3), (QGraphicsItem *)red);
3782 QCOMPARE(items.at(4), (QGraphicsItem *)blue);
3784 QCOMPARE(blue->counter, 0);
3786 // Send events to the toplevel item
3787 QGraphicsSceneMouseEvent pressEvent(QEvent::GraphicsSceneMousePress);
3788 QGraphicsSceneMouseEvent releaseEvent(QEvent::GraphicsSceneMouseRelease);
3790 pressEvent.setButton(Qt::LeftButton);
3791 pressEvent.setScenePos(blue->mapToScene(5, 5));
3792 pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
3793 releaseEvent.setButton(Qt::LeftButton);
3794 releaseEvent.setScenePos(blue->mapToScene(5, 5));
3795 releaseEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
3796 QApplication::sendEvent(&scene, &pressEvent);
3797 QApplication::sendEvent(&scene, &releaseEvent);
3799 QCOMPARE(blue->counter, 2);
3801 // Send events to a level1 item
3802 pressEvent.setScenePos(red->mapToScene(5, 5));
3803 pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
3804 releaseEvent.setScenePos(red->mapToScene(5, 5));
3805 releaseEvent.setScreenPos(view.mapFromScene(releaseEvent.scenePos()));
3806 QApplication::sendEvent(&scene, &pressEvent);
3807 QApplication::sendEvent(&scene, &releaseEvent);
3809 QCOMPARE(blue->counter, 2);
3810 QCOMPARE(red->counter, 2);
3812 // Send events to a level2 item
3813 pressEvent.setScenePos(green->mapToScene(5, 5));
3814 pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
3815 releaseEvent.setScenePos(green->mapToScene(5, 5));
3816 releaseEvent.setScreenPos(view.mapFromScene(releaseEvent.scenePos()));
3817 QApplication::sendEvent(&scene, &pressEvent);
3818 QApplication::sendEvent(&scene, &releaseEvent);
3820 QCOMPARE(blue->counter, 2);
3821 QCOMPARE(red->counter, 2);
3822 QCOMPARE(green->counter, 2);
3824 blue->setHandlesChildEvents(true);
3826 // Send events to a level1 item
3827 pressEvent.setScenePos(red->mapToScene(5, 5));
3828 pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
3829 releaseEvent.setScenePos(red->mapToScene(5, 5));
3830 releaseEvent.setScreenPos(view.mapFromScene(releaseEvent.scenePos()));
3831 QApplication::sendEvent(&scene, &pressEvent);
3832 QApplication::sendEvent(&scene, &releaseEvent);
3834 QCOMPARE(blue->counter, 4);
3835 QCOMPARE(red->counter, 2);
3837 // Send events to a level2 item
3838 pressEvent.setScenePos(green->mapToScene(5, 5));
3839 pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
3840 releaseEvent.setScenePos(green->mapToScene(5, 5));
3841 releaseEvent.setScreenPos(view.mapFromScene(releaseEvent.scenePos()));
3842 QApplication::sendEvent(&scene, &pressEvent);
3843 QApplication::sendEvent(&scene, &releaseEvent);
3845 QCOMPARE(blue->counter, 6);
3846 QCOMPARE(red->counter, 2);
3847 QCOMPARE(green->counter, 2);
3849 blue->setHandlesChildEvents(false);
3851 // Send events to a level1 item
3852 pressEvent.setScenePos(red->mapToScene(5, 5));
3853 pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
3854 releaseEvent.setScenePos(red->mapToScene(5, 5));
3855 releaseEvent.setScreenPos(view.mapFromScene(releaseEvent.scenePos()));
3856 QApplication::sendEvent(&scene, &pressEvent);
3857 QApplication::sendEvent(&scene, &releaseEvent);
3859 QCOMPARE(blue->counter, 6);
3860 QCOMPARE(red->counter, 4);
3862 // Send events to a level2 item
3863 pressEvent.setScenePos(green->mapToScene(5, 5));
3864 pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
3865 releaseEvent.setScenePos(green->mapToScene(5, 5));
3866 releaseEvent.setScreenPos(view.mapFromScene(releaseEvent.scenePos()));
3867 QApplication::sendEvent(&scene, &pressEvent);
3868 QApplication::sendEvent(&scene, &releaseEvent);
3870 QCOMPARE(blue->counter, 6);
3871 QCOMPARE(red->counter, 4);
3872 QCOMPARE(green->counter, 4);
3875 void tst_QGraphicsItem::handlesChildEvents2()
3877 ChildEventTester *root = new ChildEventTester(QRectF(0, 0, 10, 10));
3878 root->setHandlesChildEvents(true);
3879 QVERIFY(root->handlesChildEvents());
3881 ChildEventTester *child = new ChildEventTester(QRectF(0, 0, 10, 10), root);
3882 QVERIFY(!child->handlesChildEvents());
3884 ChildEventTester *child2 = new ChildEventTester(QRectF(0, 0, 10, 10));
3885 ChildEventTester *child3 = new ChildEventTester(QRectF(0, 0, 10, 10), child2);
3886 ChildEventTester *child4 = new ChildEventTester(QRectF(0, 0, 10, 10), child3);
3887 child2->setParentItem(root);
3888 QVERIFY(!child2->handlesChildEvents());
3889 QVERIFY(!child3->handlesChildEvents());
3890 QVERIFY(!child4->handlesChildEvents());
3892 QGraphicsScene scene;
3893 scene.addItem(root);
3895 QGraphicsView view(&scene);
3897 QVERIFY(QTest::qWaitForWindowExposed(&view));
3898 QApplication::processEvents();
3900 QMouseEvent event(QEvent::MouseButtonPress, view.mapFromScene(5, 5),
3901 view.viewport()->mapToGlobal(view.mapFromScene(5, 5)), Qt::LeftButton, 0, 0);
3902 QApplication::sendEvent(view.viewport(), &event);
3904 QTRY_COMPARE(root->counter, 1);
3907 void tst_QGraphicsItem::handlesChildEvents3()
3909 QGraphicsScene scene;
3910 QEvent activate(QEvent::WindowActivate);
3911 QApplication::sendEvent(&scene, &activate);
3913 ChildEventTester *group2 = new ChildEventTester(QRectF(), 0);
3914 ChildEventTester *group1 = new ChildEventTester(QRectF(), group2);
3915 ChildEventTester *leaf = new ChildEventTester(QRectF(), group1);
3916 scene.addItem(group2);
3918 leaf->setFlag(QGraphicsItem::ItemIsFocusable);
3919 group1->setFlag(QGraphicsItem::ItemIsFocusable);
3920 group1->setHandlesChildEvents(true);
3921 group2->setFlag(QGraphicsItem::ItemIsFocusable);
3922 group2->setHandlesChildEvents(true);
3925 QVERIFY(leaf->hasFocus()); // group2 stole the event, but leaf still got focus
3926 QVERIFY(!group1->hasFocus());
3927 QVERIFY(!group2->hasFocus());
3928 QCOMPARE(leaf->counter, 0);
3929 QCOMPARE(group1->counter, 0);
3930 QCOMPARE(group2->counter, 1);
3933 QVERIFY(group1->hasFocus()); // group2 stole the event, but group1 still got focus
3934 QVERIFY(!leaf->hasFocus());
3935 QVERIFY(!group2->hasFocus());
3936 QCOMPARE(leaf->counter, 0);
3937 QCOMPARE(group1->counter, 0);
3938 QCOMPARE(group2->counter, 2);
3941 QVERIFY(group2->hasFocus()); // group2 stole the event, and now group2 also has focus
3942 QVERIFY(!leaf->hasFocus());
3943 QVERIFY(!group1->hasFocus());
3944 QCOMPARE(leaf->counter, 0);
3945 QCOMPARE(group1->counter, 0);
3946 QCOMPARE(group2->counter, 3);
3950 class ChildEventFilterTester : public ChildEventTester
3953 ChildEventFilterTester(const QRectF &rect, QGraphicsItem *parent = 0)
3954 : ChildEventTester(rect, parent), filter(QEvent::None)
3957 QEvent::Type filter;
3960 bool sceneEventFilter(QGraphicsItem *item, QEvent *event)
3963 if (event->type() == filter) {
3971 void tst_QGraphicsItem::filtersChildEvents()
3973 QGraphicsScene scene;
3974 ChildEventFilterTester *root = new ChildEventFilterTester(QRectF(0, 0, 10, 10));
3975 ChildEventFilterTester *filter = new ChildEventFilterTester(QRectF(10, 10, 10, 10), root);
3976 ChildEventTester *child = new ChildEventTester(QRectF(20, 20, 10, 10), filter);
3979 filter->setFiltersChildEvents(true);
3980 filter->filter = QEvent::GraphicsSceneMousePress;
3982 scene.addItem(root);
3984 QGraphicsView view(&scene);
3986 QVERIFY(QTest::qWaitForWindowExposed(&view));
3989 QGraphicsSceneMouseEvent pressEvent(QEvent::GraphicsSceneMousePress);
3990 QGraphicsSceneMouseEvent releaseEvent(QEvent::GraphicsSceneMouseRelease);
3992 // send event to child
3993 pressEvent.setButton(Qt::LeftButton);
3994 pressEvent.setScenePos(QPointF(25, 25));//child->mapToScene(5, 5));
3995 pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
3996 releaseEvent.setButton(Qt::LeftButton);
3997 releaseEvent.setScenePos(QPointF(25, 25));//child->mapToScene(5, 5));
3998 releaseEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
3999 QApplication::sendEvent(&scene, &pressEvent);
4000 QApplication::sendEvent(&scene, &releaseEvent);
4002 QTRY_COMPARE(child->counter, 1); // mouse release is not filtered
4003 QCOMPARE(filter->counter, 1); // mouse press is filtered
4004 QCOMPARE(root->counter, 0);
4006 // add another filter
4007 root->setFiltersChildEvents(true);
4008 root->filter = QEvent::GraphicsSceneMouseRelease;
4010 // send event to child
4011 QApplication::sendEvent(&scene, &pressEvent);
4012 QApplication::sendEvent(&scene, &releaseEvent);
4014 QCOMPARE(child->counter, 1);
4015 QCOMPARE(filter->counter, 2); // mouse press is filtered
4016 QCOMPARE(root->counter, 1); // mouse release is filtered
4018 // reparent to another sub-graph
4019 ChildEventTester *parent = new ChildEventTester(QRectF(10, 10, 10, 10), root);
4020 child->setParentItem(parent);
4022 // send event to child
4023 QApplication::sendEvent(&scene, &pressEvent);
4024 QApplication::sendEvent(&scene, &releaseEvent);
4026 QCOMPARE(child->counter, 2); // mouse press is _not_ filtered
4027 QCOMPARE(parent->counter, 0);
4028 QCOMPARE(filter->counter, 2);
4029 QCOMPARE(root->counter, 2); // mouse release is filtered
4032 void tst_QGraphicsItem::filtersChildEvents2()
4034 ChildEventFilterTester *root = new ChildEventFilterTester(QRectF(0, 0, 10, 10));
4035 root->setFiltersChildEvents(true);
4036 root->filter = QEvent::GraphicsSceneMousePress;
4037 QVERIFY(root->filtersChildEvents());
4039 ChildEventTester *child = new ChildEventTester(QRectF(0, 0, 10, 10), root);
4040 QVERIFY(!child->filtersChildEvents());
4042 ChildEventTester *child2 = new ChildEventTester(QRectF(0, 0, 10, 10));
4043 ChildEventTester *child3 = new ChildEventTester(QRectF(0, 0, 10, 10), child2);
4044 ChildEventTester *child4 = new ChildEventTester(QRectF(0, 0, 10, 10), child3);
4046 child2->setParentItem(root);
4047 QVERIFY(!child2->filtersChildEvents());
4048 QVERIFY(!child3->filtersChildEvents());
4049 QVERIFY(!child4->filtersChildEvents());
4051 QGraphicsScene scene;
4052 scene.addItem(root);
4054 QGraphicsView view(&scene);
4057 QVERIFY(QTest::qWaitForWindowExposed(&view));
4058 QApplication::processEvents();
4060 QMouseEvent event(QEvent::MouseButtonPress, view.mapFromScene(5, 5),
4061 view.viewport()->mapToGlobal(view.mapFromScene(5, 5)), Qt::LeftButton, 0, 0);
4062 QApplication::sendEvent(view.viewport(), &event);
4064 QTRY_COMPARE(root->counter, 1);
4065 QCOMPARE(child->counter, 0);
4066 QCOMPARE(child2->counter, 0);
4067 QCOMPARE(child3->counter, 0);
4068 QCOMPARE(child4->counter, 0);
4071 class CustomItem : public QGraphicsItem
4074 QRectF boundingRect() const
4075 { return QRectF(-110, -110, 220, 220); }
4077 void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
4079 for (int x = -100; x <= 100; x += 25)
4080 painter->drawLine(x, -100, x, 100);
4081 for (int y = -100; y <= 100; y += 25)
4082 painter->drawLine(-100, y, 100, y);
4084 QFont font = painter->font();
4085 font.setPointSize(4);
4086 painter->setFont(font);
4087 for (int x = -100; x < 100; x += 25) {
4088 for (int y = -100; y < 100; y += 25) {
4089 painter->drawText(QRectF(x, y, 25, 25), Qt::AlignCenter, QString("%1x%2").arg(x).arg(y));
4095 void tst_QGraphicsItem::ensureVisible()
4097 QGraphicsScene scene;
4098 scene.setSceneRect(-200, -200, 400, 400);
4099 QGraphicsItem *item = new CustomItem;
4100 scene.addItem(item);
4102 QGraphicsView view(&scene);
4103 view.setFixedSize(300, 300);
4105 QVERIFY(QTest::qWaitForWindowExposed(&view));
4107 for (int i = 0; i < 25; ++i) {
4108 view.scale(qreal(1.06), qreal(1.06));
4109 QApplication::processEvents();
4112 item->ensureVisible(-100, -100, 25, 25);
4115 for (int x = -100; x < 100; x += 25) {
4116 for (int y = -100; y < 100; y += 25) {
4117 int xmargin = rand() % 75;
4118 int ymargin = rand() % 75;
4119 item->ensureVisible(x, y, 25, 25, xmargin, ymargin);
4120 QApplication::processEvents();
4122 QPolygonF viewScenePoly;
4123 viewScenePoly << view.mapToScene(view.rect().topLeft())
4124 << view.mapToScene(view.rect().topRight())
4125 << view.mapToScene(view.rect().bottomRight())
4126 << view.mapToScene(view.rect().bottomLeft());
4128 QVERIFY(scene.items(viewScenePoly).contains(item));
4131 path.addPolygon(viewScenePoly);
4132 QVERIFY(path.contains(item->mapToScene(x + 12, y + 12)));
4134 QPolygonF viewScenePolyMinusMargins;
4135 viewScenePolyMinusMargins << view.mapToScene(view.rect().topLeft() + QPoint(xmargin, ymargin))
4136 << view.mapToScene(view.rect().topRight() + QPoint(-xmargin, ymargin))
4137 << view.mapToScene(view.rect().bottomRight() + QPoint(-xmargin, -ymargin))
4138 << view.mapToScene(view.rect().bottomLeft() + QPoint(xmargin, -ymargin));
4141 path2.addPolygon(viewScenePolyMinusMargins);
4142 QVERIFY(path2.contains(item->mapToScene(x + 12, y + 12)));
4146 item->ensureVisible(100, 100, 25, 25);
4150 #ifndef QTEST_NO_CURSOR
4151 void tst_QGraphicsItem::cursor()
4153 QGraphicsScene scene;
4154 QGraphicsRectItem *item1 = scene.addRect(QRectF(0, 0, 50, 50));
4155 QGraphicsRectItem *item2 = scene.addRect(QRectF(0, 0, 50, 50));
4156 item1->setPos(-100, 0);
4157 item2->setPos(50, 0);
4159 QVERIFY(!item1->hasCursor());
4160 QVERIFY(!item2->hasCursor());
4162 item1->setCursor(Qt::IBeamCursor);
4163 item2->setCursor(Qt::PointingHandCursor);
4165 QVERIFY(item1->hasCursor());
4166 QVERIFY(item2->hasCursor());
4168 item1->setCursor(QCursor());
4169 item2->setCursor(QCursor());
4171 QVERIFY(item1->hasCursor());
4172 QVERIFY(item2->hasCursor());
4174 item1->unsetCursor();
4175 item2->unsetCursor();
4177 QVERIFY(!item1->hasCursor());
4178 QVERIFY(!item2->hasCursor());
4180 item1->setCursor(Qt::IBeamCursor);
4181 item2->setCursor(Qt::PointingHandCursor);
4184 QGraphicsView view(&scene,&topLevel);
4185 view.setFixedSize(200, 100);
4187 QTest::mouseMove(&view, view.rect().center());
4191 QCursor cursor = view.viewport()->cursor();
4194 QMouseEvent event(QEvent::MouseMove, QPoint(100, 50), Qt::NoButton, 0, 0);
4195 QApplication::sendEvent(view.viewport(), &event);
4200 QCOMPARE(view.viewport()->cursor().shape(), cursor.shape());
4203 QTest::mouseMove(view.viewport(), view.mapFromScene(item1->sceneBoundingRect().center()));
4204 QMouseEvent event(QEvent::MouseMove, view.mapFromScene(item1->sceneBoundingRect().center()), Qt::NoButton, 0, 0);
4205 QApplication::sendEvent(view.viewport(), &event);
4208 QCOMPARE(view.viewport()->cursor().shape(), item1->cursor().shape());
4211 QTest::mouseMove(view.viewport(), view.mapFromScene(item2->sceneBoundingRect().center()));
4212 QMouseEvent event(QEvent::MouseMove, view.mapFromScene(item2->sceneBoundingRect().center()), Qt::NoButton, 0, 0);
4213 QApplication::sendEvent(view.viewport(), &event);
4218 QCOMPARE(view.viewport()->cursor().shape(), item2->cursor().shape());
4221 QTest::mouseMove(view.viewport(), view.rect().center());
4222 QMouseEvent event(QEvent::MouseMove, QPoint(100, 25), Qt::NoButton, 0, 0);
4223 QApplication::sendEvent(view.viewport(), &event);
4228 QCOMPARE(view.viewport()->cursor().shape(), cursor.shape());
4232 void tst_QGraphicsItem::textControlGetterSetter()
4234 QGraphicsTextItem *item = new QGraphicsTextItem;
4235 QVERIFY(item->textControl()->parent() == item);
4236 QPointer<QWidgetTextControl> control = item->textControl();
4240 item = new QGraphicsTextItem;
4242 QPointer<QWidgetTextControl> oldControl = control;
4243 control = new QWidgetTextControl;
4245 item->setTextControl(control);
4246 QVERIFY(item->textControl() == control);
4247 QVERIFY(!control->parent());
4248 QVERIFY(!oldControl);
4250 // set some text to give it a size, to test that
4251 // setTextControl (re)connects signals
4252 const QRectF oldBoundingRect = item->boundingRect();
4253 QVERIFY(oldBoundingRect.isValid());
4254 item->setPlainText("Some text");
4256 QVERIFY(item->boundingRect().isValid());
4257 QVERIFY(item->boundingRect() != oldBoundingRect);
4259 // test that on setting a control the item size
4261 oldControl = control;
4262 control = new QWidgetTextControl;
4263 control->setPlainText("foo!");
4264 item->setTextControl(control);
4265 QCOMPARE(item->boundingRect().size(), control->document()->documentLayout()->documentSize());
4267 QVERIFY(oldControl);
4276 void tst_QGraphicsItem::defaultItemTest_QGraphicsLineItem()
4278 QGraphicsLineItem item;
4279 QCOMPARE(item.line(), QLineF());
4280 QCOMPARE(item.pen(), QPen());
4281 QCOMPARE(item.shape(), QPainterPath());
4283 item.setPen(QPen(Qt::black, 1));
4284 QCOMPARE(item.pen(), QPen(Qt::black, 1));
4285 item.setLine(QLineF(0, 0, 10, 0));
4286 QCOMPARE(item.line(), QLineF(0, 0, 10, 0));
4287 QCOMPARE(item.boundingRect(), QRectF(-0.5, -0.5, 11, 1));
4288 QCOMPARE(item.shape().elementCount(), 11);
4291 path.moveTo(0, -0.5);
4292 path.lineTo(10, -0.5);
4293 path.lineTo(10.5, -0.5);
4294 path.lineTo(10.5, 0.5);
4295 path.lineTo(10, 0.5);
4296 path.lineTo(0, 0.5);
4297 path.lineTo(-0.5, 0.5);
4298 path.lineTo(-0.5, -0.5);
4299 path.lineTo(0, -0.5);
4302 path.closeSubpath();
4304 for (int i = 0; i < 11; ++i)
4305 QCOMPARE(QPointF(item.shape().elementAt(i)), QPointF(path.elementAt(i)));
4308 void tst_QGraphicsItem::defaultItemTest_QGraphicsPixmapItem()
4310 QGraphicsPixmapItem item;
4311 QVERIFY(item.pixmap().isNull());
4312 QCOMPARE(item.offset(), QPointF());
4313 QCOMPARE(item.transformationMode(), Qt::FastTransformation);
4315 QPixmap pixmap(300, 200);
4316 pixmap.fill(Qt::red);
4317 item.setPixmap(pixmap);
4318 QCOMPARE(item.pixmap(), pixmap);
4320 item.setTransformationMode(Qt::FastTransformation);
4321 QCOMPARE(item.transformationMode(), Qt::FastTransformation);
4322 item.setTransformationMode(Qt::SmoothTransformation);
4323 QCOMPARE(item.transformationMode(), Qt::SmoothTransformation);
4325 item.setOffset(-15, -15);
4326 QCOMPARE(item.offset(), QPointF(-15, -15));
4327 item.setOffset(QPointF(-10, -10));
4328 QCOMPARE(item.offset(), QPointF(-10, -10));
4330 QCOMPARE(item.boundingRect(), QRectF(-10, -10, 300, 200));
4333 void tst_QGraphicsItem::defaultItemTest_QGraphicsTextItem()
4335 QGraphicsTextItem *text = new QGraphicsTextItem;
4336 QVERIFY(!text->openExternalLinks());
4337 QVERIFY(text->textCursor().isNull());
4338 QCOMPARE(text->defaultTextColor(), QPalette().color(QPalette::Text));
4339 QVERIFY(text->document() != 0);
4340 QCOMPARE(text->font(), QApplication::font());
4341 QCOMPARE(text->textInteractionFlags(), Qt::TextInteractionFlags(Qt::NoTextInteraction));
4342 QCOMPARE(text->textWidth(), -1.0);
4343 QCOMPARE(text->toPlainText(), QString(""));
4345 QGraphicsScene scene;
4346 scene.addItem(text);
4347 text->setPlainText("Hello world");
4348 text->setFlag(QGraphicsItem::ItemIsMovable);
4351 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
4352 event.setScenePos(QPointF(1, 1));
4353 event.setButton(Qt::LeftButton);
4354 event.setButtons(Qt::LeftButton);
4355 QApplication::sendEvent(&scene, &event);
4356 QGraphicsSceneMouseEvent event2(QEvent::GraphicsSceneMouseMove);
4357 event2.setScenePos(QPointF(11, 11));
4358 event2.setButton(Qt::LeftButton);
4359 event2.setButtons(Qt::LeftButton);
4360 QApplication::sendEvent(&scene, &event2);
4363 QCOMPARE(text->pos(), QPointF(10, 10));
4365 text->setTextInteractionFlags(Qt::NoTextInteraction);
4366 QVERIFY(!(text->flags() & QGraphicsItem::ItemAcceptsInputMethod));
4367 text->setTextInteractionFlags(Qt::TextEditorInteraction);
4368 QCOMPARE(text->textInteractionFlags(), Qt::TextInteractionFlags(Qt::TextEditorInteraction));
4369 QVERIFY(text->flags() & QGraphicsItem::ItemAcceptsInputMethod);
4372 QGraphicsSceneMouseEvent event2(QEvent::GraphicsSceneMouseMove);
4373 event2.setScenePos(QPointF(21, 21));
4374 event2.setButton(Qt::LeftButton);
4375 event2.setButtons(Qt::LeftButton);
4376 QApplication::sendEvent(&scene, &event2);
4379 QCOMPARE(text->pos(), QPointF(20, 20)); // clicked on edge, item moved
4382 void tst_QGraphicsItem::defaultItemTest_QGraphicsEllipseItem()
4384 QGraphicsEllipseItem item;
4385 QVERIFY(item.rect().isNull());
4386 QVERIFY(item.boundingRect().isNull());
4387 QVERIFY(item.shape().isEmpty());
4388 QCOMPARE(item.spanAngle(), 360 * 16);
4389 QCOMPARE(item.startAngle(), 0);
4391 item.setRect(0, 0, 100, 100);
4392 QCOMPARE(item.boundingRect(), QRectF(0, 0, 100, 100));
4394 item.setSpanAngle(90 * 16);
4395 qFuzzyCompare(item.boundingRect().left(), qreal(50.0));
4396 qFuzzyCompare(item.boundingRect().top(), qreal(0.0));
4397 qFuzzyCompare(item.boundingRect().width(), qreal(50.0));
4398 qFuzzyCompare(item.boundingRect().height(), qreal(50.0));
4400 item.setPen(QPen(Qt::black, 1));
4401 QCOMPARE(item.boundingRect(), QRectF(49.5, -0.5, 51, 51));
4403 item.setSpanAngle(180 * 16);
4404 QCOMPARE(item.boundingRect(), QRectF(-0.5, -0.5, 101, 51));
4406 item.setSpanAngle(360 * 16);
4407 QCOMPARE(item.boundingRect(), QRectF(-0.5, -0.5, 101, 101));
4410 class ItemChangeTester : public QGraphicsRectItem
4414 { setFlag(ItemSendsGeometryChanges); clear(); }
4415 ItemChangeTester(QGraphicsItem *parent) : QGraphicsRectItem(parent)
4416 { setFlag(ItemSendsGeometryChanges); clear(); }
4420 itemChangeReturnValue = QVariant();
4421 itemSceneChangeTargetScene = 0;
4427 QVariant itemChangeReturnValue;
4428 QGraphicsScene *itemSceneChangeTargetScene;
4430 QList<GraphicsItemChange> changes;
4431 QList<QVariant> values;
4432 QList<QVariant> oldValues;
4434 QVariant itemChange(GraphicsItemChange change, const QVariant &value)
4439 case QGraphicsItem::ItemPositionChange:
4442 case QGraphicsItem::ItemPositionHasChanged:
4444 case QGraphicsItem::ItemMatrixChange: {
4446 variant.setValue<QMatrix>(matrix());
4447 oldValues << variant;
4450 case QGraphicsItem::ItemTransformChange: {
4452 variant.setValue<QTransform>(transform());
4453 oldValues << variant;
4456 case QGraphicsItem::ItemTransformHasChanged:
4458 case QGraphicsItem::ItemVisibleChange:
4459 oldValues << isVisible();
4461 case QGraphicsItem::ItemVisibleHasChanged:
4463 case QGraphicsItem::ItemEnabledChange:
4464 oldValues << isEnabled();
4466 case QGraphicsItem::ItemEnabledHasChanged:
4468 case QGraphicsItem::ItemSelectedChange:
4469 oldValues << isSelected();
4471 case QGraphicsItem::ItemSelectedHasChanged:
4473 case QGraphicsItem::ItemParentChange:
4474 oldValues << QVariant::fromValue<void *>(parentItem());
4476 case QGraphicsItem::ItemParentHasChanged:
4478 case QGraphicsItem::ItemChildAddedChange:
4479 oldValues << children().size();
4481 case QGraphicsItem::ItemChildRemovedChange:
4482 oldValues << children().size();
4484 case QGraphicsItem::ItemSceneChange:
4485 oldValues << QVariant::fromValue<QGraphicsScene *>(scene());
4486 if (itemSceneChangeTargetScene
4487 && qvariant_cast<QGraphicsScene *>(value)
4488 && itemSceneChangeTargetScene != qvariant_cast<QGraphicsScene *>(value)) {
4489 return QVariant::fromValue<QGraphicsScene *>(itemSceneChangeTargetScene);
4492 case QGraphicsItem::ItemSceneHasChanged:
4494 case QGraphicsItem::ItemCursorChange:
4495 #ifndef QTEST_NO_CURSOR
4496 oldValues << cursor();
4499 case QGraphicsItem::ItemCursorHasChanged:
4501 case QGraphicsItem::ItemToolTipChange:
4502 oldValues << toolTip();
4504 case QGraphicsItem::ItemToolTipHasChanged:
4506 case QGraphicsItem::ItemFlagsChange:
4507 oldValues << quint32(flags());
4509 case QGraphicsItem::ItemFlagsHaveChanged:
4511 case QGraphicsItem::ItemZValueChange:
4512 oldValues << zValue();
4514 case QGraphicsItem::ItemZValueHasChanged:
4516 case QGraphicsItem::ItemOpacityChange:
4517 oldValues << opacity();
4519 case QGraphicsItem::ItemOpacityHasChanged:
4521 case QGraphicsItem::ItemScenePositionHasChanged:
4523 case QGraphicsItem::ItemRotationChange:
4524 oldValues << rotation();
4526 case QGraphicsItem::ItemRotationHasChanged:
4528 case QGraphicsItem::ItemScaleChange:
4529 oldValues << scale();
4531 case QGraphicsItem::ItemScaleHasChanged:
4533 case QGraphicsItem::ItemTransformOriginPointChange:
4534 oldValues << transformOriginPoint();
4536 case QGraphicsItem::ItemTransformOriginPointHasChanged:
4539 return itemChangeReturnValue.isValid() ? itemChangeReturnValue : value;
4543 void tst_QGraphicsItem::itemChange()
4545 ItemChangeTester tester;
4546 tester.itemSceneChangeTargetScene = 0;
4548 ItemChangeTester testerHelper;
4549 QVERIFY(tester.changes.isEmpty());
4550 QVERIFY(tester.values.isEmpty());
4552 int changeCount = 0;
4554 // ItemEnabledChange
4555 tester.itemChangeReturnValue = true;
4556 tester.setEnabled(false);
4558 ++changeCount; // HasChanged
4559 QCOMPARE(tester.changes.size(), changeCount);
4560 QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemEnabledChange);
4561 QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemEnabledHasChanged);
4562 QCOMPARE(tester.values.at(tester.values.size() - 2), QVariant(false));
4563 QCOMPARE(tester.values.at(tester.values.size() - 1), QVariant(true));
4564 QCOMPARE(tester.oldValues.last(), QVariant(true));
4565 QCOMPARE(tester.isEnabled(), true);
4568 // ItemMatrixChange / ItemTransformHasChanged
4569 tester.itemChangeReturnValue.setValue<QMatrix>(QMatrix().rotate(90));
4570 tester.setMatrix(QMatrix().translate(50, 0), true);
4571 ++changeCount; // notification sent too
4572 QCOMPARE(tester.changes.size(), ++changeCount);
4573 QCOMPARE(int(tester.changes.at(tester.changes.size() - 2)), int(QGraphicsItem::ItemMatrixChange));
4574 QCOMPARE(int(tester.changes.last()), int(QGraphicsItem::ItemTransformHasChanged));
4575 QCOMPARE(qvariant_cast<QMatrix>(tester.values.at(tester.values.size() - 2)),
4576 QMatrix().translate(50, 0));
4577 QCOMPARE(tester.values.last(), QVariant(QTransform(QMatrix().rotate(90))));
4579 variant.setValue<QMatrix>(QMatrix());
4580 QCOMPARE(tester.oldValues.last(), variant);
4581 QCOMPARE(tester.matrix(), QMatrix().rotate(90));
4584 tester.resetTransform();
4586 ++changeCount; // notification sent too
4588 // ItemTransformChange / ItemTransformHasChanged
4589 tester.itemChangeReturnValue.setValue<QTransform>(QTransform().rotate(90));
4590 tester.translate(50, 0);
4591 ++changeCount; // notification sent too
4593 QCOMPARE(tester.changes.size(), changeCount);
4594 QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemTransformChange);
4595 QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemTransformHasChanged);
4596 QCOMPARE(qvariant_cast<QTransform>(tester.values.at(tester.values.size() - 2)),
4597 QTransform().translate(50, 0));
4598 QCOMPARE(qvariant_cast<QTransform>(tester.values.at(tester.values.size() - 1)),
4599 QTransform().rotate(90));
4601 variant.setValue<QTransform>(QTransform());
4602 QCOMPARE(tester.oldValues.last(), variant);
4603 QCOMPARE(tester.transform(), QTransform().rotate(90));
4606 // ItemPositionChange / ItemPositionHasChanged
4607 tester.itemChangeReturnValue = QPointF(42, 0);
4608 tester.setPos(0, 42);
4609 ++changeCount; // notification sent too
4611 QCOMPARE(tester.changes.size(), changeCount);
4612 QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemPositionChange);
4613 QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemPositionHasChanged);
4614 QCOMPARE(tester.values.at(tester.changes.size() - 2), QVariant(QPointF(0, 42)));
4615 QCOMPARE(tester.values.at(tester.changes.size() - 1), QVariant(QPointF(42, 0)));
4616 QCOMPARE(tester.oldValues.last(), QVariant(QPointF()));
4617 QCOMPARE(tester.pos(), QPointF(42, 0));
4620 // ItemZValueChange / ItemZValueHasChanged
4621 tester.itemChangeReturnValue = qreal(2.0);
4622 tester.setZValue(1.0);
4623 ++changeCount; // notification sent too
4625 QCOMPARE(tester.changes.size(), changeCount);
4626 QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemZValueChange);
4627 QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemZValueHasChanged);
4628 QCOMPARE(tester.values.at(tester.changes.size() - 2), QVariant(qreal(1.0)));
4629 QCOMPARE(tester.values.at(tester.changes.size() - 1), QVariant(qreal(2.0)));
4630 QCOMPARE(tester.oldValues.last(), QVariant(qreal(0.0)));
4631 QCOMPARE(tester.zValue(), qreal(2.0));
4634 // ItemRotationChange / ItemRotationHasChanged
4635 tester.itemChangeReturnValue = qreal(15.0);
4636 tester.setRotation(10.0);
4637 ++changeCount; // notification sent too
4639 QCOMPARE(tester.changes.size(), changeCount);
4640 QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemRotationChange);
4641 QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemRotationHasChanged);
4642 QCOMPARE(tester.values.at(tester.changes.size() - 2), QVariant(qreal(10.0)));
4643 QCOMPARE(tester.values.at(tester.changes.size() - 1), QVariant(qreal(15.0)));
4644 QCOMPARE(tester.oldValues.last(), QVariant(qreal(0.0)));
4645 QCOMPARE(tester.rotation(), qreal(15.0));
4648 // ItemScaleChange / ItemScaleHasChanged
4649 tester.itemChangeReturnValue = qreal(2.0);
4650 tester.setScale(1.5);
4651 ++changeCount; // notification sent too
4653 QCOMPARE(tester.changes.size(), changeCount);
4654 QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemScaleChange);
4655 QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemScaleHasChanged);
4656 QCOMPARE(tester.values.at(tester.changes.size() - 2), QVariant(qreal(1.5)));
4657 QCOMPARE(tester.values.at(tester.changes.size() - 1), QVariant(qreal(2.0)));
4658 QCOMPARE(tester.oldValues.last(), QVariant(qreal(1.0)));
4659 QCOMPARE(tester.scale(), qreal(2.0));
4662 // ItemTransformOriginPointChange / ItemTransformOriginPointHasChanged
4663 tester.itemChangeReturnValue = QPointF(2.0, 2.0);
4664 tester.setTransformOriginPoint(1.0, 1.0);
4665 ++changeCount; // notification sent too
4667 QCOMPARE(tester.changes.size(), changeCount);
4668 QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemTransformOriginPointChange);
4669 QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemTransformOriginPointHasChanged);
4670 QCOMPARE(tester.values.at(tester.changes.size() - 2), QVariant(QPointF(1.0, 1.0)));
4671 QCOMPARE(tester.values.at(tester.changes.size() - 1), QVariant(QPointF(2.0, 2.0)));
4672 QCOMPARE(tester.oldValues.last(), QVariant(QPointF(0.0, 0.0)));
4673 QCOMPARE(tester.transformOriginPoint(), QPointF(2.0, 2.0));
4677 tester.itemChangeReturnValue = QGraphicsItem::ItemIsSelectable;
4678 tester.setFlag(QGraphicsItem::ItemIsSelectable, false);
4679 QCOMPARE(tester.changes.size(), changeCount); // No change
4680 tester.setFlag(QGraphicsItem::ItemIsSelectable, true);
4682 ++changeCount; // ItemFlagsHasChanged
4683 QCOMPARE(tester.changes.size(), changeCount);
4684 QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemFlagsChange);
4685 QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemFlagsHaveChanged);
4686 QVariant expectedFlags = QVariant::fromValue<quint32>(QGraphicsItem::GraphicsItemFlags(QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemSendsGeometryChanges));
4687 QCOMPARE(tester.values.at(tester.values.size() - 2), expectedFlags);
4688 QCOMPARE(tester.values.at(tester.values.size() - 1), QVariant::fromValue<quint32>((quint32)QGraphicsItem::ItemIsSelectable));
4691 // ItemSelectedChange
4692 tester.setSelected(false);
4693 QCOMPARE(tester.changes.size(), changeCount); // No change :-)
4694 tester.itemChangeReturnValue = true;
4695 tester.setSelected(true);
4697 ++changeCount; // ItemSelectedHasChanged
4698 QCOMPARE(tester.changes.size(), changeCount);
4699 QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemSelectedChange);
4700 QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemSelectedHasChanged);
4701 QCOMPARE(tester.values.at(tester.values.size() - 2), QVariant(true));
4702 QCOMPARE(tester.values.at(tester.values.size() - 1), QVariant(true));
4703 QCOMPARE(tester.oldValues.last(), QVariant(false));
4704 QCOMPARE(tester.isSelected(), true);
4706 tester.itemChangeReturnValue = false;
4707 tester.setSelected(true);
4709 // the value hasn't changed to the itemChange return value
4710 // bacause itemChange is never called (true -> true is a noop).
4711 QCOMPARE(tester.isSelected(), true);
4714 // ItemVisibleChange
4715 tester.itemChangeReturnValue = false;
4716 QVERIFY(tester.isVisible());
4717 tester.setVisible(false);
4718 ++changeCount; // ItemVisibleChange
4719 ++changeCount; // ItemSelectedChange
4720 ++changeCount; // ItemSelectedHasChanged
4721 ++changeCount; // ItemVisibleHasChanged
4722 QCOMPARE(tester.changes.size(), changeCount);
4723 QCOMPARE(tester.changes.at(tester.changes.size() - 4), QGraphicsItem::ItemVisibleChange);
4724 QCOMPARE(tester.changes.at(tester.changes.size() - 3), QGraphicsItem::ItemSelectedChange);
4725 QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemSelectedHasChanged);
4726 QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemVisibleHasChanged);
4727 QCOMPARE(tester.values.at(tester.values.size() - 4), QVariant(false));
4728 QCOMPARE(tester.values.at(tester.values.size() - 3), QVariant(false));
4729 QCOMPARE(tester.values.at(tester.values.size() - 2), QVariant(false));
4730 QCOMPARE(tester.values.at(tester.values.size() - 1), QVariant(false));
4731 QCOMPARE(tester.isVisible(), false);
4735 tester.itemChangeReturnValue.setValue<QGraphicsItem *>(0);
4736 tester.setParentItem(&testerHelper);
4737 QCOMPARE(tester.changes.size(), ++changeCount);
4738 QCOMPARE(tester.changes.last(), QGraphicsItem::ItemParentChange);
4739 QCOMPARE(qvariant_cast<QGraphicsItem *>(tester.values.last()), (QGraphicsItem *)&testerHelper);
4740 QCOMPARE(qvariant_cast<QGraphicsItem *>(tester.oldValues.last()), (QGraphicsItem *)0);
4741 QCOMPARE(tester.parentItem(), (QGraphicsItem *)0);
4744 // ItemOpacityChange
4745 tester.itemChangeReturnValue = 1.0;
4746 tester.setOpacity(0.7);
4747 QCOMPARE(tester.changes.size(), ++changeCount);
4748 QCOMPARE(tester.changes.last(), QGraphicsItem::ItemOpacityChange);
4749 QVERIFY(qFuzzyCompare(qreal(tester.values.last().toDouble()), qreal(0.7)));
4750 QCOMPARE(tester.oldValues.last().toDouble(), double(1.0));
4751 QCOMPARE(tester.opacity(), qreal(1.0));
4752 tester.itemChangeReturnValue = 0.7;
4753 tester.setOpacity(0.7);
4754 ++changeCount; // ItemOpacityChange
4755 ++changeCount; // ItemOpacityHasChanged
4756 QCOMPARE(tester.changes.size(), changeCount);
4757 QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemOpacityChange);
4758 QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemOpacityHasChanged);
4759 QCOMPARE(tester.opacity(), qreal(0.7));
4762 // ItemChildAddedChange
4763 tester.itemChangeReturnValue.clear();
4764 testerHelper.setParentItem(&tester);
4765 QCOMPARE(tester.changes.size(), ++changeCount);
4766 QCOMPARE(tester.changes.last(), QGraphicsItem::ItemChildAddedChange);
4767 QCOMPARE(qvariant_cast<QGraphicsItem *>(tester.values.last()), (QGraphicsItem *)&testerHelper);
4770 // ItemChildRemovedChange 1
4771 testerHelper.setParentItem(0);
4772 QCOMPARE(tester.changes.size(), ++changeCount);
4773 QCOMPARE(tester.changes.last(), QGraphicsItem::ItemChildRemovedChange);
4774 QCOMPARE(qvariant_cast<QGraphicsItem *>(tester.values.last()), (QGraphicsItem *)&testerHelper);
4776 // ItemChildRemovedChange 1
4777 ItemChangeTester *test = new ItemChangeTester;
4778 test->itemSceneChangeTargetScene = 0;
4780 QGraphicsScene *scene = new QGraphicsScene;
4781 scene->addItem(test);
4782 count = test->changes.size();
4783 //We test here the fact that when a child is deleted the parent receive only one ItemChildRemovedChange
4784 QGraphicsRectItem *child = new QGraphicsRectItem(test);
4785 //We received ItemChildAddedChange
4786 QCOMPARE(test->changes.size(), ++count);
4787 QCOMPARE(test->changes.last(), QGraphicsItem::ItemChildAddedChange);
4790 QCOMPARE(test->changes.size(), ++count);
4791 QCOMPARE(test->changes.last(), QGraphicsItem::ItemChildRemovedChange);
4793 ItemChangeTester *childTester = new ItemChangeTester(test);
4794 //Changes contains all sceneHasChanged and so on, we don't want to test that
4795 int childCount = childTester->changes.size();
4796 //We received ItemChildAddedChange
4797 QCOMPARE(test->changes.size(), ++count);
4798 child = new QGraphicsRectItem(childTester);
4799 //We received ItemChildAddedChange
4800 QCOMPARE(childTester->changes.size(), ++childCount);
4801 QCOMPARE(childTester->changes.last(), QGraphicsItem::ItemChildAddedChange);
4802 //Delete the child of the top level with all its children
4805 QCOMPARE(test->changes.size(), ++count);
4806 QCOMPARE(test->changes.last(), QGraphicsItem::ItemChildRemovedChange);
4810 // ItemChildRemovedChange 2
4811 ItemChangeTester parent;
4812 ItemChangeTester *child = new ItemChangeTester;
4813 child->setParentItem(&parent);
4814 QCOMPARE(parent.changes.last(), QGraphicsItem::ItemChildAddedChange);
4815 QCOMPARE(qvariant_cast<QGraphicsItem *>(parent.values.last()), (QGraphicsItem *)child);
4817 QCOMPARE(parent.changes.last(), QGraphicsItem::ItemChildRemovedChange);
4818 QCOMPARE(qvariant_cast<QGraphicsItem *>(parent.values.last()), (QGraphicsItem *)child);
4821 // !!! Note: If this test crashes because of double-deletion, there's
4822 // a bug somewhere in QGraphicsScene or QGraphicsItem.
4825 QGraphicsScene scene;
4826 QGraphicsScene scene2;
4827 scene.addItem(&tester);
4828 ++changeCount; // ItemSceneChange (scene)
4829 ++changeCount; // ItemSceneHasChanged (scene)
4830 QCOMPARE(tester.changes.size(), changeCount);
4832 QCOMPARE(tester.scene(), &scene);
4833 QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemSceneChange);
4834 QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemSceneHasChanged);
4835 // Item's old value was 0
4836 // Item's current value is scene
4837 QCOMPARE(qvariant_cast<QGraphicsScene *>(tester.oldValues.last()), (QGraphicsScene *)0);
4838 QCOMPARE(qvariant_cast<QGraphicsScene *>(tester.values.last()), (QGraphicsScene *)&scene);
4839 scene2.addItem(&tester);
4840 ++changeCount; // ItemSceneChange (0) was: (scene)
4841 ++changeCount; // ItemSceneHasChanged (0)
4842 ++changeCount; // ItemSceneChange (scene2) was: (0)
4843 ++changeCount; // ItemSceneHasChanged (scene2)
4844 QCOMPARE(tester.changes.size(), changeCount);
4846 QCOMPARE(tester.scene(), &scene2);
4847 QCOMPARE(tester.changes.at(tester.changes.size() - 4), QGraphicsItem::ItemSceneChange);
4848 QCOMPARE(tester.changes.at(tester.changes.size() - 3), QGraphicsItem::ItemSceneHasChanged);
4849 QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemSceneChange);
4850 QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemSceneHasChanged);
4851 // Item's last old value was scene
4852 // Item's last current value is 0
4854 QCOMPARE(qvariant_cast<QGraphicsScene *>(tester.oldValues.at(tester.oldValues.size() - 2)), (QGraphicsScene *)&scene);
4855 QCOMPARE(qvariant_cast<QGraphicsScene *>(tester.oldValues.at(tester.oldValues.size() - 1)), (QGraphicsScene *)0);
4856 QCOMPARE(qvariant_cast<QGraphicsScene *>(tester.values.at(tester.values.size() - 4)), (QGraphicsScene *)0);
4857 QCOMPARE(qvariant_cast<QGraphicsScene *>(tester.values.at(tester.values.size() - 3)), (QGraphicsScene *)0);
4858 QCOMPARE(qvariant_cast<QGraphicsScene *>(tester.values.at(tester.values.size() - 2)), (QGraphicsScene *)&scene2);
4859 QCOMPARE(qvariant_cast<QGraphicsScene *>(tester.values.at(tester.values.size() - 1)), (QGraphicsScene *)&scene2);
4860 // Item's last old value was 0
4861 // Item's last current value is scene2
4862 QCOMPARE(qvariant_cast<QGraphicsScene *>(tester.oldValues.last()), (QGraphicsScene *)0);
4863 QCOMPARE(qvariant_cast<QGraphicsScene *>(tester.values.last()), (QGraphicsScene *)&scene2);
4865 scene2.removeItem(&tester);
4866 ++changeCount; // ItemSceneChange (0) was: (scene2)
4867 ++changeCount; // ItemSceneHasChanged (0)
4868 QCOMPARE(tester.changes.size(), changeCount);
4870 QCOMPARE(tester.scene(), (QGraphicsScene *)0);
4871 QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemSceneChange);
4872 QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemSceneHasChanged);
4873 // Item's last old value was scene2
4874 // Item's last current value is 0
4875 QCOMPARE(qvariant_cast<QGraphicsScene *>(tester.oldValues.last()), (QGraphicsScene *)&scene2);
4876 QCOMPARE(qvariant_cast<QGraphicsScene *>(tester.values.at(tester.values.size() - 2)), (QGraphicsScene *)0);
4877 QCOMPARE(qvariant_cast<QGraphicsScene *>(tester.values.at(tester.values.size() - 1)), (QGraphicsScene *)0);
4879 tester.itemSceneChangeTargetScene = &scene;
4880 scene2.addItem(&tester);
4881 ++changeCount; // ItemSceneChange (scene2) was: (0)
4882 ++changeCount; // ItemSceneChange (scene) was: (0)
4883 ++changeCount; // ItemSceneHasChanged (scene)
4884 QCOMPARE(tester.values.size(), changeCount);
4886 QCOMPARE(qvariant_cast<QGraphicsScene *>(tester.values.at(tester.values.size() - 3)), (QGraphicsScene *)&scene2);
4887 QCOMPARE(qvariant_cast<QGraphicsScene *>(tester.values.at(tester.values.size() - 2)), (QGraphicsScene *)&scene);
4888 QCOMPARE(qvariant_cast<QGraphicsScene *>(tester.values.at(tester.values.size() - 1)), (QGraphicsScene *)&scene);
4890 QCOMPARE(tester.scene(), &scene);
4891 tester.itemSceneChangeTargetScene = 0;
4892 tester.itemChangeReturnValue = QVariant();
4893 scene.removeItem(&tester);
4894 ++changeCount; // ItemSceneChange
4895 ++changeCount; // ItemSceneHasChanged
4896 QCOMPARE(tester.scene(), (QGraphicsScene *)0);
4899 // ItemToolTipChange/ItemToolTipHasChanged
4900 const QString toolTip(QLatin1String("I'm soo cool"));
4901 const QString overridenToolTip(QLatin1String("No, you are not soo cool"));
4902 tester.itemChangeReturnValue = overridenToolTip;
4903 tester.setToolTip(toolTip);
4904 ++changeCount; // ItemToolTipChange
4905 ++changeCount; // ItemToolTipHasChanged
4906 QCOMPARE(tester.changes.size(), changeCount);
4907 QCOMPARE(tester.changes.at(changeCount - 2), QGraphicsItem::ItemToolTipChange);
4908 QCOMPARE(tester.values.at(changeCount - 2).toString(), toolTip);
4909 QCOMPARE(tester.changes.at(changeCount - 1), QGraphicsItem::ItemToolTipHasChanged);
4910 QCOMPARE(tester.values.at(changeCount - 1).toString(), overridenToolTip);
4911 QCOMPARE(tester.toolTip(), overridenToolTip);
4912 tester.itemChangeReturnValue = QVariant();
4916 class EventFilterTesterItem : public QGraphicsLineItem
4919 QList<QEvent::Type> filteredEvents;
4920 QList<QGraphicsItem *> filteredEventReceivers;
4921 bool handlesSceneEvents;
4923 QList<QEvent::Type> receivedEvents;
4925 EventFilterTesterItem() : handlesSceneEvents(false) {}
4928 bool sceneEventFilter(QGraphicsItem *watched, QEvent *event)
4930 filteredEvents << event->type();
4931 filteredEventReceivers << watched;
4932 return handlesSceneEvents;
4935 bool sceneEvent(QEvent *event)
4937 return QGraphicsLineItem::sceneEvent(event);
4941 void tst_QGraphicsItem::sceneEventFilter()
4943 QGraphicsScene scene;
4945 QGraphicsView view(&scene);
4947 QApplication::setActiveWindow(&view);
4948 QVERIFY(QTest::qWaitForWindowActive(&view));
4950 QGraphicsTextItem *text1 = scene.addText(QLatin1String("Text1"));
4951 QGraphicsTextItem *text2 = scene.addText(QLatin1String("Text2"));
4952 QGraphicsTextItem *text3 = scene.addText(QLatin1String("Text3"));
4953 text1->setFlag(QGraphicsItem::ItemIsFocusable);
4954 text2->setFlag(QGraphicsItem::ItemIsFocusable);
4955 text3->setFlag(QGraphicsItem::ItemIsFocusable);
4957 EventFilterTesterItem *tester = new EventFilterTesterItem;
4958 scene.addItem(tester);
4960 QTRY_VERIFY(!text1->hasFocus());
4961 text1->installSceneEventFilter(tester);
4963 QTRY_VERIFY(text1->hasFocus());
4965 QCOMPARE(tester->filteredEvents.size(), 1);
4966 QCOMPARE(tester->filteredEvents.at(0), QEvent::FocusIn);
4967 QCOMPARE(tester->filteredEventReceivers.at(0), static_cast<QGraphicsItem *>(text1));
4969 text2->installSceneEventFilter(tester);
4970 text3->installSceneEventFilter(tester);
4975 QCOMPARE(tester->filteredEvents.size(), 5);
4976 QCOMPARE(tester->filteredEvents.at(1), QEvent::FocusOut);
4977 QCOMPARE(tester->filteredEventReceivers.at(1), static_cast<QGraphicsItem *>(text1));
4978 QCOMPARE(tester->filteredEvents.at(2), QEvent::FocusIn);
4979 QCOMPARE(tester->filteredEventReceivers.at(2), static_cast<QGraphicsItem *>(text2));
4980 QCOMPARE(tester->filteredEvents.at(3), QEvent::FocusOut);
4981 QCOMPARE(tester->filteredEventReceivers.at(3), static_cast<QGraphicsItem *>(text2));
4982 QCOMPARE(tester->filteredEvents.at(4), QEvent::FocusIn);
4983 QCOMPARE(tester->filteredEventReceivers.at(4), static_cast<QGraphicsItem *>(text3));
4985 text1->removeSceneEventFilter(tester);
4988 QCOMPARE(tester->filteredEvents.size(), 6);
4989 QCOMPARE(tester->filteredEvents.at(5), QEvent::FocusOut);
4990 QCOMPARE(tester->filteredEventReceivers.at(5), static_cast<QGraphicsItem *>(text3));
4992 tester->handlesSceneEvents = true;
4995 QCOMPARE(tester->filteredEvents.size(), 7);
4996 QCOMPARE(tester->filteredEvents.at(6), QEvent::FocusIn);
4997 QCOMPARE(tester->filteredEventReceivers.at(6), static_cast<QGraphicsItem *>(text2));
4999 QVERIFY(text2->hasFocus());
5001 //Let check if the items are correctly removed from the sceneEventFilters array
5002 //to avoid stale pointers.
5004 QGraphicsScene *anotherScene = new QGraphicsScene;
5005 QGraphicsTextItem *ti = anotherScene->addText("This is a test #1");
5007 QGraphicsTextItem *ti2 = anotherScene->addText("This is a test #2");
5008 QGraphicsTextItem *ti3 = anotherScene->addText("This is a test #3");
5009 gv.setScene(anotherScene);
5011 QVERIFY(QTest::qWaitForWindowExposed(&gv));
5013 ti->installSceneEventFilter(ti2);
5014 ti3->installSceneEventFilter(ti);
5017 QTest::mouseMove(gv.viewport(), gv.mapFromScene(ti->scenePos()));
5022 class GeometryChanger : public QGraphicsItem
5025 void changeGeometry()
5026 { prepareGeometryChange(); }
5029 void tst_QGraphicsItem::prepareGeometryChange()
5032 QGraphicsScene scene;
5033 QGraphicsItem *item = scene.addRect(QRectF(0, 0, 100, 100));
5034 QVERIFY(scene.items(QRectF(0, 0, 100, 100)).contains(item));
5035 ((GeometryChanger *)item)->changeGeometry();
5036 QVERIFY(scene.items(QRectF(0, 0, 100, 100)).contains(item));
5041 class PaintTester : public QGraphicsRectItem
5044 PaintTester() : widget(NULL), painted(0) { setRect(QRectF(10, 10, 20, 20));}
5046 void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *w)
5056 void tst_QGraphicsItem::paint()
5058 QGraphicsScene scene;
5060 PaintTester paintTester;
5061 scene.addItem(&paintTester);
5063 QGraphicsView view(&scene);
5065 QVERIFY(QTest::qWaitForWindowExposed(&view));
5066 QApplication::processEvents();
5068 //we try to switch the desktop: if it fails, we skip the test
5069 if (::SwitchDesktop( ::GetThreadDesktop( ::GetCurrentThreadId() ) ) == 0) {
5070 QSKIP("The Graphics View doesn't get the paint events");
5074 QTRY_COMPARE(paintTester.widget, view.viewport());
5078 QGraphicsScene scene2;
5079 QGraphicsView view2(&scene2);
5081 QVERIFY(QTest::qWaitForWindowExposed(&view2));
5084 PaintTester tester2;
5085 scene2.addItem(&tester2);
5086 qApp->processEvents();
5088 //First show one paint
5089 QTRY_COMPARE(tester2.painted, 1);
5091 //nominal case, update call paint
5093 qApp->processEvents();
5094 QTRY_VERIFY(tester2.painted == 2);
5096 //we remove the item from the scene, number of updates is still the same
5098 scene2.removeItem(&tester2);
5099 qApp->processEvents();
5100 QTRY_VERIFY(tester2.painted == 2);
5102 //We re-add the item, the number of paint should increase
5103 scene2.addItem(&tester2);
5105 qApp->processEvents();
5106 QTRY_VERIFY(tester2.painted == 3);
5109 class HarakiriItem : public QGraphicsRectItem
5112 HarakiriItem(int harakiriPoint)
5113 : QGraphicsRectItem(QRectF(0, 0, 100, 100)), harakiri(harakiriPoint)
5118 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
5120 QGraphicsRectItem::paint(painter, option, widget);
5121 if (harakiri == 0) {
5122 // delete unsupported since 4.5
5132 if (harakiri == 1 && n == 0) {
5133 // delete unsupported
5139 if (harakiri == 2 && n == 1) {
5146 void contextMenuEvent(QGraphicsSceneContextMenuEvent *)
5148 if (harakiri == 3) {
5154 void dragEnterEvent(QGraphicsSceneDragDropEvent *event)
5157 QGraphicsRectItem::dragEnterEvent(event);
5160 void dragLeaveEvent(QGraphicsSceneDragDropEvent *event)
5163 QGraphicsRectItem::dragLeaveEvent(event);
5166 void dragMoveEvent(QGraphicsSceneDragDropEvent *event)
5169 QGraphicsRectItem::dragMoveEvent(event);
5172 void dropEvent(QGraphicsSceneDragDropEvent *event)
5175 QGraphicsRectItem::dropEvent(event);
5178 void focusInEvent(QFocusEvent *)
5180 if (harakiri == 4) {
5186 void focusOutEvent(QFocusEvent *)
5188 if (harakiri == 5) {
5194 void hoverEnterEvent(QGraphicsSceneHoverEvent *)
5196 if (harakiri == 6) {
5202 void hoverLeaveEvent(QGraphicsSceneHoverEvent *)
5204 if (harakiri == 7) {
5210 void hoverMoveEvent(QGraphicsSceneHoverEvent *)
5212 if (harakiri == 8) {
5218 void inputMethodEvent(QInputMethodEvent *event)
5221 QGraphicsRectItem::inputMethodEvent(event);
5224 QVariant inputMethodQuery(Qt::InputMethodQuery query) const
5227 return QGraphicsRectItem::inputMethodQuery(query);
5230 QVariant itemChange(GraphicsItemChange change, const QVariant &value)
5232 // deletion not supported
5233 return QGraphicsRectItem::itemChange(change, value);
5236 void keyPressEvent(QKeyEvent *)
5238 if (harakiri == 9) {
5244 void keyReleaseEvent(QKeyEvent *)
5246 if (harakiri == 10) {
5252 void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *)
5254 if (harakiri == 11) {
5260 void mouseMoveEvent(QGraphicsSceneMouseEvent *)
5262 if (harakiri == 12) {
5268 void mousePressEvent(QGraphicsSceneMouseEvent *)
5270 if (harakiri == 13) {
5276 void mouseReleaseEvent(QGraphicsSceneMouseEvent *)
5278 if (harakiri == 14) {
5284 bool sceneEvent(QEvent *event)
5286 // deletion not supported
5287 return QGraphicsRectItem::sceneEvent(event);
5290 bool sceneEventFilter(QGraphicsItem *watched, QEvent *event)
5292 // deletion not supported
5293 return QGraphicsRectItem::sceneEventFilter(watched, event);
5296 void wheelEvent(QGraphicsSceneWheelEvent *)
5298 if (harakiri == 16) {
5308 int HarakiriItem::dead;
5310 void tst_QGraphicsItem::deleteItemInEventHandlers()
5312 for (int i = 0; i < 17; ++i) {
5313 QGraphicsScene scene;
5314 HarakiriItem *item = new HarakiriItem(i);
5315 item->setAcceptsHoverEvents(true);
5316 item->setFlag(QGraphicsItem::ItemIsFocusable);
5318 scene.addItem(item);
5320 item->installSceneEventFilter(item); // <- ehey!
5322 QGraphicsView view(&scene);
5325 qApp->processEvents();
5326 qApp->processEvents();
5332 QContextMenuEvent event(QContextMenuEvent::Other,
5333 view.mapFromScene(item->scenePos()));
5334 QCoreApplication::sendEvent(view.viewport(), &event);
5337 QTest::mouseMove(view.viewport(), view.mapFromScene(item->scenePos()));
5339 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item->scenePos()));
5341 QTest::mouseDClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item->scenePos()));
5343 QTest::mouseClick(view.viewport(), Qt::RightButton, 0, view.mapFromScene(item->scenePos()));
5345 QTest::mouseMove(view.viewport(), view.mapFromScene(item->scenePos() + QPointF(20, -20)));
5353 QTest::keyPress(view.viewport(), Qt::Key_A);
5355 QTest::keyRelease(view.viewport(), Qt::Key_A);
5357 QTest::keyPress(view.viewport(), Qt::Key_A);
5359 QTest::keyRelease(view.viewport(), Qt::Key_A);
5363 class ItemPaintsOutsideShape : public QGraphicsItem
5366 QRectF boundingRect() const
5368 return QRectF(0, 0, 100, 100);
5371 void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
5373 painter->fillRect(-50, -50, 200, 200, Qt::red);
5374 painter->fillRect(0, 0, 100, 100, Qt::blue);
5378 void tst_QGraphicsItem::itemClipsToShape()
5380 QGraphicsItem *clippedItem = new ItemPaintsOutsideShape;
5381 clippedItem->setFlag(QGraphicsItem::ItemClipsToShape);
5383 QGraphicsItem *unclippedItem = new ItemPaintsOutsideShape;
5384 unclippedItem->setPos(200, 0);
5386 QGraphicsScene scene(-50, -50, 400, 200);
5387 scene.addItem(clippedItem);
5388 scene.addItem(unclippedItem);
5390 QImage image(400, 200, QImage::Format_ARGB32_Premultiplied);
5392 QPainter painter(&image);
5393 painter.setRenderHint(QPainter::Antialiasing);
5394 scene.render(&painter);
5397 QCOMPARE(image.pixel(45, 100), QRgb(0));
5398 QCOMPARE(image.pixel(100, 45), QRgb(0));
5399 QCOMPARE(image.pixel(155, 100), QRgb(0));
5400 QCOMPARE(image.pixel(45, 155), QRgb(0));
5401 QCOMPARE(image.pixel(55, 100), QColor(Qt::blue).rgba());
5402 QCOMPARE(image.pixel(100, 55), QColor(Qt::blue).rgba());
5403 QCOMPARE(image.pixel(145, 100), QColor(Qt::blue).rgba());
5404 QCOMPARE(image.pixel(55, 145), QColor(Qt::blue).rgba());
5405 QCOMPARE(image.pixel(245, 100), QColor(Qt::red).rgba());
5406 QCOMPARE(image.pixel(300, 45), QColor(Qt::red).rgba());
5407 QCOMPARE(image.pixel(355, 100), QColor(Qt::red).rgba());
5408 QCOMPARE(image.pixel(245, 155), QColor(Qt::red).rgba());
5409 QCOMPARE(image.pixel(255, 100), QColor(Qt::blue).rgba());
5410 QCOMPARE(image.pixel(300, 55), QColor(Qt::blue).rgba());
5411 QCOMPARE(image.pixel(345, 100), QColor(Qt::blue).rgba());
5412 QCOMPARE(image.pixel(255, 145), QColor(Qt::blue).rgba());
5415 void tst_QGraphicsItem::itemClipsChildrenToShape()
5417 QGraphicsScene scene;
5418 QGraphicsItem *rect = scene.addRect(0, 0, 50, 50, QPen(Qt::NoPen), QBrush(Qt::yellow));
5420 QGraphicsItem *ellipse = scene.addEllipse(0, 0, 100, 100, QPen(Qt::NoPen), QBrush(Qt::green));
5421 ellipse->setParentItem(rect);
5423 QGraphicsItem *clippedEllipse = scene.addEllipse(0, 0, 50, 50, QPen(Qt::NoPen), QBrush(Qt::blue));
5424 clippedEllipse->setParentItem(ellipse);
5426 QGraphicsItem *clippedEllipse2 = scene.addEllipse(0, 0, 25, 25, QPen(Qt::NoPen), QBrush(Qt::red));
5427 clippedEllipse2->setParentItem(clippedEllipse);
5429 QGraphicsItem *clippedEllipse3 = scene.addEllipse(50, 50, 25, 25, QPen(Qt::NoPen), QBrush(Qt::red));
5430 clippedEllipse3->setParentItem(clippedEllipse);
5432 QVERIFY(!(ellipse->flags() & QGraphicsItem::ItemClipsChildrenToShape));
5433 ellipse->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
5434 QVERIFY((ellipse->flags() & QGraphicsItem::ItemClipsChildrenToShape));
5436 QImage image(100, 100, QImage::Format_ARGB32_Premultiplied);
5438 QPainter painter(&image);
5439 painter.setRenderHint(QPainter::Antialiasing);
5440 scene.render(&painter);
5443 QCOMPARE(image.pixel(16, 16), QColor(255, 0, 0).rgba());
5444 QCOMPARE(image.pixel(32, 32), QColor(0, 0, 255).rgba());
5445 QCOMPARE(image.pixel(50, 50), QColor(0, 255, 0).rgba());
5446 QCOMPARE(image.pixel(12, 12), QColor(255, 255, 0).rgba());
5447 QCOMPARE(image.pixel(60, 60), QColor(255, 0, 0).rgba());
5450 void tst_QGraphicsItem::itemClipsChildrenToShape2()
5452 QGraphicsRectItem *parent = new QGraphicsRectItem(QRectF(0, 0, 10, 10));
5453 QGraphicsEllipseItem *child1 = new QGraphicsEllipseItem(QRectF(50, 50, 100, 100));
5454 QGraphicsRectItem *child2 = new QGraphicsRectItem(QRectF(15, 15, 80, 80));
5456 child1->setParentItem(parent);
5457 child1->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
5458 child2->setParentItem(child1);
5460 parent->setBrush(Qt::blue);
5461 child1->setBrush(Qt::green);
5462 child2->setBrush(Qt::red);
5464 QGraphicsScene scene;
5465 scene.addItem(parent);
5467 QCOMPARE(scene.itemAt(5, 5), (QGraphicsItem *)parent);
5468 QCOMPARE(scene.itemAt(15, 5), (QGraphicsItem *)0);
5469 QCOMPARE(scene.itemAt(5, 15), (QGraphicsItem *)0);
5470 QCOMPARE(scene.itemAt(60, 60), (QGraphicsItem *)0);
5471 QCOMPARE(scene.itemAt(140, 60), (QGraphicsItem *)0);
5472 QCOMPARE(scene.itemAt(60, 140), (QGraphicsItem *)0);
5473 QCOMPARE(scene.itemAt(140, 140), (QGraphicsItem *)0);
5474 QCOMPARE(scene.itemAt(75, 75), (QGraphicsItem *)child2);
5475 QCOMPARE(scene.itemAt(75, 100), (QGraphicsItem *)child1);
5476 QCOMPARE(scene.itemAt(100, 75), (QGraphicsItem *)child1);
5478 QImage image(100, 100, QImage::Format_ARGB32_Premultiplied);
5480 QPainter painter(&image);
5481 scene.render(&painter);
5484 QCOMPARE(image.pixel(5, 5), QColor(0, 0, 255).rgba());
5485 QCOMPARE(image.pixel(5, 10), QRgb(0));
5486 QCOMPARE(image.pixel(10, 5), QRgb(0));
5487 QCOMPARE(image.pixel(40, 40), QRgb(0));
5488 QCOMPARE(image.pixel(90, 40), QRgb(0));
5489 QCOMPARE(image.pixel(40, 90), QRgb(0));
5490 QCOMPARE(image.pixel(95, 95), QRgb(0));
5491 QCOMPARE(image.pixel(50, 70), QColor(0, 255, 0).rgba());
5492 QCOMPARE(image.pixel(70, 50), QColor(0, 255, 0).rgba());
5493 QCOMPARE(image.pixel(50, 60), QColor(255, 0, 0).rgba());
5494 QCOMPARE(image.pixel(60, 50), QColor(255, 0, 0).rgba());
5497 void tst_QGraphicsItem::itemClipsChildrenToShape3()
5499 // Construct a scene with nested children, each 50 pixels offset from the elder.
5500 // Set a top-level clipping flag
5501 QGraphicsScene scene;
5502 QGraphicsRectItem *parent = scene.addRect( 0, 0, 150, 150 );
5503 QGraphicsRectItem *child = scene.addRect( 0, 0, 150, 150 );
5504 QGraphicsRectItem *grandchild = scene.addRect( 0, 0, 150, 150 );
5505 child->setParentItem(parent);
5506 grandchild->setParentItem(child);
5507 child->setPos( 50, 50 );
5508 grandchild->setPos( 50, 50 );
5509 parent->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
5511 QCOMPARE(scene.itemAt(25,25), (QGraphicsItem *)parent);
5512 QCOMPARE(scene.itemAt(75,75), (QGraphicsItem *)child);
5513 QCOMPARE(scene.itemAt(125,125), (QGraphicsItem *)grandchild);
5514 QCOMPARE(scene.itemAt(175,175), (QGraphicsItem *)0);
5516 // Move child to fully overlap the parent. The grandchild should
5517 // now occupy two-thirds of the scene
5518 child->prepareGeometryChange();
5519 child->setPos( 0, 0 );
5521 QCOMPARE(scene.itemAt(25,25), (QGraphicsItem *)child);
5522 QCOMPARE(scene.itemAt(75,75), (QGraphicsItem *)grandchild);
5523 QCOMPARE(scene.itemAt(125,125), (QGraphicsItem *)grandchild);
5524 QCOMPARE(scene.itemAt(175,175), (QGraphicsItem *)0);
5527 class MyProxyWidget : public QGraphicsProxyWidget
5530 MyProxyWidget(QGraphicsItem *parent) : QGraphicsProxyWidget(parent)
5535 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
5537 QGraphicsProxyWidget::paint(painter, option, widget);
5543 void tst_QGraphicsItem::itemClipsChildrenToShape4()
5545 QGraphicsScene scene;
5546 QGraphicsView view(&scene);
5548 QGraphicsWidget * outerWidget = new QGraphicsWidget();
5549 outerWidget->setFlag(QGraphicsItem::ItemClipsChildrenToShape, true);
5550 MyProxyWidget * innerWidget = new MyProxyWidget(outerWidget);
5551 QLabel * label = new QLabel();
5552 label->setText("Welcome back my friends to the show that never ends...");
5553 innerWidget->setWidget(label);
5554 view.resize(300, 300);
5555 scene.addItem(outerWidget);
5556 outerWidget->resize( 200, 100 );
5557 scene.addEllipse( 100, 100, 100, 50 ); // <-- this is important to trigger the right codepath*
5558 //now the label is shown
5559 outerWidget->setFlag(QGraphicsItem::ItemClipsChildrenToShape, false );
5560 QApplication::setActiveWindow(&view);
5562 QTRY_COMPARE(QApplication::activeWindow(), (QWidget *)&view);
5563 QTRY_COMPARE(innerWidget->painted, true);
5566 //#define DEBUG_ITEM_CLIPS_CHILDREN_TO_SHAPE_5
5567 static inline void renderSceneToImage(QGraphicsScene *scene, QImage *image, const QString &filename)
5570 QPainter painter(image);
5571 scene->render(&painter);
5573 #ifdef DEBUG_ITEM_CLIPS_CHILDREN_TO_SHAPE_5
5574 image->save(filename);
5580 void tst_QGraphicsItem::itemClipsChildrenToShape5()
5582 class ParentItem : public QGraphicsRectItem
5585 ParentItem(qreal x, qreal y, qreal width, qreal height)
5586 : QGraphicsRectItem(x, y, width, height) {}
5588 QPainterPath shape() const
5591 path.addRect(50, 50, 200, 200);
5596 ParentItem *parent = new ParentItem(0, 0, 300, 300);
5597 parent->setBrush(Qt::blue);
5598 parent->setOpacity(0.5);
5600 const QRegion parentRegion(0, 0, 300, 300);
5601 const QRegion clippedParentRegion = parentRegion & QRect(50, 50, 200, 200);
5602 QRegion childRegion;
5603 QRegion grandChildRegion;
5605 QGraphicsRectItem *topLeftChild = new QGraphicsRectItem(0, 0, 100, 100);
5606 topLeftChild->setBrush(Qt::red);
5607 topLeftChild->setParentItem(parent);
5608 childRegion += QRect(0, 0, 100, 100);
5610 QGraphicsRectItem *topRightChild = new QGraphicsRectItem(0, 0, 100, 100);
5611 topRightChild->setBrush(Qt::red);
5612 topRightChild->setParentItem(parent);
5613 topRightChild->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
5614 topRightChild->setPos(200, 0);
5615 childRegion += QRect(200, 0, 100, 100);
5617 QGraphicsRectItem *topRightGrandChild = new QGraphicsRectItem(0, 0, 100, 100);
5618 topRightGrandChild->setBrush(Qt::green);
5619 topRightGrandChild->setParentItem(topRightChild);
5620 topRightGrandChild->setPos(-40, 40);
5621 grandChildRegion += QRect(200 - 40, 0 + 40, 100, 100) & QRect(200, 0, 100, 100);
5623 QGraphicsRectItem *bottomLeftChild = new QGraphicsRectItem(0, 0, 100, 100);
5624 bottomLeftChild->setBrush(Qt::red);
5625 bottomLeftChild->setParentItem(parent);
5626 bottomLeftChild->setFlag(QGraphicsItem::ItemClipsToShape);
5627 bottomLeftChild->setPos(0, 200);
5628 childRegion += QRect(0, 200, 100, 100);
5630 QGraphicsRectItem *bottomLeftGrandChild = new QGraphicsRectItem(0, 0, 160, 160);
5631 bottomLeftGrandChild->setBrush(Qt::green);
5632 bottomLeftGrandChild->setParentItem(bottomLeftChild);
5633 bottomLeftGrandChild->setFlag(QGraphicsItem::ItemClipsToShape);
5634 bottomLeftGrandChild->setPos(0, -60);
5635 grandChildRegion += QRect(0, 200 - 60, 160, 160);
5637 QGraphicsRectItem *bottomRightChild = new QGraphicsRectItem(0, 0, 100, 100);
5638 bottomRightChild->setBrush(Qt::red);
5639 bottomRightChild->setParentItem(parent);
5640 bottomRightChild->setPos(200, 200);
5641 childRegion += QRect(200, 200, 100, 100);
5643 QPoint controlPoints[17] = {
5644 QPoint(5, 5) , QPoint(95, 5) , QPoint(205, 5) , QPoint(295, 5) ,
5645 QPoint(5, 95) , QPoint(95, 95) , QPoint(205, 95) , QPoint(295, 95) ,
5647 QPoint(5, 205), QPoint(95, 205), QPoint(205, 205), QPoint(295, 205),
5648 QPoint(5, 295), QPoint(95, 295), QPoint(205, 295), QPoint(295, 295),
5651 const QRegion clippedChildRegion = childRegion & QRect(50, 50, 200, 200);
5652 const QRegion clippedGrandChildRegion = grandChildRegion & QRect(50, 50, 200, 200);
5654 QGraphicsScene scene;
5655 scene.addItem(parent);
5656 QImage sceneImage(300, 300, QImage::Format_ARGB32);
5658 #define VERIFY_CONTROL_POINTS(pRegion, cRegion, gRegion) \
5659 for (int i = 0; i < 17; ++i) { \
5660 QPoint controlPoint = controlPoints[i]; \
5661 QRgb pixel = sceneImage.pixel(controlPoint.x(), controlPoint.y()); \
5662 if (pRegion.contains(controlPoint)) \
5663 QVERIFY(qBlue(pixel) != 0); \
5665 QVERIFY(qBlue(pixel) == 0); \
5666 if (cRegion.contains(controlPoint)) \
5667 QVERIFY(qRed(pixel) != 0); \
5669 QVERIFY(qRed(pixel) == 0); \
5670 if (gRegion.contains(controlPoint)) \
5671 QVERIFY(qGreen(pixel) != 0); \
5673 QVERIFY(qGreen(pixel) == 0); \
5676 const QList<QGraphicsItem *> children = parent->childItems();
5677 const int childrenCount = children.count();
5679 for (int i = 0; i < 5; ++i) {
5681 QString childString;
5684 // All children stacked in front.
5685 childString = QLatin1String("ChildrenInFront.png");
5686 foreach (QGraphicsItem *child, children)
5687 child->setFlag(QGraphicsItem::ItemStacksBehindParent, false);
5690 // All children stacked behind.
5691 childString = QLatin1String("ChildrenBehind.png");
5692 foreach (QGraphicsItem *child, children)
5693 child->setFlag(QGraphicsItem::ItemStacksBehindParent, true);
5696 // First half of the children behind, second half in front.
5697 childString = QLatin1String("FirstHalfBehind_SecondHalfInFront.png");
5698 for (int j = 0; j < childrenCount; ++j) {
5699 QGraphicsItem *child = children.at(j);
5700 child->setFlag(QGraphicsItem::ItemStacksBehindParent, (j < childrenCount / 2));
5704 // First half of the children in front, second half behind.
5705 childString = QLatin1String("FirstHalfInFront_SecondHalfBehind.png");
5706 for (int j = 0; j < childrenCount; ++j) {
5707 QGraphicsItem *child = children.at(j);
5708 child->setFlag(QGraphicsItem::ItemStacksBehindParent, (j >= childrenCount / 2));
5712 // Child2 and child4 behind, rest in front.
5713 childString = QLatin1String("Child2And4Behind_RestInFront.png");
5714 for (int j = 0; j < childrenCount; ++j) {
5715 QGraphicsItem *child = children.at(j);
5716 if (j == 1 || j == 3)
5717 child->setFlag(QGraphicsItem::ItemStacksBehindParent, true);
5719 child->setFlag(QGraphicsItem::ItemStacksBehindParent, false);
5723 qFatal("internal error");
5726 // Nothing is clipped.
5727 parent->setFlag(QGraphicsItem::ItemClipsChildrenToShape, false);
5728 parent->setFlag(QGraphicsItem::ItemClipsToShape, false);
5729 clipString = QLatin1String("nothingClipped_");
5730 renderSceneToImage(&scene, &sceneImage, clipString + childString);
5731 VERIFY_CONTROL_POINTS(parentRegion, childRegion, grandChildRegion);
5733 // Parent clips children to shape.
5734 parent->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
5735 clipString = QLatin1String("parentClipsChildrenToShape_");
5736 renderSceneToImage(&scene, &sceneImage, clipString + childString);
5737 VERIFY_CONTROL_POINTS(parentRegion, clippedChildRegion, clippedGrandChildRegion);
5739 // Parent clips itself and children to shape.
5740 parent->setFlag(QGraphicsItem::ItemClipsToShape);
5741 clipString = QLatin1String("parentClipsItselfAndChildrenToShape_");
5742 renderSceneToImage(&scene, &sceneImage, clipString + childString);
5743 VERIFY_CONTROL_POINTS(clippedParentRegion, clippedChildRegion, clippedGrandChildRegion);
5745 // Parent clips itself to shape.
5746 parent->setFlag(QGraphicsItem::ItemClipsChildrenToShape, false);
5747 clipString = QLatin1String("parentClipsItselfToShape_");
5748 renderSceneToImage(&scene, &sceneImage, clipString + childString);
5749 VERIFY_CONTROL_POINTS(clippedParentRegion, childRegion, grandChildRegion);
5753 void tst_QGraphicsItem::itemClipsTextChildToShape()
5755 // Construct a scene with a rect that clips its children, with one text
5756 // child that has text that exceeds the size of the rect.
5757 QGraphicsScene scene;
5758 QGraphicsItem *rect = scene.addRect(0, 0, 50, 50, QPen(Qt::black), Qt::black);
5759 rect->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
5760 QGraphicsTextItem *text = new QGraphicsTextItem("This is a long sentence that's wider than 50 pixels.");
5761 text->setParentItem(rect);
5763 // Render this scene to a transparent image.
5764 QRectF sr = scene.itemsBoundingRect();
5765 QImage image(sr.size().toSize(), QImage::Format_ARGB32_Premultiplied);
5767 QPainter painter(&image);
5768 scene.render(&painter);
5770 // Erase the area immediately underneath the rect.
5771 painter.setCompositionMode(QPainter::CompositionMode_Source);
5772 painter.fillRect(rect->sceneBoundingRect().translated(-sr.topLeft()).adjusted(-0.5, -0.5, 0.5, 0.5),
5776 // Check that you get a truly transparent image back (i.e., the text was
5777 // clipped away, so there should be no trails left after erasing only the
5779 QImage emptyImage(scene.itemsBoundingRect().size().toSize(), QImage::Format_ARGB32_Premultiplied);
5781 QCOMPARE(image, emptyImage);
5784 void tst_QGraphicsItem::itemClippingDiscovery()
5786 // A simple scene with an ellipse parent and two rect children, one a
5787 // child of the other.
5788 QGraphicsScene scene;
5789 QGraphicsEllipseItem *clipItem = scene.addEllipse(0, 0, 100, 100);
5790 QGraphicsRectItem *leftRectItem = scene.addRect(0, 0, 50, 100);
5791 QGraphicsRectItem *rightRectItem = scene.addRect(50, 0, 50, 100);
5792 leftRectItem->setParentItem(clipItem);
5793 rightRectItem->setParentItem(clipItem);
5795 // The rects item are both visible at these points.
5796 QCOMPARE(scene.itemAt(10, 10), (QGraphicsItem *)leftRectItem);
5797 QCOMPARE(scene.itemAt(90, 90), (QGraphicsItem *)rightRectItem);
5799 // The ellipse clips the rects now.
5800 clipItem->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
5802 // The rect items are no longer visible at these points.
5803 QCOMPARE(scene.itemAt(10, 10), (QGraphicsItem *)0);
5804 if (sizeof(qreal) != sizeof(double))
5805 QSKIP("This fails due to internal rounding errors");
5806 QCOMPARE(scene.itemAt(90, 90), (QGraphicsItem *)0);
5809 void tst_QGraphicsItem::ancestorFlags()
5811 QGraphicsItem *level1 = new QGraphicsRectItem;
5812 QGraphicsItem *level21 = new QGraphicsRectItem;
5813 level21->setParentItem(level1);
5814 QGraphicsItem *level22 = new QGraphicsRectItem;
5815 level22->setParentItem(level1);
5816 QGraphicsItem *level31 = new QGraphicsRectItem;
5817 level31->setParentItem(level21);
5818 QGraphicsItem *level32 = new QGraphicsRectItem;
5819 level32->setParentItem(level21);
5821 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
5822 QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
5823 QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
5824 QCOMPARE(int(level31->d_ptr->ancestorFlags), 0);
5825 QCOMPARE(int(level32->d_ptr->ancestorFlags), 0);
5827 // HandlesChildEvents: 1) Root level sets a flag
5828 level1->setHandlesChildEvents(true);
5829 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
5830 QCOMPARE(int(level21->d_ptr->ancestorFlags), 1);
5831 QCOMPARE(int(level22->d_ptr->ancestorFlags), 1);
5832 QCOMPARE(int(level31->d_ptr->ancestorFlags), 1);
5833 QCOMPARE(int(level32->d_ptr->ancestorFlags), 1);
5835 // HandlesChildEvents: 2) Root level set it again
5836 level1->setHandlesChildEvents(true);
5837 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
5838 QCOMPARE(int(level21->d_ptr->ancestorFlags), 1);
5839 QCOMPARE(int(level22->d_ptr->ancestorFlags), 1);
5840 QCOMPARE(int(level31->d_ptr->ancestorFlags), 1);
5841 QCOMPARE(int(level32->d_ptr->ancestorFlags), 1);
5843 // HandlesChildEvents: 3) Root level unsets a flag
5844 level1->setHandlesChildEvents(false);
5845 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
5846 QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
5847 QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
5848 QCOMPARE(int(level31->d_ptr->ancestorFlags), 0);
5849 QCOMPARE(int(level32->d_ptr->ancestorFlags), 0);
5851 // HandlesChildEvents: 4) Child item sets a flag
5852 level21->setHandlesChildEvents(true);
5853 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
5854 QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
5855 QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
5856 QCOMPARE(int(level31->d_ptr->ancestorFlags), 1);
5857 QCOMPARE(int(level32->d_ptr->ancestorFlags), 1);
5859 // HandlesChildEvents: 5) Parent item sets a flag
5860 level1->setHandlesChildEvents(true);
5861 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
5862 QCOMPARE(int(level21->d_ptr->ancestorFlags), 1);
5863 QCOMPARE(int(level22->d_ptr->ancestorFlags), 1);
5864 QCOMPARE(int(level31->d_ptr->ancestorFlags), 1);
5865 QCOMPARE(int(level32->d_ptr->ancestorFlags), 1);
5867 // HandlesChildEvents: 6) Child item unsets a flag
5868 level21->setHandlesChildEvents(false);
5869 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
5870 QCOMPARE(int(level21->d_ptr->ancestorFlags), 1);
5871 QCOMPARE(int(level22->d_ptr->ancestorFlags), 1);
5872 QCOMPARE(int(level31->d_ptr->ancestorFlags), 1);
5873 QCOMPARE(int(level32->d_ptr->ancestorFlags), 1);
5875 // HandlesChildEvents: 7) Parent item unsets a flag
5876 level21->setHandlesChildEvents(true);
5877 level1->setHandlesChildEvents(false);
5878 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
5879 QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
5880 QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
5881 QCOMPARE(int(level31->d_ptr->ancestorFlags), 1);
5882 QCOMPARE(int(level32->d_ptr->ancestorFlags), 1);
5884 // Reparent the child to root
5885 level21->setParentItem(0);
5886 QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
5887 QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
5888 QCOMPARE(int(level31->d_ptr->ancestorFlags), 1);
5889 QCOMPARE(int(level32->d_ptr->ancestorFlags), 1);
5891 // Reparent the child to level1 again.
5892 level1->setHandlesChildEvents(true);
5893 level21->setParentItem(level1);
5894 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
5895 QCOMPARE(int(level21->d_ptr->ancestorFlags), 1);
5896 QCOMPARE(int(level22->d_ptr->ancestorFlags), 1);
5897 QCOMPARE(int(level31->d_ptr->ancestorFlags), 1);
5898 QCOMPARE(int(level32->d_ptr->ancestorFlags), 1);
5900 // Reparenting level31 back to level1.
5901 level31->setParentItem(level1);
5902 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
5903 QCOMPARE(int(level21->d_ptr->ancestorFlags), 1);
5904 QCOMPARE(int(level22->d_ptr->ancestorFlags), 1);
5905 QCOMPARE(int(level31->d_ptr->ancestorFlags), 1);
5906 QCOMPARE(int(level32->d_ptr->ancestorFlags), 1);
5908 // Reparenting level31 back to level21.
5909 level31->setParentItem(0);
5910 QCOMPARE(int(level31->d_ptr->ancestorFlags), 0);
5911 level31->setParentItem(level21);
5912 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
5913 QCOMPARE(int(level21->d_ptr->ancestorFlags), 1);
5914 QCOMPARE(int(level22->d_ptr->ancestorFlags), 1);
5915 QCOMPARE(int(level31->d_ptr->ancestorFlags), 1);
5916 QCOMPARE(int(level32->d_ptr->ancestorFlags), 1);
5918 // Level1 doesn't handle child events
5919 level1->setHandlesChildEvents(false);
5920 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
5921 QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
5922 QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
5923 QCOMPARE(int(level31->d_ptr->ancestorFlags), 1);
5924 QCOMPARE(int(level32->d_ptr->ancestorFlags), 1);
5926 // Nobody handles child events
5927 level21->setHandlesChildEvents(false);
5929 for (int i = 0; i < 2; ++i) {
5930 QGraphicsItem::GraphicsItemFlag flag = !i ? QGraphicsItem::ItemClipsChildrenToShape
5931 : QGraphicsItem::ItemIgnoresTransformations;
5932 int ancestorFlag = !i ? QGraphicsItemPrivate::AncestorClipsChildren
5933 : QGraphicsItemPrivate::AncestorIgnoresTransformations;
5935 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
5936 QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
5937 QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
5938 QCOMPARE(int(level31->d_ptr->ancestorFlags), 0);
5939 QCOMPARE(int(level32->d_ptr->ancestorFlags), 0);
5941 // HandlesChildEvents: 1) Root level sets a flag
5942 level1->setFlag(flag, true);
5943 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
5944 QCOMPARE(int(level21->d_ptr->ancestorFlags), ancestorFlag);
5945 QCOMPARE(int(level22->d_ptr->ancestorFlags), ancestorFlag);
5946 QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag);
5947 QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag);
5949 // HandlesChildEvents: 2) Root level set it again
5950 level1->setFlag(flag, true);
5951 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
5952 QCOMPARE(int(level21->d_ptr->ancestorFlags), ancestorFlag);
5953 QCOMPARE(int(level22->d_ptr->ancestorFlags), ancestorFlag);
5954 QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag);
5955 QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag);
5957 // HandlesChildEvents: 3) Root level unsets a flag
5958 level1->setFlag(flag, false);
5959 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
5960 QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
5961 QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
5962 QCOMPARE(int(level31->d_ptr->ancestorFlags), 0);
5963 QCOMPARE(int(level32->d_ptr->ancestorFlags), 0);
5965 // HandlesChildEvents: 4) Child item sets a flag
5966 level21->setFlag(flag, true);
5967 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
5968 QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
5969 QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
5970 QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag);
5971 QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag);
5973 // HandlesChildEvents: 5) Parent item sets a flag
5974 level1->setFlag(flag, true);
5975 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
5976 QCOMPARE(int(level21->d_ptr->ancestorFlags), ancestorFlag);
5977 QCOMPARE(int(level22->d_ptr->ancestorFlags), ancestorFlag);
5978 QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag);
5979 QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag);
5981 // HandlesChildEvents: 6) Child item unsets a flag
5982 level21->setFlag(flag, false);
5983 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
5984 QCOMPARE(int(level21->d_ptr->ancestorFlags), ancestorFlag);
5985 QCOMPARE(int(level22->d_ptr->ancestorFlags), ancestorFlag);
5986 QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag);
5987 QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag);
5989 // HandlesChildEvents: 7) Parent item unsets a flag
5990 level21->setFlag(flag, true);
5991 level1->setFlag(flag, false);
5992 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
5993 QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
5994 QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
5995 QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag);
5996 QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag);
5998 // Reparent the child to root
5999 level21->setParentItem(0);
6000 QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
6001 QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
6002 QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag);
6003 QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag);
6005 // Reparent the child to level1 again.
6006 level1->setFlag(flag, true);
6007 level21->setParentItem(level1);
6008 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
6009 QCOMPARE(int(level21->d_ptr->ancestorFlags), ancestorFlag);
6010 QCOMPARE(int(level22->d_ptr->ancestorFlags), ancestorFlag);
6011 QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag);
6012 QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag);
6014 // Reparenting level31 back to level1.
6015 level31->setParentItem(level1);
6016 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
6017 QCOMPARE(int(level21->d_ptr->ancestorFlags), ancestorFlag);
6018 QCOMPARE(int(level22->d_ptr->ancestorFlags), ancestorFlag);
6019 QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag);
6020 QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag);
6022 // Reparenting level31 back to level21.
6023 level31->setParentItem(0);
6024 QCOMPARE(int(level31->d_ptr->ancestorFlags), 0);
6025 level31->setParentItem(level21);
6026 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
6027 QCOMPARE(int(level21->d_ptr->ancestorFlags), ancestorFlag);
6028 QCOMPARE(int(level22->d_ptr->ancestorFlags), ancestorFlag);
6029 QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag);
6030 QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag);
6032 // Level1 doesn't handle child events
6033 level1->setFlag(flag, false);
6034 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
6035 QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
6036 QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
6037 QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag);
6038 QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag);
6040 // Nobody handles child events
6041 level21->setFlag(flag, false);
6042 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
6043 QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
6044 QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
6045 QCOMPARE(int(level31->d_ptr->ancestorFlags), 0);
6046 QCOMPARE(int(level32->d_ptr->ancestorFlags), 0);
6052 void tst_QGraphicsItem::untransformable()
6054 QGraphicsItem *item1 = new QGraphicsEllipseItem(QRectF(-50, -50, 100, 100));
6055 item1->setZValue(1);
6056 item1->setFlag(QGraphicsItem::ItemIgnoresTransformations);
6058 ((QGraphicsEllipseItem *)item1)->setBrush(Qt::red);
6060 QGraphicsItem *item2 = new QGraphicsEllipseItem(QRectF(-50, -50, 100, 100));
6061 item2->setParentItem(item1);
6063 item2->setPos(100, 0);
6064 ((QGraphicsEllipseItem *)item2)->setBrush(Qt::green);
6066 QGraphicsItem *item3 = new QGraphicsEllipseItem(QRectF(-50, -50, 100, 100));
6067 item3->setParentItem(item2);
6068 item3->setPos(100, 0);
6069 ((QGraphicsEllipseItem *)item3)->setBrush(Qt::blue);
6071 QGraphicsScene scene(-500, -500, 1000, 1000);
6072 scene.addItem(item1);
6075 QGraphicsView view(&scene,&topLevel);
6076 view.resize(300, 300);
6079 view.centerOn(0, 0);
6081 // Painting with the DiagCrossPattern is really slow on Mac
6082 // when zoomed out. (The test times out). Task to fix is 155567.
6083 #if !defined(Q_OS_MAC) || 1
6084 view.setBackgroundBrush(QBrush(Qt::black, Qt::DiagCrossPattern));
6087 QVERIFY(QTest::qWaitForWindowExposed(&topLevel));
6089 for (int i = 0; i < 10; ++i) {
6090 QPoint center = view.viewport()->rect().center();
6091 QCOMPARE(view.itemAt(center), item1);
6092 QCOMPARE(view.itemAt(center - QPoint(40, 0)), item1);
6093 QCOMPARE(view.itemAt(center - QPoint(-40, 0)), item1);
6094 QCOMPARE(view.itemAt(center - QPoint(0, 40)), item1);
6095 QCOMPARE(view.itemAt(center - QPoint(0, -40)), item1);
6097 center += QPoint(70, 70);
6098 QCOMPARE(view.itemAt(center - QPoint(40, 0)), item2);
6099 QCOMPARE(view.itemAt(center - QPoint(-40, 0)), item2);
6100 QCOMPARE(view.itemAt(center - QPoint(0, 40)), item2);
6101 QCOMPARE(view.itemAt(center - QPoint(0, -40)), item2);
6103 center += QPoint(0, 100);
6104 QCOMPARE(view.itemAt(center - QPoint(40, 0)), item3);
6105 QCOMPARE(view.itemAt(center - QPoint(-40, 0)), item3);
6106 QCOMPARE(view.itemAt(center - QPoint(0, 40)), item3);
6107 QCOMPARE(view.itemAt(center - QPoint(0, -40)), item3);
6109 view.scale(0.5, 0.5);
6111 view.shear(qreal(0.01), qreal(0.01));
6112 view.translate(10, 10);
6117 class ContextMenuItem : public QGraphicsRectItem
6121 : ignoreEvent(true), gotEvent(false), eventWasAccepted(false)
6125 bool eventWasAccepted;
6127 void contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
6130 eventWasAccepted = event->isAccepted();
6136 void tst_QGraphicsItem::contextMenuEventPropagation()
6138 ContextMenuItem *bottomItem = new ContextMenuItem;
6139 bottomItem->setRect(0, 0, 100, 100);
6140 ContextMenuItem *topItem = new ContextMenuItem;
6141 topItem->setParentItem(bottomItem);
6142 topItem->setRect(0, 0, 100, 100);
6144 QGraphicsScene scene;
6146 QGraphicsView view(&scene);
6147 view.setAlignment(Qt::AlignLeft | Qt::AlignTop);
6149 view.resize(200, 200);
6150 QVERIFY(QTest::qWaitForWindowExposed(&view));
6153 QContextMenuEvent event(QContextMenuEvent::Mouse, QPoint(10, 10),
6154 view.viewport()->mapToGlobal(QPoint(10, 10)));
6156 QApplication::sendEvent(view.viewport(), &event);
6157 QVERIFY(!event.isAccepted());
6159 scene.addItem(bottomItem);
6160 topItem->ignoreEvent = true;
6161 bottomItem->ignoreEvent = true;
6163 QApplication::sendEvent(view.viewport(), &event);
6164 QVERIFY(!event.isAccepted());
6165 QCOMPARE(topItem->gotEvent, true);
6166 QCOMPARE(topItem->eventWasAccepted, true);
6167 QCOMPARE(bottomItem->gotEvent, true);
6168 QCOMPARE(bottomItem->eventWasAccepted, true);
6170 topItem->ignoreEvent = false;
6171 topItem->gotEvent = false;
6172 bottomItem->gotEvent = false;
6174 QApplication::sendEvent(view.viewport(), &event);
6175 QVERIFY(event.isAccepted());
6176 QCOMPARE(topItem->gotEvent, true);
6177 QCOMPARE(bottomItem->gotEvent, false);
6178 QCOMPARE(topItem->eventWasAccepted, true);
6181 void tst_QGraphicsItem::itemIsMovable()
6183 QGraphicsRectItem *rect = new QGraphicsRectItem(-50, -50, 100, 100);
6184 rect->setFlag(QGraphicsItem::ItemIsMovable);
6186 QGraphicsScene scene;
6187 scene.addItem(rect);
6190 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
6191 event.setButton(Qt::LeftButton);
6192 event.setButtons(Qt::LeftButton);
6193 qApp->sendEvent(&scene, &event);
6196 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseMove);
6197 event.setButton(Qt::LeftButton);
6198 event.setButtons(Qt::LeftButton);
6199 qApp->sendEvent(&scene, &event);
6201 QCOMPARE(rect->pos(), QPointF(0, 0));
6203 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseMove);
6204 event.setButtons(Qt::LeftButton);
6205 event.setScenePos(QPointF(10, 10));
6206 qApp->sendEvent(&scene, &event);
6208 QCOMPARE(rect->pos(), QPointF(10, 10));
6210 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseMove);
6211 event.setButtons(Qt::RightButton);
6212 event.setScenePos(QPointF(20, 20));
6213 qApp->sendEvent(&scene, &event);
6215 QCOMPARE(rect->pos(), QPointF(10, 10));
6217 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseMove);
6218 event.setButtons(Qt::LeftButton);
6219 event.setScenePos(QPointF(30, 30));
6220 qApp->sendEvent(&scene, &event);
6222 QCOMPARE(rect->pos(), QPointF(30, 30));
6225 class ItemAddScene : public QGraphicsScene
6231 QTimer::singleShot(500, this, SLOT(newTextItem()));
6238 QGraphicsItem *item = new QGraphicsTextItem("This item will not ensure that it's visible", 0);
6239 item->setPos(.0, .0);
6244 void tst_QGraphicsItem::task141694_textItemEnsureVisible()
6247 scene.setSceneRect(-1000, -1000, 2000, 2000);
6249 QGraphicsView view(&scene);
6250 view.setFixedSize(200, 200);
6252 QVERIFY(QTest::qWaitForWindowExposed(&view));
6254 view.ensureVisible(-1000, -1000, 5, 5);
6255 int hscroll = view.horizontalScrollBar()->value();
6256 int vscroll = view.verticalScrollBar()->value();
6260 // This should not cause the view to scroll
6261 QTRY_COMPARE(view.horizontalScrollBar()->value(), hscroll);
6262 QCOMPARE(view.verticalScrollBar()->value(), vscroll);
6265 void tst_QGraphicsItem::task128696_textItemEnsureMovable()
6267 QGraphicsTextItem *item = new QGraphicsTextItem;
6268 item->setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
6269 item->setTextInteractionFlags(Qt::TextEditorInteraction);
6270 item->setPlainText("abc de\nf ghi\n j k l");
6272 QGraphicsScene scene;
6273 scene.setSceneRect(-100, -100, 200, 200);
6274 scene.addItem(item);
6276 QGraphicsView view(&scene);
6277 view.setFixedSize(200, 200);
6280 QGraphicsSceneMouseEvent event1(QEvent::GraphicsSceneMousePress);
6281 event1.setScenePos(QPointF(0, 0));
6282 event1.setButton(Qt::LeftButton);
6283 event1.setButtons(Qt::LeftButton);
6284 QApplication::sendEvent(&scene, &event1);
6285 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)item);
6287 QGraphicsSceneMouseEvent event2(QEvent::GraphicsSceneMouseMove);
6288 event2.setScenePos(QPointF(10, 10));
6289 event2.setButton(Qt::LeftButton);
6290 event2.setButtons(Qt::LeftButton);
6291 QApplication::sendEvent(&scene, &event2);
6292 QCOMPARE(item->pos(), QPointF(10, 10));
6295 void tst_QGraphicsItem::task177918_lineItemUndetected()
6297 QGraphicsScene scene;
6298 QGraphicsLineItem *line = scene.addLine(10, 10, 10, 10);
6299 QCOMPARE(line->boundingRect(), QRectF(10, 10, 0, 0));
6301 QVERIFY(!scene.items(9, 9, 2, 2, Qt::IntersectsItemShape).isEmpty());
6302 QVERIFY(!scene.items(9, 9, 2, 2, Qt::ContainsItemShape).isEmpty());
6303 QVERIFY(!scene.items(9, 9, 2, 2, Qt::IntersectsItemBoundingRect).isEmpty());
6304 QVERIFY(!scene.items(9, 9, 2, 2, Qt::ContainsItemBoundingRect).isEmpty());
6307 void tst_QGraphicsItem::task240400_clickOnTextItem_data()
6309 QTest::addColumn<int>("flags");
6310 QTest::addColumn<int>("textFlags");
6311 QTest::newRow("editor, noflags") << 0 << int(Qt::TextEditorInteraction);
6312 QTest::newRow("editor, movable") << int(QGraphicsItem::ItemIsMovable) << int(Qt::TextEditorInteraction);
6313 QTest::newRow("editor, selectable") << int(QGraphicsItem::ItemIsSelectable) << int(Qt::TextEditorInteraction);
6314 QTest::newRow("editor, movable | selectable") << int(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable)
6315 << int(Qt::TextEditorInteraction);
6316 QTest::newRow("noninteractive, noflags") << 0 << int(Qt::NoTextInteraction);
6317 QTest::newRow("noninteractive, movable") << int(QGraphicsItem::ItemIsMovable) << int(Qt::NoTextInteraction);
6318 QTest::newRow("noninteractive, selectable") << int(QGraphicsItem::ItemIsSelectable) << int(Qt::NoTextInteraction);
6319 QTest::newRow("noninteractive, movable | selectable") << int(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable)
6320 << int(Qt::NoTextInteraction);
6323 void tst_QGraphicsItem::task240400_clickOnTextItem()
6326 QFETCH(int, textFlags);
6328 QGraphicsScene scene;
6329 QEvent activate(QEvent::WindowActivate);
6330 QApplication::sendEvent(&scene, &activate);
6332 QGraphicsTextItem *item = scene.addText("Hello");
6333 item->setFlags(QGraphicsItem::GraphicsItemFlags(flags));
6334 item->setTextInteractionFlags(Qt::TextInteractionFlags(textFlags));
6335 bool focusable = (item->flags() & QGraphicsItem::ItemIsFocusable);
6336 QVERIFY(textFlags ? focusable : !focusable);
6338 int column = item->textCursor().columnNumber();
6339 QCOMPARE(column, 0);
6341 QVERIFY(!item->hasFocus());
6343 // Click in the top-left corner of the item
6345 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
6346 event.setScenePos(item->sceneBoundingRect().topLeft() + QPointF(0.1, 0.1));
6347 event.setButton(Qt::LeftButton);
6348 event.setButtons(Qt::LeftButton);
6349 QApplication::sendEvent(&scene, &event);
6351 if (flags || textFlags)
6352 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)item);
6354 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
6356 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseRelease);
6357 event.setScenePos(item->sceneBoundingRect().topLeft() + QPointF(0.1, 0.1));
6358 event.setButton(Qt::LeftButton);
6359 event.setButtons(0);
6360 QApplication::sendEvent(&scene, &event);
6363 QVERIFY(item->hasFocus());
6365 QVERIFY(!item->hasFocus());
6366 QVERIFY(!scene.mouseGrabberItem());
6367 bool selectable = (flags & QGraphicsItem::ItemIsSelectable);
6368 QVERIFY(selectable ? item->isSelected() : !item->isSelected());
6370 // Now click in the middle and check that the cursor moved.
6372 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
6373 event.setScenePos(item->sceneBoundingRect().center());
6374 event.setButton(Qt::LeftButton);
6375 event.setButtons(Qt::LeftButton);
6376 QApplication::sendEvent(&scene, &event);
6378 if (flags || textFlags)
6379 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)item);
6381 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
6383 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseRelease);
6384 event.setScenePos(item->sceneBoundingRect().center());
6385 event.setButton(Qt::LeftButton);
6386 event.setButtons(0);
6387 QApplication::sendEvent(&scene, &event);
6390 QVERIFY(item->hasFocus());
6392 QVERIFY(!item->hasFocus());
6393 QVERIFY(!scene.mouseGrabberItem());
6395 QVERIFY(selectable ? item->isSelected() : !item->isSelected());
6398 if (textFlags & Qt::TextEditorInteraction)
6399 QVERIFY(item->textCursor().columnNumber() > column);
6401 QCOMPARE(item->textCursor().columnNumber(), 0);
6404 class TextItem : public QGraphicsSimpleTextItem
6407 TextItem(const QString& text) : QGraphicsSimpleTextItem(text)
6412 void paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget)
6415 QGraphicsSimpleTextItem::paint(painter, option, widget);
6421 void tst_QGraphicsItem::ensureUpdateOnTextItem()
6423 QGraphicsScene scene;
6424 QGraphicsView view(&scene);
6426 QVERIFY(QTest::qWaitForWindowExposed(&view));
6428 TextItem *text1 = new TextItem(QLatin1String("123"));
6429 scene.addItem(text1);
6430 qApp->processEvents();
6431 QTRY_COMPARE(text1->updates,1);
6433 //same bouding rect but we have to update
6434 text1->setText(QLatin1String("321"));
6435 qApp->processEvents();
6436 QTRY_COMPARE(text1->updates,2);
6439 void tst_QGraphicsItem::task243707_addChildBeforeParent()
6441 // Task reports that adding the child before the parent leads to an
6442 // inconsistent internal state that can cause a crash. This test shows
6444 QGraphicsScene scene;
6445 QGraphicsWidget *widget = new QGraphicsWidget;
6446 QGraphicsWidget *widget2 = new QGraphicsWidget(widget);
6447 scene.addItem(widget2);
6448 QVERIFY(!widget2->parentItem());
6449 scene.addItem(widget);
6450 QVERIFY(!widget->commonAncestorItem(widget2));
6451 QVERIFY(!widget2->commonAncestorItem(widget));
6454 void tst_QGraphicsItem::task197802_childrenVisibility()
6456 QGraphicsScene scene;
6457 QGraphicsRectItem item(QRectF(0,0,20,20));
6459 QGraphicsRectItem *item2 = new QGraphicsRectItem(QRectF(0,0,10,10), &item);
6460 scene.addItem(&item);
6462 //freshly created: both visible
6463 QVERIFY(item.isVisible());
6464 QVERIFY(item2->isVisible());
6466 //hide child: parent visible, child not
6468 QVERIFY(item.isVisible());
6469 QVERIFY(!item2->isVisible());
6471 //hide parent: parent and child invisible
6473 QVERIFY(!item.isVisible());
6474 QVERIFY(!item2->isVisible());
6476 //ask to show the child: parent and child invisible anyways
6478 QVERIFY(!item.isVisible());
6479 QVERIFY(!item2->isVisible());
6481 //show the parent: both parent and child visible
6483 QVERIFY(item.isVisible());
6484 QVERIFY(item2->isVisible());
6489 void tst_QGraphicsItem::boundingRegion_data()
6491 QTest::addColumn<QLineF>("line");
6492 QTest::addColumn<qreal>("granularity");
6493 QTest::addColumn<QTransform>("transform");
6494 QTest::addColumn<QRegion>("expectedRegion");
6496 QTest::newRow("(0, 0, 10, 10) | 0.0 | identity | {(0, 0, 10, 10)}") << QLineF(0, 0, 10, 10) << qreal(0.0) << QTransform()
6497 << QRegion(QRect(0, 0, 10, 10));
6498 QTest::newRow("(0, 0, 10, 0) | 0.0 | identity | {(0, 0, 10, 10)}") << QLineF(0, 0, 10, 0) << qreal(0.0) << QTransform()
6499 << QRegion(QRect(0, 0, 10, 1));
6500 QTest::newRow("(0, 0, 10, 0) | 0.5 | identity | {(0, 0, 10, 1)}") << QLineF(0, 0, 10, 0) << qreal(0.5) << QTransform()
6501 << QRegion(QRect(0, 0, 10, 1));
6502 QTest::newRow("(0, 0, 10, 0) | 1.0 | identity | {(0, 0, 10, 1)}") << QLineF(0, 0, 10, 0) << qreal(1.0) << QTransform()
6503 << QRegion(QRect(0, 0, 10, 1));
6504 QTest::newRow("(0, 0, 0, 10) | 0.0 | identity | {(0, 0, 10, 10)}") << QLineF(0, 0, 0, 10) << qreal(0.0) << QTransform()
6505 << QRegion(QRect(0, 0, 1, 10));
6506 QTest::newRow("(0, 0, 0, 10) | 0.5 | identity | {(0, 0, 1, 10)}") << QLineF(0, 0, 0, 10) << qreal(0.5) << QTransform()
6507 << QRegion(QRect(0, 0, 1, 10));
6508 QTest::newRow("(0, 0, 0, 10) | 1.0 | identity | {(0, 0, 1, 10)}") << QLineF(0, 0, 0, 10) << qreal(1.0) << QTransform()
6509 << QRegion(QRect(0, 0, 1, 10));
6512 void tst_QGraphicsItem::boundingRegion()
6514 QFETCH(QLineF, line);
6515 QFETCH(qreal, granularity);
6516 QFETCH(QTransform, transform);
6517 QFETCH(QRegion, expectedRegion);
6519 QGraphicsLineItem item(line);
6520 QCOMPARE(item.boundingRegionGranularity(), qreal(0.0));
6521 item.setBoundingRegionGranularity(granularity);
6522 QCOMPARE(item.boundingRegionGranularity(), granularity);
6523 QCOMPARE(item.boundingRegion(transform), expectedRegion);
6526 void tst_QGraphicsItem::itemTransform_parentChild()
6528 QGraphicsScene scene;
6529 QGraphicsItem *parent = scene.addRect(0, 0, 100, 100);
6530 QGraphicsItem *child = scene.addRect(0, 0, 100, 100);
6531 child->setParentItem(parent);
6532 child->setPos(10, 10);
6536 QCOMPARE(child->itemTransform(parent).map(QPointF(10, 10)), QPointF(-10, 30));
6537 QCOMPARE(parent->itemTransform(child).map(QPointF(-10, 30)), QPointF(10, 10));
6540 void tst_QGraphicsItem::itemTransform_siblings()
6542 QGraphicsScene scene;
6543 QGraphicsItem *parent = scene.addRect(0, 0, 100, 100);
6544 QGraphicsItem *brother = scene.addRect(0, 0, 100, 100);
6545 QGraphicsItem *sister = scene.addRect(0, 0, 100, 100);
6546 parent->scale(10, 5);
6547 parent->rotate(-180);
6548 parent->shear(2, 3);
6550 brother->setParentItem(parent);
6551 sister->setParentItem(parent);
6553 brother->setPos(10, 10);
6554 brother->scale(2, 2);
6555 brother->rotate(90);
6556 sister->setPos(10, 10);
6557 sister->scale(2, 2);
6560 QCOMPARE(brother->itemTransform(sister).map(QPointF(10, 10)), QPointF(10, 10));
6561 QCOMPARE(sister->itemTransform(brother).map(QPointF(10, 10)), QPointF(10, 10));
6564 void tst_QGraphicsItem::itemTransform_unrelated()
6566 QGraphicsScene scene;
6567 QGraphicsItem *stranger1 = scene.addRect(0, 0, 100, 100);
6568 QGraphicsItem *stranger2 = scene.addRect(0, 0, 100, 100);
6569 stranger1->setPos(10, 10);
6570 stranger1->scale(2, 2);
6571 stranger1->rotate(90);
6572 stranger2->setPos(10, 10);
6573 stranger2->scale(2, 2);
6574 stranger2->rotate(90);
6576 QCOMPARE(stranger1->itemTransform(stranger2).map(QPointF(10, 10)), QPointF(10, 10));
6577 QCOMPARE(stranger2->itemTransform(stranger1).map(QPointF(10, 10)), QPointF(10, 10));
6580 void tst_QGraphicsItem::opacity_data()
6582 QTest::addColumn<qreal>("p_opacity");
6583 QTest::addColumn<int>("p_opacityFlags");
6584 QTest::addColumn<qreal>("c1_opacity");
6585 QTest::addColumn<int>("c1_opacityFlags");
6586 QTest::addColumn<qreal>("c2_opacity");
6587 QTest::addColumn<int>("c2_opacityFlags");
6588 QTest::addColumn<qreal>("p_effectiveOpacity");
6589 QTest::addColumn<qreal>("c1_effectiveOpacity");
6590 QTest::addColumn<qreal>("c2_effectiveOpacity");
6591 QTest::addColumn<qreal>("c3_effectiveOpacity");
6593 // Modify the opacity and see how it propagates
6594 QTest::newRow("A: 1.0 0 1.0 0 1.0 1.0 1.0 1.0 1.0") << qreal(1.0) << 0 << qreal(1.0) << 0 << qreal(1.0) << 0
6595 << qreal(1.0) << qreal(1.0) << qreal(1.0) << qreal(1.0);
6596 QTest::newRow("B: 0.5 0 1.0 0 1.0 1.0 1.0 1.0 1.0") << qreal(0.5) << 0 << qreal(1.0) << 0 << qreal(1.0) << 0
6597 << qreal(0.5) << qreal(0.5) << qreal(0.5) << qreal(0.5);
6598 QTest::newRow("C: 0.5 0 0.1 0 1.0 1.0 1.0 1.0 1.0") << qreal(0.5) << 0 << qreal(0.1) << 0 << qreal(1.0) << 0
6599 << qreal(0.5) << qreal(0.05) << qreal(0.05) << qreal(0.05);
6600 QTest::newRow("D: 0.0 0 1.0 0 1.0 1.0 1.0 1.0 1.0") << qreal(0.0) << 0 << qreal(1.0) << 0 << qreal(1.0) << 0
6601 << qreal(0.0) << qreal(0.0) << qreal(0.0) << qreal(0.0);
6603 // Parent doesn't propagate to children - now modify the opacity and see how it propagates
6604 int flags = QGraphicsItem::ItemDoesntPropagateOpacityToChildren;
6605 QTest::newRow("E: 1.0 2 1.0 0 1.0 1.0 1.0 1.0 1.0") << qreal(1.0) << flags << qreal(1.0) << 0 << qreal(1.0) << 0
6606 << qreal(1.0) << qreal(1.0) << qreal(1.0) << qreal(1.0);
6607 QTest::newRow("F: 0.5 2 1.0 0 1.0 1.0 1.0 1.0 1.0") << qreal(0.5) << flags << qreal(1.0) << 0 << qreal(1.0) << 0
6608 << qreal(0.5) << qreal(1.0) << qreal(1.0) << qreal(1.0);
6609 QTest::newRow("G: 0.5 2 0.1 0 1.0 1.0 1.0 1.0 1.0") << qreal(0.5) << flags << qreal(0.1) << 0 << qreal(1.0) << 0
6610 << qreal(0.5) << qreal(0.1) << qreal(0.1) << qreal(0.1);
6611 QTest::newRow("H: 0.0 2 1.0 0 1.0 1.0 1.0 1.0 1.0") << qreal(0.0) << flags << qreal(1.0) << 0 << qreal(1.0) << 0
6612 << qreal(0.0) << qreal(1.0) << qreal(1.0) << qreal(1.0);
6614 // Child ignores parent - now modify the opacity and see how it propagates
6615 flags = QGraphicsItem::ItemIgnoresParentOpacity;
6616 QTest::newRow("I: 1.0 0 1.0 1 1.0 1.0 1.0 1.0 1.0") << qreal(1.0) << 0 << qreal(1.0) << flags << qreal(1.0) << 0
6617 << qreal(1.0) << qreal(1.0) << qreal(1.0) << qreal(1.0);
6618 QTest::newRow("J: 1.0 0 1.0 1 1.0 1.0 1.0 1.0 1.0") << qreal(0.5) << 0 << qreal(0.5) << flags << qreal(0.5) << 0
6619 << qreal(0.5) << qreal(0.5) << qreal(0.25) << qreal(0.25);
6620 QTest::newRow("K: 1.0 0 1.0 1 1.0 1.0 1.0 1.0 1.0") << qreal(0.2) << 0 << qreal(0.2) << flags << qreal(0.2) << 0
6621 << qreal(0.2) << qreal(0.2) << qreal(0.04) << qreal(0.04);
6622 QTest::newRow("L: 1.0 0 1.0 1 1.0 1.0 1.0 1.0 1.0") << qreal(0.0) << 0 << qreal(0.0) << flags << qreal(0.0) << 0
6623 << qreal(0.0) << qreal(0.0) << qreal(0.0) << qreal(0.0);
6625 // Child ignores parent and doesn't propagate - now modify the opacity and see how it propagates
6626 flags = QGraphicsItem::ItemIgnoresParentOpacity | QGraphicsItem::ItemDoesntPropagateOpacityToChildren;
6627 QTest::newRow("M: 1.0 0 1.0 1 1.0 1.0 1.0 1.0 1.0") << qreal(1.0) << 0 // p
6628 << qreal(1.0) << flags // c1 (no prop)
6629 << qreal(1.0) << 0 // c2
6630 << qreal(1.0) << qreal(1.0) << qreal(1.0) << qreal(1.0);
6631 QTest::newRow("M: 0.5 0 1.0 1 1.0 1.0 1.0 1.0 1.0") << qreal(0.5) << 0 // p
6632 << qreal(1.0) << flags // c1 (no prop)
6633 << qreal(1.0) << 0 // c2
6634 << qreal(0.5) << qreal(1.0) << qreal(1.0) << qreal(1.0);
6635 QTest::newRow("M: 0.5 0 0.5 1 1.0 1.0 1.0 1.0 1.0") << qreal(0.5) << 0 // p
6636 << qreal(0.5) << flags // c1 (no prop)
6637 << qreal(1.0) << 0 // c2
6638 << qreal(0.5) << qreal(0.5) << qreal(1.0) << qreal(1.0);
6639 QTest::newRow("M: 0.5 0 0.5 1 0.5 1.0 1.0 1.0 1.0") << qreal(0.5) << 0 // p
6640 << qreal(0.5) << flags // c1 (no prop)
6641 << qreal(0.5) << 0 // c2
6642 << qreal(0.5) << qreal(0.5) << qreal(0.5) << qreal(0.5);
6643 QTest::newRow("M: 1.0 0 0.5 1 0.5 1.0 1.0 1.0 1.0") << qreal(1.0) << 0 // p
6644 << qreal(0.5) << flags // c1 (no prop)
6645 << qreal(0.5) << 0 // c2
6646 << qreal(1.0) << qreal(0.5) << qreal(0.5) << qreal(0.5);
6649 void tst_QGraphicsItem::opacity()
6651 QFETCH(qreal, p_opacity);
6652 QFETCH(int, p_opacityFlags);
6653 QFETCH(qreal, p_effectiveOpacity);
6654 QFETCH(qreal, c1_opacity);
6655 QFETCH(int, c1_opacityFlags);
6656 QFETCH(qreal, c1_effectiveOpacity);
6657 QFETCH(qreal, c2_opacity);
6658 QFETCH(int, c2_opacityFlags);
6659 QFETCH(qreal, c2_effectiveOpacity);
6660 QFETCH(qreal, c3_effectiveOpacity);
6662 QGraphicsRectItem *p = new QGraphicsRectItem;
6663 QGraphicsRectItem *c1 = new QGraphicsRectItem(p);
6664 QGraphicsRectItem *c2 = new QGraphicsRectItem(c1);
6665 QGraphicsRectItem *c3 = new QGraphicsRectItem(c2);
6667 QCOMPARE(p->opacity(), qreal(1.0));
6668 QCOMPARE(p->effectiveOpacity(), qreal(1.0));
6669 int opacityMask = QGraphicsItem::ItemIgnoresParentOpacity | QGraphicsItem::ItemDoesntPropagateOpacityToChildren;
6670 QVERIFY(!(p->flags() & opacityMask));
6672 p->setOpacity(p_opacity);
6673 c1->setOpacity(c1_opacity);
6674 c2->setOpacity(c2_opacity);
6675 p->setFlags(QGraphicsItem::GraphicsItemFlags(p->flags() | p_opacityFlags));
6676 c1->setFlags(QGraphicsItem::GraphicsItemFlags(c1->flags() | c1_opacityFlags));
6677 c2->setFlags(QGraphicsItem::GraphicsItemFlags(c2->flags() | c2_opacityFlags));
6679 QCOMPARE(int(p->flags() & opacityMask), p_opacityFlags);
6680 QCOMPARE(int(c1->flags() & opacityMask), c1_opacityFlags);
6681 QCOMPARE(int(c2->flags() & opacityMask), c2_opacityFlags);
6682 QCOMPARE(p->opacity(), p_opacity);
6683 QCOMPARE(p->effectiveOpacity(), p_effectiveOpacity);
6684 QCOMPARE(c1->effectiveOpacity(), c1_effectiveOpacity);
6685 QCOMPARE(c2->effectiveOpacity(), c2_effectiveOpacity);
6686 QCOMPARE(c3->effectiveOpacity(), c3_effectiveOpacity);
6689 void tst_QGraphicsItem::opacity2()
6691 EventTester *parent = new EventTester;
6692 EventTester *child = new EventTester(parent);
6693 EventTester *grandChild = new EventTester(child);
6695 QGraphicsScene scene;
6696 scene.addItem(parent);
6698 MyGraphicsView view(&scene);
6700 QVERIFY(QTest::qWaitForWindowActive(&view));
6701 QTRY_VERIFY(view.repaints >= 1);
6703 #define RESET_REPAINT_COUNTERS \
6704 parent->repaints = 0; \
6705 child->repaints = 0; \
6706 grandChild->repaints = 0; \
6709 RESET_REPAINT_COUNTERS
6711 child->setOpacity(0.0);
6713 QTRY_COMPARE(view.repaints, 1);
6714 QCOMPARE(parent->repaints, 1);
6715 QCOMPARE(child->repaints, 0);
6716 QCOMPARE(grandChild->repaints, 0);
6718 RESET_REPAINT_COUNTERS
6720 child->setOpacity(1.0);
6722 QTRY_COMPARE(view.repaints, 1);
6723 QCOMPARE(parent->repaints, 1);
6724 QCOMPARE(child->repaints, 1);
6725 QCOMPARE(grandChild->repaints, 1);
6727 RESET_REPAINT_COUNTERS
6729 parent->setOpacity(0.0);
6731 QTRY_COMPARE(view.repaints, 1);
6732 QCOMPARE(parent->repaints, 0);
6733 QCOMPARE(child->repaints, 0);
6734 QCOMPARE(grandChild->repaints, 0);
6736 RESET_REPAINT_COUNTERS
6738 parent->setOpacity(1.0);
6740 QTRY_COMPARE(view.repaints, 1);
6741 QCOMPARE(parent->repaints, 1);
6742 QCOMPARE(child->repaints, 1);
6743 QCOMPARE(grandChild->repaints, 1);
6745 grandChild->setFlag(QGraphicsItem::ItemIgnoresParentOpacity);
6746 RESET_REPAINT_COUNTERS
6748 child->setOpacity(0.0);
6750 QTRY_COMPARE(view.repaints, 1);
6751 QCOMPARE(parent->repaints, 1);
6752 QCOMPARE(child->repaints, 0);
6753 QCOMPARE(grandChild->repaints, 1);
6755 RESET_REPAINT_COUNTERS
6757 child->setOpacity(0.0); // Already 0.0; no change.
6759 QTRY_COMPARE(view.repaints, 0);
6760 QCOMPARE(parent->repaints, 0);
6761 QCOMPARE(child->repaints, 0);
6762 QCOMPARE(grandChild->repaints, 0);
6765 void tst_QGraphicsItem::opacityZeroUpdates()
6767 EventTester *parent = new EventTester;
6768 EventTester *child = new EventTester(parent);
6770 child->setPos(10, 10);
6772 QGraphicsScene scene;
6773 scene.addItem(parent);
6775 MyGraphicsView view(&scene);
6777 QVERIFY(QTest::qWaitForWindowActive(&view));
6778 QTRY_VERIFY(view.repaints > 0);
6781 parent->setOpacity(0.0);
6785 // transforming items bounding rect to view coordinates
6786 const QRect childDeviceBoundingRect = child->deviceTransform(view.viewportTransform())
6787 .mapRect(child->boundingRect()).toRect();
6788 const QRect parentDeviceBoundingRect = parent->deviceTransform(view.viewportTransform())
6789 .mapRect(parent->boundingRect()).toRect();
6791 QRegion expectedRegion = parentDeviceBoundingRect.adjusted(-2, -2, 2, 2);
6792 expectedRegion += childDeviceBoundingRect.adjusted(-2, -2, 2, 2);
6794 COMPARE_REGIONS(view.paintedRegion, expectedRegion);
6797 class StacksBehindParentHelper : public QGraphicsRectItem
6800 StacksBehindParentHelper(QList<QGraphicsItem *> *paintedItems, const QRectF &rect, QGraphicsItem *parent = 0)
6801 : QGraphicsRectItem(rect, parent), paintedItems(paintedItems)
6804 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
6806 QGraphicsRectItem::paint(painter, option, widget);
6807 paintedItems->append(this);
6811 QList<QGraphicsItem *> *paintedItems;
6814 void tst_QGraphicsItem::itemStacksBehindParent()
6816 StacksBehindParentHelper *parent1 = new StacksBehindParentHelper(&paintedItems, QRectF(0, 0, 100, 50));
6817 StacksBehindParentHelper *child11 = new StacksBehindParentHelper(&paintedItems, QRectF(-10, 10, 50, 50), parent1);
6818 StacksBehindParentHelper *grandChild111 = new StacksBehindParentHelper(&paintedItems, QRectF(-20, 20, 50, 50), child11);
6819 StacksBehindParentHelper *child12 = new StacksBehindParentHelper(&paintedItems, QRectF(60, 10, 50, 50), parent1);
6820 StacksBehindParentHelper *grandChild121 = new StacksBehindParentHelper(&paintedItems, QRectF(70, 20, 50, 50), child12);
6822 StacksBehindParentHelper *parent2 = new StacksBehindParentHelper(&paintedItems, QRectF(0, 0, 100, 50));
6823 StacksBehindParentHelper *child21 = new StacksBehindParentHelper(&paintedItems, QRectF(-10, 10, 50, 50), parent2);
6824 StacksBehindParentHelper *grandChild211 = new StacksBehindParentHelper(&paintedItems, QRectF(-20, 20, 50, 50), child21);
6825 StacksBehindParentHelper *child22 = new StacksBehindParentHelper(&paintedItems, QRectF(60, 10, 50, 50), parent2);
6826 StacksBehindParentHelper *grandChild221 = new StacksBehindParentHelper(&paintedItems, QRectF(70, 20, 50, 50), child22);
6828 parent1->setData(0, "parent1");
6829 child11->setData(0, "child11");
6830 grandChild111->setData(0, "grandChild111");
6831 child12->setData(0, "child12");
6832 grandChild121->setData(0, "grandChild121");
6833 parent2->setData(0, "parent2");
6834 child21->setData(0, "child21");
6835 grandChild211->setData(0, "grandChild211");
6836 child22->setData(0, "child22");
6837 grandChild221->setData(0, "grandChild221");
6839 // Disambiguate siblings
6840 parent1->setZValue(1);
6841 child11->setZValue(1);
6842 child21->setZValue(1);
6844 QGraphicsScene scene;
6845 scene.addItem(parent1);
6846 scene.addItem(parent2);
6848 QGraphicsView view(&scene);
6850 QVERIFY(QTest::qWaitForWindowExposed(&view));
6851 QTRY_VERIFY(!paintedItems.isEmpty());
6853 paintedItems.clear();
6854 view.viewport()->update();
6855 QApplication::processEvents();
6856 QTRY_COMPARE(scene.items(0, 0, 100, 100), (QList<QGraphicsItem *>()
6857 << grandChild111 << child11
6858 << grandChild121 << child12 << parent1
6859 << grandChild211 << child21
6860 << grandChild221 << child22 << parent2));
6861 QTRY_COMPARE(paintedItems, QList<QGraphicsItem *>()
6862 << parent2 << child22 << grandChild221
6863 << child21 << grandChild211
6864 << parent1 << child12 << grandChild121
6865 << child11 << grandChild111);
6867 child11->setFlag(QGraphicsItem::ItemStacksBehindParent);
6869 paintedItems.clear();
6870 QApplication::processEvents();
6872 QTRY_COMPARE(scene.items(0, 0, 100, 100), (QList<QGraphicsItem *>()
6873 << grandChild121 << child12 << parent1
6874 << grandChild111 << child11
6875 << grandChild211 << child21
6876 << grandChild221 << child22 << parent2));
6877 QCOMPARE(paintedItems, QList<QGraphicsItem *>()
6878 << parent2 << child22 << grandChild221
6879 << child21 << grandChild211
6880 << child11 << grandChild111
6881 << parent1 << child12 << grandChild121);
6883 child12->setFlag(QGraphicsItem::ItemStacksBehindParent);
6884 paintedItems.clear();
6886 QApplication::processEvents();
6888 QTRY_COMPARE(scene.items(0, 0, 100, 100), (QList<QGraphicsItem *>()
6889 << parent1 << grandChild111 << child11
6890 << grandChild121 << child12
6891 << grandChild211 << child21
6892 << grandChild221 << child22 << parent2));
6893 QCOMPARE(paintedItems, QList<QGraphicsItem *>()
6894 << parent2 << child22 << grandChild221
6895 << child21 << grandChild211
6896 << child12 << grandChild121
6897 << child11 << grandChild111 << parent1);
6900 class ClippingAndTransformsScene : public QGraphicsScene
6903 QList<QGraphicsItem *> drawnItems;
6905 void drawItems(QPainter *painter, int numItems, QGraphicsItem *items[],
6906 const QStyleOptionGraphicsItem options[], QWidget *widget = 0)
6909 for (int i = 0; i < numItems; ++i)
6910 drawnItems << items[i];
6911 QGraphicsScene::drawItems(painter, numItems, items, options, widget);
6915 void tst_QGraphicsItem::nestedClipping()
6917 ClippingAndTransformsScene scene;
6918 scene.setSceneRect(-50, -50, 200, 200);
6920 QGraphicsRectItem *root = new QGraphicsRectItem(QRectF(0, 0, 100, 100));
6921 root->setBrush(QColor(0, 0, 255));
6922 root->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
6923 QGraphicsRectItem *l1 = new QGraphicsRectItem(QRectF(0, 0, 100, 100));
6924 l1->setParentItem(root);
6926 l1->setBrush(QColor(255, 0, 0));
6927 l1->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
6928 QGraphicsEllipseItem *l2 = new QGraphicsEllipseItem(QRectF(0, 0, 100, 100));
6929 l2->setParentItem(l1);
6931 l2->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
6932 l2->setBrush(QColor(255, 255, 0));
6933 QGraphicsRectItem *l3 = new QGraphicsRectItem(QRectF(0, 0, 25, 25));
6934 l3->setParentItem(l2);
6935 l3->setBrush(QColor(0, 255, 0));
6936 l3->setPos(50 - 12, -12);
6938 scene.addItem(root);
6940 root->setData(0, "root");
6941 l1->setData(0, "l1");
6942 l2->setData(0, "l2");
6943 l3->setData(0, "l3");
6945 QGraphicsView view(&scene);
6946 view.setOptimizationFlag(QGraphicsView::IndirectPainting);
6948 QVERIFY(QTest::qWaitForWindowExposed(&view));
6951 QList<QGraphicsItem *> expected;
6952 expected << root << l1 << l2 << l3;
6953 QTRY_COMPARE(scene.drawnItems, expected);
6955 QImage image(200, 200, QImage::Format_ARGB32_Premultiplied);
6958 QPainter painter(&image);
6959 scene.render(&painter);
6962 // Check transparent areas
6963 QCOMPARE(image.pixel(100, 25), qRgba(0, 0, 0, 0));
6964 QCOMPARE(image.pixel(100, 175), qRgba(0, 0, 0, 0));
6965 QCOMPARE(image.pixel(25, 100), qRgba(0, 0, 0, 0));
6966 QCOMPARE(image.pixel(175, 100), qRgba(0, 0, 0, 0));
6967 QCOMPARE(image.pixel(70, 80), qRgba(255, 0, 0, 255));
6968 QCOMPARE(image.pixel(80, 130), qRgba(255, 255, 0, 255));
6969 QCOMPARE(image.pixel(92, 105), qRgba(0, 255, 0, 255));
6970 QCOMPARE(image.pixel(105, 105), qRgba(0, 0, 255, 255));
6972 // Enable this to compare if the test starts failing.
6973 image.save("nestedClipping_reference.png");
6977 class TransformDebugItem : public QGraphicsRectItem
6980 TransformDebugItem()
6981 : QGraphicsRectItem(QRectF(-10, -10, 20, 20))
6983 setBrush(QColor(qrand() % 256, qrand() % 256, qrand() % 256));
6988 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
6989 QWidget *widget = 0)
6991 x = painter->worldTransform();
6992 QGraphicsRectItem::paint(painter, option, widget);
6996 void tst_QGraphicsItem::nestedClippingTransforms()
6998 TransformDebugItem *rootClipper = new TransformDebugItem;
6999 rootClipper->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
7000 TransformDebugItem *child = new TransformDebugItem;
7001 child->setParentItem(rootClipper);
7002 child->setPos(2, 2);
7003 TransformDebugItem *grandChildClipper = new TransformDebugItem;
7004 grandChildClipper->setParentItem(child);
7005 grandChildClipper->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
7006 grandChildClipper->setPos(4, 4);
7007 TransformDebugItem *greatGrandChild = new TransformDebugItem;
7008 greatGrandChild->setPos(2, 2);
7009 greatGrandChild->setParentItem(grandChildClipper);
7010 TransformDebugItem *grandChildClipper2 = new TransformDebugItem;
7011 grandChildClipper2->setParentItem(child);
7012 grandChildClipper2->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
7013 grandChildClipper2->setPos(8, 8);
7014 TransformDebugItem *greatGrandChild2 = new TransformDebugItem;
7015 greatGrandChild2->setPos(2, 2);
7016 greatGrandChild2->setParentItem(grandChildClipper2);
7017 TransformDebugItem *grandChildClipper3 = new TransformDebugItem;
7018 grandChildClipper3->setParentItem(child);
7019 grandChildClipper3->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
7020 grandChildClipper3->setPos(12, 12);
7021 TransformDebugItem *greatGrandChild3 = new TransformDebugItem;
7022 greatGrandChild3->setPos(2, 2);
7023 greatGrandChild3->setParentItem(grandChildClipper3);
7025 QGraphicsScene scene;
7026 scene.addItem(rootClipper);
7028 QImage image(scene.itemsBoundingRect().size().toSize(), QImage::Format_ARGB32_Premultiplied);
7034 QCOMPARE(rootClipper->x, QTransform(1, 0, 0, 0, 1, 0, 10, 10, 1));
7035 QCOMPARE(child->x, QTransform(1, 0, 0, 0, 1, 0, 12, 12, 1));
7036 QCOMPARE(grandChildClipper->x, QTransform(1, 0, 0, 0, 1, 0, 16, 16, 1));
7037 QCOMPARE(greatGrandChild->x, QTransform(1, 0, 0, 0, 1, 0, 18, 18, 1));
7038 QCOMPARE(grandChildClipper2->x, QTransform(1, 0, 0, 0, 1, 0, 20, 20, 1));
7039 QCOMPARE(greatGrandChild2->x, QTransform(1, 0, 0, 0, 1, 0, 22, 22, 1));
7040 QCOMPARE(grandChildClipper3->x, QTransform(1, 0, 0, 0, 1, 0, 24, 24, 1));
7041 QCOMPARE(greatGrandChild3->x, QTransform(1, 0, 0, 0, 1, 0, 26, 26, 1));
7044 void tst_QGraphicsItem::sceneTransformCache()
7046 // Test that an item's scene transform is updated correctly when the
7047 // parent is transformed.
7048 QGraphicsScene scene;
7049 QGraphicsRectItem *rect = scene.addRect(0, 0, 100, 100);
7050 QGraphicsRectItem *rect2 = scene.addRect(0, 0, 100, 100);
7051 rect2->setParentItem(rect);
7053 rect->translate(0, 50);
7054 QGraphicsView view(&scene);
7056 QVERIFY(QTest::qWaitForWindowExposed(&view));
7057 rect->translate(0, 100);
7059 x.translate(0, 150);
7061 QCOMPARE(rect2->sceneTransform(), x);
7063 scene.removeItem(rect);
7065 //Crazy use case : rect4 child of rect3 so the transformation of rect4 will be cached.Good!
7066 //We remove rect4 from the scene, then the validTransform bit flag is set to 0 and the index of the cache
7067 //add to the freeTransformSlots. The problem was that sceneTransformIndex was not set to -1 so if a new item arrive
7068 //with a child (rect6) that will be cached then it will take the freeSlot (ex rect4) and put it his transform. But if rect4 is
7069 //added back to the scene then it will set the transform to his old sceneTransformIndex value that will erase the new
7070 //value of rect6 so rect6 transform will be wrong.
7071 QGraphicsRectItem *rect3 = scene.addRect(0, 0, 100, 100);
7072 QGraphicsRectItem *rect4 = scene.addRect(0, 0, 100, 100);
7073 rect3->setPos(QPointF(10,10));
7075 rect4->setParentItem(rect3);
7076 rect4->setPos(QPointF(10,10));
7078 QCOMPARE(rect4->mapToScene(rect4->boundingRect().topLeft()), QPointF(20,20));
7080 scene.removeItem(rect4);
7081 //rect4 transform is local only
7082 QCOMPARE(rect4->mapToScene(rect4->boundingRect().topLeft()), QPointF(10,10));
7084 QGraphicsRectItem *rect5 = scene.addRect(0, 0, 100, 100);
7085 QGraphicsRectItem *rect6 = scene.addRect(0, 0, 100, 100);
7086 rect5->setPos(QPointF(20,20));
7088 rect6->setParentItem(rect5);
7089 rect6->setPos(QPointF(10,10));
7090 //test if rect6 transform is ok
7091 QCOMPARE(rect6->mapToScene(rect6->boundingRect().topLeft()), QPointF(30,30));
7093 scene.addItem(rect4);
7095 QCOMPARE(rect4->mapToScene(rect4->boundingRect().topLeft()), QPointF(10,10));
7096 //test if rect6 transform is still correct
7097 QCOMPARE(rect6->mapToScene(rect6->boundingRect().topLeft()), QPointF(30,30));
7100 void tst_QGraphicsItem::tabChangesFocus_data()
7102 QTest::addColumn<bool>("tabChangesFocus");
7103 QTest::newRow("tab changes focus") << true;
7104 QTest::newRow("tab doesn't change focus") << false;
7107 void tst_QGraphicsItem::tabChangesFocus()
7109 QFETCH(bool, tabChangesFocus);
7111 QGraphicsScene scene;
7112 QGraphicsTextItem *item = scene.addText("Hello");
7113 item->setTabChangesFocus(tabChangesFocus);
7114 item->setTextInteractionFlags(Qt::TextEditorInteraction);
7117 QDial *dial1 = new QDial;
7118 QGraphicsView *view = new QGraphicsView(&scene);
7120 QDial *dial2 = new QDial;
7121 QVBoxLayout *layout = new QVBoxLayout;
7122 layout->addWidget(dial1);
7123 layout->addWidget(view);
7124 layout->addWidget(dial2);
7127 widget.setLayout(layout);
7129 QVERIFY(QTest::qWaitForWindowActive(&widget));
7131 QTRY_VERIFY(scene.isActive());
7135 QTRY_VERIFY(dial1->hasFocus());
7137 QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
7139 QTRY_VERIFY(view->hasFocus());
7140 QTRY_VERIFY(item->hasFocus());
7142 QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
7145 if (tabChangesFocus) {
7146 QTRY_VERIFY(!view->hasFocus());
7147 QTRY_VERIFY(!item->hasFocus());
7148 QTRY_VERIFY(dial2->hasFocus());
7150 QTRY_VERIFY(view->hasFocus());
7151 QTRY_VERIFY(item->hasFocus());
7152 QCOMPARE(item->toPlainText(), QString("\tHello"));
7156 void tst_QGraphicsItem::cacheMode()
7158 QGraphicsScene scene(0, 0, 100, 100);
7159 QGraphicsView view(&scene);
7160 view.resize(150, 150);
7162 QApplication::setActiveWindow(&view);
7163 QVERIFY(QTest::qWaitForWindowActive(&view));
7165 // Increase the probability of window activation
7166 // not causing another repaint of test items.
7169 EventTester *tester = new EventTester;
7170 EventTester *testerChild = new EventTester;
7171 testerChild->setParentItem(tester);
7172 EventTester *testerChild2 = new EventTester;
7173 testerChild2->setParentItem(testerChild);
7174 testerChild2->setFlag(QGraphicsItem::ItemIgnoresTransformations);
7176 scene.addItem(tester);
7179 for (int i = 0; i < 2; ++i) {
7180 // No visual change.
7181 QTRY_COMPARE(tester->repaints, 1);
7182 QCOMPARE(testerChild->repaints, 1);
7183 QCOMPARE(testerChild2->repaints, 1);
7184 tester->setCacheMode(QGraphicsItem::NoCache);
7185 testerChild->setCacheMode(QGraphicsItem::NoCache);
7186 testerChild2->setCacheMode(QGraphicsItem::NoCache);
7188 QTRY_COMPARE(tester->repaints, 1);
7189 QCOMPARE(testerChild->repaints, 1);
7190 QCOMPARE(testerChild2->repaints, 1);
7191 tester->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
7192 testerChild->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
7193 testerChild2->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
7197 // The first move causes a repaint as the item is painted into its pixmap.
7198 // (Only occurs if the item has previously been painted without cache).
7199 tester->setPos(10, 10);
7200 testerChild->setPos(10, 10);
7201 testerChild2->setPos(10, 10);
7203 QTRY_COMPARE(tester->repaints, 2);
7204 QCOMPARE(testerChild->repaints, 2);
7205 QCOMPARE(testerChild2->repaints, 2);
7207 // Consecutive moves should not repaint.
7208 tester->setPos(20, 20);
7209 testerChild->setPos(20, 20);
7210 testerChild2->setPos(20, 20);
7212 QCOMPARE(tester->repaints, 2);
7213 QCOMPARE(testerChild->repaints, 2);
7214 QCOMPARE(testerChild2->repaints, 2);
7216 // Translating does not result in a repaint.
7217 tester->translate(10, 10);
7219 QTRY_COMPARE(tester->repaints, 2);
7220 QCOMPARE(testerChild->repaints, 2);
7221 QCOMPARE(testerChild2->repaints, 2);
7223 // Rotating results in a repaint.
7226 QTRY_COMPARE(tester->repaints, 3);
7227 QCOMPARE(testerChild->repaints, 3);
7228 QCOMPARE(testerChild2->repaints, 2);
7230 // Change to ItemCoordinateCache (triggers repaint).
7231 tester->setCacheMode(QGraphicsItem::ItemCoordinateCache); // autosize
7232 testerChild->setCacheMode(QGraphicsItem::ItemCoordinateCache); // autosize
7233 testerChild2->setCacheMode(QGraphicsItem::ItemCoordinateCache); // autosize
7235 QTRY_COMPARE(tester->repaints, 4);
7236 QCOMPARE(testerChild->repaints, 4);
7237 QCOMPARE(testerChild2->repaints, 3);
7239 // Rotating items with ItemCoordinateCache doesn't cause a repaint.
7241 testerChild->rotate(22);
7242 testerChild2->rotate(22);
7244 QTRY_COMPARE(tester->repaints, 4);
7245 QTRY_COMPARE(testerChild->repaints, 4);
7246 QTRY_COMPARE(testerChild2->repaints, 3);
7247 tester->resetTransform();
7248 testerChild->resetTransform();
7249 testerChild2->resetTransform();
7251 // Explicit update causes a repaint.
7252 tester->update(0, 0, 5, 5);
7254 QTRY_COMPARE(tester->repaints, 5);
7255 QCOMPARE(testerChild->repaints, 4);
7256 QCOMPARE(testerChild2->repaints, 3);
7258 // Updating outside the item's bounds does not cause a repaint.
7259 tester->update(10, 10, 5, 5);
7261 QTRY_COMPARE(tester->repaints, 5);
7262 QCOMPARE(testerChild->repaints, 4);
7263 QCOMPARE(testerChild2->repaints, 3);
7265 // Resizing an item should cause a repaint of that item. (because of
7267 tester->setGeometry(QRectF(-15, -15, 30, 30));
7269 QTRY_COMPARE(tester->repaints, 6);
7270 QCOMPARE(testerChild->repaints, 4);
7271 QCOMPARE(testerChild2->repaints, 3);
7274 tester->setCacheMode(QGraphicsItem::ItemCoordinateCache, QSize(30, 30));
7275 testerChild->setCacheMode(QGraphicsItem::ItemCoordinateCache, QSize(30, 30));
7276 testerChild2->setCacheMode(QGraphicsItem::ItemCoordinateCache, QSize(30, 30));
7278 QTRY_COMPARE(tester->repaints, 7);
7279 QCOMPARE(testerChild->repaints, 5);
7280 QCOMPARE(testerChild2->repaints, 4);
7282 // Resizing the item should cause a repaint.
7283 testerChild->setGeometry(QRectF(-15, -15, 30, 30));
7285 QTRY_COMPARE(tester->repaints, 7);
7286 QCOMPARE(testerChild->repaints, 6);
7287 QCOMPARE(testerChild2->repaints, 4);
7289 // Scaling the view does not cause a repaint.
7290 view.scale(0.7, 0.7);
7292 QTRY_COMPARE(tester->repaints, 7);
7293 QCOMPARE(testerChild->repaints, 6);
7294 QCOMPARE(testerChild2->repaints, 4);
7296 // Switch to device coordinate cache.
7297 tester->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
7298 testerChild->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
7299 testerChild2->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
7301 QTRY_COMPARE(tester->repaints, 8);
7302 QCOMPARE(testerChild->repaints, 7);
7303 QCOMPARE(testerChild2->repaints, 5);
7305 // Scaling the view back should cause repaints for two of the items.
7306 view.setTransform(QTransform());
7308 QTRY_COMPARE(tester->repaints, 9);
7309 QCOMPARE(testerChild->repaints, 8);
7310 QCOMPARE(testerChild2->repaints, 5);
7312 // Rotating the base item (perspective) should repaint two items.
7313 tester->setTransform(QTransform().rotate(10, Qt::XAxis));
7315 QTRY_COMPARE(tester->repaints, 10);
7316 QCOMPARE(testerChild->repaints, 9);
7317 QCOMPARE(testerChild2->repaints, 5);
7319 // Moving the middle item should case a repaint even if it's a move,
7320 // because the parent is rotated with a perspective.
7321 testerChild->setPos(1, 1);
7323 QTRY_COMPARE(tester->repaints, 11);
7324 QTRY_COMPARE(testerChild->repaints, 10);
7325 QTRY_COMPARE(testerChild2->repaints, 5);
7326 tester->resetTransform();
7329 tester->setGeometry(QRectF(-4000, -4000, 8000, 8000));
7330 QTRY_COMPARE(tester->repaints, 12);
7331 QTRY_COMPARE(testerChild->repaints, 11);
7332 QTRY_COMPARE(testerChild2->repaints, 5);
7334 // Move the large item - will cause a repaint as the
7335 // cache is clipped.
7336 tester->setPos(5, 0);
7337 QTRY_COMPARE(tester->repaints, 13);
7338 QTRY_COMPARE(testerChild->repaints, 11);
7339 QTRY_COMPARE(testerChild2->repaints, 5);
7341 // Hiding and showing should invalidate the cache
7345 QTRY_COMPARE(tester->repaints, 14);
7346 QTRY_COMPARE(testerChild->repaints, 12);
7347 QTRY_COMPARE(testerChild2->repaints, 6);
7350 void tst_QGraphicsItem::cacheMode2()
7352 QGraphicsScene scene(0, 0, 100, 100);
7353 QGraphicsView view(&scene);
7354 view.resize(150, 150);
7356 QApplication::setActiveWindow(&view);
7357 QVERIFY(QTest::qWaitForWindowActive(&view));
7359 // Increase the probability of window activation
7360 // not causing another repaint of test items.
7363 EventTester *tester = new EventTester;
7364 scene.addItem(tester);
7366 QTRY_COMPARE(tester->repaints, 1);
7368 // Switching from NoCache to NoCache (no repaint)
7369 tester->setCacheMode(QGraphicsItem::NoCache);
7371 QTRY_COMPARE(tester->repaints, 1);
7373 // Switching from NoCache to DeviceCoordinateCache (no repaint)
7374 tester->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
7376 QTRY_COMPARE(tester->repaints, 1);
7378 // Switching from DeviceCoordinateCache to DeviceCoordinateCache (no repaint)
7379 tester->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
7381 QTRY_COMPARE(tester->repaints, 1);
7383 // Switching from DeviceCoordinateCache to NoCache (no repaint)
7384 tester->setCacheMode(QGraphicsItem::NoCache);
7386 QTRY_COMPARE(tester->repaints, 1);
7388 // Switching from NoCache to ItemCoordinateCache (repaint)
7389 tester->setCacheMode(QGraphicsItem::ItemCoordinateCache);
7391 QTRY_COMPARE(tester->repaints, 2);
7393 // Switching from ItemCoordinateCache to ItemCoordinateCache (no repaint)
7394 tester->setCacheMode(QGraphicsItem::ItemCoordinateCache);
7396 QTRY_COMPARE(tester->repaints, 2);
7398 // Switching from ItemCoordinateCache to ItemCoordinateCache with different size (repaint)
7399 tester->setCacheMode(QGraphicsItem::ItemCoordinateCache, QSize(100, 100));
7401 QTRY_COMPARE(tester->repaints, 3);
7403 // Switching from ItemCoordinateCache to NoCache (repaint)
7404 tester->setCacheMode(QGraphicsItem::NoCache);
7406 QTRY_COMPARE(tester->repaints, 4);
7408 // Switching from DeviceCoordinateCache to ItemCoordinateCache (repaint)
7409 tester->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
7411 QTRY_COMPARE(tester->repaints, 4);
7412 tester->setCacheMode(QGraphicsItem::ItemCoordinateCache);
7414 QTRY_COMPARE(tester->repaints, 5);
7416 // Switching from ItemCoordinateCache to DeviceCoordinateCache (repaint)
7417 tester->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
7419 QTRY_COMPARE(tester->repaints, 6);
7422 void tst_QGraphicsItem::updateCachedItemAfterMove()
7424 // A simple item that uses ItemCoordinateCache
7425 EventTester *tester = new EventTester;
7426 tester->setCacheMode(QGraphicsItem::ItemCoordinateCache);
7428 // Add to a scene, show in a view, ensure it's painted and reset its
7430 QGraphicsScene scene;
7431 scene.addItem(tester);
7432 QGraphicsView view(&scene);
7434 QVERIFY(QTest::qWaitForWindowExposed(&view));
7437 QTRY_VERIFY(tester->repaints > 0);
7438 tester->repaints = 0;
7440 // Move the item, should not cause repaints
7441 tester->setPos(10, 0);
7443 QCOMPARE(tester->repaints, 0);
7445 // Move then update, should cause one repaint
7446 tester->setPos(20, 0);
7449 QCOMPARE(tester->repaints, 1);
7451 // Hiding the item doesn't cause a repaint
7454 QCOMPARE(tester->repaints, 1);
7456 // Moving a hidden item doesn't cause a repaint
7457 tester->setPos(30, 0);
7460 QCOMPARE(tester->repaints, 1);
7463 class Track : public QGraphicsRectItem
7466 Track(const QRectF &rect)
7467 : QGraphicsRectItem(rect)
7469 setAcceptHoverEvents(true);
7472 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0)
7474 QGraphicsRectItem::paint(painter, option, widget);
7475 painter->drawText(boundingRect(), Qt::AlignCenter, QString("%1x%2\n%3x%4").arg(p.x()).arg(p.y()).arg(sp.x()).arg(sp.y()));
7479 void hoverMoveEvent(QGraphicsSceneHoverEvent *event)
7482 sp = event->widget()->mapFromGlobal(event->screenPos());
7490 void tst_QGraphicsItem::deviceTransform_data()
7492 QTest::addColumn<bool>("untransformable1");
7493 QTest::addColumn<bool>("untransformable2");
7494 QTest::addColumn<bool>("untransformable3");
7495 QTest::addColumn<qreal>("rotation1");
7496 QTest::addColumn<qreal>("rotation2");
7497 QTest::addColumn<qreal>("rotation3");
7498 QTest::addColumn<QTransform>("deviceX");
7499 QTest::addColumn<QPointF>("mapResult1");
7500 QTest::addColumn<QPointF>("mapResult2");
7501 QTest::addColumn<QPointF>("mapResult3");
7503 QTest::newRow("nil") << false << false << false
7504 << qreal(0.0) << qreal(0.0) << qreal(0.0)
7506 << QPointF(150, 150) << QPointF(250, 250) << QPointF(350, 350);
7507 QTest::newRow("deviceX rot 90") << false << false << false
7508 << qreal(0.0) << qreal(0.0) << qreal(0.0)
7509 << QTransform().rotate(90)
7510 << QPointF(-150, 150) << QPointF(-250, 250) << QPointF(-350, 350);
7511 QTest::newRow("deviceX rot 90 100") << true << false << false
7512 << qreal(0.0) << qreal(0.0) << qreal(0.0)
7513 << QTransform().rotate(90)
7514 << QPointF(-50, 150) << QPointF(50, 250) << QPointF(150, 350);
7515 QTest::newRow("deviceX rot 90 010") << false << true << false
7516 << qreal(0.0) << qreal(0.0) << qreal(0.0)
7517 << QTransform().rotate(90)
7518 << QPointF(-150, 150) << QPointF(-150, 250) << QPointF(-50, 350);
7519 QTest::newRow("deviceX rot 90 001") << false << false << true
7520 << qreal(0.0) << qreal(0.0) << qreal(0.0)
7521 << QTransform().rotate(90)
7522 << QPointF(-150, 150) << QPointF(-250, 250) << QPointF(-250, 350);
7523 QTest::newRow("deviceX rot 90 111") << true << true << true
7524 << qreal(0.0) << qreal(0.0) << qreal(0.0)
7525 << QTransform().rotate(90)
7526 << QPointF(-50, 150) << QPointF(50, 250) << QPointF(150, 350);
7527 QTest::newRow("deviceX rot 90 101") << true << false << true
7528 << qreal(0.0) << qreal(0.0) << qreal(0.0)
7529 << QTransform().rotate(90)
7530 << QPointF(-50, 150) << QPointF(50, 250) << QPointF(150, 350);
7533 void tst_QGraphicsItem::deviceTransform()
7535 QFETCH(bool, untransformable1);
7536 QFETCH(bool, untransformable2);
7537 QFETCH(bool, untransformable3);
7538 QFETCH(qreal, rotation1);
7539 QFETCH(qreal, rotation2);
7540 QFETCH(qreal, rotation3);
7541 QFETCH(QTransform, deviceX);
7542 QFETCH(QPointF, mapResult1);
7543 QFETCH(QPointF, mapResult2);
7544 QFETCH(QPointF, mapResult3);
7546 QGraphicsScene scene;
7547 Track *rect1 = new Track(QRectF(0, 0, 100, 100));
7548 Track *rect2 = new Track(QRectF(0, 0, 100, 100));
7549 Track *rect3 = new Track(QRectF(0, 0, 100, 100));
7550 rect2->setParentItem(rect1);
7551 rect3->setParentItem(rect2);
7552 rect1->setPos(100, 100);
7553 rect2->setPos(100, 100);
7554 rect3->setPos(100, 100);
7555 rect1->rotate(rotation1);
7556 rect2->rotate(rotation2);
7557 rect3->rotate(rotation3);
7558 rect1->setFlag(QGraphicsItem::ItemIgnoresTransformations, untransformable1);
7559 rect2->setFlag(QGraphicsItem::ItemIgnoresTransformations, untransformable2);
7560 rect3->setFlag(QGraphicsItem::ItemIgnoresTransformations, untransformable3);
7561 rect1->setBrush(Qt::red);
7562 rect2->setBrush(Qt::green);
7563 rect3->setBrush(Qt::blue);
7564 scene.addItem(rect1);
7566 QCOMPARE(rect1->deviceTransform(deviceX).map(QPointF(50, 50)), mapResult1);
7567 QCOMPARE(rect2->deviceTransform(deviceX).map(QPointF(50, 50)), mapResult2);
7568 QCOMPARE(rect3->deviceTransform(deviceX).map(QPointF(50, 50)), mapResult3);
7571 void tst_QGraphicsItem::update()
7573 QGraphicsScene scene;
7574 scene.setSceneRect(-100, -100, 200, 200);
7576 MyGraphicsView view(&scene,&topLevel);
7578 topLevel.resize(300, 300);
7580 QVERIFY(QTest::qWaitForWindowExposed(&topLevel));
7582 EventTester *item = new EventTester;
7583 scene.addItem(item);
7584 QTest::qWait(100); // Make sure all pending updates are processed.
7587 item->update(); // Item marked as dirty
7588 scene.update(); // Entire scene marked as dirty
7589 qApp->processEvents();
7590 QCOMPARE(item->repaints, 1);
7592 // Make sure the dirty state from the previous update is reset so that
7593 // the item don't think it is already dirty and discards this update.
7595 qApp->processEvents();
7596 QCOMPARE(item->repaints, 2);
7598 // Make sure a partial update doesn't cause a full update to be discarded.
7601 item->update(QRectF(0, 0, 5, 5));
7603 qApp->processEvents();
7604 QCOMPARE(item->repaints, 1);
7605 QCOMPARE(view.repaints, 1);
7606 QRect itemDeviceBoundingRect = item->deviceTransform(view.viewportTransform())
7607 .mapRect(item->boundingRect()).toAlignedRect();
7608 QRegion expectedRegion = itemDeviceBoundingRect.adjusted(-2, -2, 2, 2);
7609 // The entire item's bounding rect (adjusted for antialiasing) should have been painted.
7610 QCOMPARE(view.paintedRegion, expectedRegion);
7612 // Make sure update requests outside the bounding rect are discarded.
7615 item->update(-15, -15, 5, 5); // Item's brect: (-10, -10, 20, 20)
7616 qApp->processEvents();
7617 QCOMPARE(item->repaints, 0);
7618 QCOMPARE(view.repaints, 0);
7620 // Make sure the area occupied by an item is repainted when hiding it.
7623 item->update(); // Full update; all sub-sequent update requests are discarded.
7624 item->hide(); // visible set to 0. ignoreVisible must be set to 1; the item won't be processed otherwise.
7625 qApp->processEvents();
7626 QCOMPARE(item->repaints, 0);
7627 QCOMPARE(view.repaints, 1);
7628 // The entire item's bounding rect (adjusted for antialiasing) should have been painted.
7629 QCOMPARE(view.paintedRegion, expectedRegion);
7631 // Make sure item is repainted when shown (after being hidden).
7635 qApp->processEvents();
7636 QCOMPARE(item->repaints, 1);
7637 QCOMPARE(view.repaints, 1);
7638 // The entire item's bounding rect (adjusted for antialiasing) should have been painted.
7639 QCOMPARE(view.paintedRegion, expectedRegion);
7643 qApp->processEvents();
7645 const QPointF originalPos = item->pos();
7646 item->setPos(5000, 5000);
7647 qApp->processEvents();
7648 QCOMPARE(item->repaints, 0);
7649 QCOMPARE(view.repaints, 0);
7650 qApp->processEvents();
7652 item->setPos(originalPos);
7653 qApp->processEvents();
7654 QCOMPARE(item->repaints, 0);
7655 QCOMPARE(view.repaints, 0);
7657 qApp->processEvents();
7658 QCOMPARE(item->repaints, 1);
7659 QCOMPARE(view.repaints, 1);
7660 // The entire item's bounding rect (adjusted for antialiasing) should have been painted.
7661 QCOMPARE(view.paintedRegion, expectedRegion);
7663 QGraphicsViewPrivate *viewPrivate = static_cast<QGraphicsViewPrivate *>(qt_widget_private(&view));
7664 item->setPos(originalPos + QPoint(50, 50));
7665 viewPrivate->updateAll();
7666 QVERIFY(viewPrivate->fullUpdatePending);
7670 item->setPos(originalPos);
7672 qApp->processEvents();
7673 QCOMPARE(item->repaints, 1);
7674 QCOMPARE(view.repaints, 1);
7675 COMPARE_REGIONS(view.paintedRegion, expectedRegion + expectedRegion.translated(50, 50));
7677 // Make sure moving a parent item triggers an update on the children
7678 // (even though the parent itself is outside the viewport).
7679 QGraphicsRectItem *parent = new QGraphicsRectItem(0, 0, 10, 10);
7680 parent->setPos(-400, 0);
7681 item->setParentItem(parent);
7682 item->setPos(400, 0);
7683 scene.addItem(parent);
7685 itemDeviceBoundingRect = item->deviceTransform(view.viewportTransform())
7686 .mapRect(item->boundingRect()).toAlignedRect();
7687 expectedRegion = itemDeviceBoundingRect.adjusted(-2, -2, 2, 2);
7690 parent->translate(-400, 0);
7691 qApp->processEvents();
7692 QCOMPARE(item->repaints, 0);
7693 QCOMPARE(view.repaints, 1);
7694 QCOMPARE(view.paintedRegion, expectedRegion);
7697 parent->translate(400, 0);
7698 qApp->processEvents();
7699 QCOMPARE(item->repaints, 1);
7700 QCOMPARE(view.repaints, 1);
7701 QCOMPARE(view.paintedRegion, expectedRegion);
7702 QCOMPARE(view.paintedRegion, expectedRegion);
7705 void tst_QGraphicsItem::setTransformProperties_data()
7707 QTest::addColumn<QPointF>("origin");
7708 QTest::addColumn<qreal>("rotation");
7709 QTest::addColumn<qreal>("scale");
7711 QTest::newRow("nothing") << QPointF() << qreal(0.0) << qreal(1.0);
7713 QTest::newRow("rotation") << QPointF() << qreal(42.2) << qreal(1.0);
7715 QTest::newRow("rotation dicentred") << QPointF(qreal(22.3), qreal(-56.2))
7719 QTest::newRow("Scale") << QPointF() << qreal(0.0)
7722 QTest::newRow("Everything dicentred") << QPointF(qreal(22.3), qreal(-56.2)) << qreal(-175) << qreal(196);
7726 * the normal QCOMPARE doesn't work because it doesn't use qFuzzyCompare
7728 #define QCOMPARE_TRANSFORM(X1, X2) QVERIFY(((X1)*(X2).inverted()).isIdentity())
7730 void tst_QGraphicsItem::setTransformProperties()
7732 QFETCH(QPointF,origin);
7733 QFETCH(qreal,rotation);
7734 QFETCH(qreal,scale);
7737 result.translate(origin.x(), origin.y());
7738 result.rotate(rotation, Qt::ZAxis);
7739 result.scale(scale, scale);
7740 result.translate(-origin.x(), -origin.y());
7742 QGraphicsScene scene;
7743 QGraphicsRectItem *item = new QGraphicsRectItem(QRectF(0, 0, 100, 100));
7744 scene.addItem(item);
7746 item->setRotation(rotation);
7747 item->setScale(scale);
7748 item->setTransformOriginPoint(origin);
7750 QCOMPARE(item->rotation(), rotation);
7751 QCOMPARE(item->scale(), scale);
7752 QCOMPARE(item->transformOriginPoint(), origin);
7754 QCOMPARE(QTransform(), item->transform());
7755 QCOMPARE(result, item->sceneTransform());
7757 //-----------------------------------------------------------------
7758 //Change the rotation Z
7759 item->setRotation(45);
7761 result2.translate(origin.x(), origin.y());
7763 result2.scale(scale, scale);
7764 result2.translate(-origin.x(), -origin.y());
7766 QCOMPARE(item->rotation(), 45.);
7767 QCOMPARE(item->scale(), scale);
7768 QCOMPARE(item->transformOriginPoint(), origin);
7770 QCOMPARE(QTransform(), item->transform());
7771 QCOMPARE(result2, item->sceneTransform());
7773 //-----------------------------------------------------------------
7774 // calling setTransform() and setPos should change the sceneTransform
7775 item->setTransform(result);
7776 item->setPos(100, -150.5);
7778 QCOMPARE(item->rotation(), 45.);
7779 QCOMPARE(item->scale(), scale);
7780 QCOMPARE(item->transformOriginPoint(), origin);
7781 QCOMPARE(result, item->transform());
7783 QTransform result3(result);
7785 result3.translate(origin.x(), origin.y());
7787 result3.scale(scale, scale);
7788 result3.translate(-origin.x(), -origin.y());
7790 result3 *= QTransform::fromTranslate(100, -150.5); //the pos;
7792 QCOMPARE(result3, item->sceneTransform());
7794 //-----------------------------------------------------
7795 // setting the propertiees should be the same as setting a transform
7796 {//with center origin on the matrix
7797 QGraphicsRectItem *item1 = new QGraphicsRectItem(QRectF(50.2, -150, 230.5, 119));
7798 scene.addItem(item1);
7799 QGraphicsRectItem *item2 = new QGraphicsRectItem(QRectF(50.2, -150, 230.5, 119));
7800 scene.addItem(item2);
7802 item1->setPos(12.3, -5);
7803 item2->setPos(12.3, -5);
7804 item1->setRotation(rotation);
7805 item1->setScale(scale);
7806 item1->setTransformOriginPoint(origin);
7808 item2->setTransform(result);
7810 QCOMPARE_TRANSFORM(item1->sceneTransform(), item2->sceneTransform());
7812 QCOMPARE_TRANSFORM(item1->itemTransform(item2), QTransform());
7813 QCOMPARE_TRANSFORM(item2->itemTransform(item1), QTransform());
7817 class MyStyleOptionTester : public QGraphicsRectItem
7820 MyStyleOptionTester(const QRectF &rect)
7821 : QGraphicsRectItem(rect), startTrack(false)
7824 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0)
7827 //Doesn't use the extended style option so the exposed rect is the boundingRect
7828 if (!(flags() & QGraphicsItem::ItemUsesExtendedStyleOption)) {
7829 QCOMPARE(option->exposedRect, boundingRect());
7830 QCOMPARE(option->matrix, QMatrix());
7832 QVERIFY(option->exposedRect != QRect());
7833 QVERIFY(option->exposedRect != boundingRect());
7834 QCOMPARE(option->matrix, sceneTransform().toAffine());
7837 QGraphicsRectItem::paint(painter, option, widget);
7842 void tst_QGraphicsItem::itemUsesExtendedStyleOption()
7844 QGraphicsScene scene(0, 0, 300, 300);
7845 QGraphicsPixmapItem item;
7846 item.setFlag(QGraphicsItem::ItemUsesExtendedStyleOption, true);
7847 QCOMPARE(item.flags(), QGraphicsItem::GraphicsItemFlags(QGraphicsItem::ItemUsesExtendedStyleOption));
7848 item.setFlag(QGraphicsItem::ItemUsesExtendedStyleOption, false);
7849 QCOMPARE(item.flags(), 0);
7851 //We now test the content of the style option
7852 MyStyleOptionTester *rect = new MyStyleOptionTester(QRect(0, 0, 100, 100));
7853 scene.addItem(rect);
7854 rect->setPos(200, 200);
7856 QGraphicsView view(&scene, &topLevel);
7857 topLevel.setWindowFlags(Qt::X11BypassWindowManagerHint);
7858 rect->startTrack = false;
7860 QVERIFY(QTest::qWaitForWindowExposed(&topLevel));
7862 rect->startTrack = true;
7863 rect->update(10, 10, 10, 10);
7865 rect->startTrack = false;
7866 rect->setFlag(QGraphicsItem::ItemUsesExtendedStyleOption, true);
7867 QVERIFY((rect->flags() & QGraphicsItem::ItemUsesExtendedStyleOption));
7869 rect->startTrack = true;
7870 rect->update(10, 10, 10, 10);
7874 void tst_QGraphicsItem::itemSendsGeometryChanges()
7876 ItemChangeTester item;
7880 QTransform x = QTransform().rotate(45);
7881 QPointF pos(10, 10);
7885 QPointF origin(1.0, 1.0);
7886 item.setTransform(x);
7888 item.setRotation(r);
7890 item.setTransformOriginPoint(origin);
7891 QCOMPARE(item.transform(), x);
7892 QCOMPARE(item.pos(), pos);
7893 QCOMPARE(item.rotation(), r);
7894 QCOMPARE(item.scale(), s);
7895 QCOMPARE(item.transformOriginPoint(), origin);
7896 QCOMPARE(item.changes.size(), 0);
7899 QCOMPARE(item.changes.size(), 2); // opacity
7901 item.setFlag(QGraphicsItem::ItemSendsGeometryChanges);
7902 QCOMPARE(item.changes.size(), 4); // flags
7903 item.setTransform(QTransform());
7904 item.setPos(QPointF());
7905 QCOMPARE(item.changes.size(), 8); // transform + pos
7906 QCOMPARE(item.transform(), QTransform());
7907 QCOMPARE(item.pos(), QPointF());
7908 QCOMPARE(item.opacity(), o);
7909 item.setRotation(0.0);
7911 item.setTransformOriginPoint(0.0, 0.0);
7912 QCOMPARE(item.changes.size(), 14); // rotation + scale + origin
7913 QCOMPARE(item.rotation(), qreal(0.0));
7914 QCOMPARE(item.scale(), qreal(1.0));
7915 QCOMPARE(item.transformOriginPoint(), QPointF(0.0, 0.0));
7917 QCOMPARE(item.changes, QList<QGraphicsItem::GraphicsItemChange>()
7918 << QGraphicsItem::ItemOpacityChange
7919 << QGraphicsItem::ItemOpacityHasChanged
7920 << QGraphicsItem::ItemFlagsChange
7921 << QGraphicsItem::ItemFlagsHaveChanged
7922 << QGraphicsItem::ItemTransformChange
7923 << QGraphicsItem::ItemTransformHasChanged
7924 << QGraphicsItem::ItemPositionChange
7925 << QGraphicsItem::ItemPositionHasChanged
7926 << QGraphicsItem::ItemRotationChange
7927 << QGraphicsItem::ItemRotationHasChanged
7928 << QGraphicsItem::ItemScaleChange
7929 << QGraphicsItem::ItemScaleHasChanged
7930 << QGraphicsItem::ItemTransformOriginPointChange
7931 << QGraphicsItem::ItemTransformOriginPointHasChanged);
7934 // Make sure we update moved items correctly.
7935 void tst_QGraphicsItem::moveItem()
7937 QGraphicsScene scene;
7938 scene.setSceneRect(-50, -50, 200, 200);
7940 MyGraphicsView view(&scene);
7942 QVERIFY(QTest::qWaitForWindowExposed(&view));
7944 EventTester *parent = new EventTester;
7945 EventTester *child = new EventTester(parent);
7946 EventTester *grandChild = new EventTester(child);
7948 #define RESET_COUNTERS \
7949 parent->repaints = 0; \
7950 child->repaints = 0; \
7951 grandChild->repaints = 0; \
7954 scene.addItem(parent);
7959 // Item's boundingRect: (-10, -10, 20, 20).
7960 QRect parentDeviceBoundingRect = parent->deviceTransform(view.viewportTransform())
7961 .mapRect(parent->boundingRect()).toAlignedRect()
7962 .adjusted(-2, -2, 2, 2); // Adjusted for antialiasing.
7964 parent->setPos(20, 20);
7965 qApp->processEvents();
7966 QCOMPARE(parent->repaints, 1);
7967 QCOMPARE(view.repaints, 1);
7968 QRegion expectedParentRegion = parentDeviceBoundingRect; // old position
7969 parentDeviceBoundingRect.translate(20, 20);
7970 expectedParentRegion += parentDeviceBoundingRect; // new position
7971 COMPARE_REGIONS(view.paintedRegion, expectedParentRegion);
7975 child->setPos(20, 20);
7976 qApp->processEvents();
7977 QCOMPARE(parent->repaints, 1);
7978 QCOMPARE(child->repaints, 1);
7979 QCOMPARE(view.repaints, 1);
7980 const QRegion expectedChildRegion = expectedParentRegion.translated(20, 20);
7981 COMPARE_REGIONS(view.paintedRegion, expectedChildRegion);
7985 grandChild->setPos(20, 20);
7986 qApp->processEvents();
7987 QCOMPARE(parent->repaints, 1);
7988 QCOMPARE(child->repaints, 1);
7989 QCOMPARE(grandChild->repaints, 1);
7990 QCOMPARE(view.repaints, 1);
7991 const QRegion expectedGrandChildRegion = expectedParentRegion.translated(40, 40);
7992 COMPARE_REGIONS(view.paintedRegion, expectedGrandChildRegion);
7996 parent->translate(20, 20);
7997 qApp->processEvents();
7998 QCOMPARE(parent->repaints, 1);
7999 QCOMPARE(child->repaints, 1);
8000 QCOMPARE(grandChild->repaints, 1);
8001 QCOMPARE(view.repaints, 1);
8002 expectedParentRegion.translate(20, 20);
8003 expectedParentRegion += expectedChildRegion.translated(20, 20);
8004 expectedParentRegion += expectedGrandChildRegion.translated(20, 20);
8005 COMPARE_REGIONS(view.paintedRegion, expectedParentRegion);
8008 void tst_QGraphicsItem::moveLineItem()
8010 QGraphicsScene scene;
8011 scene.setSceneRect(0, 0, 200, 200);
8012 QGraphicsLineItem *item = new QGraphicsLineItem(0, 0, 100, 0);
8013 item->setPos(50, 50);
8014 scene.addItem(item);
8016 MyGraphicsView view(&scene);
8018 QVERIFY(QTest::qWaitForWindowActive(&view));
8021 QRectF brect = item->boundingRect();
8022 // Do same adjustments as in qgraphicsscene.cpp
8024 brect.adjust(qreal(-0.00001), 0, qreal(0.00001), 0);
8025 if (!brect.height())
8026 brect.adjust(0, qreal(-0.00001), 0, qreal(0.00001));
8027 const QRect itemDeviceBoundingRect = item->deviceTransform(view.viewportTransform())
8028 .mapRect(brect).toAlignedRect();
8029 QRegion expectedRegion = itemDeviceBoundingRect.adjusted(-2, -2, 2, 2); // antialiasing
8031 // Make sure the calculated region is correct.
8034 QTRY_COMPARE(view.paintedRegion, expectedRegion);
8037 // Old position: (50, 50)
8038 item->setPos(50, 100);
8039 expectedRegion += expectedRegion.translated(0, 50);
8041 QCOMPARE(view.paintedRegion, expectedRegion);
8044 void tst_QGraphicsItem::sorting_data()
8046 QTest::addColumn<int>("index");
8048 QTest::newRow("NoIndex") << int(QGraphicsScene::NoIndex);
8049 QTest::newRow("BspTreeIndex") << int(QGraphicsScene::BspTreeIndex);
8052 void tst_QGraphicsItem::sorting()
8054 if (qGuiApp->styleHints()->showIsFullScreen())
8055 QSKIP("Skipped because Platform is auto maximizing");
8057 _paintedItems.clear();
8059 QGraphicsScene scene;
8060 QGraphicsItem *grid[100][100];
8061 for (int x = 0; x < 100; ++x) {
8062 for (int y = 0; y < 100; ++y) {
8063 PainterItem *item = new PainterItem;
8064 item->setPos(x * 25, y * 25);
8065 item->setData(0, QString("%1x%2").arg(x).arg(y));
8067 scene.addItem(item);
8071 PainterItem *item1 = new PainterItem;
8072 PainterItem *item2 = new PainterItem;
8073 item1->setData(0, "item1");
8074 item2->setData(0, "item2");
8075 scene.addItem(item1);
8076 scene.addItem(item2);
8078 QGraphicsView view(&scene);
8079 // Use Qt::Tool as fully decorated windows have a minimum width of 160 on Windows.
8080 view.setWindowFlags(view.windowFlags() | Qt::Tool);
8081 view.setResizeAnchor(QGraphicsView::NoAnchor);
8082 view.setTransformationAnchor(QGraphicsView::NoAnchor);
8083 view.resize(120, 100);
8084 view.setFrameStyle(0);
8086 qApp->setActiveWindow(&view);
8087 QVERIFY(QTest::qWaitForWindowActive(&view));
8090 _paintedItems.clear();
8092 view.viewport()->repaint();
8093 #if defined(Q_OS_MAC)
8094 // There's no difference between repaint and update on the Mac,
8095 // so we have to process events here to make sure we get the event.
8099 QCOMPARE(_paintedItems, QList<QGraphicsItem *>()
8100 << grid[0][0] << grid[0][1] << grid[0][2] << grid[0][3]
8101 << grid[1][0] << grid[1][1] << grid[1][2] << grid[1][3]
8102 << grid[2][0] << grid[2][1] << grid[2][2] << grid[2][3]
8103 << grid[3][0] << grid[3][1] << grid[3][2] << grid[3][3]
8104 << grid[4][0] << grid[4][1] << grid[4][2] << grid[4][3]
8108 void tst_QGraphicsItem::itemHasNoContents()
8110 PainterItem *item1 = new PainterItem;
8111 PainterItem *item2 = new PainterItem;
8112 item2->setParentItem(item1);
8113 item2->setPos(50, 50);
8114 item1->setFlag(QGraphicsItem::ItemHasNoContents);
8115 item1->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
8117 QGraphicsScene scene;
8118 scene.addItem(item1);
8120 QGraphicsView view(&scene);
8122 qApp->setActiveWindow(&view);
8123 QVERIFY(QTest::qWaitForWindowActive(&view));
8124 QTRY_VERIFY(!_paintedItems.isEmpty());
8126 _paintedItems.clear();
8128 view.viewport()->repaint();
8130 // There's no difference between update() and repaint() on the Mac,
8131 // so we have to process events here to make sure we get the event.
8135 QTRY_COMPARE(_paintedItems, QList<QGraphicsItem *>() << item2);
8138 void tst_QGraphicsItem::hitTestUntransformableItem()
8140 QGraphicsScene scene;
8141 scene.setSceneRect(-100, -100, 200, 200);
8143 QGraphicsView view(&scene);
8145 QVERIFY(QTest::qWaitForWindowExposed(&view));
8147 // Confuse the BSP with dummy items.
8148 QGraphicsRectItem *dummy = new QGraphicsRectItem(0, 0, 20, 20);
8149 dummy->setPos(-100, -100);
8150 scene.addItem(dummy);
8151 for (int i = 0; i < 100; ++i) {
8152 QGraphicsItem *parent = dummy;
8153 dummy = new QGraphicsRectItem(0, 0, 20, 20);
8154 dummy->setPos(-100 + i, -100 + i);
8155 dummy->setParentItem(parent);
8158 QGraphicsRectItem *item1 = new QGraphicsRectItem(0, 0, 20, 20);
8159 item1->setPos(-200, -200);
8161 QGraphicsRectItem *item2 = new QGraphicsRectItem(0, 0, 20, 20);
8162 item2->setFlag(QGraphicsItem::ItemIgnoresTransformations);
8163 item2->setParentItem(item1);
8164 item2->setPos(200, 200);
8166 QGraphicsRectItem *item3 = new QGraphicsRectItem(0, 0, 20, 20);
8167 item3->setParentItem(item2);
8168 item3->setPos(80, 80);
8170 scene.addItem(item1);
8173 QList<QGraphicsItem *> items = scene.items(QPointF(80, 80));
8174 QCOMPARE(items.size(), 1);
8175 QCOMPARE(items.at(0), static_cast<QGraphicsItem*>(item3));
8177 scene.setItemIndexMethod(QGraphicsScene::NoIndex);
8180 items = scene.items(QPointF(80, 80));
8181 QCOMPARE(items.size(), 1);
8182 QCOMPARE(items.at(0), static_cast<QGraphicsItem*>(item3));
8185 void tst_QGraphicsItem::hitTestGraphicsEffectItem()
8187 QGraphicsScene scene;
8188 scene.setSceneRect(-100, -100, 200, 200);
8192 QGraphicsView view(&scene, &toplevel);
8193 toplevel.resize(300, 300);
8195 QVERIFY(QTest::qWaitForWindowExposed(&toplevel));
8197 // Confuse the BSP with dummy items.
8198 QGraphicsRectItem *dummy = new QGraphicsRectItem(0, 0, 20, 20);
8199 dummy->setPos(-100, -100);
8200 scene.addItem(dummy);
8201 for (int i = 0; i < 100; ++i) {
8202 QGraphicsItem *parent = dummy;
8203 dummy = new QGraphicsRectItem(0, 0, 20, 20);
8204 dummy->setPos(-100 + i, -100 + i);
8205 dummy->setParentItem(parent);
8208 const QRectF itemBoundingRect(0, 0, 20, 20);
8209 EventTester *item1 = new EventTester;
8210 item1->br = itemBoundingRect;
8211 item1->setPos(-200, -200);
8212 item1->brush = Qt::red;
8214 EventTester *item2 = new EventTester;
8215 item2->br = itemBoundingRect;
8216 item2->setFlag(QGraphicsItem::ItemIgnoresTransformations);
8217 item2->setParentItem(item1);
8218 item2->setPos(200, 200);
8219 item2->brush = Qt::green;
8221 EventTester *item3 = new EventTester;
8222 item3->br = itemBoundingRect;
8223 item3->setParentItem(item2);
8224 item3->setPos(80, 80);
8225 item3->brush = Qt::blue;
8227 scene.addItem(item1);
8230 item1->repaints = 0;
8231 item2->repaints = 0;
8232 item3->repaints = 0;
8234 // Apply shadow effect to the entire sub-tree.
8235 QGraphicsDropShadowEffect *shadow = new QGraphicsDropShadowEffect;
8236 shadow->setOffset(-20, -20);
8237 item1->setGraphicsEffect(shadow);
8240 // Make sure all visible items are repainted.
8241 QCOMPARE(item1->repaints, 1);
8242 QCOMPARE(item2->repaints, 1);
8243 QCOMPARE(item3->repaints, 1);
8245 // Make sure an item doesn't respond to a click on its shadow.
8246 QList<QGraphicsItem *> items = scene.items(QPointF(75, 75));
8247 QVERIFY(items.isEmpty());
8248 items = scene.items(QPointF(80, 80));
8249 QCOMPARE(items.size(), 1);
8250 QCOMPARE(items.at(0), static_cast<QGraphicsItem *>(item3));
8252 scene.setItemIndexMethod(QGraphicsScene::NoIndex);
8255 items = scene.items(QPointF(75, 75));
8256 QVERIFY(items.isEmpty());
8257 items = scene.items(QPointF(80, 80));
8258 QCOMPARE(items.size(), 1);
8259 QCOMPARE(items.at(0), static_cast<QGraphicsItem *>(item3));
8262 void tst_QGraphicsItem::focusProxy()
8264 QGraphicsScene scene;
8265 QEvent activate(QEvent::WindowActivate);
8266 QApplication::sendEvent(&scene, &activate);
8268 QGraphicsItem *item = scene.addRect(0, 0, 10, 10);
8269 item->setFlag(QGraphicsItem::ItemIsFocusable);
8270 QVERIFY(!item->focusProxy());
8272 QGraphicsItem *item2 = scene.addRect(0, 0, 10, 10);
8273 item2->setFlag(QGraphicsItem::ItemIsFocusable);
8274 item->setFocusProxy(item2);
8275 QCOMPARE(item->focusProxy(), item2);
8278 QVERIFY(item->hasFocus());
8279 QVERIFY(item2->hasFocus());
8281 // Try to make a focus chain loop
8283 QTextStream stream(&err);
8284 stream << "QGraphicsItem::setFocusProxy: "
8285 << (void*)item << " is already in the focus proxy chain" << flush;
8286 QTest::ignoreMessage(QtWarningMsg, err.toLatin1().constData());
8287 item2->setFocusProxy(item); // fails
8288 QCOMPARE(item->focusProxy(), (QGraphicsItem *)item2);
8289 QCOMPARE(item2->focusProxy(), (QGraphicsItem *)0);
8291 // Try to assign self as focus proxy
8292 QTest::ignoreMessage(QtWarningMsg, "QGraphicsItem::setFocusProxy: cannot assign self as focus proxy");
8293 item->setFocusProxy(item); // fails
8294 QCOMPARE(item->focusProxy(), (QGraphicsItem *)item2);
8295 QCOMPARE(item2->focusProxy(), (QGraphicsItem *)0);
8297 // Reset the focus proxy
8298 item->setFocusProxy(0);
8299 QCOMPARE(item->focusProxy(), (QGraphicsItem *)0);
8300 QVERIFY(!item->hasFocus());
8301 QVERIFY(item2->hasFocus());
8304 item->setFocusProxy(item2);
8305 QCOMPARE(item->focusProxy(), (QGraphicsItem *)item2);
8307 QCOMPARE(item->focusProxy(), (QGraphicsItem *)0);
8309 // Test event delivery
8310 item2 = scene.addRect(0, 0, 10, 10);
8311 item2->setFlag(QGraphicsItem::ItemIsFocusable);
8312 item->setFocusProxy(item2);
8315 EventSpy focusInSpy(&scene, item, QEvent::FocusIn);
8316 EventSpy focusOutSpy(&scene, item, QEvent::FocusOut);
8317 EventSpy focusInSpy2(&scene, item2, QEvent::FocusIn);
8318 EventSpy focusOutSpy2(&scene, item2, QEvent::FocusOut);
8319 QCOMPARE(focusInSpy.count(), 0);
8320 QCOMPARE(focusOutSpy.count(), 0);
8321 QCOMPARE(focusInSpy2.count(), 0);
8322 QCOMPARE(focusOutSpy2.count(), 0);
8325 QCOMPARE(focusInSpy.count(), 0);
8326 QCOMPARE(focusInSpy2.count(), 1);
8328 QCOMPARE(focusOutSpy.count(), 0);
8329 QCOMPARE(focusOutSpy2.count(), 1);
8331 // Test two items proxying one item.
8332 QGraphicsItem *item3 = scene.addRect(0, 0, 10, 10);
8333 item3->setFlag(QGraphicsItem::ItemIsFocusable);
8334 item3->setFocusProxy(item2); // item and item3 use item2 as proxy
8336 QCOMPARE(item->focusProxy(), item2);
8337 QCOMPARE(item2->focusProxy(), (QGraphicsItem *)0);
8338 QCOMPARE(item3->focusProxy(), item2);
8340 QCOMPARE(item->focusProxy(), (QGraphicsItem *)0);
8341 QCOMPARE(item3->focusProxy(), (QGraphicsItem *)0);
8344 void tst_QGraphicsItem::subFocus()
8346 // Construct a text item that's not part of a scene (yet)
8347 // and has no parent. Setting focus on it will not make
8348 // the item gain input focus; that requires a scene. But
8349 // it does set subfocus, indicating that the item wishes
8350 // to gain focus later.
8351 QGraphicsTextItem *text = new QGraphicsTextItem("Hello");
8352 text->setTextInteractionFlags(Qt::TextEditorInteraction);
8353 QVERIFY(!text->hasFocus());
8355 QVERIFY(!text->hasFocus());
8356 QCOMPARE(text->focusItem(), (QGraphicsItem *)text);
8359 QGraphicsTextItem *text2 = new QGraphicsTextItem("Hi");
8360 text2->setTextInteractionFlags(Qt::TextEditorInteraction);
8361 text2->setPos(30, 30);
8363 // Add both items to a scene and check that it's text that
8365 QGraphicsScene scene;
8366 QEvent activate(QEvent::WindowActivate);
8367 QApplication::sendEvent(&scene, &activate);
8369 scene.addItem(text);
8370 scene.addItem(text2);
8371 QVERIFY(text->hasFocus());
8373 text->setData(0, "text");
8374 text2->setData(0, "text2");
8376 // Remove text2 and set subfocus on it. Then readd. Reparent it onto the
8377 // other item and see that it gains input focus.
8378 scene.removeItem(text2);
8380 scene.addItem(text2);
8381 QCOMPARE(text2->focusItem(), (QGraphicsItem *)text2);
8382 text2->setParentItem(text);
8383 QCOMPARE(text->focusItem(), (QGraphicsItem *)text2);
8384 QCOMPARE(text2->focusItem(), (QGraphicsItem *)text2);
8385 QVERIFY(!text->hasFocus());
8386 QVERIFY(text2->hasFocus());
8388 // Remove both items from the scene, restore subfocus and
8389 // readd them. Now the subfocus should kick in and give
8391 scene.removeItem(text);
8392 QCOMPARE(text->focusItem(), (QGraphicsItem *)0);
8393 QCOMPARE(text2->focusItem(), (QGraphicsItem *)0);
8395 QCOMPARE(text->focusItem(), (QGraphicsItem *)text2);
8396 QCOMPARE(text2->focusItem(), (QGraphicsItem *)text2);
8397 scene.addItem(text);
8399 // Hiding and showing text should pass focus to text2.
8400 QCOMPARE(text->focusItem(), (QGraphicsItem *)text2);
8401 QVERIFY(text2->hasFocus());
8403 // Subfocus should repropagate to root when reparenting.
8404 QGraphicsRectItem *rect = new QGraphicsRectItem;
8405 QGraphicsRectItem *rect2 = new QGraphicsRectItem(rect);
8406 QGraphicsRectItem *rect3 = new QGraphicsRectItem(rect2);
8407 rect3->setFlag(QGraphicsItem::ItemIsFocusable);
8409 text->setData(0, "text");
8410 text2->setData(0, "text2");
8411 rect->setData(0, "rect");
8412 rect2->setData(0, "rect2");
8413 rect3->setData(0, "rect3");
8416 QVERIFY(!rect3->hasFocus());
8417 QCOMPARE(rect->focusItem(), (QGraphicsItem *)rect3);
8418 QCOMPARE(rect2->focusItem(), (QGraphicsItem *)rect3);
8419 QCOMPARE(rect3->focusItem(), (QGraphicsItem *)rect3);
8420 rect->setParentItem(text2);
8421 QCOMPARE(text->focusItem(), (QGraphicsItem *)rect3);
8422 QCOMPARE(text2->focusItem(), (QGraphicsItem *)rect3);
8423 QCOMPARE(rect->focusItem(), (QGraphicsItem *)rect3);
8424 QCOMPARE(rect2->focusItem(), (QGraphicsItem *)rect3);
8425 QCOMPARE(rect3->focusItem(), (QGraphicsItem *)rect3);
8426 QVERIFY(!rect->hasFocus());
8427 QVERIFY(!rect2->hasFocus());
8428 QVERIFY(rect3->hasFocus());
8431 QCOMPARE(text->focusItem(), (QGraphicsItem *)0);
8432 QCOMPARE(text2->focusItem(), (QGraphicsItem *)0);
8433 QCOMPARE(rect->focusItem(), (QGraphicsItem *)0);
8436 void tst_QGraphicsItem::focusProxyDeletion()
8438 QGraphicsRectItem *rect = new QGraphicsRectItem;
8439 QGraphicsRectItem *rect2 = new QGraphicsRectItem;
8440 rect->setFocusProxy(rect2);
8441 QCOMPARE(rect->focusProxy(), (QGraphicsItem *)rect2);
8444 QCOMPARE(rect->focusProxy(), (QGraphicsItem *)0);
8446 rect2 = new QGraphicsRectItem;
8447 rect->setFocusProxy(rect2);
8448 delete rect; // don't crash
8450 rect = new QGraphicsRectItem;
8451 rect->setFocusProxy(rect2);
8452 QGraphicsScene *scene = new QGraphicsScene;
8453 scene->addItem(rect);
8454 scene->addItem(rect2);
8456 QCOMPARE(rect->focusProxy(), (QGraphicsItem *)0);
8458 rect2 = new QGraphicsRectItem;
8459 QTest::ignoreMessage(QtWarningMsg, "QGraphicsItem::setFocusProxy: focus proxy must be in same scene");
8460 rect->setFocusProxy(rect2);
8461 QCOMPARE(rect->focusProxy(), (QGraphicsItem *)0);
8462 scene->addItem(rect2);
8463 rect->setFocusProxy(rect2);
8464 QCOMPARE(rect->focusProxy(), (QGraphicsItem *)rect2);
8465 delete rect; // don't crash
8467 rect = new QGraphicsRectItem;
8468 rect2 = new QGraphicsRectItem;
8469 rect->setFocusProxy(rect2);
8470 QCOMPARE(rect->focusProxy(), (QGraphicsItem *)rect2);
8471 scene->addItem(rect);
8472 scene->addItem(rect2);
8473 rect->setFocusProxy(rect2);
8474 delete scene; // don't crash
8477 void tst_QGraphicsItem::negativeZStacksBehindParent()
8479 QGraphicsRectItem rect;
8480 QCOMPARE(rect.zValue(), qreal(0.0));
8481 QVERIFY(!(rect.flags() & QGraphicsItem::ItemNegativeZStacksBehindParent));
8482 QVERIFY(!(rect.flags() & QGraphicsItem::ItemStacksBehindParent));
8484 QCOMPARE(rect.zValue(), qreal(-1.0));
8485 QVERIFY(!(rect.flags() & QGraphicsItem::ItemStacksBehindParent));
8487 rect.setFlag(QGraphicsItem::ItemNegativeZStacksBehindParent);
8488 QVERIFY(rect.flags() & QGraphicsItem::ItemNegativeZStacksBehindParent);
8489 QVERIFY(!(rect.flags() & QGraphicsItem::ItemStacksBehindParent));
8491 QVERIFY(rect.flags() & QGraphicsItem::ItemStacksBehindParent);
8493 QVERIFY(!(rect.flags() & QGraphicsItem::ItemStacksBehindParent));
8494 rect.setFlag(QGraphicsItem::ItemNegativeZStacksBehindParent, false);
8496 rect.setFlag(QGraphicsItem::ItemNegativeZStacksBehindParent, true);
8497 QVERIFY(rect.flags() & QGraphicsItem::ItemStacksBehindParent);
8498 rect.setFlag(QGraphicsItem::ItemNegativeZStacksBehindParent, false);
8499 QVERIFY(rect.flags() & QGraphicsItem::ItemStacksBehindParent);
8502 void tst_QGraphicsItem::setGraphicsEffect()
8504 // Check that we don't have any effect by default.
8505 QGraphicsItem *item = new QGraphicsRectItem(0, 0, 10, 10);
8506 QVERIFY(!item->graphicsEffect());
8509 QPointer<QGraphicsEffect> blurEffect = new QGraphicsBlurEffect;
8510 item->setGraphicsEffect(blurEffect);
8511 QCOMPARE(item->graphicsEffect(), static_cast<QGraphicsEffect *>(blurEffect));
8513 // Ensure the existing effect is deleted when setting a new one.
8514 QPointer<QGraphicsEffect> shadowEffect = new QGraphicsDropShadowEffect;
8515 item->setGraphicsEffect(shadowEffect);
8516 QVERIFY(!blurEffect);
8517 QCOMPARE(item->graphicsEffect(), static_cast<QGraphicsEffect *>(shadowEffect));
8518 blurEffect = new QGraphicsBlurEffect;
8520 // Ensure the effect is uninstalled when setting it on a new target.
8521 QGraphicsItem *anotherItem = new QGraphicsRectItem(0, 0, 10, 10);
8522 anotherItem->setGraphicsEffect(blurEffect);
8523 item->setGraphicsEffect(blurEffect);
8524 QVERIFY(!anotherItem->graphicsEffect());
8525 QVERIFY(!shadowEffect);
8527 // Ensure the existing effect is deleted when deleting the item.
8529 QVERIFY(!blurEffect);
8532 // Ensure the effect is uninstalled when deleting it
8533 item = new QGraphicsRectItem(0, 0, 10, 10);
8534 blurEffect = new QGraphicsBlurEffect;
8535 item->setGraphicsEffect(blurEffect);
8537 QVERIFY(!item->graphicsEffect());
8539 // Ensure the existing effect is uninstalled and deleted when setting a null effect
8540 blurEffect = new QGraphicsBlurEffect;
8541 item->setGraphicsEffect(blurEffect);
8542 item->setGraphicsEffect(0);
8543 QVERIFY(!item->graphicsEffect());
8544 QVERIFY(!blurEffect);
8549 void tst_QGraphicsItem::panel()
8551 QGraphicsScene scene;
8553 QGraphicsRectItem *panel1 = new QGraphicsRectItem;
8554 QGraphicsRectItem *panel2 = new QGraphicsRectItem;
8555 QGraphicsRectItem *panel3 = new QGraphicsRectItem;
8556 QGraphicsRectItem *panel4 = new QGraphicsRectItem;
8557 QGraphicsRectItem *notPanel1 = new QGraphicsRectItem;
8558 QGraphicsRectItem *notPanel2 = new QGraphicsRectItem;
8559 panel1->setFlag(QGraphicsItem::ItemIsPanel);
8560 panel2->setFlag(QGraphicsItem::ItemIsPanel);
8561 panel3->setFlag(QGraphicsItem::ItemIsPanel);
8562 panel4->setFlag(QGraphicsItem::ItemIsPanel);
8563 scene.addItem(panel1);
8564 scene.addItem(panel2);
8565 scene.addItem(panel3);
8566 scene.addItem(panel4);
8567 scene.addItem(notPanel1);
8568 scene.addItem(notPanel2);
8570 EventSpy spy_activate_panel1(&scene, panel1, QEvent::WindowActivate);
8571 EventSpy spy_deactivate_panel1(&scene, panel1, QEvent::WindowDeactivate);
8572 EventSpy spy_activate_panel2(&scene, panel2, QEvent::WindowActivate);
8573 EventSpy spy_deactivate_panel2(&scene, panel2, QEvent::WindowDeactivate);
8574 EventSpy spy_activate_panel3(&scene, panel3, QEvent::WindowActivate);
8575 EventSpy spy_deactivate_panel3(&scene, panel3, QEvent::WindowDeactivate);
8576 EventSpy spy_activate_panel4(&scene, panel4, QEvent::WindowActivate);
8577 EventSpy spy_deactivate_panel4(&scene, panel4, QEvent::WindowDeactivate);
8578 EventSpy spy_activate_notPanel1(&scene, notPanel1, QEvent::WindowActivate);
8579 EventSpy spy_deactivate_notPanel1(&scene, notPanel1, QEvent::WindowDeactivate);
8580 EventSpy spy_activate_notPanel2(&scene, notPanel1, QEvent::WindowActivate);
8581 EventSpy spy_deactivate_notPanel2(&scene, notPanel1, QEvent::WindowDeactivate);
8583 QCOMPARE(spy_activate_panel1.count(), 0);
8584 QCOMPARE(spy_deactivate_panel1.count(), 0);
8585 QCOMPARE(spy_activate_panel2.count(), 0);
8586 QCOMPARE(spy_deactivate_panel2.count(), 0);
8587 QCOMPARE(spy_activate_panel3.count(), 0);
8588 QCOMPARE(spy_deactivate_panel3.count(), 0);
8589 QCOMPARE(spy_activate_panel4.count(), 0);
8590 QCOMPARE(spy_deactivate_panel4.count(), 0);
8591 QCOMPARE(spy_activate_notPanel1.count(), 0);
8592 QCOMPARE(spy_deactivate_notPanel1.count(), 0);
8593 QCOMPARE(spy_activate_notPanel2.count(), 0);
8594 QCOMPARE(spy_deactivate_notPanel2.count(), 0);
8596 QVERIFY(!scene.activePanel());
8597 QVERIFY(!scene.isActive());
8599 QEvent activate(QEvent::WindowActivate);
8600 QEvent deactivate(QEvent::WindowDeactivate);
8602 QApplication::sendEvent(&scene, &activate);
8604 // No previous activation, so the scene is active.
8605 QVERIFY(scene.isActive());
8606 QCOMPARE(scene.activePanel(), (QGraphicsItem *)panel1);
8607 QVERIFY(panel1->isActive());
8608 QVERIFY(!panel2->isActive());
8609 QVERIFY(!panel3->isActive());
8610 QVERIFY(!panel4->isActive());
8611 QVERIFY(!notPanel1->isActive());
8612 QVERIFY(!notPanel2->isActive());
8613 QCOMPARE(spy_deactivate_notPanel1.count(), 0);
8614 QCOMPARE(spy_deactivate_notPanel2.count(), 0);
8615 QCOMPARE(spy_activate_panel1.count(), 1);
8616 QCOMPARE(spy_activate_panel2.count(), 0);
8617 QCOMPARE(spy_activate_panel3.count(), 0);
8618 QCOMPARE(spy_activate_panel4.count(), 0);
8620 // Switch back to scene.
8621 scene.setActivePanel(0);
8622 QVERIFY(!scene.activePanel());
8623 QVERIFY(!panel1->isActive());
8624 QVERIFY(!panel2->isActive());
8625 QVERIFY(!panel3->isActive());
8626 QVERIFY(!panel4->isActive());
8627 QVERIFY(notPanel1->isActive());
8628 QVERIFY(notPanel2->isActive());
8629 QCOMPARE(spy_activate_notPanel1.count(), 1);
8630 QCOMPARE(spy_activate_notPanel2.count(), 1);
8632 // Deactivate the scene
8633 QApplication::sendEvent(&scene, &deactivate);
8634 QVERIFY(!scene.activePanel());
8635 QVERIFY(!panel1->isActive());
8636 QVERIFY(!panel2->isActive());
8637 QVERIFY(!panel3->isActive());
8638 QVERIFY(!panel4->isActive());
8639 QVERIFY(!notPanel1->isActive());
8640 QVERIFY(!notPanel2->isActive());
8641 QCOMPARE(spy_deactivate_notPanel1.count(), 1);
8642 QCOMPARE(spy_deactivate_notPanel2.count(), 1);
8644 // Reactivate the scene
8645 QApplication::sendEvent(&scene, &activate);
8646 QVERIFY(!scene.activePanel());
8647 QVERIFY(!panel1->isActive());
8648 QVERIFY(!panel2->isActive());
8649 QVERIFY(!panel3->isActive());
8650 QVERIFY(!panel4->isActive());
8651 QVERIFY(notPanel1->isActive());
8652 QVERIFY(notPanel2->isActive());
8653 QCOMPARE(spy_activate_notPanel1.count(), 2);
8654 QCOMPARE(spy_activate_notPanel2.count(), 2);
8657 scene.setActivePanel(panel1);
8658 QVERIFY(panel1->isActive());
8659 QCOMPARE(spy_deactivate_notPanel1.count(), 2);
8660 QCOMPARE(spy_deactivate_notPanel2.count(), 2);
8661 QCOMPARE(spy_activate_panel1.count(), 2);
8663 // Deactivate the scene
8664 QApplication::sendEvent(&scene, &deactivate);
8665 QVERIFY(!panel1->isActive());
8666 QCOMPARE(spy_deactivate_panel1.count(), 2);
8668 // Reactivate the scene
8669 QApplication::sendEvent(&scene, &activate);
8670 QVERIFY(panel1->isActive());
8671 QCOMPARE(spy_activate_panel1.count(), 3);
8673 // Deactivate the scene
8674 QApplication::sendEvent(&scene, &deactivate);
8675 QVERIFY(!panel1->isActive());
8676 QVERIFY(!scene.activePanel());
8677 scene.setActivePanel(0);
8679 // Reactivate the scene
8680 QApplication::sendEvent(&scene, &activate);
8681 QVERIFY(!panel1->isActive());
8684 void tst_QGraphicsItem::panelWithFocusItem()
8686 QGraphicsScene scene;
8687 QEvent activate(QEvent::WindowActivate);
8688 QApplication::sendEvent(&scene, &activate);
8690 QGraphicsRectItem *parentPanel = new QGraphicsRectItem;
8691 QGraphicsRectItem *parentPanelFocusItem = new QGraphicsRectItem(parentPanel);
8692 parentPanel->setFlag(QGraphicsItem::ItemIsPanel);
8693 parentPanelFocusItem->setFlag(QGraphicsItem::ItemIsFocusable);
8694 parentPanelFocusItem->setFocus();
8695 scene.addItem(parentPanel);
8697 QVERIFY(parentPanel->isActive());
8698 QVERIFY(parentPanelFocusItem->hasFocus());
8699 QCOMPARE(parentPanel->focusItem(), (QGraphicsItem *)parentPanelFocusItem);
8700 QCOMPARE(parentPanelFocusItem->focusItem(), (QGraphicsItem *)parentPanelFocusItem);
8702 QGraphicsRectItem *childPanel = new QGraphicsRectItem;
8703 QGraphicsRectItem *childPanelFocusItem = new QGraphicsRectItem(childPanel);
8704 childPanel->setFlag(QGraphicsItem::ItemIsPanel);
8705 childPanelFocusItem->setFlag(QGraphicsItem::ItemIsFocusable);
8706 childPanelFocusItem->setFocus();
8708 QVERIFY(!childPanelFocusItem->hasFocus());
8709 QCOMPARE(childPanel->focusItem(), (QGraphicsItem *)childPanelFocusItem);
8710 QCOMPARE(childPanelFocusItem->focusItem(), (QGraphicsItem *)childPanelFocusItem);
8712 childPanel->setParentItem(parentPanel);
8714 QVERIFY(!parentPanel->isActive());
8715 QVERIFY(!parentPanelFocusItem->hasFocus());
8716 QCOMPARE(parentPanel->focusItem(), (QGraphicsItem *)parentPanelFocusItem);
8717 QCOMPARE(parentPanelFocusItem->focusItem(), (QGraphicsItem *)parentPanelFocusItem);
8719 QVERIFY(childPanel->isActive());
8720 QVERIFY(childPanelFocusItem->hasFocus());
8721 QCOMPARE(childPanel->focusItem(), (QGraphicsItem *)childPanelFocusItem);
8722 QCOMPARE(childPanelFocusItem->focusItem(), (QGraphicsItem *)childPanelFocusItem);
8726 QVERIFY(parentPanel->isActive());
8727 QVERIFY(parentPanelFocusItem->hasFocus());
8728 QCOMPARE(parentPanel->focusItem(), (QGraphicsItem *)parentPanelFocusItem);
8729 QCOMPARE(parentPanelFocusItem->focusItem(), (QGraphicsItem *)parentPanelFocusItem);
8732 void tst_QGraphicsItem::addPanelToActiveScene()
8734 QGraphicsScene scene;
8735 QVERIFY(!scene.isActive());
8737 QGraphicsRectItem *rect = new QGraphicsRectItem;
8738 scene.addItem(rect);
8739 QVERIFY(!rect->isActive());
8740 scene.removeItem(rect);
8742 QEvent activate(QEvent::WindowActivate);
8743 QEvent deactivate(QEvent::WindowDeactivate);
8745 QApplication::sendEvent(&scene, &activate);
8746 QVERIFY(scene.isActive());
8747 scene.addItem(rect);
8748 QVERIFY(rect->isActive());
8749 scene.removeItem(rect);
8751 rect->setFlag(QGraphicsItem::ItemIsPanel);
8752 scene.addItem(rect);
8753 QVERIFY(rect->isActive());
8754 QCOMPARE(scene.activePanel(), (QGraphicsItem *)rect);
8756 QGraphicsRectItem *rect2 = new QGraphicsRectItem;
8757 scene.addItem(rect2);
8758 QVERIFY(rect->isActive());
8759 QCOMPARE(scene.activePanel(), (QGraphicsItem *)rect);
8762 void tst_QGraphicsItem::activate()
8764 QGraphicsScene scene;
8765 QGraphicsRectItem *rect = scene.addRect(-10, -10, 20, 20);
8766 QVERIFY(!rect->isActive());
8768 QEvent activate(QEvent::WindowActivate);
8769 QEvent deactivate(QEvent::WindowDeactivate);
8771 QApplication::sendEvent(&scene, &activate);
8773 // Non-panel item (active when scene is active).
8774 QVERIFY(rect->isActive());
8776 QGraphicsRectItem *rect2 = new QGraphicsRectItem;
8777 rect2->setFlag(QGraphicsItem::ItemIsPanel);
8778 QGraphicsRectItem *rect3 = new QGraphicsRectItem;
8779 rect3->setFlag(QGraphicsItem::ItemIsPanel);
8781 // Test normal activation.
8782 QVERIFY(!rect2->isActive());
8783 scene.addItem(rect2);
8784 QVERIFY(rect2->isActive()); // first panel item is activated
8785 scene.addItem(rect3);
8786 QVERIFY(!rect3->isActive()); // second panel item is _not_ activated
8787 rect3->setActive(true);
8788 QVERIFY(rect3->isActive());
8789 scene.removeItem(rect3);
8790 QVERIFY(!rect3->isActive()); // no panel is active anymore
8791 QCOMPARE(scene.activePanel(), (QGraphicsItem *)0);
8792 scene.addItem(rect3);
8793 QVERIFY(rect3->isActive()); // second panel item is activated
8795 // Test pending activation.
8796 scene.removeItem(rect3);
8797 rect2->setActive(true);
8798 QVERIFY(rect2->isActive()); // first panel item is activated
8799 rect3->setActive(true);
8800 QVERIFY(!rect3->isActive()); // not active (yet)
8801 scene.addItem(rect3);
8802 QVERIFY(rect3->isActive()); // now becomes active
8804 // Test pending deactivation.
8805 scene.removeItem(rect3);
8806 rect3->setActive(false);
8807 scene.addItem(rect3);
8808 QVERIFY(!rect3->isActive()); // doesn't become active
8810 // Child of panel activation.
8811 rect3->setActive(true);
8812 QGraphicsRectItem *rect4 = new QGraphicsRectItem;
8813 rect4->setFlag(QGraphicsItem::ItemIsPanel);
8814 QGraphicsRectItem *rect5 = new QGraphicsRectItem(rect4);
8815 QGraphicsRectItem *rect6 = new QGraphicsRectItem(rect5);
8816 scene.addItem(rect4);
8817 QCOMPARE(scene.activePanel(), (QGraphicsItem *)rect3);
8818 scene.removeItem(rect4);
8819 rect6->setActive(true);
8820 scene.addItem(rect4);
8821 QVERIFY(rect4->isActive());
8822 QVERIFY(rect5->isActive());
8823 QVERIFY(rect6->isActive());
8824 QCOMPARE(scene.activePanel(), (QGraphicsItem *)rect4);
8825 scene.removeItem(rect4); // no active panel
8826 rect6->setActive(false);
8827 scene.addItem(rect4);
8828 QVERIFY(!rect4->isActive());
8829 QVERIFY(!rect5->isActive());
8830 QVERIFY(!rect6->isActive());
8831 QCOMPARE(scene.activePanel(), (QGraphicsItem *)0);
8833 // Controlling auto-activation when the scene changes activation.
8834 rect4->setActive(true);
8835 QApplication::sendEvent(&scene, &deactivate);
8836 QVERIFY(!scene.isActive());
8837 QVERIFY(!rect4->isActive());
8838 rect4->setActive(false);
8839 QApplication::sendEvent(&scene, &activate);
8840 QVERIFY(scene.isActive());
8841 QVERIFY(!scene.activePanel());
8842 QVERIFY(!rect4->isActive());
8845 void tst_QGraphicsItem::setActivePanelOnInactiveScene()
8847 QGraphicsScene scene;
8848 QGraphicsRectItem *item = scene.addRect(QRectF());
8849 QGraphicsRectItem *panel = scene.addRect(QRectF());
8850 panel->setFlag(QGraphicsItem::ItemIsPanel);
8852 EventSpy itemActivateSpy(&scene, item, QEvent::WindowActivate);
8853 EventSpy itemDeactivateSpy(&scene, item, QEvent::WindowDeactivate);
8854 EventSpy panelActivateSpy(&scene, panel, QEvent::WindowActivate);
8855 EventSpy panelDeactivateSpy(&scene, panel, QEvent::WindowDeactivate);
8856 EventSpy sceneActivationChangeSpy(&scene, QEvent::ActivationChange);
8858 scene.setActivePanel(panel);
8859 QCOMPARE(scene.activePanel(), (QGraphicsItem *)0);
8860 QCOMPARE(itemActivateSpy.count(), 0);
8861 QCOMPARE(itemDeactivateSpy.count(), 0);
8862 QCOMPARE(panelActivateSpy.count(), 0);
8863 QCOMPARE(panelDeactivateSpy.count(), 0);
8864 QCOMPARE(sceneActivationChangeSpy.count(), 0);
8867 void tst_QGraphicsItem::activationOnShowHide()
8869 QGraphicsScene scene;
8870 QEvent activate(QEvent::WindowActivate);
8871 QApplication::sendEvent(&scene, &activate);
8873 QGraphicsRectItem *rootPanel = scene.addRect(QRectF());
8874 rootPanel->setFlag(QGraphicsItem::ItemIsPanel);
8875 rootPanel->setActive(true);
8877 QGraphicsRectItem *subPanel = new QGraphicsRectItem;
8878 subPanel->setFlag(QGraphicsItem::ItemIsPanel);
8880 // Reparenting onto an active panel auto-activates the child panel.
8881 subPanel->setParentItem(rootPanel);
8882 QVERIFY(subPanel->isActive());
8883 QVERIFY(!rootPanel->isActive());
8885 // Hiding an active child panel will reactivate the parent panel.
8887 QVERIFY(rootPanel->isActive());
8889 // Showing a child panel will auto-activate it.
8891 QVERIFY(subPanel->isActive());
8892 QVERIFY(!rootPanel->isActive());
8894 // Adding an unrelated panel doesn't affect activation.
8895 QGraphicsRectItem *otherPanel = new QGraphicsRectItem;
8896 otherPanel->setFlag(QGraphicsItem::ItemIsPanel);
8897 scene.addItem(otherPanel);
8898 QVERIFY(subPanel->isActive());
8900 // Showing an unrelated panel doesn't affect activation.
8903 QVERIFY(subPanel->isActive());
8905 // Add a non-panel item.
8906 QGraphicsRectItem *otherItem = new QGraphicsRectItem;
8907 scene.addItem(otherItem);
8908 otherItem->setActive(true);
8909 QVERIFY(otherItem->isActive());
8911 // Reparent a panel onto an active non-panel item.
8912 subPanel->setParentItem(otherItem);
8913 QVERIFY(subPanel->isActive());
8915 // Showing a child panel of a non-panel item will activate it.
8917 QVERIFY(!subPanel->isActive());
8918 QVERIFY(otherItem->isActive());
8920 QVERIFY(subPanel->isActive());
8922 // Hiding a toplevel active panel will pass activation back
8923 // to the non-panel items.
8924 rootPanel->setActive(true);
8926 QVERIFY(!rootPanel->isActive());
8927 QVERIFY(otherItem->isActive());
8930 class MoveWhileDying : public QGraphicsRectItem
8933 MoveWhileDying(QGraphicsItem *parent = 0)
8934 : QGraphicsRectItem(parent)
8938 foreach (QGraphicsItem *c, childItems()) {
8939 foreach (QGraphicsItem *cc, c->childItems()) {
8944 if (QGraphicsItem *p = parentItem()) { p->moveBy(10, 10); }
8948 void tst_QGraphicsItem::moveWhileDeleting()
8950 QGraphicsScene scene;
8951 QGraphicsRectItem *rect = new QGraphicsRectItem;
8952 MoveWhileDying *silly = new MoveWhileDying(rect);
8953 QGraphicsRectItem *child = new QGraphicsRectItem(silly);
8954 scene.addItem(rect);
8955 delete rect; // don't crash!
8957 rect = new QGraphicsRectItem;
8958 silly = new MoveWhileDying(rect);
8959 child = new QGraphicsRectItem(silly);
8961 QGraphicsView view(&scene);
8963 QVERIFY(QTest::qWaitForWindowExposed(&view));
8967 rect = new QGraphicsRectItem;
8968 rect->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
8969 silly = new MoveWhileDying(rect);
8970 child = new QGraphicsRectItem(silly);
8976 rect = new MoveWhileDying;
8977 rect->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
8978 child = new QGraphicsRectItem(rect);
8979 silly = new MoveWhileDying(child);
8986 class MyRectItem : public QGraphicsWidget
8990 MyRectItem(QGraphicsItem *parent = 0) : QGraphicsWidget(parent)
8995 void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
8997 painter->setBrush(brush);
8998 painter->drawRect(boundingRect());
9003 topLevel->collidingItems(Qt::IntersectsItemBoundingRect);
9006 QGraphicsItem *topLevel;
9011 void tst_QGraphicsItem::ensureDirtySceneTransform()
9013 QGraphicsScene scene;
9015 MyRectItem *topLevel = new MyRectItem;
9016 topLevel->setGeometry(0, 0, 100, 100);
9017 topLevel->setPos(-50, -50);
9018 topLevel->brush = QBrush(QColor(Qt::black));
9019 scene.addItem(topLevel);
9021 MyRectItem *parent = new MyRectItem;
9022 parent->topLevel = topLevel;
9023 parent->setGeometry(0, 0, 100, 100);
9024 parent->setPos(0, 0);
9025 parent->brush = QBrush(QColor(Qt::magenta));
9026 parent->setObjectName("parent");
9027 scene.addItem(parent);
9029 MyRectItem *child = new MyRectItem(parent);
9030 child->setGeometry(0, 0, 80, 80);
9031 child->setPos(10, 10);
9032 child->setObjectName("child");
9033 child->brush = QBrush(QColor(Qt::blue));
9035 MyRectItem *child2 = new MyRectItem(parent);
9036 child2->setGeometry(0, 0, 80, 80);
9037 child2->setPos(15, 15);
9038 child2->setObjectName("child2");
9039 child2->brush = QBrush(QColor(Qt::green));
9041 MyRectItem *child3 = new MyRectItem(parent);
9042 child3->setGeometry(0, 0, 80, 80);
9043 child3->setPos(20, 20);
9044 child3->setObjectName("child3");
9045 child3->brush = QBrush(QColor(Qt::gray));
9047 QGraphicsView view(&scene);
9049 QApplication::setActiveWindow(&view);
9050 QVERIFY(QTest::qWaitForWindowActive(&view));
9051 QCOMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
9053 //We move the parent
9055 QApplication::processEvents();
9057 //We check if all items moved
9058 QCOMPARE(child->pos(), QPointF(10, 10));
9059 QCOMPARE(child2->pos(), QPointF(15, 15));
9060 QCOMPARE(child3->pos(), QPointF(20, 20));
9062 QCOMPARE(child->sceneBoundingRect(), QRectF(-90, -90, 80, 80));
9063 QCOMPARE(child2->sceneBoundingRect(), QRectF(-85, -85, 80, 80));
9064 QCOMPARE(child3->sceneBoundingRect(), QRectF(-80, -80, 80, 80));
9066 QCOMPARE(child->sceneTransform(), QTransform::fromTranslate(-90, -90));
9067 QCOMPARE(child2->sceneTransform(), QTransform::fromTranslate(-85, -85));
9068 QCOMPARE(child3->sceneTransform(), QTransform::fromTranslate(-80, -80));
9071 void tst_QGraphicsItem::focusScope()
9073 // ItemIsFocusScope is an internal feature (for now).
9074 QGraphicsScene scene;
9076 QGraphicsRectItem *scope3 = new QGraphicsRectItem;
9077 scope3->setData(0, "scope3");
9078 scope3->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsFocusScope);
9080 QVERIFY(!scope3->focusScopeItem());
9081 QCOMPARE(scope3->focusItem(), (QGraphicsItem *)scope3);
9083 QGraphicsRectItem *scope2 = new QGraphicsRectItem;
9084 scope2->setData(0, "scope2");
9085 scope2->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsFocusScope);
9087 QVERIFY(!scope2->focusScopeItem());
9088 scope3->setParentItem(scope2);
9089 QCOMPARE(scope2->focusScopeItem(), (QGraphicsItem *)scope3);
9090 QCOMPARE(scope2->focusItem(), (QGraphicsItem *)scope3);
9092 QGraphicsRectItem *scope1 = new QGraphicsRectItem;
9093 scope1->setData(0, "scope1");
9094 scope1->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsFocusScope);
9096 QVERIFY(!scope1->focusScopeItem());
9097 scope2->setParentItem(scope1);
9099 QCOMPARE(scope1->focusItem(), (QGraphicsItem *)scope3);
9100 QCOMPARE(scope2->focusItem(), (QGraphicsItem *)scope3);
9101 QCOMPARE(scope3->focusItem(), (QGraphicsItem *)scope3);
9102 QCOMPARE(scope1->focusScopeItem(), (QGraphicsItem *)scope2);
9103 QCOMPARE(scope2->focusScopeItem(), (QGraphicsItem *)scope3);
9104 QCOMPARE(scope3->focusScopeItem(), (QGraphicsItem *)0);
9106 scene.addItem(scope1);
9108 QEvent windowActivate(QEvent::WindowActivate);
9109 qApp->sendEvent(&scene, &windowActivate);
9112 QCOMPARE(scope1->focusItem(), (QGraphicsItem *)scope3);
9113 QCOMPARE(scope2->focusItem(), (QGraphicsItem *)scope3);
9114 QCOMPARE(scope3->focusItem(), (QGraphicsItem *)scope3);
9115 QCOMPARE(scope1->focusScopeItem(), (QGraphicsItem *)scope2);
9116 QCOMPARE(scope2->focusScopeItem(), (QGraphicsItem *)scope3);
9117 QCOMPARE(scope3->focusScopeItem(), (QGraphicsItem *)0);
9119 QVERIFY(scope3->hasFocus());
9122 QVERIFY(scope2->hasFocus());
9124 QVERIFY(scope1->hasFocus());
9126 QVERIFY(scope2->hasFocus());
9128 QVERIFY(scope3->hasFocus());
9130 QVERIFY(!scope3->hasFocus());
9132 QVERIFY(scope3->hasFocus());
9133 scope3->clearFocus();
9134 QVERIFY(scope2->hasFocus());
9135 scope2->clearFocus();
9136 QVERIFY(scope1->hasFocus());
9139 QVERIFY(!scope2->hasFocus());
9140 QVERIFY(scope1->hasFocus());
9142 QVERIFY(scope2->hasFocus());
9144 QVERIFY(scope3->hasFocus());
9146 QGraphicsRectItem *rect4 = new QGraphicsRectItem;
9147 rect4->setData(0, "rect4");
9148 rect4->setParentItem(scope3);
9150 QGraphicsRectItem *rect5 = new QGraphicsRectItem;
9151 rect5->setData(0, "rect5");
9152 rect5->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsFocusScope);
9154 rect5->setParentItem(rect4);
9155 QCOMPARE(scope3->focusScopeItem(), (QGraphicsItem *)rect5);
9156 QVERIFY(rect5->hasFocus());
9158 rect4->setParentItem(0);
9159 QVERIFY(rect5->hasFocus());
9160 QCOMPARE(scope3->focusScopeItem(), (QGraphicsItem *)0);
9161 QCOMPARE(scope3->focusItem(), (QGraphicsItem *)0);
9162 QVERIFY(!scope3->hasFocus());
9164 QGraphicsRectItem *rectA = new QGraphicsRectItem;
9165 QGraphicsRectItem *scopeA = new QGraphicsRectItem(rectA);
9166 scopeA->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsFocusScope);
9168 QGraphicsRectItem *scopeB = new QGraphicsRectItem(scopeA);
9169 scopeB->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsFocusScope);
9172 scene.addItem(rectA);
9173 QVERIFY(rect5->hasFocus());
9174 QVERIFY(!scopeB->hasFocus());
9177 QVERIFY(scopeB->hasFocus());
9178 QCOMPARE(scopeB->focusItem(), (QGraphicsItem *)scopeB);
9181 void tst_QGraphicsItem::focusScope2()
9183 QGraphicsRectItem *child1 = new QGraphicsRectItem;
9184 child1->setFlags(QGraphicsItem::ItemIsFocusable);
9186 QCOMPARE(child1->focusItem(), (QGraphicsItem *)child1);
9188 QGraphicsRectItem *child2 = new QGraphicsRectItem;
9189 child2->setFlags(QGraphicsItem::ItemIsFocusable);
9191 QGraphicsRectItem *rootFocusScope = new QGraphicsRectItem;
9192 rootFocusScope->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsFocusScope);
9193 rootFocusScope->setFocus();
9194 QCOMPARE(rootFocusScope->focusItem(), (QGraphicsItem *)rootFocusScope);
9196 child1->setParentItem(rootFocusScope);
9197 child2->setParentItem(rootFocusScope);
9199 QCOMPARE(rootFocusScope->focusScopeItem(), (QGraphicsItem *)child1);
9200 QCOMPARE(rootFocusScope->focusItem(), (QGraphicsItem *)child1);
9202 QGraphicsRectItem *siblingChild1 = new QGraphicsRectItem;
9203 siblingChild1->setFlags(QGraphicsItem::ItemIsFocusable);
9204 siblingChild1->setFocus();
9206 QGraphicsRectItem *siblingChild2 = new QGraphicsRectItem;
9207 siblingChild2->setFlags(QGraphicsItem::ItemIsFocusable);
9209 QGraphicsRectItem *siblingFocusScope = new QGraphicsRectItem;
9210 siblingFocusScope->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsFocusScope);
9212 siblingChild1->setParentItem(siblingFocusScope);
9213 siblingChild2->setParentItem(siblingFocusScope);
9215 QCOMPARE(siblingFocusScope->focusScopeItem(), (QGraphicsItem *)siblingChild1);
9216 QCOMPARE(siblingFocusScope->focusItem(), (QGraphicsItem *)0);
9218 QGraphicsItem *root = new QGraphicsRectItem;
9219 rootFocusScope->setParentItem(root);
9220 siblingFocusScope->setParentItem(root);
9222 QCOMPARE(root->focusItem(), (QGraphicsItem *)child1);
9224 QGraphicsScene scene;
9225 scene.addItem(root);
9227 QEvent activate(QEvent::WindowActivate);
9228 qApp->sendEvent(&scene, &activate);
9231 QCOMPARE(scene.focusItem(), (QGraphicsItem *)child1);
9233 // You cannot set focus on a descendant of a focus scope directly;
9234 // this will only change the scope's focus scope item pointer. If
9235 // you want to give true input focus, you must set it directly on
9237 siblingChild2->setFocus();
9238 QVERIFY(!siblingChild2->hasFocus());
9239 QVERIFY(!siblingChild2->focusItem());
9240 QCOMPARE(siblingFocusScope->focusScopeItem(), (QGraphicsItem *)siblingChild2);
9241 QCOMPARE(siblingFocusScope->focusItem(), (QGraphicsItem *)0);
9243 // Set focus on the scope; focus is forwarded to the focus scope item.
9244 siblingFocusScope->setFocus();
9245 QVERIFY(siblingChild2->hasFocus());
9246 QVERIFY(siblingChild2->focusItem());
9247 QCOMPARE(siblingFocusScope->focusScopeItem(), (QGraphicsItem *)siblingChild2);
9248 QCOMPARE(siblingFocusScope->focusItem(), (QGraphicsItem *)siblingChild2);
9251 void tst_QGraphicsItem::stackBefore()
9253 QGraphicsRectItem parent;
9254 QGraphicsRectItem *child1 = new QGraphicsRectItem(QRectF(0, 0, 5, 5), &parent);
9255 QGraphicsRectItem *child2 = new QGraphicsRectItem(QRectF(0, 0, 5, 5), &parent);
9256 QGraphicsRectItem *child3 = new QGraphicsRectItem(QRectF(0, 0, 5, 5), &parent);
9257 QGraphicsRectItem *child4 = new QGraphicsRectItem(QRectF(0, 0, 5, 5), &parent);
9258 QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child1 << child2 << child3 << child4));
9259 child1->setData(0, "child1");
9260 child2->setData(0, "child2");
9261 child3->setData(0, "child3");
9262 child4->setData(0, "child4");
9264 // Remove and append
9265 child2->setParentItem(0);
9266 child2->setParentItem(&parent);
9267 QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child1 << child3 << child4 << child2));
9269 // Move child2 before child1
9270 child2->stackBefore(child1); // 2134
9271 QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child2 << child1 << child3 << child4));
9272 child2->stackBefore(child2); // 2134
9273 QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child2 << child1 << child3 << child4));
9274 child1->setZValue(1); // 2341
9275 QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child2 << child3 << child4 << child1));
9276 child1->stackBefore(child2); // 2341
9277 QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child2 << child3 << child4 << child1));
9278 child1->setZValue(0); // 1234
9279 QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child1 << child2 << child3 << child4));
9280 child4->stackBefore(child1); // 4123
9281 QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child4 << child1 << child2 << child3));
9282 child4->setZValue(1); // 1234 (4123)
9283 QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child1 << child2 << child3 << child4));
9284 child3->stackBefore(child1); // 3124 (4312)
9285 QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child3 << child1 << child2 << child4));
9286 child4->setZValue(0); // 4312
9287 QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child4 << child3 << child1 << child2));
9289 // Make them all toplevels
9290 child1->setParentItem(0);
9291 child2->setParentItem(0);
9292 child3->setParentItem(0);
9293 child4->setParentItem(0);
9295 QGraphicsScene scene;
9296 scene.addItem(child1);
9297 scene.addItem(child2);
9298 scene.addItem(child3);
9299 scene.addItem(child4);
9300 QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder),
9301 (QList<QGraphicsItem *>() << child1 << child2 << child3 << child4));
9303 // Remove and append
9304 scene.removeItem(child2);
9305 scene.addItem(child2);
9306 QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child1 << child3 << child4 << child2));
9308 // Move child2 before child1
9309 child2->stackBefore(child1); // 2134
9310 QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child2 << child1 << child3 << child4));
9311 child2->stackBefore(child2); // 2134
9312 QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child2 << child1 << child3 << child4));
9313 child1->setZValue(1); // 2341
9314 QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child2 << child3 << child4 << child1));
9315 child1->stackBefore(child2); // 2341
9316 QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child2 << child3 << child4 << child1));
9317 child1->setZValue(0); // 1234
9318 QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child1 << child2 << child3 << child4));
9319 child4->stackBefore(child1); // 4123
9320 QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child4 << child1 << child2 << child3));
9321 child4->setZValue(1); // 1234 (4123)
9322 QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child1 << child2 << child3 << child4));
9323 child3->stackBefore(child1); // 3124 (4312)
9324 QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child3 << child1 << child2 << child4));
9325 child4->setZValue(0); // 4312
9326 QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child4 << child3 << child1 << child2));
9329 void tst_QGraphicsItem::QTBUG_4233_updateCachedWithSceneRect()
9331 EventTester *tester = new EventTester;
9332 tester->setCacheMode(QGraphicsItem::ItemCoordinateCache);
9334 QGraphicsScene scene;
9335 scene.addItem(tester);
9336 scene.setSceneRect(-100, -100, 200, 200); // contains the tester item
9338 QGraphicsView view(&scene);
9340 QApplication::setActiveWindow(&view);
9341 QVERIFY(QTest::qWaitForWindowActive(&view));
9342 QCOMPARE(QApplication::activeWindow(), (QWidget *)&view);
9344 QTRY_COMPARE(tester->repaints, 1);
9346 scene.update(); // triggers "updateAll" optimization
9347 qApp->processEvents();
9348 qApp->processEvents(); // in 4.6 only one processEvents is necessary
9350 QCOMPARE(tester->repaints, 1);
9352 scene.update(); // triggers "updateAll" optimization
9354 qApp->processEvents();
9355 qApp->processEvents(); // in 4.6 only one processEvents is necessary
9357 QCOMPARE(tester->repaints, 2);
9360 void tst_QGraphicsItem::sceneModality()
9362 // 1) Test mouse events (delivery/propagation/redirection)
9363 // 2) Test hover events (incl. leave on block, enter on unblock)
9364 // 3) Test cursor stuff (incl. unset on block, set on unblock)
9365 // 4) Test clickfocus
9366 // 5) Test grab/ungrab events (possibly ungrab on block, regrab on unblock)
9367 // 6) ### modality for non-panels is unsupported for now
9368 QGraphicsScene scene;
9370 QGraphicsRectItem *bottomItem = scene.addRect(-150, -100, 300, 200);
9371 bottomItem->setFlag(QGraphicsItem::ItemIsFocusable);
9372 bottomItem->setBrush(Qt::yellow);
9374 QGraphicsRectItem *leftParent = scene.addRect(-50, -50, 100, 100);
9375 leftParent->setFlag(QGraphicsItem::ItemIsPanel);
9376 leftParent->setBrush(Qt::blue);
9378 QGraphicsRectItem *leftChild = scene.addRect(-25, -25, 50, 50);
9379 leftChild->setFlag(QGraphicsItem::ItemIsPanel);
9380 leftChild->setBrush(Qt::green);
9381 leftChild->setParentItem(leftParent);
9383 QGraphicsRectItem *rightParent = scene.addRect(-50, -50, 100, 100);
9384 rightParent->setFlag(QGraphicsItem::ItemIsPanel);
9385 rightParent->setBrush(Qt::red);
9386 QGraphicsRectItem *rightChild = scene.addRect(-25, -25, 50, 50);
9387 rightChild->setFlag(QGraphicsItem::ItemIsPanel);
9388 rightChild->setBrush(Qt::gray);
9389 rightChild->setParentItem(rightParent);
9391 leftParent->setPos(-75, 0);
9392 rightParent->setPos(75, 0);
9394 bottomItem->setData(0, "bottomItem");
9395 leftParent->setData(0, "leftParent");
9396 leftChild->setData(0, "leftChild");
9397 rightParent->setData(0, "rightParent");
9398 rightChild->setData(0, "rightChild");
9400 scene.setSceneRect(scene.itemsBoundingRect().adjusted(-50, -50, 50, 50));
9402 EventSpy2 leftParentSpy(&scene, leftParent);
9403 EventSpy2 leftChildSpy(&scene, leftChild);
9404 EventSpy2 rightParentSpy(&scene, rightParent);
9405 EventSpy2 rightChildSpy(&scene, rightChild);
9406 EventSpy2 bottomItemSpy(&scene, bottomItem);
9408 // Scene modality, also test multiple scene modal items
9409 leftChild->setPanelModality(QGraphicsItem::SceneModal);
9410 QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0);
9411 QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1);
9412 QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 1);
9413 QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 1);
9414 QCOMPARE(bottomItemSpy.counts[QEvent::WindowBlocked], 0); // not a panel
9416 // Click inside left child
9417 sendMouseClick(&scene, leftChild->scenePos(), Qt::LeftButton);
9418 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 1);
9419 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMouseRelease], 0); // no grab
9420 QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9421 QCOMPARE(rightParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9422 QCOMPARE(rightChildSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9423 QCOMPARE(bottomItemSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9425 // Click on left parent, event goes to modal child
9426 sendMouseClick(&scene, leftParent->sceneBoundingRect().topLeft() + QPointF(5, 5), Qt::LeftButton);
9427 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 2);
9428 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMouseRelease], 0); // no grab
9429 QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9430 QCOMPARE(rightParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9431 QCOMPARE(rightChildSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9432 QCOMPARE(bottomItemSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9434 // Click on all other items and outside the items
9435 sendMouseClick(&scene, rightParent->sceneBoundingRect().topLeft() + QPointF(5, 5), Qt::LeftButton);
9436 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 3);
9437 sendMouseClick(&scene, rightChild->scenePos(), Qt::LeftButton);
9438 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 4);
9439 sendMouseClick(&scene, bottomItem->scenePos(), Qt::LeftButton);
9440 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 5);
9441 sendMouseClick(&scene, QPointF(10000, 10000), Qt::LeftButton);
9442 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 6);
9443 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMouseRelease], 0); // no grab
9444 QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9445 QCOMPARE(rightParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9446 QCOMPARE(rightChildSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9447 QCOMPARE(bottomItemSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9449 leftChildSpy.counts.clear();
9450 rightChildSpy.counts.clear();
9451 leftParentSpy.counts.clear();
9452 rightParentSpy.counts.clear();
9453 bottomItemSpy.counts.clear();
9455 leftChild->setPanelModality(QGraphicsItem::NonModal);
9456 QCOMPARE(leftChildSpy.counts[QEvent::WindowUnblocked], 0);
9457 QCOMPARE(rightChildSpy.counts[QEvent::WindowUnblocked], 1);
9458 QCOMPARE(leftParentSpy.counts[QEvent::WindowUnblocked], 1);
9459 QCOMPARE(rightParentSpy.counts[QEvent::WindowUnblocked], 1);
9460 QCOMPARE(bottomItemSpy.counts[QEvent::WindowUnblocked], 0);
9462 // Left parent enters scene modality.
9463 leftParent->setPanelModality(QGraphicsItem::SceneModal);
9464 QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0);
9465 QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 1);
9466 QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 0);
9467 QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 1);
9468 QCOMPARE(bottomItemSpy.counts[QEvent::WindowBlocked], 0);
9470 // Click inside left child.
9471 sendMouseClick(&scene, leftChild->scenePos(), Qt::LeftButton);
9472 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 1);
9473 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMouseRelease], 0);
9474 QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // panel stops propagation
9475 QCOMPARE(rightParentSpy.counts[QEvent::GraphicsSceneMousePress], 0);
9476 QCOMPARE(rightChildSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9477 QCOMPARE(bottomItemSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9479 // Click on left parent.
9480 sendMouseClick(&scene, leftParent->sceneBoundingRect().topLeft() + QPointF(5, 5), Qt::LeftButton);
9481 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 1);
9482 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMouseRelease], 0);
9483 QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 1);
9484 QCOMPARE(rightParentSpy.counts[QEvent::GraphicsSceneMousePress], 0);
9485 QCOMPARE(rightChildSpy.counts[QEvent::GraphicsSceneMousePress], 0);
9486 QCOMPARE(bottomItemSpy.counts[QEvent::GraphicsSceneMousePress], 0);
9488 // Click on all other items and outside the items
9489 sendMouseClick(&scene, rightParent->sceneBoundingRect().topLeft() + QPointF(5, 5), Qt::LeftButton);
9490 QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 2);
9491 sendMouseClick(&scene, rightChild->scenePos(), Qt::LeftButton);
9492 QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 3);
9493 sendMouseClick(&scene, bottomItem->scenePos(), Qt::LeftButton);
9494 QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 4);
9495 sendMouseClick(&scene, QPointF(10000, 10000), Qt::LeftButton);
9496 QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 5);
9497 QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMouseRelease], 0);
9498 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 1);
9499 QCOMPARE(rightParentSpy.counts[QEvent::GraphicsSceneMousePress], 0);
9500 QCOMPARE(rightChildSpy.counts[QEvent::GraphicsSceneMousePress], 0);
9501 QCOMPARE(bottomItemSpy.counts[QEvent::GraphicsSceneMousePress], 0);
9503 leftChildSpy.counts.clear();
9504 rightChildSpy.counts.clear();
9505 leftParentSpy.counts.clear();
9506 rightParentSpy.counts.clear();
9507 bottomItemSpy.counts.clear();
9509 // Now both left parent and child are scene modal. Left parent is blocked.
9510 leftChild->setPanelModality(QGraphicsItem::SceneModal);
9511 QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0);
9512 QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 0);
9513 QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1);
9514 QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 0);
9515 QCOMPARE(bottomItemSpy.counts[QEvent::WindowBlocked], 0);
9517 // Click inside left child
9518 sendMouseClick(&scene, leftChild->scenePos(), Qt::LeftButton);
9519 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 1);
9520 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMouseRelease], 0); // no grab
9521 QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9522 QCOMPARE(rightParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9523 QCOMPARE(rightChildSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9524 QCOMPARE(bottomItemSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9526 // Click on left parent, event goes to modal child
9527 sendMouseClick(&scene, leftParent->sceneBoundingRect().topLeft() + QPointF(5, 5), Qt::LeftButton);
9528 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 2);
9529 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMouseRelease], 0); // no grab
9530 QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9531 QCOMPARE(rightParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9532 QCOMPARE(rightChildSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9533 QCOMPARE(bottomItemSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9535 // Click on all other items and outside the items
9536 sendMouseClick(&scene, rightParent->sceneBoundingRect().topLeft() + QPointF(5, 5), Qt::LeftButton);
9537 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 3);
9538 sendMouseClick(&scene, rightChild->scenePos(), Qt::LeftButton);
9539 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 4);
9540 sendMouseClick(&scene, bottomItem->scenePos(), Qt::LeftButton);
9541 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 5);
9542 sendMouseClick(&scene, QPointF(10000, 10000), Qt::LeftButton);
9543 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 6);
9544 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMouseRelease], 0); // no grab
9545 QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9546 QCOMPARE(rightParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9547 QCOMPARE(rightChildSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9548 QCOMPARE(bottomItemSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9550 leftChildSpy.counts.clear();
9551 rightChildSpy.counts.clear();
9552 leftParentSpy.counts.clear();
9553 rightParentSpy.counts.clear();
9554 bottomItemSpy.counts.clear();
9556 // Right child enters scene modality, only left child is blocked.
9557 rightChild->setPanelModality(QGraphicsItem::SceneModal);
9558 QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 1);
9559 QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 0);
9560 QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 0);
9561 QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 0);
9562 QCOMPARE(bottomItemSpy.counts[QEvent::WindowBlocked], 0);
9565 void tst_QGraphicsItem::panelModality()
9567 // 1) Test mouse events (delivery/propagation/redirection)
9568 // 2) Test hover events (incl. leave on block, enter on unblock)
9569 // 3) Test cursor stuff (incl. unset on block, set on unblock)
9570 // 4) Test clickfocus
9571 // 5) Test grab/ungrab events (possibly ungrab on block, regrab on unblock)
9572 // 6) ### modality for non-panels is unsupported for now
9573 QGraphicsScene scene;
9575 QGraphicsRectItem *bottomItem = scene.addRect(-150, -100, 300, 200);
9576 bottomItem->setFlag(QGraphicsItem::ItemIsFocusable);
9577 bottomItem->setBrush(Qt::yellow);
9579 QGraphicsRectItem *leftParent = scene.addRect(-50, -50, 100, 100);
9580 leftParent->setFlag(QGraphicsItem::ItemIsPanel);
9581 leftParent->setBrush(Qt::blue);
9583 QGraphicsRectItem *leftChild = scene.addRect(-25, -25, 50, 50);
9584 leftChild->setFlag(QGraphicsItem::ItemIsPanel);
9585 leftChild->setBrush(Qt::green);
9586 leftChild->setParentItem(leftParent);
9588 QGraphicsRectItem *rightParent = scene.addRect(-50, -50, 100, 100);
9589 rightParent->setFlag(QGraphicsItem::ItemIsPanel);
9590 rightParent->setBrush(Qt::red);
9591 QGraphicsRectItem *rightChild = scene.addRect(-25, -25, 50, 50);
9592 rightChild->setFlag(QGraphicsItem::ItemIsPanel);
9593 rightChild->setBrush(Qt::gray);
9594 rightChild->setParentItem(rightParent);
9596 leftParent->setPos(-75, 0);
9597 rightParent->setPos(75, 0);
9599 bottomItem->setData(0, "bottomItem");
9600 leftParent->setData(0, "leftParent");
9601 leftChild->setData(0, "leftChild");
9602 rightParent->setData(0, "rightParent");
9603 rightChild->setData(0, "rightChild");
9605 scene.setSceneRect(scene.itemsBoundingRect().adjusted(-50, -50, 50, 50));
9607 EventSpy2 leftParentSpy(&scene, leftParent);
9608 EventSpy2 leftChildSpy(&scene, leftChild);
9609 EventSpy2 rightParentSpy(&scene, rightParent);
9610 EventSpy2 rightChildSpy(&scene, rightChild);
9611 EventSpy2 bottomItemSpy(&scene, bottomItem);
9613 // Left Child enters panel modality, only left parent is blocked.
9614 leftChild->setPanelModality(QGraphicsItem::PanelModal);
9615 QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0);
9616 QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 0);
9617 QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1);
9618 QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 0);
9619 QCOMPARE(bottomItemSpy.counts[QEvent::WindowBlocked], 0);
9621 leftChild->setPanelModality(QGraphicsItem::NonModal);
9622 leftChildSpy.counts.clear();
9623 rightChildSpy.counts.clear();
9624 leftParentSpy.counts.clear();
9625 rightParentSpy.counts.clear();
9626 bottomItemSpy.counts.clear();
9628 // Left parent enter panel modality, nothing is blocked.
9629 leftParent->setPanelModality(QGraphicsItem::PanelModal);
9630 QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0);
9631 QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 0);
9632 QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 0);
9633 QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 0);
9634 QCOMPARE(bottomItemSpy.counts[QEvent::WindowBlocked], 0);
9636 // Left child enters panel modality, left parent is blocked again.
9637 leftChild->setPanelModality(QGraphicsItem::PanelModal);
9638 QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0);
9639 QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 0);
9640 QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1);
9641 QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 0);
9642 QCOMPARE(bottomItemSpy.counts[QEvent::WindowBlocked], 0);
9644 leftChildSpy.counts.clear();
9645 rightChildSpy.counts.clear();
9646 leftParentSpy.counts.clear();
9647 rightParentSpy.counts.clear();
9648 bottomItemSpy.counts.clear();
9650 leftChild->setPanelModality(QGraphicsItem::NonModal);
9651 QCOMPARE(leftParentSpy.counts[QEvent::WindowUnblocked], 1);
9652 leftParent->setPanelModality(QGraphicsItem::NonModal);
9653 QCOMPARE(leftChildSpy.counts[QEvent::WindowUnblocked], 0);
9654 QCOMPARE(rightChildSpy.counts[QEvent::WindowUnblocked], 0);
9655 QCOMPARE(leftParentSpy.counts[QEvent::WindowUnblocked], 1);
9656 QCOMPARE(rightParentSpy.counts[QEvent::WindowUnblocked], 0);
9657 QCOMPARE(bottomItemSpy.counts[QEvent::WindowUnblocked], 0);
9659 leftChildSpy.counts.clear();
9660 rightChildSpy.counts.clear();
9661 leftParentSpy.counts.clear();
9662 rightParentSpy.counts.clear();
9663 bottomItemSpy.counts.clear();
9665 // Left and right child enter panel modality, both parents are blocked.
9666 rightChild->setPanelModality(QGraphicsItem::PanelModal);
9667 QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 0);
9668 QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 1);
9669 leftChild->setPanelModality(QGraphicsItem::PanelModal);
9670 QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1);
9671 QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 1);
9674 void tst_QGraphicsItem::mixedModality()
9676 // 1) Test mouse events (delivery/propagation/redirection)
9677 // 2) Test hover events (incl. leave on block, enter on unblock)
9678 // 3) Test cursor stuff (incl. unset on block, set on unblock)
9679 // 4) Test clickfocus
9680 // 5) Test grab/ungrab events (possibly ungrab on block, regrab on unblock)
9681 // 6) ### modality for non-panels is unsupported for now
9682 QGraphicsScene scene;
9684 QGraphicsRectItem *bottomItem = scene.addRect(-150, -100, 300, 200);
9685 bottomItem->setFlag(QGraphicsItem::ItemIsFocusable);
9686 bottomItem->setBrush(Qt::yellow);
9688 QGraphicsRectItem *leftParent = scene.addRect(-50, -50, 100, 100);
9689 leftParent->setFlag(QGraphicsItem::ItemIsPanel);
9690 leftParent->setBrush(Qt::blue);
9692 QGraphicsRectItem *leftChild = scene.addRect(-25, -25, 50, 50);
9693 leftChild->setFlag(QGraphicsItem::ItemIsPanel);
9694 leftChild->setBrush(Qt::green);
9695 leftChild->setParentItem(leftParent);
9697 QGraphicsRectItem *rightParent = scene.addRect(-50, -50, 100, 100);
9698 rightParent->setFlag(QGraphicsItem::ItemIsPanel);
9699 rightParent->setBrush(Qt::red);
9700 QGraphicsRectItem *rightChild = scene.addRect(-25, -25, 50, 50);
9701 rightChild->setFlag(QGraphicsItem::ItemIsPanel);
9702 rightChild->setBrush(Qt::gray);
9703 rightChild->setParentItem(rightParent);
9705 leftParent->setPos(-75, 0);
9706 rightParent->setPos(75, 0);
9708 bottomItem->setData(0, "bottomItem");
9709 leftParent->setData(0, "leftParent");
9710 leftChild->setData(0, "leftChild");
9711 rightParent->setData(0, "rightParent");
9712 rightChild->setData(0, "rightChild");
9714 scene.setSceneRect(scene.itemsBoundingRect().adjusted(-50, -50, 50, 50));
9716 EventSpy2 leftParentSpy(&scene, leftParent);
9717 EventSpy2 leftChildSpy(&scene, leftChild);
9718 EventSpy2 rightParentSpy(&scene, rightParent);
9719 EventSpy2 rightChildSpy(&scene, rightChild);
9720 EventSpy2 bottomItemSpy(&scene, bottomItem);
9722 // Left Child enters panel modality, only left parent is blocked.
9723 leftChild->setPanelModality(QGraphicsItem::PanelModal);
9724 QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0);
9725 QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 0);
9726 QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1);
9727 QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 0);
9729 // Left parent enters scene modality, which blocks everything except the child.
9730 leftParent->setPanelModality(QGraphicsItem::SceneModal);
9731 QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0);
9732 QCOMPARE(leftChildSpy.counts[QEvent::WindowUnblocked], 0);
9733 QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 1);
9734 QCOMPARE(rightChildSpy.counts[QEvent::WindowUnblocked], 0);
9735 QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1);
9736 QCOMPARE(leftParentSpy.counts[QEvent::WindowUnblocked], 0);
9737 QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 1);
9738 QCOMPARE(rightParentSpy.counts[QEvent::WindowUnblocked], 0);
9740 // Right child enters panel modality (changes nothing).
9741 rightChild->setPanelModality(QGraphicsItem::PanelModal);
9742 QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0);
9743 QCOMPARE(leftChildSpy.counts[QEvent::WindowUnblocked], 0);
9744 QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 1);
9745 QCOMPARE(rightChildSpy.counts[QEvent::WindowUnblocked], 0);
9746 QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1);
9747 QCOMPARE(leftParentSpy.counts[QEvent::WindowUnblocked], 0);
9748 QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 1);
9749 QCOMPARE(rightParentSpy.counts[QEvent::WindowUnblocked], 0);
9751 // Left parent leaves modality. Right child is unblocked.
9752 leftParent->setPanelModality(QGraphicsItem::NonModal);
9753 QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0);
9754 QCOMPARE(leftChildSpy.counts[QEvent::WindowUnblocked], 0);
9755 QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 1);
9756 QCOMPARE(rightChildSpy.counts[QEvent::WindowUnblocked], 1);
9757 QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1);
9758 QCOMPARE(leftParentSpy.counts[QEvent::WindowUnblocked], 0);
9759 QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 1);
9760 QCOMPARE(rightParentSpy.counts[QEvent::WindowUnblocked], 0);
9762 // Right child "upgrades" its modality to scene modal. Left child is blocked.
9763 // Right parent is unaffected.
9764 rightChild->setPanelModality(QGraphicsItem::SceneModal);
9765 QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 1);
9766 QCOMPARE(leftChildSpy.counts[QEvent::WindowUnblocked], 0);
9767 QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 1);
9768 QCOMPARE(rightChildSpy.counts[QEvent::WindowUnblocked], 1);
9769 QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1);
9770 QCOMPARE(leftParentSpy.counts[QEvent::WindowUnblocked], 0);
9771 QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 1);
9772 QCOMPARE(rightParentSpy.counts[QEvent::WindowUnblocked], 0);
9774 // "downgrade" right child back to panel modal, left child is unblocked
9775 rightChild->setPanelModality(QGraphicsItem::PanelModal);
9776 QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 1);
9777 QCOMPARE(leftChildSpy.counts[QEvent::WindowUnblocked], 1);
9778 QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 1);
9779 QCOMPARE(rightChildSpy.counts[QEvent::WindowUnblocked], 1);
9780 QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1);
9781 QCOMPARE(leftParentSpy.counts[QEvent::WindowUnblocked], 0);
9782 QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 1);
9783 QCOMPARE(rightParentSpy.counts[QEvent::WindowUnblocked], 0);
9786 void tst_QGraphicsItem::modality_hover()
9788 QGraphicsScene scene;
9789 QGraphicsRectItem *rect1 = scene.addRect(-50, -50, 100, 100);
9790 rect1->setFlag(QGraphicsItem::ItemIsPanel);
9791 rect1->setAcceptHoverEvents(true);
9792 rect1->setData(0, "rect1");
9794 QGraphicsRectItem *rect2 = scene.addRect(-50, -50, 100, 100);
9795 rect2->setParentItem(rect1);
9796 rect2->setFlag(QGraphicsItem::ItemIsPanel);
9797 rect2->setAcceptHoverEvents(true);
9798 rect2->setPos(50, 50);
9799 rect2->setPanelModality(QGraphicsItem::SceneModal);
9800 rect2->setData(0, "rect2");
9802 EventSpy2 rect1Spy(&scene, rect1);
9803 EventSpy2 rect2Spy(&scene, rect2);
9805 sendMouseMove(&scene, QPointF(-25, -25));
9807 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverEnter], 0);
9808 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverMove], 0);
9809 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverLeave], 0);
9811 sendMouseMove(&scene, QPointF(75, 75));
9813 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverEnter], 0);
9814 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverMove], 0);
9815 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverLeave], 0);
9816 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverEnter], 1);
9817 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverMove], 1);
9818 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverLeave], 0);
9820 sendMouseMove(&scene, QPointF(-25, -25));
9822 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverLeave], 1);
9823 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverEnter], 0);
9824 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverMove], 0);
9825 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverLeave], 0);
9827 rect2->setPanelModality(QGraphicsItem::NonModal);
9829 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverEnter], 1);
9830 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverMove], 1);
9832 sendMouseMove(&scene, QPointF(75, 75));
9834 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverEnter], 2);
9835 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverMove], 2);
9837 rect2->setPanelModality(QGraphicsItem::SceneModal);
9839 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverLeave], 1);
9840 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverEnter], 2);
9841 // changing modality causes a spurious GraphicsSceneHoveMove, even though the mouse didn't
9843 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverMove], 3);
9845 sendMouseMove(&scene, QPointF(-25, -25));
9847 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverLeave], 2);
9848 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverEnter], 1);
9849 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverMove], 1);
9850 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverLeave], 1);
9852 rect2->setPanelModality(QGraphicsItem::PanelModal);
9854 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverEnter], 1);
9855 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverMove], 1);
9856 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverLeave], 1);
9857 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverEnter], 2);
9858 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverMove], 3);
9859 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverLeave], 2);
9861 rect2->setPanelModality(QGraphicsItem::NonModal);
9863 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverEnter], 2);
9864 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverMove], 2);
9865 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverEnter], 2);
9866 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverMove], 3);
9867 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverLeave], 2);
9870 void tst_QGraphicsItem::modality_mouseGrabber()
9872 QGraphicsScene scene;
9873 QGraphicsRectItem *rect1 = scene.addRect(-50, -50, 100, 100);
9874 rect1->setFlag(QGraphicsItem::ItemIsPanel);
9875 rect1->setFlag(QGraphicsItem::ItemIsMovable);
9876 rect1->setData(0, "rect1");
9878 QGraphicsRectItem *rect2 = scene.addRect(-50, -50, 100, 100);
9879 rect2->setParentItem(rect1);
9880 rect2->setFlag(QGraphicsItem::ItemIsPanel);
9881 rect2->setFlag(QGraphicsItem::ItemIsMovable);
9882 rect2->setPos(50, 50);
9883 rect2->setData(0, "rect2");
9885 EventSpy2 rect1Spy(&scene, rect1);
9886 EventSpy2 rect2Spy(&scene, rect2);
9889 // pressing mouse on rect1 starts implicit grab
9890 sendMousePress(&scene, QPoint(-25, -25));
9891 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 1);
9892 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMousePress], 1);
9893 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 0);
9894 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
9895 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
9896 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) rect1);
9898 // grab lost when rect1 is modally shadowed
9899 rect2->setPanelModality(QGraphicsItem::SceneModal);
9900 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 1);
9901 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 1);
9902 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
9903 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
9904 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
9906 // releasing goes nowhere
9907 sendMouseRelease(&scene, QPoint(-25, -25));
9908 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 1);
9909 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMouseRelease], 0);
9910 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 1);
9911 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
9912 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneMouseRelease], 0);
9913 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
9914 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
9916 // pressing mouse on rect1 starts implicit grab on rect2 (since it is modal)
9917 sendMouseClick(&scene, QPoint(-25, -25));
9918 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 1);
9919 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMousePress], 1);
9920 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMouseRelease], 0);
9921 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 1);
9922 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1);
9923 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneMousePress], 1);
9924 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneMouseRelease], 1);
9925 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1);
9927 rect2->setPanelModality(QGraphicsItem::NonModal);
9929 // pressing mouse on rect1 starts implicit grab
9930 sendMousePress(&scene, QPoint(-25, -25));
9931 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 2);
9932 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMousePress], 2);
9933 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 1);
9934 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1);
9935 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1);
9936 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) rect1);
9938 // grab lost to rect2 when rect1 is modally shadowed
9939 rect2->setPanelModality(QGraphicsItem::SceneModal);
9940 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 2);
9941 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 2);
9942 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1);
9943 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1);
9944 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
9946 // rect1 does *not* re-grab when rect2 is no longer modal
9947 rect2->setPanelModality(QGraphicsItem::NonModal);
9948 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 2);
9949 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 2);
9950 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1);
9951 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1);
9952 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
9954 // release goes nowhere
9955 sendMouseRelease(&scene, QPoint(-25, -25));
9956 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 2);
9957 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMouseRelease], 0);
9958 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 2);
9959 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1);
9960 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1);
9961 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
9964 // repeat the test using PanelModal
9965 rect2->setPanelModality(QGraphicsItem::NonModal);
9966 rect1Spy.counts.clear();
9967 rect2Spy.counts.clear();
9969 // pressing mouse on rect1 starts implicit grab
9970 sendMousePress(&scene, QPoint(-25, -25));
9971 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 1);
9972 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMousePress], 1);
9973 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 0);
9974 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
9975 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
9976 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) rect1);
9978 // grab lost when rect1 is modally shadowed
9979 rect2->setPanelModality(QGraphicsItem::PanelModal);
9980 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 1);
9981 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 1);
9982 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
9983 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
9984 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
9986 // releasing goes nowhere
9987 sendMouseRelease(&scene, QPoint(-25, -25));
9988 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 1);
9989 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMouseRelease], 0);
9990 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 1);
9991 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
9992 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneMouseRelease], 0);
9993 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
9994 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
9996 // pressing mouse on rect1 starts implicit grab on rect2 (since it is modal)
9997 sendMouseClick(&scene, QPoint(-25, -25));
9998 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 1);
9999 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMousePress], 1);
10000 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMouseRelease], 0);
10001 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 1);
10002 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1);
10003 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneMousePress], 1);
10004 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneMouseRelease], 1);
10005 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1);
10007 rect2->setPanelModality(QGraphicsItem::NonModal);
10009 // pressing mouse on rect1 starts implicit grab
10010 sendMousePress(&scene, QPoint(-25, -25));
10011 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 2);
10012 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMousePress], 2);
10013 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 1);
10014 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1);
10015 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1);
10016 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) rect1);
10018 // grab lost to rect2 when rect1 is modally shadowed
10019 rect2->setPanelModality(QGraphicsItem::PanelModal);
10020 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 2);
10021 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 2);
10022 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1);
10023 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1);
10024 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
10026 // rect1 does *not* re-grab when rect2 is no longer modal
10027 rect2->setPanelModality(QGraphicsItem::NonModal);
10028 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 2);
10029 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 2);
10030 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1);
10031 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1);
10032 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
10034 // release goes nowhere
10035 sendMouseRelease(&scene, QPoint(-25, -25));
10036 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 2);
10037 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMouseRelease], 0);
10038 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 2);
10039 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1);
10040 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1);
10041 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
10045 // repeat the PanelModal tests, but this time the mouse events will be on a non-modal item,
10046 // meaning normal grabbing should work
10047 rect2->setPanelModality(QGraphicsItem::NonModal);
10048 rect1Spy.counts.clear();
10049 rect2Spy.counts.clear();
10051 QGraphicsRectItem *rect3 = scene.addRect(-50, -50, 100, 100);
10052 rect3->setFlag(QGraphicsItem::ItemIsPanel);
10053 rect3->setFlag(QGraphicsItem::ItemIsMovable);
10054 rect3->setPos(150, 50);
10055 rect3->setData(0, "rect3");
10057 EventSpy2 rect3Spy(&scene, rect3);
10059 // pressing mouse on rect3 starts implicit grab
10060 sendMousePress(&scene, QPoint(150, 50));
10061 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 0);
10062 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 0);
10063 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
10064 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
10065 QCOMPARE(rect3Spy.counts[QEvent::GrabMouse], 1);
10066 QCOMPARE(rect3Spy.counts[QEvent::GraphicsSceneMousePress], 1);
10067 QCOMPARE(rect3Spy.counts[QEvent::UngrabMouse], 0);
10068 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) rect3);
10070 // grab is *not* lost when rect1 is modally shadowed by rect2
10071 rect2->setPanelModality(QGraphicsItem::PanelModal);
10072 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 0);
10073 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 0);
10074 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
10075 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
10076 QCOMPARE(rect3Spy.counts[QEvent::GrabMouse], 1);
10077 QCOMPARE(rect3Spy.counts[QEvent::UngrabMouse], 0);
10078 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) rect3);
10080 // releasing goes to rect3
10081 sendMouseRelease(&scene, QPoint(150, 50));
10082 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 0);
10083 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 0);
10084 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
10085 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
10086 QCOMPARE(rect3Spy.counts[QEvent::GrabMouse], 1);
10087 QCOMPARE(rect3Spy.counts[QEvent::GraphicsSceneMouseRelease], 1);
10088 QCOMPARE(rect3Spy.counts[QEvent::UngrabMouse], 1);
10089 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
10091 rect2->setPanelModality(QGraphicsItem::NonModal);
10093 // pressing mouse on rect3 starts implicit grab
10094 sendMousePress(&scene, QPoint(150, 50));
10095 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 0);
10096 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 0);
10097 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
10098 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
10099 QCOMPARE(rect3Spy.counts[QEvent::GrabMouse], 2);
10100 QCOMPARE(rect3Spy.counts[QEvent::UngrabMouse], 1);
10101 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) rect3);
10103 // grab is not lost
10104 rect2->setPanelModality(QGraphicsItem::PanelModal);
10105 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 0);
10106 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 0);
10107 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
10108 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
10109 QCOMPARE(rect3Spy.counts[QEvent::GrabMouse], 2);
10110 QCOMPARE(rect3Spy.counts[QEvent::UngrabMouse], 1);
10111 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) rect3);
10113 // grab stays on rect3
10114 rect2->setPanelModality(QGraphicsItem::NonModal);
10115 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 0);
10116 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 0);
10117 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
10118 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
10119 QCOMPARE(rect3Spy.counts[QEvent::GrabMouse], 2);
10120 QCOMPARE(rect3Spy.counts[QEvent::UngrabMouse], 1);
10121 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) rect3);
10123 // release goes to rect3
10124 sendMouseRelease(&scene, QPoint(150, 50));
10125 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 0);
10126 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 0);
10127 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
10128 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
10129 QCOMPARE(rect3Spy.counts[QEvent::GrabMouse], 2);
10130 QCOMPARE(rect3Spy.counts[QEvent::UngrabMouse], 2);
10131 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
10135 void tst_QGraphicsItem::modality_clickFocus()
10137 QGraphicsScene scene;
10138 QGraphicsRectItem *rect1 = scene.addRect(-50, -50, 100, 100);
10139 rect1->setFlag(QGraphicsItem::ItemIsPanel);
10140 rect1->setFlag(QGraphicsItem::ItemIsFocusable);
10141 rect1->setData(0, "rect1");
10143 QGraphicsRectItem *rect2 = scene.addRect(-50, -50, 100, 100);
10144 rect2->setParentItem(rect1);
10145 rect2->setFlag(QGraphicsItem::ItemIsPanel);
10146 rect2->setFlag(QGraphicsItem::ItemIsFocusable);
10147 rect2->setPos(50, 50);
10148 rect2->setData(0, "rect2");
10150 QEvent windowActivateEvent(QEvent::WindowActivate);
10151 QApplication::sendEvent(&scene, &windowActivateEvent);
10153 EventSpy2 rect1Spy(&scene, rect1);
10154 EventSpy2 rect2Spy(&scene, rect2);
10156 // activate rect1, it should not get focus
10157 rect1->setActive(true);
10158 QCOMPARE(scene.focusItem(), (QGraphicsItem *) 0);
10160 // focus stays unset when rect2 becomes modal
10161 rect2->setPanelModality(QGraphicsItem::SceneModal);
10162 QCOMPARE(scene.focusItem(), (QGraphicsItem *) 0);
10163 QCOMPARE(rect1Spy.counts[QEvent::FocusIn], 0);
10164 QCOMPARE(rect1Spy.counts[QEvent::FocusOut], 0);
10165 QCOMPARE(rect2Spy.counts[QEvent::FocusIn], 0);
10166 QCOMPARE(rect2Spy.counts[QEvent::FocusOut], 0);
10168 // clicking on rect1 should not set it's focus item
10169 sendMouseClick(&scene, QPointF(-25, -25));
10170 QCOMPARE(rect1->focusItem(), (QGraphicsItem *) 0);
10171 QCOMPARE(rect1Spy.counts[QEvent::FocusIn], 0);
10172 QCOMPARE(rect1Spy.counts[QEvent::FocusOut], 0);
10173 QCOMPARE(rect2Spy.counts[QEvent::FocusIn], 0);
10174 QCOMPARE(rect2Spy.counts[QEvent::FocusOut], 0);
10176 // clicking on rect2 gives it focus
10177 rect2->setActive(true);
10178 sendMouseClick(&scene, QPointF(75, 75));
10179 QCOMPARE(scene.focusItem(), (QGraphicsItem *) rect2);
10180 QCOMPARE(rect1Spy.counts[QEvent::FocusIn], 0);
10181 QCOMPARE(rect1Spy.counts[QEvent::FocusOut], 0);
10182 QCOMPARE(rect2Spy.counts[QEvent::FocusIn], 1);
10183 QCOMPARE(rect2Spy.counts[QEvent::FocusOut], 0);
10185 // clicking on rect1 does *not* give it focus
10186 rect1->setActive(true);
10187 sendMouseClick(&scene, QPointF(-25, -25));
10188 QCOMPARE(scene.focusItem(), (QGraphicsItem *) 0);
10189 QCOMPARE(rect1Spy.counts[QEvent::FocusIn], 0);
10190 QCOMPARE(rect1Spy.counts[QEvent::FocusOut], 0);
10191 QCOMPARE(rect2Spy.counts[QEvent::FocusIn], 1);
10192 QCOMPARE(rect2Spy.counts[QEvent::FocusOut], 1);
10194 // focus doesn't change when leaving modality either
10195 rect2->setPanelModality(QGraphicsItem::NonModal);
10196 QCOMPARE(scene.focusItem(), (QGraphicsItem *) 0);
10197 QCOMPARE(rect1Spy.counts[QEvent::FocusIn], 0);
10198 QCOMPARE(rect1Spy.counts[QEvent::FocusOut], 0);
10199 QCOMPARE(rect2Spy.counts[QEvent::FocusIn], 1);
10200 QCOMPARE(rect2Spy.counts[QEvent::FocusOut], 1);
10202 // click on rect1, it should get focus now
10203 sendMouseClick(&scene, QPointF(-25, -25));
10204 QCOMPARE(scene.focusItem(), (QGraphicsItem *) rect1);
10205 QCOMPARE(rect1Spy.counts[QEvent::FocusIn], 1);
10206 QCOMPARE(rect1Spy.counts[QEvent::FocusOut], 0);
10207 QCOMPARE(rect2Spy.counts[QEvent::FocusIn], 1);
10208 QCOMPARE(rect2Spy.counts[QEvent::FocusOut], 1);
10211 void tst_QGraphicsItem::modality_keyEvents()
10213 QGraphicsScene scene;
10214 QGraphicsRectItem *rect1 = scene.addRect(-50, -50, 100, 100);
10215 rect1->setFlag(QGraphicsItem::ItemIsPanel);
10216 rect1->setFlag(QGraphicsItem::ItemIsFocusable);
10217 rect1->setData(0, "rect1");
10219 QGraphicsRectItem *rect1child = scene.addRect(-10, -10, 20, 20);
10220 rect1child->setParentItem(rect1);
10221 rect1child->setFlag(QGraphicsItem::ItemIsFocusable);
10222 rect1child->setData(0, "rect1child1");
10224 QGraphicsRectItem *rect2 = scene.addRect(-50, -50, 100, 100);
10225 rect2->setParentItem(rect1);
10226 rect2->setFlag(QGraphicsItem::ItemIsPanel);
10227 rect2->setFlag(QGraphicsItem::ItemIsFocusable);
10228 rect2->setPos(50, 50);
10229 rect2->setData(0, "rect2");
10231 QGraphicsRectItem *rect2child = scene.addRect(-10, -10, 20, 20);
10232 rect2child->setParentItem(rect2);
10233 rect2child->setFlag(QGraphicsItem::ItemIsFocusable);
10234 rect2child->setData(0, "rect2child1");
10236 QEvent windowActivateEvent(QEvent::WindowActivate);
10237 QApplication::sendEvent(&scene, &windowActivateEvent);
10239 EventSpy2 rect1Spy(&scene, rect1);
10240 EventSpy2 rect1childSpy(&scene, rect1child);
10241 EventSpy2 rect2Spy(&scene, rect2);
10242 EventSpy2 rect2childSpy(&scene, rect2child);
10244 // activate rect1 and give it rect1child focus
10245 rect1->setActive(true);
10246 rect1child->setFocus();
10247 QCOMPARE(scene.focusItem(), (QGraphicsItem *) rect1child);
10249 // focus stays on rect1child when rect2 becomes modal
10250 rect2->setPanelModality(QGraphicsItem::SceneModal);
10251 QCOMPARE(scene.focusItem(), (QGraphicsItem *) rect1child);
10253 // but key events to rect1child should be neither delivered nor propagated
10254 sendKeyClick(&scene, Qt::Key_A);
10255 sendKeyClick(&scene, Qt::Key_S);
10256 sendKeyClick(&scene, Qt::Key_D);
10257 sendKeyClick(&scene, Qt::Key_F);
10258 QCOMPARE(rect1childSpy.counts[QEvent::KeyPress], 0);
10259 QCOMPARE(rect1childSpy.counts[QEvent::KeyRelease], 0);
10260 QCOMPARE(rect1Spy.counts[QEvent::KeyPress], 0);
10261 QCOMPARE(rect1Spy.counts[QEvent::KeyRelease], 0);
10263 // change to panel modality, rect1child1 keeps focus
10264 rect2->setPanelModality(QGraphicsItem::PanelModal);
10265 QCOMPARE(scene.focusItem(), (QGraphicsItem *) rect1child);
10267 // still no key events
10268 sendKeyClick(&scene, Qt::Key_J);
10269 sendKeyClick(&scene, Qt::Key_K);
10270 sendKeyClick(&scene, Qt::Key_L);
10271 sendKeyClick(&scene, Qt::Key_Semicolon);
10272 QCOMPARE(rect1childSpy.counts[QEvent::KeyPress], 0);
10273 QCOMPARE(rect1childSpy.counts[QEvent::KeyRelease], 0);
10274 QCOMPARE(rect1Spy.counts[QEvent::KeyPress], 0);
10275 QCOMPARE(rect1Spy.counts[QEvent::KeyRelease], 0);
10278 void tst_QGraphicsItem::itemIsInFront()
10280 QGraphicsScene scene;
10281 QGraphicsRectItem *rect1 = new QGraphicsRectItem;
10282 rect1->setData(0, "rect1");
10283 scene.addItem(rect1);
10285 QGraphicsRectItem *rect1child1 = new QGraphicsRectItem(rect1);
10286 rect1child1->setZValue(1);
10287 rect1child1->setData(0, "rect1child1");
10289 QGraphicsRectItem *rect1child2 = new QGraphicsRectItem(rect1);
10290 rect1child2->setParentItem(rect1);
10291 rect1child2->setData(0, "rect1child2");
10293 QGraphicsRectItem *rect1child1_1 = new QGraphicsRectItem(rect1child1);
10294 rect1child1_1->setData(0, "rect1child1_1");
10296 QGraphicsRectItem *rect1child1_2 = new QGraphicsRectItem(rect1child1);
10297 rect1child1_2->setFlag(QGraphicsItem::ItemStacksBehindParent);
10298 rect1child1_2->setData(0, "rect1child1_2");
10300 QGraphicsRectItem *rect2 = new QGraphicsRectItem;
10301 rect2->setData(0, "rect2");
10302 scene.addItem(rect2);
10304 QGraphicsRectItem *rect2child1 = new QGraphicsRectItem(rect2);
10305 rect2child1->setData(0, "rect2child1");
10307 QCOMPARE(qt_closestItemFirst(rect1, rect1), false);
10308 QCOMPARE(qt_closestItemFirst(rect1, rect2), false);
10309 QCOMPARE(qt_closestItemFirst(rect1child1, rect2child1), false);
10310 QCOMPARE(qt_closestItemFirst(rect1child1, rect1child2), true);
10311 QCOMPARE(qt_closestItemFirst(rect1child1_1, rect1child2), true);
10312 QCOMPARE(qt_closestItemFirst(rect1child1_1, rect1child1), true);
10313 QCOMPARE(qt_closestItemFirst(rect1child1_2, rect1child2), true);
10314 QCOMPARE(qt_closestItemFirst(rect1child1_2, rect1child1), false);
10315 QCOMPARE(qt_closestItemFirst(rect1child1_2, rect1), true);
10316 QCOMPARE(qt_closestItemFirst(rect1child1_2, rect2), false);
10317 QCOMPARE(qt_closestItemFirst(rect1child1_2, rect2child1), false);
10320 class ScenePosChangeTester : public ItemChangeTester
10323 ScenePosChangeTester()
10325 ScenePosChangeTester(QGraphicsItem *parent) : ItemChangeTester(parent)
10329 void tst_QGraphicsItem::scenePosChange()
10331 ScenePosChangeTester* root = new ScenePosChangeTester;
10332 ScenePosChangeTester* child1 = new ScenePosChangeTester(root);
10333 ScenePosChangeTester* grandChild1 = new ScenePosChangeTester(child1);
10334 ScenePosChangeTester* child2 = new ScenePosChangeTester(root);
10335 ScenePosChangeTester* grandChild2 = new ScenePosChangeTester(child2);
10337 child1->setFlag(QGraphicsItem::ItemSendsScenePositionChanges, true);
10338 grandChild2->setFlag(QGraphicsItem::ItemSendsScenePositionChanges, true);
10340 QVERIFY(child1->flags() & QGraphicsItem::ItemSendsScenePositionChanges);
10341 QVERIFY(grandChild2->flags() & QGraphicsItem::ItemSendsScenePositionChanges);
10343 QGraphicsScene scene;
10344 scene.addItem(root);
10346 // ignore uninteresting changes
10349 grandChild1->clear();
10350 grandChild2->clear();
10353 root->moveBy(1.0, 1.0);
10354 QCOMPARE(child1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 1);
10355 QCOMPARE(grandChild1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 0);
10356 QCOMPARE(child2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 0);
10357 QCOMPARE(grandChild2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 1);
10360 child2->moveBy(1.0, 1.0);
10361 QCOMPARE(child1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 1);
10362 QCOMPARE(grandChild1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 0);
10363 QCOMPARE(child2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 0);
10364 QCOMPARE(grandChild2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 2);
10367 grandChild2->setParentItem(child1);
10368 child1->moveBy(1.0, 1.0);
10369 QCOMPARE(child1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 2);
10370 QCOMPARE(grandChild1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 0);
10371 QCOMPARE(child2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 0);
10372 QCOMPARE(grandChild2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 3);
10375 grandChild1->setFlag(QGraphicsItem::ItemSendsScenePositionChanges, true);
10376 grandChild2->setFlag(QGraphicsItem::ItemSendsScenePositionChanges, false);
10377 QCoreApplication::processEvents(); // QGraphicsScenePrivate::_q_updateScenePosDescendants()
10378 child1->moveBy(1.0, 1.0);
10379 QCOMPARE(child1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 3);
10380 QCOMPARE(grandChild1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 1);
10381 QCOMPARE(child2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 0);
10382 QCOMPARE(grandChild2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 3);
10385 scene.removeItem(grandChild1);
10386 delete grandChild2; grandChild2 = 0;
10387 QCoreApplication::processEvents(); // QGraphicsScenePrivate::_q_updateScenePosDescendants()
10388 root->moveBy(1.0, 1.0);
10389 QCOMPARE(child1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 4);
10390 QCOMPARE(grandChild1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 1);
10391 QCOMPARE(child2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 0);
10394 QCOMPARE(child1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 5);
10395 QCOMPARE(grandChild1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 1);
10396 QCOMPARE(child2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 0);
10399 QCOMPARE(child1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 6);
10400 QCOMPARE(grandChild1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 1);
10401 QCOMPARE(child2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 0);
10404 void tst_QGraphicsItem::textItem_shortcuts()
10409 QGraphicsScene scene;
10410 QGraphicsView view(&scene);
10411 l.addWidget(&view);
10412 QPushButton b("Push Me");
10415 QGraphicsTextItem *item = scene.addText("Troll Text");
10416 item->setFlag(QGraphicsItem::ItemIsFocusable);
10417 item->setTextInteractionFlags(Qt::TextEditorInteraction);
10419 QVERIFY(QTest::qWaitForWindowExposed(&w));
10422 QTRY_VERIFY(item->hasFocus());
10423 QVERIFY(item->textCursor().selectedText().isEmpty());
10425 // Shortcut should work (select all)
10426 QTest::keyClick(&view, Qt::Key_A, Qt::ControlModifier);
10427 QTRY_COMPARE(item->textCursor().selectedText(), item->toPlainText());
10428 QTextCursor tc = item->textCursor();
10429 tc.clearSelection();
10430 item->setTextCursor(tc);
10431 QVERIFY(item->textCursor().selectedText().isEmpty());
10433 // Shortcut should also work if the text item has the focus and another widget
10434 // has the same shortcut.
10435 b.setShortcut(QKeySequence("CTRL+A"));
10436 QTest::keyClick(&view, Qt::Key_A, Qt::ControlModifier);
10437 QTRY_COMPARE(item->textCursor().selectedText(), item->toPlainText());
10440 void tst_QGraphicsItem::scroll()
10442 // Create two overlapping rectangles in the scene:
10447 // +---| | <- item2
10451 EventTester *item1 = new EventTester;
10452 item1->br = QRectF(0, 0, 200, 200);
10453 item1->brush = Qt::red;
10454 item1->setFlag(QGraphicsItem::ItemUsesExtendedStyleOption);
10456 EventTester *item2 = new EventTester;
10457 item2->br = QRectF(0, 0, 200, 200);
10458 item2->brush = Qt::blue;
10459 item2->setFlag(QGraphicsItem::ItemUsesExtendedStyleOption);
10460 item2->setPos(100, 100);
10462 QGraphicsScene scene(0, 0, 300, 300);
10463 scene.addItem(item1);
10464 scene.addItem(item2);
10466 MyGraphicsView view(&scene);
10467 view.setFrameStyle(0);
10469 QVERIFY(QTest::qWaitForWindowActive(&view));
10470 QTRY_VERIFY(view.repaints > 0);
10476 const QRectF item1BoundingRect = item1->boundingRect();
10477 const QRectF item2BoundingRect = item2->boundingRect();
10480 // Item1 should get full exposure
10481 // Item2 should get exposure for the part that overlaps item1.
10482 item1->scroll(0, -10);
10483 QTRY_VERIFY(view.repaints > 0);
10484 QCOMPARE(item1->lastExposedRect, item1BoundingRect);
10486 QRectF expectedItem2Expose = item2BoundingRect;
10487 // NB! Adjusted by 2 pixels for antialiasing
10488 expectedItem2Expose &= item1->mapRectToItem(item2, item1BoundingRect.adjusted(-2, -2, 2, 2));
10489 QCOMPARE(item2->lastExposedRect, expectedItem2Expose);
10491 // Enable ItemCoordinateCache on item1.
10493 item1->setCacheMode(QGraphicsItem::ItemCoordinateCache);
10494 QTRY_VERIFY(view.repaints > 0);
10500 // Item1 should only get expose for the newly exposed area (accelerated scroll).
10501 // Item2 should get exposure for the part that overlaps item1.
10502 item1->scroll(0, -10, QRectF(50, 50, 100, 100));
10503 QTRY_VERIFY(view.repaints > 0);
10504 QCOMPARE(item1->lastExposedRect, QRectF(50, 140, 100, 10));
10506 expectedItem2Expose = item2BoundingRect;
10507 // NB! Adjusted by 2 pixels for antialiasing
10508 expectedItem2Expose &= item1->mapRectToItem(item2, QRectF(50, 50, 100, 100).adjusted(-2, -2, 2, 2));
10509 QCOMPARE(item2->lastExposedRect, expectedItem2Expose);
10512 Q_DECLARE_METATYPE(QGraphicsItem::GraphicsItemFlag);
10514 void tst_QGraphicsItem::focusHandling_data()
10516 QTest::addColumn<QGraphicsItem::GraphicsItemFlag>("focusFlag");
10517 QTest::addColumn<bool>("useStickyFocus");
10518 QTest::addColumn<int>("expectedFocusItem"); // 0: none, 1: focusableUnder, 2: itemWithFocus
10520 QTest::newRow("Focus goes through.")
10521 << static_cast<QGraphicsItem::GraphicsItemFlag>(0x0) << false << 1;
10523 QTest::newRow("Focus goes through, even with sticky scene.")
10524 << static_cast<QGraphicsItem::GraphicsItemFlag>(0x0) << true << 1;
10526 QTest::newRow("With ItemStopsClickFocusPropagation, we cannot focus the item beneath the flagged one (but can still focus-out).")
10527 << QGraphicsItem::ItemStopsClickFocusPropagation << false << 0;
10529 QTest::newRow("With ItemStopsClickFocusPropagation, we cannot focus the item beneath the flagged one (and cannot focus-out if scene is sticky).")
10530 << QGraphicsItem::ItemStopsClickFocusPropagation << true << 2;
10532 QTest::newRow("With ItemStopsFocusHandling, focus cannot be changed by presses.")
10533 << QGraphicsItem::ItemStopsFocusHandling << false << 2;
10535 QTest::newRow("With ItemStopsFocusHandling, focus cannot be changed by presses (even if scene is sticky).")
10536 << QGraphicsItem::ItemStopsFocusHandling << true << 2;
10539 void tst_QGraphicsItem::focusHandling()
10541 QFETCH(QGraphicsItem::GraphicsItemFlag, focusFlag);
10542 QFETCH(bool, useStickyFocus);
10543 QFETCH(int, expectedFocusItem);
10545 class MyItem : public QGraphicsRectItem
10548 MyItem() : QGraphicsRectItem(0, 0, 100, 100) {}
10549 void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
10551 painter->fillRect(boundingRect(), hasFocus() ? QBrush(Qt::red) : brush());
10555 QGraphicsRectItem *noFocusOnTop = new MyItem;
10556 noFocusOnTop->setFlag(QGraphicsItem::ItemIsFocusable, false);
10557 noFocusOnTop->setBrush(Qt::yellow);
10559 QGraphicsRectItem *focusableUnder = new MyItem;
10560 focusableUnder->setBrush(Qt::blue);
10561 focusableUnder->setFlag(QGraphicsItem::ItemIsFocusable);
10562 focusableUnder->setPos(50, 50);
10564 QGraphicsRectItem *itemWithFocus = new MyItem;
10565 itemWithFocus->setBrush(Qt::black);
10566 itemWithFocus->setFlag(QGraphicsItem::ItemIsFocusable);
10567 itemWithFocus->setPos(250, 10);
10569 QGraphicsScene scene(-50, -50, 400, 400);
10570 scene.addItem(noFocusOnTop);
10571 scene.addItem(focusableUnder);
10572 scene.addItem(itemWithFocus);
10573 scene.setStickyFocus(useStickyFocus);
10575 noFocusOnTop->setFlag(focusFlag);
10576 focusableUnder->stackBefore(noFocusOnTop);
10577 itemWithFocus->setFocus();
10579 QGraphicsView view(&scene);
10581 QVERIFY(QTest::qWaitForWindowExposed(&view));
10583 QApplication::setActiveWindow(&view);
10584 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
10585 QVERIFY(itemWithFocus->hasFocus());
10587 const QPointF mousePressPoint = noFocusOnTop->mapToScene(noFocusOnTop->boundingRect().center());
10588 const QList<QGraphicsItem *> itemsAtMousePressPosition = scene.items(mousePressPoint);
10589 QVERIFY(itemsAtMousePressPosition.contains(noFocusOnTop));
10591 sendMousePress(&scene, mousePressPoint);
10593 switch (expectedFocusItem) {
10595 QCOMPARE(scene.focusItem(), static_cast<QGraphicsRectItem *>(0));
10598 QCOMPARE(scene.focusItem(), focusableUnder);
10601 QCOMPARE(scene.focusItem(), itemWithFocus);
10605 // Sanity check - manually setting the focus must work regardless of our
10606 // focus handling flags:
10607 focusableUnder->setFocus();
10608 QCOMPARE(scene.focusItem(), focusableUnder);
10611 void tst_QGraphicsItem::touchEventPropagation_data()
10613 QTest::addColumn<QGraphicsItem::GraphicsItemFlag>("flag");
10614 QTest::addColumn<int>("expectedCount");
10616 QTest::newRow("ItemIsPanel")
10617 << QGraphicsItem::ItemIsPanel << 0;
10618 QTest::newRow("ItemStopsClickFocusPropagation")
10619 << QGraphicsItem::ItemStopsClickFocusPropagation << 1;
10620 QTest::newRow("ItemStopsFocusHandling")
10621 << QGraphicsItem::ItemStopsFocusHandling << 1;
10624 void tst_QGraphicsItem::touchEventPropagation()
10626 QFETCH(QGraphicsItem::GraphicsItemFlag, flag);
10627 QFETCH(int, expectedCount);
10629 class Testee : public QGraphicsRectItem
10632 int touchBeginEventCount;
10635 : QGraphicsRectItem(0, 0, 100, 100)
10636 , touchBeginEventCount(0)
10638 setAcceptTouchEvents(true);
10639 setFlag(QGraphicsItem::ItemIsFocusable, false);
10642 bool sceneEvent(QEvent *ev)
10644 if (ev->type() == QEvent::TouchBegin)
10645 ++touchBeginEventCount;
10647 return QGraphicsRectItem::sceneEvent(ev);
10651 Testee *touchEventReceiver = new Testee;
10652 QGraphicsItem *topMost = new QGraphicsRectItem(touchEventReceiver->boundingRect());
10654 QGraphicsScene scene;
10655 scene.addItem(topMost);
10656 scene.addItem(touchEventReceiver);
10658 topMost->setAcceptTouchEvents(true);
10659 topMost->setZValue(FLT_MAX);
10660 topMost->setFlag(QGraphicsItem::ItemIsFocusable, false);
10661 topMost->setFlag(flag, true);
10663 QGraphicsView view(&scene);
10664 view.setSceneRect(touchEventReceiver->boundingRect());
10666 QVERIFY(QTest::qWaitForWindowExposed(&view));
10668 QCOMPARE(touchEventReceiver->touchBeginEventCount, 0);
10670 QTouchEvent::TouchPoint tp(0);
10671 tp.setState(Qt::TouchPointPressed);
10672 tp.setScenePos(view.sceneRect().center());
10673 tp.setLastScenePos(view.sceneRect().center());
10675 QList<QTouchEvent::TouchPoint> touchPoints;
10678 sendMousePress(&scene, tp.scenePos());
10679 QTouchDevice *device = new QTouchDevice;
10680 device->setType(QTouchDevice::TouchScreen);
10681 QWindowSystemInterface::registerTouchDevice(device);
10682 QTouchEvent touchBegin(QEvent::TouchBegin, device, Qt::NoModifier, Qt::TouchPointPressed, touchPoints);
10684 qApp->sendEvent(&scene, &touchBegin);
10685 QCOMPARE(touchEventReceiver->touchBeginEventCount, expectedCount);
10688 void tst_QGraphicsItem::deviceCoordinateCache_simpleRotations()
10690 // Make sure we don't invalidate the cache when applying simple
10691 // (90, 180, 270, 360) rotation transforms to the item.
10692 QGraphicsRectItem *item = new QGraphicsRectItem(0, 0, 300, 200);
10693 item->setBrush(Qt::red);
10694 item->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
10696 QGraphicsScene scene;
10697 scene.setSceneRect(0, 0, 300, 200);
10698 scene.addItem(item);
10700 MyGraphicsView view(&scene);
10702 QVERIFY(QTest::qWaitForWindowExposed(&view));
10703 QTRY_VERIFY(view.repaints > 0);
10705 QGraphicsItemCache *itemCache = QGraphicsItemPrivate::get(item)->extraItemCache();
10706 QVERIFY(itemCache);
10707 QPixmapCache::Key currentKey = itemCache->deviceData.value(view.viewport()).key;
10709 // Trigger an update and verify that the cache is unchanged.
10710 QPixmapCache::Key oldKey = currentKey;
10712 view.viewport()->update();
10713 QTRY_VERIFY(view.repaints > 0);
10714 currentKey = itemCache->deviceData.value(view.viewport()).key;
10715 QCOMPARE(currentKey, oldKey);
10717 // Check 90, 180, 270 and 360 degree rotations.
10718 for (int angle = 90; angle <= 360; angle += 90) {
10719 // Rotate item and verify that the cache was invalidated.
10720 oldKey = currentKey;
10722 QTransform transform;
10723 transform.translate(150, 100);
10724 transform.rotate(angle);
10725 transform.translate(-150, -100);
10726 item->setTransform(transform);
10727 QTRY_VERIFY(view.repaints > 0);
10728 currentKey = itemCache->deviceData.value(view.viewport()).key;
10729 QVERIFY(currentKey != oldKey);
10732 // Trigger an update and verify that the cache is unchanged.
10733 oldKey = currentKey;
10735 view.viewport()->update();
10736 QTRY_VERIFY(view.repaints > 0);
10737 currentKey = itemCache->deviceData.value(view.viewport()).key;
10738 QCOMPARE(currentKey, oldKey);
10741 // 45 degree rotation.
10742 oldKey = currentKey;
10744 QTransform transform;
10745 transform.translate(150, 100);
10746 transform.rotate(45);
10747 transform.translate(-150, -100);
10748 item->setTransform(transform);
10749 QTRY_VERIFY(view.repaints > 0);
10750 currentKey = itemCache->deviceData.value(view.viewport()).key;
10751 QVERIFY(currentKey != oldKey);
10753 // Trigger an update and verify that the cache was invalidated.
10754 // We should always invalidate the cache for non-trivial transforms.
10755 oldKey = currentKey;
10757 view.viewport()->update();
10758 QTRY_VERIFY(view.repaints > 0);
10759 currentKey = itemCache->deviceData.value(view.viewport()).key;
10760 QVERIFY(currentKey != oldKey);
10763 void tst_QGraphicsItem::QTBUG_5418_textItemSetDefaultColor()
10765 struct Item : public QGraphicsTextItem
10768 void paint(QPainter *painter, const QStyleOptionGraphicsItem *opt, QWidget *wid)
10771 QGraphicsTextItem::paint(painter, opt, wid);
10775 Item *i = new Item;
10777 i->setPlainText("I AM A TROLL");
10779 QGraphicsScene scene;
10780 QGraphicsView view(&scene);
10782 QVERIFY(QTest::qWaitForWindowExposed(&view));
10784 QApplication::processEvents();
10785 QTRY_VERIFY(i->painted);
10786 QApplication::processEvents();
10789 QColor col(Qt::red);
10790 i->setDefaultTextColor(col);
10791 QApplication::processEvents();
10792 QTRY_COMPARE(i->painted, 1); //check that changing the color force an update
10794 i->painted = false;
10795 QImage image(400, 200, QImage::Format_RGB32);
10797 QPainter painter(&image);
10798 scene.render(&painter);
10800 QCOMPARE(i->painted, 1);
10802 int numRedPixel = 0;
10803 QRgb rgb = col.rgb();
10804 for (int y = 0; y < image.height(); ++y) {
10805 for (int x = 0; x < image.width(); ++x) {
10806 // Because of antialiasing we allow a certain range of errors here.
10807 QRgb pixel = image.pixel(x, y);
10808 if (qAbs((int)(pixel & 0xff) - (int)(rgb & 0xff)) +
10809 qAbs((int)((pixel & 0xff00) >> 8) - (int)((rgb & 0xff00) >> 8)) +
10810 qAbs((int)((pixel & 0xff0000) >> 16) - (int)((rgb & 0xff0000) >> 16)) <= 50) {
10811 if (++numRedPixel >= 10) {
10817 QCOMPARE(numRedPixel, -1); //color not found, FAIL!
10820 i->setDefaultTextColor(col);
10821 QApplication::processEvents();
10822 QCOMPARE(i->painted, 0); //same color as before should not trigger an update (QTBUG-6242)
10825 void tst_QGraphicsItem::QTBUG_6738_missingUpdateWithSetParent()
10827 // In all 3 test cases below the reparented item should disappear
10828 EventTester *parent = new EventTester;
10829 EventTester *child = new EventTester(parent);
10830 EventTester *child2 = new EventTester(parent);
10831 EventTester *child3 = new EventTester(parent);
10832 EventTester *child4 = new EventTester(parent);
10834 child->setPos(10, 10);
10835 child2->setPos(20, 20);
10836 child3->setPos(30, 30);
10837 child4->setPos(40, 40);
10839 QGraphicsScene scene;
10840 scene.addItem(parent);
10842 MyGraphicsView view(&scene);
10844 qApp->setActiveWindow(&view);
10845 QVERIFY(QTest::qWaitForWindowActive(&view));
10846 QTRY_VERIFY(view.repaints > 0);
10850 child2->setVisible(false);
10851 child2->setParentItem(child);
10853 QTRY_VERIFY(view.repaints == 1);
10857 child3->setOpacity(0.0);
10858 child3->setParentItem(child);
10860 QTRY_VERIFY(view.repaints == 1);
10864 child4->setParentItem(child);
10865 child4->setVisible(false);
10867 QTRY_VERIFY(view.repaints == 1);
10870 void tst_QGraphicsItem::QT_2653_fullUpdateDiscardingOpacityUpdate()
10872 QGraphicsScene scene(0, 0, 200, 200);
10873 MyGraphicsView view(&scene);
10875 EventTester *parentGreen = new EventTester();
10876 parentGreen->setGeometry(QRectF(20, 20, 100, 100));
10877 parentGreen->brush = Qt::green;
10879 EventTester *childYellow = new EventTester(parentGreen);
10880 childYellow->setGeometry(QRectF(10, 10, 50, 50));
10881 childYellow->brush = Qt::yellow;
10883 scene.addItem(parentGreen);
10885 childYellow->setOpacity(0.0);
10886 parentGreen->setOpacity(0.0);
10888 // set any of the flags below to trigger a fullUpdate to reproduce the bug:
10889 // ItemIgnoresTransformations, ItemClipsChildrenToShape, ItemIsSelectable
10890 parentGreen->setFlag(QGraphicsItem::ItemIgnoresTransformations);
10893 QVERIFY(QTest::qWaitForWindowActive(&view));
10896 parentGreen->setOpacity(1.0);
10898 QTRY_COMPARE(view.repaints, 1);
10901 childYellow->repaints = 0;
10903 childYellow->setOpacity(1.0);
10905 QTRY_COMPARE(view.repaints, 1);
10906 QTRY_COMPARE(childYellow->repaints, 1);
10909 void tst_QGraphicsItem::QTBUG_7714_fullUpdateDiscardingOpacityUpdate2()
10911 QGraphicsScene scene(0, 0, 200, 200);
10912 MyGraphicsView view(&scene);
10913 MyGraphicsView origView(&scene);
10915 EventTester *parentGreen = new EventTester();
10916 parentGreen->setGeometry(QRectF(20, 20, 100, 100));
10917 parentGreen->brush = Qt::green;
10919 EventTester *childYellow = new EventTester(parentGreen);
10920 childYellow->setGeometry(QRectF(10, 10, 50, 50));
10921 childYellow->brush = Qt::yellow;
10923 scene.addItem(parentGreen);
10926 QVERIFY(QTest::qWaitForWindowActive(&origView));
10927 origView.setGeometry(origView.width() + 20, 20,
10928 origView.width(), origView.height());
10930 parentGreen->setFlag(QGraphicsItem::ItemIgnoresTransformations);
10933 childYellow->setOpacity(0.0);
10935 QTRY_COMPARE(origView.repaints, 1);
10938 qApp->setActiveWindow(&view);
10939 QVERIFY(QTest::qWaitForWindowActive(&view));
10943 childYellow->setOpacity(1.0);
10945 QTRY_COMPARE(origView.repaints, 1);
10946 QTRY_COMPARE(view.repaints, 1);
10949 void tst_QGraphicsItem::QT_2649_focusScope()
10951 QGraphicsScene *scene = new QGraphicsScene;
10953 QGraphicsRectItem *subFocusItem = new QGraphicsRectItem;
10954 subFocusItem->setFlags(QGraphicsItem::ItemIsFocusable);
10955 subFocusItem->setFocus();
10956 QCOMPARE(subFocusItem->focusItem(), (QGraphicsItem *)subFocusItem);
10958 QGraphicsRectItem *scope = new QGraphicsRectItem;
10959 scope->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsFocusScope);
10961 subFocusItem->setParentItem(scope);
10962 QCOMPARE(subFocusItem->focusItem(), (QGraphicsItem *)subFocusItem);
10963 QCOMPARE(subFocusItem->focusScopeItem(), (QGraphicsItem *)0);
10964 QCOMPARE(scope->focusItem(), (QGraphicsItem *)subFocusItem);
10965 QCOMPARE(scope->focusScopeItem(), (QGraphicsItem *)subFocusItem);
10967 QGraphicsRectItem *rootItem = new QGraphicsRectItem;
10968 rootItem->setFlags(QGraphicsItem::ItemIsFocusable);
10969 scope->setParentItem(rootItem);
10970 QCOMPARE(rootItem->focusItem(), (QGraphicsItem *)subFocusItem);
10971 QCOMPARE(rootItem->focusScopeItem(), (QGraphicsItem *)0);
10972 QCOMPARE(subFocusItem->focusItem(), (QGraphicsItem *)subFocusItem);
10973 QCOMPARE(subFocusItem->focusScopeItem(), (QGraphicsItem *)0);
10974 QCOMPARE(scope->focusItem(), (QGraphicsItem *)subFocusItem);
10975 QCOMPARE(scope->focusScopeItem(), (QGraphicsItem *)subFocusItem);
10977 scene->addItem(rootItem);
10979 QEvent windowActivate(QEvent::WindowActivate);
10980 qApp->sendEvent(scene, &windowActivate);
10983 QCOMPARE(rootItem->focusItem(), (QGraphicsItem *)subFocusItem);
10984 QCOMPARE(scope->focusItem(), (QGraphicsItem *)subFocusItem);
10985 QCOMPARE(subFocusItem->focusItem(), (QGraphicsItem *)subFocusItem);
10986 QCOMPARE(rootItem->focusScopeItem(), (QGraphicsItem *)0);
10987 QCOMPARE(scope->focusScopeItem(), (QGraphicsItem *)subFocusItem);
10988 QCOMPARE(subFocusItem->focusScopeItem(), (QGraphicsItem *)0);
10989 QVERIFY(subFocusItem->hasFocus());
10993 QCOMPARE(rootItem->focusItem(), (QGraphicsItem *)0);
10994 QCOMPARE(scope->focusItem(), (QGraphicsItem *)0);
10995 QCOMPARE(subFocusItem->focusItem(), (QGraphicsItem *)0);
10996 QCOMPARE(rootItem->focusScopeItem(), (QGraphicsItem *)0);
10997 QCOMPARE(scope->focusScopeItem(), (QGraphicsItem *)subFocusItem);
10998 QCOMPARE(subFocusItem->focusScopeItem(), (QGraphicsItem *)0);
10999 QVERIFY(!subFocusItem->hasFocus());
11003 QCOMPARE(rootItem->focusItem(), (QGraphicsItem *)subFocusItem);
11004 QCOMPARE(scope->focusItem(), (QGraphicsItem *)subFocusItem);
11005 QCOMPARE(subFocusItem->focusItem(), (QGraphicsItem *)subFocusItem);
11006 QCOMPARE(rootItem->focusScopeItem(), (QGraphicsItem *)0);
11007 QCOMPARE(scope->focusScopeItem(), (QGraphicsItem *)subFocusItem);
11008 QCOMPARE(subFocusItem->focusScopeItem(), (QGraphicsItem *)0);
11009 QVERIFY(subFocusItem->hasFocus());
11011 // This should not crash
11016 class MyGraphicsItemWithItemChange : public QGraphicsWidget
11019 MyGraphicsItemWithItemChange(QGraphicsItem *parent = 0) : QGraphicsWidget(parent)
11022 QVariant itemChange(GraphicsItemChange change, const QVariant &value)
11024 if (change == QGraphicsItem::ItemSceneHasChanged) {
11025 foreach (QGraphicsView *view, scene()->views()) {
11026 //We trigger a sort of unindexed items in the BSP
11030 return QGraphicsWidget::itemChange(change, value);
11034 void tst_QGraphicsItem::sortItemsWhileAdding()
11036 QGraphicsScene scene;
11037 QGraphicsView view(&scene);
11038 QGraphicsWidget grandGrandParent;
11039 grandGrandParent.resize(200, 200);
11040 scene.addItem(&grandGrandParent);
11041 QGraphicsWidget grandParent;
11042 grandParent.resize(200, 200);
11043 QGraphicsWidget parent(&grandParent);
11044 parent.resize(200, 200);
11045 MyGraphicsItemWithItemChange item(&parent);
11046 grandParent.setParentItem(&grandGrandParent);
11049 void tst_QGraphicsItem::doNotMarkFullUpdateIfNotInScene()
11051 struct Item : public QGraphicsTextItem
11054 void paint(QPainter *painter, const QStyleOptionGraphicsItem *opt, QWidget *wid)
11057 QGraphicsTextItem::paint(painter, opt, wid);
11060 QGraphicsScene scene;
11061 MyGraphicsView view(&scene);
11062 Item *item = new Item;
11064 item->setPlainText("Grandparent");
11065 Item *item2 = new Item;
11066 item2->setPlainText("parent");
11067 item2->painted = 0;
11068 Item *item3 = new Item;
11069 item3->setPlainText("child");
11070 item3->painted = 0;
11071 QGraphicsOpacityEffect *effect = new QGraphicsOpacityEffect;
11072 effect->setOpacity(0.5);
11073 item2->setGraphicsEffect(effect);
11074 item3->setParentItem(item2);
11075 item2->setParentItem(item);
11076 scene.addItem(item);
11078 QTest::qWaitForWindowActive(view.windowHandle());
11079 view.activateWindow();
11080 QTRY_VERIFY(view.isActiveWindow());
11081 QTRY_VERIFY(view.repaints >= 1);
11082 int count = view.repaints;
11083 QTRY_COMPARE(item->painted, count);
11084 // cached as graphics effects, not painted multiple times
11085 QTRY_COMPARE(item2->painted, 1);
11086 QTRY_COMPARE(item3->painted, 1);
11088 QApplication::processEvents();
11089 QTRY_COMPARE(item->painted, count + 1);
11090 QTRY_COMPARE(item2->painted, 2);
11091 QTRY_COMPARE(item3->painted, 2);
11093 QApplication::processEvents();
11094 QTRY_COMPARE(item->painted, count + 2);
11095 QTRY_COMPARE(item2->painted, 3);
11096 QTRY_COMPARE(item3->painted, 3);
11099 void tst_QGraphicsItem::itemDiesDuringDraggingOperation()
11101 QGraphicsScene scene;
11102 QGraphicsView view(&scene);
11103 QGraphicsRectItem *item = new QGraphicsRectItem(QRectF(0, 0, 100, 100));
11104 item->setFlag(QGraphicsItem::ItemIsMovable);
11105 item->setAcceptDrops(true);
11106 scene.addItem(item);
11108 QApplication::setActiveWindow(&view);
11109 QVERIFY(QTest::qWaitForWindowActive(&view));
11110 QCOMPARE(QApplication::activeWindow(), (QWidget *)&view);
11111 QGraphicsSceneDragDropEvent dragEnter(QEvent::GraphicsSceneDragEnter);
11112 dragEnter.setScenePos(item->boundingRect().center());
11113 QApplication::sendEvent(&scene, &dragEnter);
11114 QGraphicsSceneDragDropEvent event(QEvent::GraphicsSceneDragMove);
11115 event.setScenePos(item->boundingRect().center());
11116 QApplication::sendEvent(&scene, &event);
11117 QVERIFY(QGraphicsScenePrivate::get(&scene)->dragDropItem == item);
11119 QVERIFY(QGraphicsScenePrivate::get(&scene)->dragDropItem == 0);
11122 void tst_QGraphicsItem::QTBUG_12112_focusItem()
11124 QGraphicsScene scene;
11125 QGraphicsView view(&scene);
11126 QGraphicsRectItem *item1 = new QGraphicsRectItem(0, 0, 20, 20);
11127 item1->setFlag(QGraphicsItem::ItemIsFocusable);
11128 QGraphicsRectItem *item2 = new QGraphicsRectItem(20, 20, 20, 20);
11129 item2->setFlag(QGraphicsItem::ItemIsFocusable);
11131 scene.addItem(item2);
11132 scene.addItem(item1);
11135 QApplication::setActiveWindow(&view);
11136 QVERIFY(QTest::qWaitForWindowActive(&view));
11137 QCOMPARE(QApplication::activeWindow(), (QWidget *)&view);
11139 QVERIFY(item1->focusItem());
11140 QVERIFY(!item2->focusItem());
11143 QVERIFY(!item1->focusItem());
11144 QVERIFY(item2->focusItem());
11147 void tst_QGraphicsItem::QTBUG_13473_sceneposchange()
11149 ScenePosChangeTester* parent = new ScenePosChangeTester;
11150 ScenePosChangeTester* child = new ScenePosChangeTester(parent);
11152 // parent's disabled ItemSendsGeometryChanges flag must not affect
11153 // child's scene pos change notifications
11154 parent->setFlag(QGraphicsItem::ItemSendsGeometryChanges, false);
11155 child->setFlag(QGraphicsItem::ItemSendsScenePositionChanges, true);
11157 QGraphicsScene scene;
11158 scene.addItem(parent);
11160 // ignore uninteresting changes
11165 parent->moveBy(1.0, 1.0);
11166 QCOMPARE(child->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 1);
11169 parent->setTransform(QTransform::fromScale(0.5, 0.5));
11170 QCOMPARE(child->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 2);
11173 class MyGraphicsWidget : public QGraphicsWidget {
11177 : QGraphicsWidget(0)
11179 QGraphicsLinearLayout *lay = new QGraphicsLinearLayout(Qt::Vertical);
11180 QLatin1String wiseWords("AZ BUKI VEDI");
11181 QString sentence(wiseWords);
11182 QStringList words = sentence.split(QLatin1Char(' '), QString::SkipEmptyParts);
11183 for (int i = 0; i < words.count(); ++i) {
11184 QGraphicsProxyWidget *proxy = new QGraphicsProxyWidget(this);
11185 QLabel *label = new QLabel(words.at(i));
11186 proxy->setWidget(label);
11187 proxy->setFocusPolicy(Qt::StrongFocus);
11188 proxy->setFlag(QGraphicsItem::ItemAcceptsInputMethod, true);
11190 proxy->setVisible(false);
11192 lay->addItem(proxy);
11199 class MyWidgetWindow : public QGraphicsWidget
11203 : QGraphicsWidget(0, Qt::Window)
11205 QGraphicsLinearLayout *lay = new QGraphicsLinearLayout(Qt::Vertical);
11206 MyGraphicsWidget *widget = new MyGraphicsWidget();
11207 lay->addItem(widget);
11212 void tst_QGraphicsItem::QTBUG_16374_crashInDestructor()
11214 QGraphicsScene scene;
11215 QGraphicsView view(&scene);
11217 MyWidgetWindow win;
11218 scene.addItem(&win);
11221 QVERIFY(QTest::qWaitForWindowExposed(&view));
11224 void tst_QGraphicsItem::QTBUG_20699_focusScopeCrash()
11226 QGraphicsScene scene;
11227 QGraphicsView view(&scene);
11228 QGraphicsPixmapItem fs;
11229 fs.setFlags(QGraphicsItem::ItemIsFocusScope | QGraphicsItem::ItemIsFocusable);
11230 scene.addItem(&fs);
11231 QGraphicsPixmapItem* fs2 = new QGraphicsPixmapItem(&fs);
11232 fs2->setFlags(QGraphicsItem::ItemIsFocusScope | QGraphicsItem::ItemIsFocusable);
11233 QGraphicsPixmapItem* fi2 = new QGraphicsPixmapItem(&fs);
11234 fi2->setFlags(QGraphicsItem::ItemIsFocusable);
11235 QGraphicsPixmapItem* fi = new QGraphicsPixmapItem(fs2);
11236 fi->setFlags(QGraphicsItem::ItemIsFocusable);
11241 QVERIFY(QTest::qWaitForWindowExposed(&view));
11243 fi->setParentItem(fi2);
11246 fi->setParentItem(fs2);
11250 fi->setParentItem(fi2);
11255 QTEST_MAIN(tst_QGraphicsItem)
11256 #include "tst_qgraphicsitem.moc"