1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the test suite of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
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 <QInputContext>
65 #include <QPushButton>
67 #include <QGraphicsLinearLayout>
73 Q_DECLARE_METATYPE(QList<int>)
74 Q_DECLARE_METATYPE(QList<QRectF>)
75 Q_DECLARE_METATYPE(QPainterPath)
76 Q_DECLARE_METATYPE(QPointF)
77 Q_DECLARE_METATYPE(QRectF)
79 #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
81 #define Q_CHECK_PAINTEVENTS \
82 if (::SwitchDesktop(::GetThreadDesktop(::GetCurrentThreadId())) == 0) \
83 QSKIP("The Graphics View doesn't get the paint events");
85 #define Q_CHECK_PAINTEVENTS
89 // On mac (cocoa) we always get full update.
90 // So check that the expected region is contained inside the actual
91 #define COMPARE_REGIONS(ACTUAL, EXPECTED) QVERIFY((EXPECTED).subtracted(ACTUAL).isEmpty())
93 #define COMPARE_REGIONS QTRY_COMPARE
96 #include "../../../platformquirks.h"
98 static QGraphicsRectItem staticItem; //QTBUG-7629, we should not crash at exit.
100 static void sendMousePress(QGraphicsScene *scene, const QPointF &point, Qt::MouseButton button = Qt::LeftButton)
102 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
103 event.setScenePos(point);
104 event.setButton(button);
105 event.setButtons(button);
106 QApplication::sendEvent(scene, &event);
109 static void sendMouseMove(QGraphicsScene *scene, const QPointF &point,
110 Qt::MouseButton button = Qt::NoButton, Qt::MouseButtons /* buttons */ = 0)
112 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseMove);
113 event.setScenePos(point);
114 event.setButton(button);
115 event.setButtons(button);
116 QApplication::sendEvent(scene, &event);
119 static void sendMouseRelease(QGraphicsScene *scene, const QPointF &point, Qt::MouseButton button = Qt::LeftButton)
121 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseRelease);
122 event.setScenePos(point);
123 event.setButton(button);
124 QApplication::sendEvent(scene, &event);
127 static void sendMouseClick(QGraphicsScene *scene, const QPointF &point, Qt::MouseButton button = Qt::LeftButton)
129 sendMousePress(scene, point, button);
130 sendMouseRelease(scene, point, button);
133 static void sendKeyPress(QGraphicsScene *scene, Qt::Key key)
135 QKeyEvent keyEvent(QEvent::KeyPress, key, Qt::NoModifier);
136 QApplication::sendEvent(scene, &keyEvent);
139 static void sendKeyRelease(QGraphicsScene *scene, Qt::Key key)
141 QKeyEvent keyEvent(QEvent::KeyRelease, key, Qt::NoModifier);
142 QApplication::sendEvent(scene, &keyEvent);
145 static void sendKeyClick(QGraphicsScene *scene, Qt::Key key)
147 sendKeyPress(scene, key);
148 sendKeyRelease(scene, key);
151 class EventSpy : public QGraphicsWidget
155 EventSpy(QObject *watched, QEvent::Type type)
156 : _count(0), spied(type)
158 watched->installEventFilter(this);
161 EventSpy(QGraphicsScene *scene, QGraphicsItem *watched, QEvent::Type type)
162 : _count(0), spied(type)
164 scene->addItem(this);
165 watched->installSceneEventFilter(this);
168 int count() const { return _count; }
171 bool eventFilter(QObject *watched, QEvent *event)
174 if (event->type() == spied)
179 bool sceneEventFilter(QGraphicsItem *watched, QEvent *event)
182 if (event->type() == spied)
191 class EventSpy2 : public QGraphicsWidget
195 EventSpy2(QObject *watched)
197 watched->installEventFilter(this);
200 EventSpy2(QGraphicsScene *scene, QGraphicsItem *watched)
202 scene->addItem(this);
203 watched->installSceneEventFilter(this);
206 QMap<QEvent::Type, int> counts;
209 bool eventFilter(QObject *watched, QEvent *event)
212 ++counts[event->type()];
216 bool sceneEventFilter(QGraphicsItem *watched, QEvent *event)
219 ++counts[event->type()];
224 class EventTester : public QGraphicsItem
227 EventTester(QGraphicsItem *parent = 0) : QGraphicsItem(parent), repaints(0)
228 { br = QRectF(-10, -10, 20, 20); }
230 void setGeometry(const QRectF &rect)
232 prepareGeometryChange();
237 QRectF boundingRect() const
240 void paint(QPainter *painter, const QStyleOptionGraphicsItem *o, QWidget *)
242 hints = painter->renderHints();
243 painter->setBrush(brush);
244 painter->drawRect(boundingRect());
245 lastExposedRect = o->exposedRect;
249 bool sceneEvent(QEvent *event)
251 events << event->type();
252 return QGraphicsItem::sceneEvent(event);
258 hints = QPainter::RenderHints(0);
260 lastExposedRect = QRectF();
263 QList<QEvent::Type> events;
264 QPainter::RenderHints hints;
267 QRectF lastExposedRect;
271 class MyGraphicsView : public QGraphicsView
275 QRegion paintedRegion;
276 MyGraphicsView(QGraphicsScene *scene, QWidget *parent=0) : QGraphicsView(scene,parent), repaints(0) {}
277 void paintEvent(QPaintEvent *e)
279 paintedRegion += e->region();
281 QGraphicsView::paintEvent(e);
283 void reset() { repaints = 0; paintedRegion = QRegion(); }
286 class tst_QGraphicsItem : public QObject
295 void constructionWithParent();
297 void deleteChildItem();
300 void setParentItem();
303 void inputMethodHints();
307 void explicitlyVisible();
309 void explicitlyEnabled();
312 void selected_group();
313 void selected_textItem();
314 void selected_multi();
315 void acceptedMouseButtons();
316 void acceptsHoverEvents();
317 void childAcceptsHoverEvents();
327 void collidesWith_item();
328 void collidesWith_path_data();
329 void collidesWith_path();
330 void collidesWithItemWithClip();
333 void mapFromToParent();
334 void mapFromToScene();
335 void mapFromToItem();
336 void mapRectFromToParent_data();
337 void mapRectFromToParent();
339 void commonAncestorItem();
342 void graphicsitem_cast();
343 void hoverEventsGenerateRepaints();
344 void boundingRects_data();
345 void boundingRects();
346 void boundingRects2();
347 void sceneBoundingRect();
348 void childrenBoundingRect();
349 void childrenBoundingRectTransformed();
350 void childrenBoundingRect2();
351 void childrenBoundingRect3();
352 void childrenBoundingRect4();
353 void childrenBoundingRect5();
358 void warpChildrenIntoGroup();
359 void removeFromGroup();
360 void handlesChildEvents();
361 void handlesChildEvents2();
362 void handlesChildEvents3();
363 void filtersChildEvents();
364 void filtersChildEvents2();
365 void ensureVisible();
367 //void textControlGetterSetter();
368 void defaultItemTest_QGraphicsLineItem();
369 void defaultItemTest_QGraphicsPixmapItem();
370 void defaultItemTest_QGraphicsTextItem();
371 void defaultItemTest_QGraphicsEllipseItem();
373 void sceneEventFilter();
374 void prepareGeometryChange();
376 void deleteItemInEventHandlers();
377 void itemClipsToShape();
378 void itemClipsChildrenToShape();
379 void itemClipsChildrenToShape2();
380 void itemClipsChildrenToShape3();
381 void itemClipsChildrenToShape4();
382 void itemClipsChildrenToShape5();
383 void itemClipsTextChildToShape();
384 void itemClippingDiscovery();
385 void ancestorFlags();
386 void untransformable();
387 void contextMenuEventPropagation();
388 void itemIsMovable();
389 void boundingRegion_data();
390 void boundingRegion();
391 void itemTransform_parentChild();
392 void itemTransform_siblings();
393 void itemTransform_unrelated();
397 void opacityZeroUpdates();
398 void itemStacksBehindParent();
399 void nestedClipping();
400 void nestedClippingTransforms();
401 void sceneTransformCache();
402 void tabChangesFocus();
403 void tabChangesFocus_data();
406 void updateCachedItemAfterMove();
407 void deviceTransform_data();
408 void deviceTransform();
410 void setTransformProperties_data();
411 void setTransformProperties();
412 void itemUsesExtendedStyleOption();
413 void itemSendsGeometryChanges();
418 void itemHasNoContents();
419 void hitTestUntransformableItem();
420 void hitTestGraphicsEffectItem();
423 void focusProxyDeletion();
424 void negativeZStacksBehindParent();
425 void setGraphicsEffect();
427 void addPanelToActiveScene();
428 void panelWithFocusItem();
430 void setActivePanelOnInactiveScene();
431 void activationOnShowHide();
432 void moveWhileDeleting();
433 void ensureDirtySceneTransform();
437 void sceneModality();
438 void panelModality();
439 void mixedModality();
440 void modality_hover();
441 void modality_mouseGrabber();
442 void modality_clickFocus();
443 void modality_keyEvents();
444 void itemIsInFront();
445 void scenePosChange();
446 void updateMicroFocus();
447 void textItem_shortcuts();
449 void focusHandling_data();
450 void focusHandling();
451 void touchEventPropagation_data();
452 void touchEventPropagation();
453 void deviceCoordinateCache_simpleRotations();
455 // task specific tests below me
456 void task141694_textItemEnsureVisible();
457 void task128696_textItemEnsureMovable();
458 void ensureUpdateOnTextItem();
459 void task177918_lineItemUndetected();
460 void task240400_clickOnTextItem_data();
461 void task240400_clickOnTextItem();
462 void task243707_addChildBeforeParent();
463 void task197802_childrenVisibility();
464 void QTBUG_4233_updateCachedWithSceneRect();
465 void QTBUG_5418_textItemSetDefaultColor();
466 void QTBUG_6738_missingUpdateWithSetParent();
467 void QTBUG_7714_fullUpdateDiscardingOpacityUpdate2();
468 void QT_2653_fullUpdateDiscardingOpacityUpdate();
469 void QT_2649_focusScope();
470 void sortItemsWhileAdding();
471 void doNotMarkFullUpdateIfNotInScene();
472 void itemDiesDuringDraggingOperation();
473 void QTBUG_12112_focusItem();
474 void QTBUG_13473_sceneposchange();
475 void QTBUG_16374_crashInDestructor();
476 void QTBUG_20699_focusScopeCrash();
479 QList<QGraphicsItem *> paintedItems;
482 void tst_QGraphicsItem::init()
484 #ifdef Q_OS_WINCE //disable magic for WindowsCE
485 qApp->setAutoMaximizeThreshold(-1);
489 void tst_QGraphicsItem::construction()
491 for (int i = 0; i < 7; ++i) {
495 item = new QGraphicsEllipseItem;
496 QCOMPARE(int(item->type()), int(QGraphicsEllipseItem::Type));
497 QCOMPARE(qgraphicsitem_cast<QGraphicsEllipseItem *>(item), (QGraphicsEllipseItem *)item);
498 QCOMPARE(qgraphicsitem_cast<QGraphicsRectItem *>(item), (QGraphicsRectItem *)0);
499 QCOMPARE(item->flags(), 0);
502 item = new QGraphicsLineItem;
503 QCOMPARE(int(item->type()), int(QGraphicsLineItem::Type));
504 QCOMPARE(qgraphicsitem_cast<QGraphicsLineItem *>(item), (QGraphicsLineItem *)item);
505 QCOMPARE(qgraphicsitem_cast<QGraphicsRectItem *>(item), (QGraphicsRectItem *)0);
506 QCOMPARE(item->flags(), 0);
509 item = new QGraphicsPathItem;
510 QCOMPARE(int(item->type()), int(QGraphicsPathItem::Type));
511 QCOMPARE(qgraphicsitem_cast<QGraphicsPathItem *>(item), (QGraphicsPathItem *)item);
512 QCOMPARE(qgraphicsitem_cast<QGraphicsRectItem *>(item), (QGraphicsRectItem *)0);
513 QCOMPARE(item->flags(), 0);
516 item = new QGraphicsPixmapItem;
517 QCOMPARE(int(item->type()), int(QGraphicsPixmapItem::Type));
518 QCOMPARE(qgraphicsitem_cast<QGraphicsPixmapItem *>(item), (QGraphicsPixmapItem *)item);
519 QCOMPARE(qgraphicsitem_cast<QGraphicsRectItem *>(item), (QGraphicsRectItem *)0);
520 QCOMPARE(item->flags(), 0);
523 item = new QGraphicsPolygonItem;
524 QCOMPARE(int(item->type()), int(QGraphicsPolygonItem::Type));
525 QCOMPARE(qgraphicsitem_cast<QGraphicsPolygonItem *>(item), (QGraphicsPolygonItem *)item);
526 QCOMPARE(qgraphicsitem_cast<QGraphicsRectItem *>(item), (QGraphicsRectItem *)0);
527 QCOMPARE(item->flags(), 0);
530 item = new QGraphicsRectItem;
531 QCOMPARE(int(item->type()), int(QGraphicsRectItem::Type));
532 QCOMPARE(qgraphicsitem_cast<QGraphicsRectItem *>(item), (QGraphicsRectItem *)item);
533 QCOMPARE(qgraphicsitem_cast<QGraphicsLineItem *>(item), (QGraphicsLineItem *)0);
534 QCOMPARE(item->flags(), 0);
537 item = new QGraphicsTextItem;
538 QCOMPARE(int(item->type()), int(QGraphicsTextItem::Type));
539 QCOMPARE(qgraphicsitem_cast<QGraphicsTextItem *>(item), (QGraphicsTextItem *)item);
540 QCOMPARE(qgraphicsitem_cast<QGraphicsRectItem *>(item), (QGraphicsRectItem *)0);
541 // This is the only item that uses an extended style option.
542 QCOMPARE(item->flags(), QGraphicsItem::GraphicsItemFlags(QGraphicsItem::ItemUsesExtendedStyleOption));
545 qFatal("You broke the logic, please fix!");
549 QCOMPARE(item->scene(), (QGraphicsScene *)0);
550 QCOMPARE(item->parentItem(), (QGraphicsItem *)0);
551 QVERIFY(item->children().isEmpty());
552 QVERIFY(item->isVisible());
553 QVERIFY(item->isEnabled());
554 QVERIFY(!item->isSelected());
555 QCOMPARE(item->acceptedMouseButtons(), Qt::MouseButtons(0x1f));
556 if (item->type() == QGraphicsTextItem::Type)
557 QVERIFY(item->acceptsHoverEvents());
559 QVERIFY(!item->acceptsHoverEvents());
560 QVERIFY(!item->hasFocus());
561 QCOMPARE(item->pos(), QPointF());
562 QCOMPARE(item->matrix(), QMatrix());
563 QCOMPARE(item->sceneMatrix(), QMatrix());
564 QCOMPARE(item->zValue(), qreal(0));
565 QCOMPARE(item->sceneBoundingRect(), QRectF());
566 QCOMPARE(item->shape(), QPainterPath());
567 QVERIFY(!item->contains(QPointF(0, 0)));
568 QVERIFY(!item->collidesWithItem(0));
569 QVERIFY(item->collidesWithItem(item));
570 QVERIFY(!item->collidesWithPath(QPainterPath()));
571 QVERIFY(!item->isAncestorOf(0));
572 QVERIFY(!item->isAncestorOf(item));
573 QCOMPARE(item->data(0), QVariant());
578 class BoundingRectItem : public QGraphicsRectItem
581 BoundingRectItem(QGraphicsItem *parent = 0)
582 : QGraphicsRectItem(0, 0, parent ? 200 : 100, parent ? 200 : 100,
586 QRectF boundingRect() const
588 QRectF tmp = QGraphicsRectItem::boundingRect();
589 foreach (QGraphicsItem *child, children())
590 tmp |= child->boundingRect(); // <- might be pure virtual
595 void tst_QGraphicsItem::constructionWithParent()
597 // This test causes a crash if item1 calls item2's pure virtuals before the
598 // object has been constructed.
599 QGraphicsItem *item0 = new BoundingRectItem;
600 QGraphicsItem *item1 = new BoundingRectItem;
601 QGraphicsScene scene;
602 scene.addItem(item0);
603 scene.addItem(item1);
604 QGraphicsItem *item2 = new BoundingRectItem(item1);
605 QCOMPARE(item1->children(), QList<QGraphicsItem *>() << item2);
606 QCOMPARE(item1->boundingRect(), QRectF(0, 0, 200, 200));
608 item2->setParentItem(item0);
609 QCOMPARE(item0->children(), QList<QGraphicsItem *>() << item2);
610 QCOMPARE(item0->boundingRect(), QRectF(0, 0, 200, 200));
613 static int itemDeleted = 0;
614 class Item : public QGraphicsRectItem
621 void tst_QGraphicsItem::destruction()
623 QCOMPARE(itemDeleted, 0);
625 QGraphicsItem *parent = new QGraphicsRectItem;
626 Item *child = new Item;
627 child->setParentItem(parent);
628 QCOMPARE(child->parentItem(), parent);
630 QCOMPARE(itemDeleted, 1);
633 QGraphicsItem *parent = new QGraphicsRectItem;
634 Item *child = new Item;
635 child->setParentItem(parent);
636 QCOMPARE(parent->children().size(), 1);
638 QCOMPARE(parent->children().size(), 0);
640 QCOMPARE(itemDeleted, 2);
643 QGraphicsScene scene;
644 QGraphicsItem *parent = new QGraphicsRectItem;
645 Item *child = new Item;
646 QCOMPARE(child->parentItem(), (QGraphicsItem *)0);
647 child->setParentItem(parent);
648 QCOMPARE(child->parentItem(), parent);
649 scene.addItem(parent);
650 QCOMPARE(child->parentItem(), parent);
652 QCOMPARE(itemDeleted, 3);
655 QGraphicsScene scene;
656 QGraphicsItem *parent = new QGraphicsRectItem;
657 Item *child = new Item;
658 child->setParentItem(parent);
659 scene.addItem(parent);
660 QCOMPARE(child->scene(), &scene);
661 QCOMPARE(parent->children().size(), 1);
663 QCOMPARE(parent->children().size(), 0);
665 QCOMPARE(itemDeleted, 4);
668 QGraphicsScene scene;
669 QGraphicsItem *parent = new QGraphicsRectItem;
670 Item *child = new Item;
671 child->setParentItem(parent);
672 scene.addItem(parent);
673 QCOMPARE(child->scene(), &scene);
674 scene.removeItem(parent);
675 QCOMPARE(child->scene(), (QGraphicsScene *)0);
677 QCOMPARE(itemDeleted, 5);
680 QGraphicsScene scene;
681 QGraphicsItem *parent = new QGraphicsRectItem;
682 Item *child = new Item;
683 child->setParentItem(parent);
684 QCOMPARE(child->scene(), (QGraphicsScene *)0);
685 QCOMPARE(parent->scene(), (QGraphicsScene *)0);
686 scene.addItem(parent);
687 QCOMPARE(child->scene(), &scene);
688 scene.removeItem(child);
689 QCOMPARE(child->scene(), (QGraphicsScene *)0);
690 QCOMPARE(parent->scene(), &scene);
691 QCOMPARE(child->parentItem(), (QGraphicsItem *)0);
692 QVERIFY(parent->children().isEmpty());
694 QCOMPARE(itemDeleted, 5);
696 QCOMPARE(itemDeleted, 6);
699 QGraphicsScene scene;
700 QGraphicsItem *parent = new QGraphicsRectItem;
701 Item *child = new Item;
702 child->setParentItem(parent);
703 scene.addItem(parent);
704 scene.removeItem(child);
705 scene.removeItem(parent);
708 QCOMPARE(itemDeleted, 7);
711 QGraphicsScene scene;
712 QGraphicsItem *parent = new QGraphicsRectItem;
713 Item *child = new Item;
714 child->setParentItem(parent);
715 scene.addItem(parent);
716 QGraphicsScene scene2;
717 scene2.addItem(parent);
719 QCOMPARE(itemDeleted, 8);
722 QGraphicsScene scene;
723 QGraphicsItem *parent = new QGraphicsRectItem;
724 Item *child = new Item;
725 child->setParentItem(parent);
726 scene.addItem(parent);
727 QCOMPARE(child->scene(), &scene);
728 QGraphicsScene scene2;
729 scene2.addItem(parent);
730 QCOMPARE(child->scene(), &scene2);
731 scene.addItem(parent);
732 QCOMPARE(child->scene(), &scene);
733 scene2.addItem(parent);
734 QCOMPARE(child->scene(), &scene2);
736 QCOMPARE(itemDeleted, 9);
739 QGraphicsScene scene;
740 QGraphicsItem *parent = new QGraphicsRectItem;
741 Item *child = new Item;
742 child->setParentItem(parent);
743 scene.addItem(parent);
744 QCOMPARE(child->scene(), &scene);
745 QGraphicsScene scene2;
746 scene2.addItem(child);
747 QCOMPARE(child->scene(), &scene2);
749 QCOMPARE(itemDeleted, 9);
751 QCOMPARE(itemDeleted, 10);
754 QGraphicsScene scene;
755 QGraphicsItem *root = new QGraphicsRectItem;
756 QGraphicsItem *parent = root;
757 QGraphicsItem *middleItem = 0;
758 for (int i = 0; i < 99; ++i) {
759 Item *child = new Item;
760 child->setParentItem(parent);
767 QCOMPARE(scene.items().size(), 100);
769 QGraphicsScene scene2;
770 scene2.addItem(middleItem);
773 QCOMPARE(itemDeleted, 59);
775 QCOMPARE(itemDeleted, 109);
777 QGraphicsScene *scene = new QGraphicsScene;
778 QGraphicsRectItem *parent = new QGraphicsRectItem;
779 Item *child = new Item;
780 child->setParentItem(parent);
781 parent->setVisible(false);
782 scene->addItem(parent);
783 QCOMPARE(child->parentItem(), static_cast<QGraphicsItem*>(parent));
785 QCOMPARE(itemDeleted, 110);
789 void tst_QGraphicsItem::deleteChildItem()
791 QGraphicsScene scene;
792 QGraphicsItem *rect = scene.addRect(QRectF());
793 QGraphicsItem *child1 = new QGraphicsRectItem(rect);
794 QGraphicsItem *child2 = new QGraphicsRectItem(rect);
795 QGraphicsItem *child3 = new QGraphicsRectItem(rect);
798 child2->setParentItem(0);
802 void tst_QGraphicsItem::scene()
804 QGraphicsRectItem *item = new QGraphicsRectItem;
805 QCOMPARE(item->scene(), (QGraphicsScene *)0);
807 QGraphicsScene scene;
809 QCOMPARE(item->scene(), (QGraphicsScene *)&scene);
811 QGraphicsScene scene2;
812 scene2.addItem(item);
813 QCOMPARE(item->scene(), (QGraphicsScene *)&scene2);
815 scene2.removeItem(item);
816 QCOMPARE(item->scene(), (QGraphicsScene *)0);
821 void tst_QGraphicsItem::parentItem()
823 QGraphicsRectItem item;
824 QCOMPARE(item.parentItem(), (QGraphicsItem *)0);
826 QGraphicsRectItem *item2 = new QGraphicsRectItem(QRectF(), &item);
827 QCOMPARE(item2->parentItem(), (QGraphicsItem *)&item);
828 item2->setParentItem(&item);
829 QCOMPARE(item2->parentItem(), (QGraphicsItem *)&item);
830 item2->setParentItem(0);
831 QCOMPARE(item2->parentItem(), (QGraphicsItem *)0);
836 void tst_QGraphicsItem::setParentItem()
838 QGraphicsScene scene;
839 QGraphicsItem *item = scene.addRect(QRectF(0, 0, 10, 10));
840 QCOMPARE(item->scene(), &scene);
842 QGraphicsRectItem *child = new QGraphicsRectItem;
843 QCOMPARE(child->scene(), (QGraphicsScene *)0);
845 // This implicitly adds the item to the parent's scene
846 child->setParentItem(item);
847 QCOMPARE(child->scene(), &scene);
849 // This just makes it a toplevel
850 child->setParentItem(0);
851 QCOMPARE(child->scene(), &scene);
853 // Add the child back to the parent, then remove the parent from the scene
854 child->setParentItem(item);
855 scene.removeItem(item);
856 QCOMPARE(child->scene(), (QGraphicsScene *)0);
859 void tst_QGraphicsItem::children()
861 QGraphicsRectItem item;
862 QVERIFY(item.children().isEmpty());
864 QGraphicsRectItem *item2 = new QGraphicsRectItem(QRectF(), &item);
865 QCOMPARE(item.children().size(), 1);
866 QCOMPARE(item.children().first(), (QGraphicsItem *)item2);
867 QVERIFY(item2->children().isEmpty());
870 QVERIFY(item.children().isEmpty());
873 void tst_QGraphicsItem::flags()
875 QGraphicsRectItem *item = new QGraphicsRectItem(QRectF(-10, -10, 20, 20));
876 QCOMPARE(item->flags(), 0);
878 QGraphicsScene scene;
879 QEvent activate(QEvent::WindowActivate);
880 QApplication::sendEvent(&scene, &activate);
886 item->setFlag(QGraphicsItem::ItemIsFocusable, false);
887 QVERIFY(!item->hasFocus());
889 QVERIFY(!item->hasFocus());
891 item->setFlag(QGraphicsItem::ItemIsFocusable, true);
892 QVERIFY(!item->hasFocus());
894 QVERIFY(item->hasFocus());
895 QVERIFY(scene.hasFocus());
897 item->setFlag(QGraphicsItem::ItemIsFocusable, false);
898 QVERIFY(!item->hasFocus());
899 QVERIFY(scene.hasFocus());
903 item->setFlag(QGraphicsItem::ItemIsSelectable, false);
904 QVERIFY(!item->isSelected());
905 item->setSelected(true);
906 QVERIFY(!item->isSelected());
908 item->setFlag(QGraphicsItem::ItemIsSelectable, true);
909 QVERIFY(!item->isSelected());
910 item->setSelected(true);
911 QVERIFY(item->isSelected());
912 item->setFlag(QGraphicsItem::ItemIsSelectable, false);
913 QVERIFY(!item->isSelected());
917 item->setFlag(QGraphicsItem::ItemIsMovable, false);
918 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
919 event.setScenePos(QPointF(0, 0));
920 event.setButton(Qt::LeftButton);
921 event.setButtons(Qt::LeftButton);
922 QApplication::sendEvent(&scene, &event);
923 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0); // mouse grabber is reset
925 QGraphicsSceneMouseEvent event2(QEvent::GraphicsSceneMouseMove);
926 event2.setScenePos(QPointF(10, 10));
927 event2.setButton(Qt::LeftButton);
928 event2.setButtons(Qt::LeftButton);
929 QApplication::sendEvent(&scene, &event2);
930 QCOMPARE(item->pos(), QPointF());
932 QGraphicsSceneMouseEvent event3(QEvent::GraphicsSceneMouseRelease);
933 event3.setScenePos(QPointF(10, 10));
934 event3.setButtons(0);
935 QApplication::sendEvent(&scene, &event3);
936 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
938 item->setFlag(QGraphicsItem::ItemIsMovable, true);
939 QGraphicsSceneMouseEvent event4(QEvent::GraphicsSceneMousePress);
940 event4.setScenePos(QPointF(0, 0));
941 event4.setButton(Qt::LeftButton);
942 event4.setButtons(Qt::LeftButton);
943 QApplication::sendEvent(&scene, &event4);
944 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)item);
945 QGraphicsSceneMouseEvent event5(QEvent::GraphicsSceneMouseMove);
946 event5.setScenePos(QPointF(10, 10));
947 event5.setButton(Qt::LeftButton);
948 event5.setButtons(Qt::LeftButton);
949 QApplication::sendEvent(&scene, &event5);
950 QCOMPARE(item->pos(), QPointF(10, 10));
953 QGraphicsItem* clippingParent = new QGraphicsRectItem;
954 clippingParent->setFlag(QGraphicsItem::ItemClipsChildrenToShape, true);
956 QGraphicsItem* nonClippingParent = new QGraphicsRectItem;
957 nonClippingParent->setFlag(QGraphicsItem::ItemClipsChildrenToShape, false);
959 QGraphicsItem* child = new QGraphicsRectItem(nonClippingParent);
960 QVERIFY(!child->isClipped());
962 child->setParentItem(clippingParent);
963 QVERIFY(child->isClipped());
965 child->setParentItem(nonClippingParent);
966 QVERIFY(!child->isClipped());
970 class ImhTester : public QGraphicsItem
972 QRectF boundingRect() const { return QRectF(); }
973 void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *) {}
976 void tst_QGraphicsItem::inputMethodHints()
978 ImhTester *item = new ImhTester;
979 item->setFlag(QGraphicsItem::ItemAcceptsInputMethod, true);
980 item->setFlag(QGraphicsItem::ItemIsFocusable, true);
981 QCOMPARE(item->inputMethodHints(), Qt::ImhNone);
982 ImhTester *item2 = new ImhTester;
983 item2->setFlag(QGraphicsItem::ItemAcceptsInputMethod, true);
984 item2->setFlag(QGraphicsItem::ItemIsFocusable, true);
985 Qt::InputMethodHints imHints = item2->inputMethodHints();
986 imHints |= Qt::ImhHiddenText;
987 item2->setInputMethodHints(imHints);
988 QGraphicsScene scene;
990 scene.addItem(item2);
991 QGraphicsView view(&scene);
992 QApplication::setActiveWindow(&view);
994 QTest::qWaitForWindowShown(&view);
996 QTRY_VERIFY(item->hasFocus());
997 QCOMPARE(view.inputMethodHints(), item->inputMethodHints());
999 QTRY_VERIFY(item2->hasFocus());
1000 QCOMPARE(view.inputMethodHints(), item2->inputMethodHints());
1001 item->setFlag(QGraphicsItem::ItemAcceptsInputMethod, false);
1003 QTRY_VERIFY(item->hasFocus());
1004 //Focus has changed but the new item doesn't accept input method, no hints.
1005 QCOMPARE(view.inputMethodHints(), 0);
1007 QTRY_VERIFY(item2->hasFocus());
1008 QCOMPARE(view.inputMethodHints(), item2->inputMethodHints());
1009 imHints = item2->inputMethodHints();
1010 imHints |= (Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText);
1011 item2->setInputMethodHints(imHints);
1012 QCOMPARE(view.inputMethodHints(), item2->inputMethodHints());
1013 QGraphicsProxyWidget *widget = new QGraphicsProxyWidget;
1014 QLineEdit *edit = new QLineEdit;
1015 edit->setEchoMode(QLineEdit::Password);
1016 scene.addItem(widget);
1018 QTRY_VERIFY(widget->hasFocus());
1019 //No widget on the proxy, so no hints
1020 QCOMPARE(view.inputMethodHints(), 0);
1021 widget->setWidget(edit);
1022 //View should match with the line edit
1023 QCOMPARE(view.inputMethodHints(), edit->inputMethodHints());
1026 void tst_QGraphicsItem::toolTip()
1028 QString toolTip = "Qt rocks!";
1030 QGraphicsRectItem *item = new QGraphicsRectItem(QRectF(0, 0, 100, 100));
1031 item->setPen(QPen(Qt::red, 1));
1032 item->setBrush(QBrush(Qt::blue));
1033 QVERIFY(item->toolTip().isEmpty());
1034 item->setToolTip(toolTip);
1035 QCOMPARE(item->toolTip(), toolTip);
1037 QGraphicsScene scene;
1038 scene.addItem(item);
1040 QGraphicsView view(&scene);
1041 view.setFixedSize(200, 200);
1045 QHelpEvent helpEvent(QEvent::ToolTip, view.viewport()->rect().topLeft(),
1046 view.viewport()->mapToGlobal(view.viewport()->rect().topLeft()));
1047 QApplication::sendEvent(view.viewport(), &helpEvent);
1050 bool foundView = false;
1051 bool foundTipLabel = false;
1052 foreach (QWidget *widget, QApplication::topLevelWidgets()) {
1053 if (widget == &view)
1055 if (widget->inherits("QTipLabel"))
1056 foundTipLabel = true;
1059 QVERIFY(!foundTipLabel);
1063 QHelpEvent helpEvent(QEvent::ToolTip, view.viewport()->rect().center(),
1064 view.viewport()->mapToGlobal(view.viewport()->rect().center()));
1065 QApplication::sendEvent(view.viewport(), &helpEvent);
1068 bool foundView = false;
1069 bool foundTipLabel = false;
1070 foreach (QWidget *widget, QApplication::topLevelWidgets()) {
1071 if (widget == &view)
1073 if (widget->inherits("QTipLabel"))
1074 foundTipLabel = true;
1077 QVERIFY(foundTipLabel);
1081 QHelpEvent helpEvent(QEvent::ToolTip, view.viewport()->rect().topLeft(),
1082 view.viewport()->mapToGlobal(view.viewport()->rect().topLeft()));
1083 QApplication::sendEvent(view.viewport(), &helpEvent);
1086 bool foundView = false;
1087 bool foundTipLabel = false;
1088 foreach (QWidget *widget, QApplication::topLevelWidgets()) {
1089 if (widget == &view)
1091 if (widget->inherits("QTipLabel") && widget->isVisible())
1092 foundTipLabel = true;
1095 QVERIFY(!foundTipLabel);
1099 void tst_QGraphicsItem::visible()
1101 QGraphicsItem *item = new QGraphicsRectItem(QRectF(-10, -10, 20, 20));
1102 item->setFlag(QGraphicsItem::ItemIsMovable);
1103 QVERIFY(item->isVisible());
1104 item->setVisible(false);
1105 QVERIFY(!item->isVisible());
1106 item->setVisible(true);
1107 QVERIFY(item->isVisible());
1109 QGraphicsScene scene;
1110 QEvent activate(QEvent::WindowActivate);
1111 QApplication::sendEvent(&scene, &activate);
1113 scene.addItem(item);
1114 QVERIFY(item->isVisible());
1115 QCOMPARE(scene.itemAt(0, 0), item);
1116 item->setVisible(false);
1117 QCOMPARE(scene.itemAt(0, 0), (QGraphicsItem *)0);
1118 item->setVisible(true);
1119 QCOMPARE(scene.itemAt(0, 0), item);
1121 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
1122 event.setButton(Qt::LeftButton);
1123 event.setScenePos(QPointF(0, 0));
1124 QApplication::sendEvent(&scene, &event);
1125 QCOMPARE(scene.mouseGrabberItem(), item);
1126 item->setVisible(false);
1127 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
1128 item->setVisible(true);
1129 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
1131 item->setFlag(QGraphicsItem::ItemIsFocusable);
1133 QVERIFY(item->hasFocus());
1134 item->setVisible(false);
1135 QVERIFY(!item->hasFocus());
1136 item->setVisible(true);
1137 QVERIFY(!item->hasFocus());
1140 void tst_QGraphicsItem::isVisibleTo()
1142 QGraphicsScene scene;
1143 QGraphicsItem *parent = scene.addRect(QRectF(0, 0, 100, 100));
1144 QGraphicsItem *child = scene.addRect(QRectF(25, 25, 50, 50));
1145 QGraphicsItem *grandChild = scene.addRect(QRectF(50, 50, 50, 50));
1146 QGraphicsItem *stranger = scene.addRect(100, 100, 100, 100);
1148 child->setParentItem(parent);
1149 grandChild->setParentItem(child);
1151 QVERIFY(grandChild->isVisible());
1152 QVERIFY(grandChild->isVisibleTo(grandChild));
1153 QVERIFY(grandChild->isVisibleTo(child));
1154 QVERIFY(grandChild->isVisibleTo(parent));
1155 QVERIFY(grandChild->isVisibleTo(0));
1156 QVERIFY(child->isVisible());
1157 QVERIFY(child->isVisibleTo(child));
1158 QVERIFY(child->isVisibleTo(parent));
1159 QVERIFY(child->isVisibleTo(0));
1160 QVERIFY(parent->isVisible());
1161 QVERIFY(parent->isVisibleTo(parent));
1162 QVERIFY(parent->isVisibleTo(0));
1163 QVERIFY(!parent->isVisibleTo(child));
1164 QVERIFY(!child->isVisibleTo(grandChild));
1165 QVERIFY(!grandChild->isVisibleTo(stranger));
1166 QVERIFY(!child->isVisibleTo(stranger));
1167 QVERIFY(!parent->isVisibleTo(stranger));
1168 QVERIFY(!stranger->isVisibleTo(grandChild));
1169 QVERIFY(!stranger->isVisibleTo(child));
1170 QVERIFY(!stranger->isVisibleTo(parent));
1172 // Case 1: only parent is explicitly hidden
1175 QVERIFY(!grandChild->isVisible());
1176 QVERIFY(grandChild->isVisibleTo(grandChild));
1177 QVERIFY(grandChild->isVisibleTo(child));
1178 QVERIFY(grandChild->isVisibleTo(parent));
1179 QVERIFY(!grandChild->isVisibleTo(0));
1180 QVERIFY(!child->isVisible());
1181 QVERIFY(child->isVisibleTo(child));
1182 QVERIFY(child->isVisibleTo(parent));
1183 QVERIFY(!child->isVisibleTo(0));
1184 QVERIFY(!parent->isVisible());
1185 QVERIFY(!parent->isVisibleTo(parent));
1186 QVERIFY(!parent->isVisibleTo(0));
1187 QVERIFY(!parent->isVisibleTo(child));
1188 QVERIFY(!child->isVisibleTo(grandChild));
1189 QVERIFY(!grandChild->isVisibleTo(stranger));
1190 QVERIFY(!child->isVisibleTo(stranger));
1191 QVERIFY(!parent->isVisibleTo(stranger));
1192 QVERIFY(!stranger->isVisibleTo(grandChild));
1193 QVERIFY(!stranger->isVisibleTo(child));
1194 QVERIFY(!stranger->isVisibleTo(parent));
1196 // Case 2: only child is hidden
1200 QVERIFY(!grandChild->isVisible());
1201 QVERIFY(grandChild->isVisibleTo(grandChild));
1202 QVERIFY(grandChild->isVisibleTo(child));
1203 QVERIFY(!grandChild->isVisibleTo(parent));
1204 QVERIFY(!grandChild->isVisibleTo(0));
1205 QVERIFY(!child->isVisible());
1206 QVERIFY(!child->isVisibleTo(child));
1207 QVERIFY(!child->isVisibleTo(parent));
1208 QVERIFY(!child->isVisibleTo(0));
1209 QVERIFY(parent->isVisible());
1210 QVERIFY(parent->isVisibleTo(parent));
1211 QVERIFY(parent->isVisibleTo(0));
1212 QVERIFY(!parent->isVisibleTo(child));
1213 QVERIFY(!child->isVisibleTo(grandChild));
1214 QVERIFY(!grandChild->isVisibleTo(stranger));
1215 QVERIFY(!child->isVisibleTo(stranger));
1216 QVERIFY(!parent->isVisibleTo(stranger));
1217 QVERIFY(!stranger->isVisibleTo(grandChild));
1218 QVERIFY(!stranger->isVisibleTo(child));
1219 QVERIFY(!stranger->isVisibleTo(parent));
1221 // Case 3: only grand child is hidden
1225 QVERIFY(!grandChild->isVisible());
1226 QVERIFY(!grandChild->isVisibleTo(grandChild));
1227 QVERIFY(!grandChild->isVisibleTo(child));
1228 QVERIFY(!grandChild->isVisibleTo(parent));
1229 QVERIFY(!grandChild->isVisibleTo(0));
1230 QVERIFY(child->isVisible());
1231 QVERIFY(child->isVisibleTo(child));
1232 QVERIFY(child->isVisibleTo(parent));
1233 QVERIFY(child->isVisibleTo(0));
1234 QVERIFY(parent->isVisible());
1235 QVERIFY(parent->isVisibleTo(parent));
1236 QVERIFY(parent->isVisibleTo(0));
1237 QVERIFY(!parent->isVisibleTo(child));
1238 QVERIFY(!child->isVisibleTo(grandChild));
1239 QVERIFY(!grandChild->isVisibleTo(stranger));
1240 QVERIFY(!child->isVisibleTo(stranger));
1241 QVERIFY(!parent->isVisibleTo(stranger));
1242 QVERIFY(!stranger->isVisibleTo(grandChild));
1243 QVERIFY(!stranger->isVisibleTo(child));
1244 QVERIFY(!stranger->isVisibleTo(parent));
1247 void tst_QGraphicsItem::explicitlyVisible()
1249 QGraphicsScene scene;
1250 QGraphicsItem *parent = scene.addRect(QRectF(0, 0, 100, 100));
1251 QGraphicsItem *child = scene.addRect(QRectF(25, 25, 50, 50));
1252 child->setParentItem(parent);
1254 QVERIFY(parent->isVisible());
1255 QVERIFY(child->isVisible());
1259 QVERIFY(!parent->isVisible());
1260 QVERIFY(!child->isVisible());
1265 QVERIFY(parent->isVisible());
1266 QVERIFY(!child->isVisible());
1270 QVERIFY(!parent->isVisible());
1271 QVERIFY(!child->isVisible());
1275 QVERIFY(parent->isVisible());
1276 QVERIFY(!child->isVisible()); // <- explicitly hidden
1280 QVERIFY(child->isVisible());
1284 QVERIFY(!parent->isVisible());
1285 QVERIFY(!child->isVisible()); // <- explicit show doesn't work
1289 QVERIFY(parent->isVisible());
1290 QVERIFY(child->isVisible()); // <- no longer explicitly hidden
1292 // ------------------- Reparenting ------------------------------
1294 QGraphicsItem *parent2 = scene.addRect(-50, -50, 200, 200);
1295 QVERIFY(parent2->isVisible());
1297 // Reparent implicitly hidden item to a visible parent.
1299 QVERIFY(!parent->isVisible());
1300 QVERIFY(!child->isVisible());
1301 child->setParentItem(parent2);
1302 QVERIFY(parent2->isVisible());
1303 QVERIFY(child->isVisible());
1305 // Reparent implicitly hidden item to a hidden parent.
1306 child->setParentItem(parent);
1308 child->setParentItem(parent2);
1309 QVERIFY(!parent2->isVisible());
1310 QVERIFY(!child->isVisible());
1312 // Reparent explicitly hidden item to a visible parent.
1315 child->setParentItem(parent);
1316 QVERIFY(parent->isVisible());
1317 QVERIFY(!child->isVisible());
1319 // Reparent explicitly hidden item to a hidden parent.
1320 child->setParentItem(parent2);
1321 QVERIFY(!parent2->isVisible());
1322 QVERIFY(!child->isVisible());
1324 // Reparent explicitly hidden item to a visible parent.
1326 child->setParentItem(parent);
1327 QVERIFY(parent->isVisible());
1328 QVERIFY(!child->isVisible());
1330 // Reparent visible item to a hidden parent.
1333 child->setParentItem(parent2);
1334 QVERIFY(!parent2->isVisible());
1335 QVERIFY(!child->isVisible());
1337 QVERIFY(parent2->isVisible());
1338 QVERIFY(child->isVisible());
1340 // Reparent implicitly hidden child to root.
1342 QVERIFY(!child->isVisible());
1343 child->setParentItem(0);
1344 QVERIFY(child->isVisible());
1346 // Reparent an explicitly hidden child to root.
1348 child->setParentItem(parent2);
1350 QVERIFY(!child->isVisible());
1351 child->setParentItem(0);
1352 QVERIFY(!child->isVisible());
1355 void tst_QGraphicsItem::enabled()
1357 QGraphicsRectItem *item = new QGraphicsRectItem(QRectF(-10, -10, 20, 20));
1358 item->setFlag(QGraphicsItem::ItemIsMovable);
1359 QVERIFY(item->isEnabled());
1360 item->setEnabled(false);
1361 QVERIFY(!item->isEnabled());
1362 item->setEnabled(true);
1363 QVERIFY(item->isEnabled());
1364 item->setEnabled(false);
1365 item->setFlag(QGraphicsItem::ItemIsFocusable);
1366 QGraphicsScene scene;
1367 QEvent activate(QEvent::WindowActivate);
1368 QApplication::sendEvent(&scene, &activate);
1370 scene.addItem(item);
1372 QVERIFY(!item->hasFocus());
1373 item->setEnabled(true);
1375 QVERIFY(item->hasFocus());
1376 item->setEnabled(false);
1377 QVERIFY(!item->hasFocus());
1379 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
1380 event.setButton(Qt::LeftButton);
1381 event.setScenePos(QPointF(0, 0));
1382 QApplication::sendEvent(&scene, &event);
1383 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
1384 item->setEnabled(true);
1385 QApplication::sendEvent(&scene, &event);
1386 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)item);
1387 item->setEnabled(false);
1388 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
1391 void tst_QGraphicsItem::explicitlyEnabled()
1393 QGraphicsScene scene;
1394 QGraphicsItem *parent = scene.addRect(QRectF(0, 0, 100, 100));
1395 QGraphicsItem *child = scene.addRect(QRectF(25, 25, 50, 50));
1396 child->setParentItem(parent);
1398 QVERIFY(parent->isEnabled());
1399 QVERIFY(child->isEnabled());
1401 parent->setEnabled(false);
1403 QVERIFY(!parent->isEnabled());
1404 QVERIFY(!child->isEnabled());
1406 parent->setEnabled(true);
1407 child->setEnabled(false);
1409 QVERIFY(parent->isEnabled());
1410 QVERIFY(!child->isEnabled());
1412 parent->setEnabled(false);
1414 QVERIFY(!parent->isEnabled());
1415 QVERIFY(!child->isEnabled());
1417 parent->setEnabled(true);
1419 QVERIFY(parent->isEnabled());
1420 QVERIFY(!child->isEnabled()); // <- explicitly disabled
1422 child->setEnabled(true);
1424 QVERIFY(child->isEnabled());
1426 parent->setEnabled(false);
1428 QVERIFY(!parent->isEnabled());
1429 QVERIFY(!child->isEnabled()); // <- explicit enabled doesn't work
1431 parent->setEnabled(true);
1433 QVERIFY(parent->isEnabled());
1434 QVERIFY(child->isEnabled()); // <- no longer explicitly disabled
1436 // ------------------- Reparenting ------------------------------
1438 QGraphicsItem *parent2 = scene.addRect(-50, -50, 200, 200);
1439 QVERIFY(parent2->isEnabled());
1441 // Reparent implicitly hidden item to a enabled parent.
1442 parent->setEnabled(false);
1443 QVERIFY(!parent->isEnabled());
1444 QVERIFY(!child->isEnabled());
1445 child->setParentItem(parent2);
1446 QVERIFY(parent2->isEnabled());
1447 QVERIFY(child->isEnabled());
1449 // Reparent implicitly hidden item to a hidden parent.
1450 child->setParentItem(parent);
1451 parent2->setEnabled(false);
1452 child->setParentItem(parent2);
1453 QVERIFY(!parent2->isEnabled());
1454 QVERIFY(!child->isEnabled());
1456 // Reparent explicitly hidden item to a enabled parent.
1457 child->setEnabled(false);
1458 parent->setEnabled(true);
1459 child->setParentItem(parent);
1460 QVERIFY(parent->isEnabled());
1461 QVERIFY(!child->isEnabled());
1463 // Reparent explicitly hidden item to a hidden parent.
1464 child->setParentItem(parent2);
1465 QVERIFY(!parent2->isEnabled());
1466 QVERIFY(!child->isEnabled());
1468 // Reparent explicitly hidden item to a enabled parent.
1469 parent->setEnabled(true);
1470 child->setParentItem(parent);
1471 QVERIFY(parent->isEnabled());
1472 QVERIFY(!child->isEnabled());
1474 // Reparent enabled item to a hidden parent.
1475 child->setEnabled(true);
1476 parent2->setEnabled(false);
1477 child->setParentItem(parent2);
1478 QVERIFY(!parent2->isEnabled());
1479 QVERIFY(!child->isEnabled());
1480 parent2->setEnabled(true);
1481 QVERIFY(parent2->isEnabled());
1482 QVERIFY(child->isEnabled());
1484 // Reparent implicitly hidden child to root.
1485 parent2->setEnabled(false);
1486 QVERIFY(!child->isEnabled());
1487 child->setParentItem(0);
1488 QVERIFY(child->isEnabled());
1490 // Reparent an explicitly hidden child to root.
1491 child->setEnabled(false);
1492 child->setParentItem(parent2);
1493 parent2->setEnabled(true);
1494 QVERIFY(!child->isEnabled());
1495 child->setParentItem(0);
1496 QVERIFY(!child->isEnabled());
1499 class SelectChangeItem : public QGraphicsRectItem
1502 SelectChangeItem() : QGraphicsRectItem(-50, -50, 100, 100) { setBrush(Qt::blue); }
1506 QVariant itemChange(GraphicsItemChange change, const QVariant &value)
1508 if (change == ItemSelectedChange)
1509 values << value.toBool();
1510 return QGraphicsRectItem::itemChange(change, value);
1514 void tst_QGraphicsItem::selected()
1516 SelectChangeItem *item = new SelectChangeItem;
1517 item->setFlag(QGraphicsItem::ItemIsSelectable);
1518 QVERIFY(!item->isSelected());
1519 QVERIFY(item->values.isEmpty());
1520 item->setSelected(true);
1521 QCOMPARE(item->values.size(), 1);
1522 QCOMPARE(item->values.last(), true);
1523 QVERIFY(item->isSelected());
1524 item->setSelected(false);
1525 QCOMPARE(item->values.size(), 2);
1526 QCOMPARE(item->values.last(), false);
1527 QVERIFY(!item->isSelected());
1528 item->setSelected(true);
1529 QCOMPARE(item->values.size(), 3);
1530 item->setEnabled(false);
1531 QCOMPARE(item->values.size(), 4);
1532 QCOMPARE(item->values.last(), false);
1533 QVERIFY(!item->isSelected());
1534 item->setEnabled(true);
1535 QCOMPARE(item->values.size(), 4);
1536 item->setSelected(true);
1537 QCOMPARE(item->values.size(), 5);
1538 QCOMPARE(item->values.last(), true);
1539 QVERIFY(item->isSelected());
1540 item->setVisible(false);
1541 QCOMPARE(item->values.size(), 6);
1542 QCOMPARE(item->values.last(), false);
1543 QVERIFY(!item->isSelected());
1544 item->setVisible(true);
1545 QCOMPARE(item->values.size(), 6);
1546 item->setSelected(true);
1547 QCOMPARE(item->values.size(), 7);
1548 QCOMPARE(item->values.last(), true);
1549 QVERIFY(item->isSelected());
1551 QGraphicsScene scene(-100, -100, 200, 200);
1552 scene.addItem(item);
1553 QCOMPARE(scene.selectedItems(), QList<QGraphicsItem *>() << item);
1554 item->setSelected(false);
1555 QVERIFY(scene.selectedItems().isEmpty());
1556 item->setSelected(true);
1557 QCOMPARE(scene.selectedItems(), QList<QGraphicsItem *>() << item);
1558 item->setSelected(false);
1559 QVERIFY(scene.selectedItems().isEmpty());
1561 // Interactive selection
1562 QGraphicsView view(&scene);
1563 view.setFixedSize(250, 250);
1566 QTest::qWaitForWindowShown(&view);
1567 qApp->processEvents();
1568 qApp->processEvents();
1570 scene.clearSelection();
1571 QCOMPARE(item->values.size(), 10);
1572 QCOMPARE(item->values.last(), false);
1573 QVERIFY(!item->isSelected());
1575 // Click inside and check that it's selected
1576 QTest::mouseMove(view.viewport());
1577 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item->scenePos()));
1578 QCOMPARE(item->values.size(), 11);
1579 QCOMPARE(item->values.last(), true);
1580 QVERIFY(item->isSelected());
1582 // Click outside and check that it's not selected
1583 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item->scenePos() + QPointF(item->boundingRect().width(), item->boundingRect().height())));
1584 QCOMPARE(item->values.size(), 12);
1585 QCOMPARE(item->values.last(), false);
1586 QVERIFY(!item->isSelected());
1588 SelectChangeItem *item2 = new SelectChangeItem;
1589 item2->setFlag(QGraphicsItem::ItemIsSelectable);
1590 item2->setPos(100, 0);
1591 scene.addItem(item2);
1593 // Click inside and check that it's selected
1594 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item->scenePos()));
1595 QCOMPARE(item->values.size(), 13);
1596 QCOMPARE(item->values.last(), true);
1597 QVERIFY(item->isSelected());
1599 // Click inside item2 and check that it's selected, and item is not
1600 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item2->scenePos()));
1601 QCOMPARE(item->values.size(), 14);
1602 QCOMPARE(item->values.last(), false);
1603 QVERIFY(!item->isSelected());
1604 QCOMPARE(item2->values.size(), 1);
1605 QCOMPARE(item2->values.last(), true);
1606 QVERIFY(item2->isSelected());
1609 void tst_QGraphicsItem::selected2()
1611 // Selecting an item, then moving another previously caused a crash.
1612 QGraphicsScene scene;
1613 QGraphicsItem *line1 = scene.addRect(QRectF(0, 0, 100, 100));
1614 line1->setPos(-105, 0);
1615 line1->setFlag(QGraphicsItem::ItemIsSelectable);
1617 QGraphicsItem *line2 = scene.addRect(QRectF(0, 0, 100, 100));
1618 line2->setFlag(QGraphicsItem::ItemIsMovable);
1620 line1->setSelected(true);
1623 QGraphicsSceneMouseEvent mousePress(QEvent::GraphicsSceneMousePress);
1624 mousePress.setScenePos(QPointF(50, 50));
1625 mousePress.setButton(Qt::LeftButton);
1626 QApplication::sendEvent(&scene, &mousePress);
1627 QVERIFY(mousePress.isAccepted());
1630 QGraphicsSceneMouseEvent mouseMove(QEvent::GraphicsSceneMouseMove);
1631 mouseMove.setScenePos(QPointF(60, 60));
1632 mouseMove.setButton(Qt::LeftButton);
1633 mouseMove.setButtons(Qt::LeftButton);
1634 QApplication::sendEvent(&scene, &mouseMove);
1635 QVERIFY(mouseMove.isAccepted());
1639 void tst_QGraphicsItem::selected_group()
1641 QGraphicsScene scene;
1642 QGraphicsItem *item1 = scene.addRect(QRectF());
1643 QGraphicsItem *item2 = scene.addRect(QRectF());
1644 item1->setFlag(QGraphicsItem::ItemIsSelectable);
1645 item2->setFlag(QGraphicsItem::ItemIsSelectable);
1646 scene.addRect(QRectF())->setParentItem(item1);
1647 QGraphicsItem *leaf = scene.addRect(QRectF());
1648 leaf->setFlag(QGraphicsItem::ItemIsSelectable);
1649 leaf->setParentItem(item2);
1651 QGraphicsItemGroup *group = scene.createItemGroup(QList<QGraphicsItem *>() << item1 << item2);
1652 QCOMPARE(group->scene(), &scene);
1653 group->setFlag(QGraphicsItem::ItemIsSelectable);
1654 foreach (QGraphicsItem *item, scene.items()) {
1656 QVERIFY(!item->group());
1658 QCOMPARE(item->group(), group);
1661 QVERIFY(group->handlesChildEvents());
1662 QVERIFY(!group->isSelected());
1663 group->setSelected(false);
1664 QVERIFY(!group->isSelected());
1665 group->setSelected(true);
1666 QVERIFY(group->isSelected());
1667 foreach (QGraphicsItem *item, scene.items())
1668 QVERIFY(item->isSelected());
1669 group->setSelected(false);
1670 QVERIFY(!group->isSelected());
1671 foreach (QGraphicsItem *item, scene.items())
1672 QVERIFY(!item->isSelected());
1673 leaf->setSelected(true);
1674 foreach (QGraphicsItem *item, scene.items())
1675 QVERIFY(item->isSelected());
1676 leaf->setSelected(false);
1677 foreach (QGraphicsItem *item, scene.items())
1678 QVERIFY(!item->isSelected());
1680 leaf->setSelected(true);
1681 QGraphicsScene scene2;
1682 scene2.addItem(item1);
1683 QVERIFY(!item1->isSelected());
1684 QVERIFY(item2->isSelected());
1687 void tst_QGraphicsItem::selected_textItem()
1689 QGraphicsScene scene;
1690 QGraphicsTextItem *text = scene.addText(QLatin1String("Text"));
1691 text->setFlag(QGraphicsItem::ItemIsSelectable);
1693 QGraphicsView view(&scene);
1695 QTest::qWaitForWindowShown(&view);
1698 QTRY_VERIFY(!text->isSelected());
1699 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0,
1700 view.mapFromScene(text->mapToScene(0, 0)));
1701 QTRY_VERIFY(text->isSelected());
1703 text->setSelected(false);
1704 text->setTextInteractionFlags(Qt::TextEditorInteraction);
1706 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0,
1707 view.mapFromScene(text->mapToScene(0, 0)));
1708 QTRY_VERIFY(text->isSelected());
1711 void tst_QGraphicsItem::selected_multi()
1713 // Test multiselection behavior
1714 QGraphicsScene scene;
1716 // Create two disjoint items
1717 QGraphicsItem *item1 = scene.addRect(QRectF(-10, -10, 20, 20));
1718 QGraphicsItem *item2 = scene.addRect(QRectF(-10, -10, 20, 20));
1719 item1->setPos(-15, 0);
1720 item2->setPos(15, 20);
1722 // Make both items selectable
1723 item1->setFlag(QGraphicsItem::ItemIsSelectable);
1724 item2->setFlag(QGraphicsItem::ItemIsSelectable);
1726 // Create and show a view
1727 QGraphicsView view(&scene);
1729 view.fitInView(scene.sceneRect());
1730 qApp->processEvents();
1732 QVERIFY(!item1->isSelected());
1733 QVERIFY(!item2->isSelected());
1739 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item1->scenePos()));
1741 QVERIFY(item1->isSelected());
1742 QVERIFY(!item2->isSelected());
1745 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item2->scenePos()));
1747 QVERIFY(item2->isSelected());
1748 QVERIFY(!item1->isSelected());
1750 // Ctrl-click on item1
1751 QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(item1->scenePos()));
1753 QVERIFY(item2->isSelected());
1754 QVERIFY(item1->isSelected());
1756 // Ctrl-click on item1 again
1757 QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(item1->scenePos()));
1759 QVERIFY(item2->isSelected());
1760 QVERIFY(!item1->isSelected());
1762 // Ctrl-click on item2
1763 QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(item2->scenePos()));
1765 QVERIFY(!item2->isSelected());
1766 QVERIFY(!item1->isSelected());
1769 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item1->scenePos()));
1771 QVERIFY(item1->isSelected());
1772 QVERIFY(!item2->isSelected());
1775 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(0, 0));
1777 QVERIFY(!item1->isSelected());
1778 QVERIFY(!item2->isSelected());
1781 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item1->scenePos()));
1783 QVERIFY(item1->isSelected());
1784 QVERIFY(!item2->isSelected());
1786 // Ctrl-click on scene
1787 QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(0, 0));
1789 QVERIFY(!item1->isSelected());
1790 QVERIFY(!item2->isSelected());
1793 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item1->scenePos()));
1795 QVERIFY(item1->isSelected());
1796 QVERIFY(!item2->isSelected());
1799 QTest::mousePress(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item2->scenePos()));
1801 QVERIFY(!item1->isSelected());
1802 QVERIFY(item2->isSelected());
1805 QTest::mouseRelease(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item2->scenePos()));
1807 QVERIFY(!item1->isSelected());
1808 QVERIFY(item2->isSelected());
1811 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item1->scenePos()));
1813 QVERIFY(item1->isSelected());
1814 QVERIFY(!item2->isSelected());
1816 // Ctrl-click on item1
1817 QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(item1->scenePos()));
1819 QVERIFY(!item1->isSelected());
1820 QVERIFY(!item2->isSelected());
1822 // Ctrl-press on item1
1823 QTest::mousePress(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(item1->scenePos()));
1825 QVERIFY(!item1->isSelected());
1826 QVERIFY(!item2->isSelected());
1829 // Ctrl-move on item1
1830 QMouseEvent event(QEvent::MouseMove, view.mapFromScene(item1->scenePos()) + QPoint(1, 0), Qt::LeftButton, Qt::LeftButton, Qt::ControlModifier);
1831 QApplication::sendEvent(view.viewport(), &event);
1833 QVERIFY(!item1->isSelected());
1834 QVERIFY(!item2->isSelected());
1838 QTest::mouseRelease(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(item1->scenePos()));
1840 QVERIFY(item1->isSelected());
1841 QVERIFY(!item2->isSelected());
1843 item1->setFlag(QGraphicsItem::ItemIsMovable);
1844 item1->setSelected(false);
1846 // Ctrl-press on item1
1847 QTest::mousePress(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(item1->scenePos()));
1849 QVERIFY(!item1->isSelected());
1850 QVERIFY(!item2->isSelected());
1853 // Ctrl-move on item1
1854 QMouseEvent event(QEvent::MouseMove, view.mapFromScene(item1->scenePos()) + QPoint(1, 0), Qt::LeftButton, Qt::LeftButton, Qt::ControlModifier);
1855 QApplication::sendEvent(view.viewport(), &event);
1857 QVERIFY(item1->isSelected());
1858 QVERIFY(!item2->isSelected());
1862 QTest::mouseRelease(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(item1->scenePos()));
1864 QVERIFY(item1->isSelected());
1865 QVERIFY(!item2->isSelected());
1868 void tst_QGraphicsItem::acceptedMouseButtons()
1870 QGraphicsScene scene;
1871 QGraphicsRectItem *item1 = scene.addRect(QRectF(-10, -10, 20, 20));
1872 QGraphicsRectItem *item2 = scene.addRect(QRectF(-10, -10, 20, 20));
1873 item2->setZValue(1);
1875 item1->setFlag(QGraphicsItem::ItemIsMovable);
1876 item2->setFlag(QGraphicsItem::ItemIsMovable);
1878 QCOMPARE(item1->acceptedMouseButtons(), Qt::MouseButtons(0x1f));
1879 QCOMPARE(item2->acceptedMouseButtons(), Qt::MouseButtons(0x1f));
1881 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
1882 event.setButton(Qt::LeftButton);
1883 event.setScenePos(QPointF(0, 0));
1884 QApplication::sendEvent(&scene, &event);
1885 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)item2);
1886 item2->setAcceptedMouseButtons(0);
1887 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
1888 QApplication::sendEvent(&scene, &event);
1889 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)item1);
1892 class HoverItem : public QGraphicsRectItem
1895 HoverItem(const QRectF &rect)
1896 : QGraphicsRectItem(rect), hoverInCount(0),
1897 hoverMoveCount(0), hoverOutCount(0)
1904 void hoverEnterEvent(QGraphicsSceneHoverEvent *)
1907 void hoverMoveEvent(QGraphicsSceneHoverEvent *)
1908 { ++hoverMoveCount; }
1910 void hoverLeaveEvent(QGraphicsSceneHoverEvent *)
1911 { ++hoverOutCount; }
1914 void tst_QGraphicsItem::acceptsHoverEvents()
1916 QGraphicsScene scene;
1917 HoverItem *item1 = new HoverItem(QRectF(-10, -10, 20, 20));
1918 HoverItem *item2 = new HoverItem(QRectF(-5, -5, 10, 10));
1919 scene.addItem(item1);
1920 scene.addItem(item2);
1921 item2->setZValue(1);
1923 QVERIFY(!item1->acceptsHoverEvents());
1924 QVERIFY(!item2->acceptsHoverEvents());
1925 item1->setAcceptsHoverEvents(true);
1926 item2->setAcceptsHoverEvents(true);
1928 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseMove);
1929 event.setScenePos(QPointF(-100, -100));
1930 QApplication::sendEvent(&scene, &event);
1931 event.setScenePos(QPointF(-2.5, -2.5));
1932 QApplication::sendEvent(&scene, &event);
1934 QCOMPARE(item1->hoverInCount, 0);
1935 QCOMPARE(item2->hoverInCount, 1);
1937 item1->setAcceptsHoverEvents(false);
1938 item2->setAcceptsHoverEvents(false);
1940 event.setScenePos(QPointF(-100, -100));
1941 QApplication::sendEvent(&scene, &event);
1942 event.setScenePos(QPointF(-2.5, -2.5));
1943 QApplication::sendEvent(&scene, &event);
1945 QCOMPARE(item1->hoverInCount, 0);
1946 QCOMPARE(item2->hoverInCount, 1);
1948 item1->setAcceptsHoverEvents(true);
1949 item2->setAcceptsHoverEvents(false);
1951 event.setScenePos(QPointF(-100, -100));
1952 QApplication::sendEvent(&scene, &event);
1953 event.setScenePos(QPointF(-2.5, -2.5));
1954 QApplication::sendEvent(&scene, &event);
1956 QCOMPARE(item1->hoverInCount, 1);
1957 QCOMPARE(item2->hoverInCount, 1);
1960 void tst_QGraphicsItem::childAcceptsHoverEvents()
1962 QGraphicsScene scene;
1963 HoverItem *item1 = new HoverItem(QRectF(-10, -10, 20, 20));
1964 HoverItem *item2 = new HoverItem(QRectF(-5, -5, 10, 10));
1966 scene.addItem(item1);
1967 scene.addItem(item2);
1968 item2->setParentItem(item1);
1969 item2->setAcceptHoverEvents(true);
1971 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseMove);
1972 event.setScenePos(QPointF(-100, -100));
1973 QApplication::sendEvent(&scene, &event);
1974 QCOMPARE(item2->hoverInCount, 0);
1975 QCOMPARE(item2->hoverMoveCount, 0);
1976 QCOMPARE(item2->hoverOutCount, 0);
1977 QCOMPARE(item1->hoverInCount, 0);
1978 QCOMPARE(item1->hoverMoveCount, 0);
1979 QCOMPARE(item1->hoverOutCount, 0);
1981 event.setScenePos(QPointF(-2.5, -2.5));
1982 QApplication::sendEvent(&scene, &event);
1984 QCOMPARE(item2->hoverInCount, 1);
1985 QCOMPARE(item2->hoverMoveCount, 1);
1986 QCOMPARE(item2->hoverOutCount, 0);
1987 QCOMPARE(item1->hoverInCount, 0);
1988 QCOMPARE(item1->hoverMoveCount, 0);
1989 QCOMPARE(item1->hoverOutCount, 0);
1991 event.setScenePos(QPointF(0, 0));
1992 QApplication::sendEvent(&scene, &event);
1994 QCOMPARE(item2->hoverInCount, 1);
1995 QCOMPARE(item2->hoverMoveCount, 2);
1996 QCOMPARE(item2->hoverOutCount, 0);
1997 QCOMPARE(item1->hoverInCount, 0);
1998 QCOMPARE(item1->hoverMoveCount, 0);
1999 QCOMPARE(item1->hoverOutCount, 0);
2001 event.setScenePos(QPointF(-7, -7));
2002 QApplication::sendEvent(&scene, &event);
2004 QCOMPARE(item2->hoverInCount, 1);
2005 QCOMPARE(item2->hoverMoveCount, 2);
2006 QCOMPARE(item2->hoverOutCount, 1);
2007 QCOMPARE(item1->hoverInCount, 0);
2008 QCOMPARE(item1->hoverMoveCount, 0);
2009 QCOMPARE(item1->hoverOutCount, 0);
2011 event.setScenePos(QPointF(0, 0));
2012 QApplication::sendEvent(&scene, &event);
2014 QCOMPARE(item2->hoverInCount, 2);
2015 QCOMPARE(item2->hoverMoveCount, 3);
2016 QCOMPARE(item2->hoverOutCount, 1);
2017 QCOMPARE(item1->hoverInCount, 0);
2018 QCOMPARE(item1->hoverMoveCount, 0);
2019 QCOMPARE(item1->hoverOutCount, 0);
2021 HoverItem *item0 = new HoverItem(QRectF(-20, -20, 20, 20));
2022 scene.addItem(item0);
2023 item1->setParentItem(item0);
2024 item0->setAcceptHoverEvents(true);
2026 event.setScenePos(QPointF(-100, -100));
2027 QApplication::sendEvent(&scene, &event);
2029 event.setScenePos(QPointF(-15, -15));
2030 QApplication::sendEvent(&scene, &event);
2032 QCOMPARE(item2->hoverInCount, 2);
2033 QCOMPARE(item2->hoverMoveCount, 3);
2034 QCOMPARE(item2->hoverOutCount, 2);
2035 QCOMPARE(item1->hoverInCount, 0);
2036 QCOMPARE(item1->hoverMoveCount, 0);
2037 QCOMPARE(item1->hoverOutCount, 0);
2038 QCOMPARE(item0->hoverInCount, 1);
2039 QCOMPARE(item0->hoverMoveCount, 1);
2040 QCOMPARE(item0->hoverOutCount, 0);
2043 void tst_QGraphicsItem::hasFocus()
2045 QGraphicsLineItem *line = new QGraphicsLineItem;
2046 QVERIFY(!line->hasFocus());
2048 QVERIFY(!line->hasFocus());
2050 QGraphicsScene scene;
2051 QEvent activate(QEvent::WindowActivate);
2052 QApplication::sendEvent(&scene, &activate);
2054 scene.addItem(line);
2057 QVERIFY(!line->hasFocus());
2058 line->setFlag(QGraphicsItem::ItemIsFocusable);
2060 QVERIFY(line->hasFocus());
2062 QGraphicsScene scene2;
2063 QApplication::sendEvent(&scene2, &activate);
2065 scene2.addItem(line);
2066 QVERIFY(!line->hasFocus());
2068 QCOMPARE(scene.focusItem(), (QGraphicsItem *)0);
2069 QCOMPARE(scene2.focusItem(), (QGraphicsItem *)0);
2072 QVERIFY(line->hasFocus());
2074 QVERIFY(!line->hasFocus());
2076 QGraphicsLineItem *line2 = new QGraphicsLineItem;
2077 line2->setFlag(QGraphicsItem::ItemIsFocusable);
2078 scene2.addItem(line2);
2081 QVERIFY(!line->hasFocus());
2082 QVERIFY(line2->hasFocus());
2084 QVERIFY(line->hasFocus());
2085 QVERIFY(!line2->hasFocus());
2088 void tst_QGraphicsItem::pos()
2090 QGraphicsItem *child = new QGraphicsLineItem;
2091 QGraphicsItem *parent = new QGraphicsLineItem;
2093 QCOMPARE(child->pos(), QPointF());
2094 QCOMPARE(parent->pos(), QPointF());
2096 child->setParentItem(parent);
2097 child->setPos(10, 10);
2099 QCOMPARE(child->pos(), QPointF(10, 10));
2101 parent->setPos(10, 10);
2103 QCOMPARE(parent->pos(), QPointF(10, 10));
2104 QCOMPARE(child->pos(), QPointF(10, 10));
2110 void tst_QGraphicsItem::scenePos()
2112 QGraphicsItem *child = new QGraphicsLineItem;
2113 QGraphicsItem *parent = new QGraphicsLineItem;
2115 QCOMPARE(child->scenePos(), QPointF());
2116 QCOMPARE(parent->scenePos(), QPointF());
2118 child->setParentItem(parent);
2119 child->setPos(10, 10);
2121 QCOMPARE(child->scenePos(), QPointF(10, 10));
2123 parent->setPos(10, 10);
2125 QCOMPARE(parent->scenePos(), QPointF(10, 10));
2126 QCOMPARE(child->scenePos(), QPointF(20, 20));
2128 parent->setPos(20, 20);
2130 QCOMPARE(parent->scenePos(), QPointF(20, 20));
2131 QCOMPARE(child->scenePos(), QPointF(30, 30));
2137 void tst_QGraphicsItem::matrix()
2139 QGraphicsLineItem line;
2140 QCOMPARE(line.matrix(), QMatrix());
2141 line.setMatrix(QMatrix().rotate(90));
2142 QCOMPARE(line.matrix(), QMatrix().rotate(90));
2143 line.setMatrix(QMatrix().rotate(90));
2144 QCOMPARE(line.matrix(), QMatrix().rotate(90));
2145 line.setMatrix(QMatrix().rotate(90), true);
2146 QCOMPARE(line.matrix(), QMatrix().rotate(180));
2147 line.setMatrix(QMatrix().rotate(-90), true);
2148 QCOMPARE(line.matrix(), QMatrix().rotate(90));
2150 QCOMPARE(line.matrix(), QMatrix());
2153 QCOMPARE(line.matrix(), QMatrix().rotate(90));
2155 QCOMPARE(line.matrix(), QMatrix().rotate(90).rotate(90));
2159 QCOMPARE(line.matrix(), QMatrix().scale(2, 4));
2161 QCOMPARE(line.matrix(), QMatrix().scale(2, 4).scale(2, 4));
2165 QCOMPARE(line.matrix(), QMatrix().shear(2, 4));
2167 QCOMPARE(line.matrix(), QMatrix().shear(2, 4).shear(2, 4));
2170 line.translate(10, 10);
2171 QCOMPARE(line.matrix(), QMatrix().translate(10, 10));
2172 line.translate(10, 10);
2173 QCOMPARE(line.matrix(), QMatrix().translate(10, 10).translate(10, 10));
2177 void tst_QGraphicsItem::sceneMatrix()
2179 QGraphicsLineItem *parent = new QGraphicsLineItem;
2180 QGraphicsLineItem *child = new QGraphicsLineItem(QLineF(), parent);
2182 QCOMPARE(parent->sceneMatrix(), QMatrix());
2183 QCOMPARE(child->sceneMatrix(), QMatrix());
2185 parent->translate(10, 10);
2186 QCOMPARE(parent->sceneMatrix(), QMatrix().translate(10, 10));
2187 QCOMPARE(child->sceneMatrix(), QMatrix().translate(10, 10));
2189 child->translate(10, 10);
2190 QCOMPARE(parent->sceneMatrix(), QMatrix().translate(10, 10));
2191 QCOMPARE(child->sceneMatrix(), QMatrix().translate(20, 20));
2194 QCOMPARE(parent->sceneMatrix(), QMatrix().translate(10, 10).rotate(90));
2195 QCOMPARE(child->sceneMatrix(), QMatrix().translate(10, 10).rotate(90).translate(10, 10));
2201 void tst_QGraphicsItem::setMatrix()
2203 QGraphicsScene scene;
2204 qRegisterMetaType<QList<QRectF> >("QList<QRectF>");
2205 QSignalSpy spy(&scene, SIGNAL(changed(QList<QRectF>)));
2206 QRectF unrotatedRect(-12, -34, 56, 78);
2207 QGraphicsRectItem item(unrotatedRect, 0, &scene);
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 = qVariantValue<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);
2268 qt_x11_wait_for_window_manager(&view);
2270 QApplication::processEvents();
2272 QApplication::sendPostedEvents(); //glib workaround
2275 QTRY_VERIFY(!_paintedItems.isEmpty());
2276 QVERIFY((_paintedItems.size() % 4) == 0);
2277 for (int i = 0; i < 3; ++i)
2278 QVERIFY(_paintedItems.at(i)->zValue() < _paintedItems.at(i + 1)->zValue());
2281 void tst_QGraphicsItem::shape()
2283 QGraphicsLineItem line(QLineF(-10, -10, 20, 20));
2285 // We unfortunately need this hack as QPainterPathStroker will set a width of 1.0
2286 // if we pass a value of 0.0 to QPainterPathStroker::setWidth()
2287 const qreal penWidthZero = qreal(0.00000001);
2289 QPainterPathStroker ps;
2290 ps.setWidth(penWidthZero);
2292 QPainterPath path(line.line().p1());
2293 path.lineTo(line.line().p2());
2294 QPainterPath p = ps.createStroke(path);
2296 QCOMPARE(line.shape(), p);
2299 linePen.setWidthF(5.0);
2300 linePen.setCapStyle(Qt::RoundCap);
2301 line.setPen(linePen);
2303 ps.setCapStyle(line.pen().capStyle());
2304 ps.setWidth(line.pen().widthF());
2305 p = ps.createStroke(path);
2307 QCOMPARE(line.shape(), p);
2309 linePen.setCapStyle(Qt::FlatCap);
2310 line.setPen(linePen);
2311 ps.setCapStyle(line.pen().capStyle());
2312 p = ps.createStroke(path);
2314 QCOMPARE(line.shape(), p);
2316 linePen.setCapStyle(Qt::SquareCap);
2317 line.setPen(linePen);
2318 ps.setCapStyle(line.pen().capStyle());
2319 p = ps.createStroke(path);
2321 QCOMPARE(line.shape(), p);
2323 QGraphicsRectItem rect(QRectF(-10, -10, 20, 20));
2324 QPainterPathStroker ps1;
2325 ps1.setWidth(penWidthZero);
2326 path = QPainterPath();
2327 path.addRect(rect.rect());
2328 p = ps1.createStroke(path);
2330 QCOMPARE(rect.shape(), p);
2332 QGraphicsEllipseItem ellipse(QRectF(-10, -10, 20, 20));
2333 QPainterPathStroker ps2;
2334 ps2.setWidth(ellipse.pen().widthF() <= 0.0 ? penWidthZero : ellipse.pen().widthF());
2335 path = QPainterPath();
2336 path.addEllipse(ellipse.rect());
2337 p = ps2.createStroke(path);
2339 QCOMPARE(ellipse.shape(), p);
2341 QPainterPathStroker ps3;
2342 ps3.setWidth(penWidthZero);
2343 p = ps3.createStroke(path);
2345 QGraphicsPathItem pathItem(path);
2346 QCOMPARE(pathItem.shape(), p);
2348 QRegion region(QRect(0, 0, 300, 200));
2349 region = region.subtracted(QRect(50, 50, 200, 100));
2351 QImage image(300, 200, QImage::Format_ARGB32_Premultiplied);
2353 QPainter painter(&image);
2354 painter.setClipRegion(region);
2355 painter.fillRect(0, 0, 300, 200, Qt::green);
2357 QPixmap pixmap = QPixmap::fromImage(image);
2359 QGraphicsPixmapItem pixmapItem(pixmap);
2360 path = QPainterPath();
2361 path.addRegion(region);
2364 QBitmap bitmap(300, 200);
2366 QPainter painter(&bitmap);
2367 painter.setClipRegion(region);
2368 painter.fillRect(0, 0, 300, 200, Qt::color1);
2371 QBitmap bitmap2(300, 200);
2373 painter.begin(&bitmap2);
2374 painter.setClipPath(pixmapItem.shape());
2375 painter.fillRect(0, 0, 300, 200, Qt::color1);
2378 QCOMPARE(bitmap.toImage(), bitmap2.toImage());
2382 poly << QPointF(0, 0) << QPointF(10, 0) << QPointF(0, 10);
2383 QGraphicsPolygonItem polygon(poly);
2384 path = QPainterPath();
2385 path.addPolygon(poly);
2387 QPainterPathStroker ps4;
2388 ps4.setWidth(penWidthZero);
2389 p = ps4.createStroke(path);
2391 QCOMPARE(polygon.shape(), p);
2394 void tst_QGraphicsItem::contains()
2396 if (sizeof(qreal) != sizeof(double))
2397 QSKIP("Skipped due to rounding errors");
2400 QGraphicsRectItem rect(QRectF(-10, -10, 20, 20));
2401 QVERIFY(!rect.contains(QPointF(-11, -10)));
2402 QVERIFY(rect.contains(QPointF(-10, -10)));
2403 QVERIFY(!rect.contains(QPointF(-11, 0)));
2404 QVERIFY(rect.contains(QPointF(-10, 0)));
2405 QVERIFY(rect.contains(QPointF(0, -10)));
2406 QVERIFY(rect.contains(QPointF(0, 0)));
2407 QVERIFY(rect.contains(QPointF(9, 9)));
2410 QGraphicsEllipseItem ellipse(QRectF(-10, -10, 20, 20));
2411 QVERIFY(!ellipse.contains(QPointF(-10, -10)));
2412 QVERIFY(ellipse.contains(QPointF(-9, 0)));
2413 QVERIFY(ellipse.contains(QPointF(0, -9)));
2414 QVERIFY(ellipse.contains(QPointF(0, 0)));
2415 QVERIFY(!ellipse.contains(QPointF(9, 9)));
2418 QGraphicsLineItem line(QLineF(-10, -10, 20, 20));
2419 QVERIFY(!line.contains(QPointF(-10, 0)));
2420 QVERIFY(!line.contains(QPointF(0, -10)));
2421 QVERIFY(!line.contains(QPointF(10, 0)));
2422 QVERIFY(!line.contains(QPointF(0, 10)));
2423 QVERIFY(line.contains(QPointF(0, 0)));
2424 QVERIFY(line.contains(QPointF(-9, -9)));
2425 QVERIFY(line.contains(QPointF(9, 9)));
2428 QGraphicsPolygonItem polygon(QPolygonF()
2432 QVERIFY(polygon.contains(QPointF(1, 1)));
2433 QVERIFY(polygon.contains(QPointF(4, 4)));
2434 QVERIFY(polygon.contains(QPointF(1, 4)));
2435 QVERIFY(polygon.contains(QPointF(4, 1)));
2436 QVERIFY(!polygon.contains(QPointF(8, 8)));
2437 QVERIFY(polygon.contains(QPointF(1, 8)));
2438 QVERIFY(polygon.contains(QPointF(8, 1)));
2441 void tst_QGraphicsItem::collidesWith_item()
2444 QGraphicsRectItem rect(QRectF(-10, -10, 20, 20));
2445 QGraphicsRectItem rect2(QRectF(-10, -10, 20, 20));
2446 QVERIFY(rect.collidesWithItem(&rect2));
2447 QVERIFY(rect2.collidesWithItem(&rect));
2448 rect2.setPos(21, 21);
2449 QVERIFY(!rect.collidesWithItem(&rect2));
2450 QVERIFY(!rect2.collidesWithItem(&rect));
2451 rect2.setPos(-21, -21);
2452 QVERIFY(!rect.collidesWithItem(&rect2));
2453 QVERIFY(!rect2.collidesWithItem(&rect));
2454 rect2.setPos(-17, -17);
2455 QVERIFY(rect.collidesWithItem(&rect2));
2456 QVERIFY(rect2.collidesWithItem(&rect));
2458 QGraphicsEllipseItem ellipse(QRectF(-10, -10, 20, 20));
2459 QGraphicsEllipseItem ellipse2(QRectF(-10, -10, 20, 20));
2460 QVERIFY(ellipse.collidesWithItem(&ellipse2));
2461 QVERIFY(ellipse2.collidesWithItem(&ellipse));
2462 ellipse2.setPos(21, 21);
2463 QVERIFY(!ellipse.collidesWithItem(&ellipse2));
2464 QVERIFY(!ellipse2.collidesWithItem(&ellipse));
2465 ellipse2.setPos(-21, -21);
2466 QVERIFY(!ellipse.collidesWithItem(&ellipse2));
2467 QVERIFY(!ellipse2.collidesWithItem(&ellipse));
2469 ellipse2.setPos(-17, -17);
2470 QVERIFY(!ellipse.collidesWithItem(&ellipse2));
2471 QVERIFY(!ellipse2.collidesWithItem(&ellipse));
2474 QGraphicsScene scene;
2475 QGraphicsRectItem rect(20, 20, 100, 100, 0, &scene);
2476 QGraphicsRectItem rect2(40, 40, 50, 50, 0, &scene);
2478 QGraphicsLineItem line(0, 0, 200, 200, 0, &scene);
2481 QCOMPARE(scene.items().size(), 3);
2483 QList<QGraphicsItem *> col1 = rect.collidingItems();
2484 QCOMPARE(col1.size(), 2);
2485 QCOMPARE(col1.first(), static_cast<QGraphicsItem *>(&line));
2486 QCOMPARE(col1.last(), static_cast<QGraphicsItem *>(&rect2));
2488 QList<QGraphicsItem *> col2 = rect2.collidingItems();
2489 QCOMPARE(col2.size(), 2);
2490 QCOMPARE(col2.first(), static_cast<QGraphicsItem *>(&line));
2491 QCOMPARE(col2.last(), static_cast<QGraphicsItem *>(&rect));
2493 QList<QGraphicsItem *> col3 = line.collidingItems();
2494 QCOMPARE(col3.size(), 2);
2495 QCOMPARE(col3.first(), static_cast<QGraphicsItem *>(&rect2));
2496 QCOMPARE(col3.last(), static_cast<QGraphicsItem *>(&rect));
2500 void tst_QGraphicsItem::collidesWith_path_data()
2502 QTest::addColumn<QPointF>("pos");
2503 QTest::addColumn<QMatrix>("matrix");
2504 QTest::addColumn<QPainterPath>("shape");
2505 QTest::addColumn<bool>("rectCollides");
2506 QTest::addColumn<bool>("ellipseCollides");
2508 QTest::newRow("nothing") << QPointF(0, 0) << QMatrix() << QPainterPath() << false << false;
2511 rect.addRect(0, 0, 20, 20);
2513 QTest::newRow("rect1") << QPointF(0, 0) << QMatrix() << rect << true << true;
2514 QTest::newRow("rect2") << QPointF(0, 0) << QMatrix().translate(21, 21) << rect << false << false;
2515 QTest::newRow("rect3") << QPointF(21, 21) << QMatrix() << rect << false << false;
2518 void tst_QGraphicsItem::collidesWith_path()
2520 QFETCH(QPointF, pos);
2521 QFETCH(QMatrix, matrix);
2522 QFETCH(QPainterPath, shape);
2523 QFETCH(bool, rectCollides);
2524 QFETCH(bool, ellipseCollides);
2526 QGraphicsRectItem rect(QRectF(0, 0, 20, 20));
2527 QGraphicsEllipseItem ellipse(QRectF(0, 0, 20, 20));
2530 rect.setMatrix(matrix);
2532 ellipse.setPos(pos);
2533 ellipse.setMatrix(matrix);
2535 QPainterPath mappedShape = rect.sceneMatrix().inverted().map(shape);
2538 QVERIFY(rect.collidesWithPath(mappedShape));
2540 QVERIFY(!rect.collidesWithPath(mappedShape));
2542 if (ellipseCollides)
2543 QVERIFY(ellipse.collidesWithPath(mappedShape));
2545 QVERIFY(!ellipse.collidesWithPath(mappedShape));
2548 void tst_QGraphicsItem::collidesWithItemWithClip()
2550 QGraphicsScene scene;
2552 QGraphicsEllipseItem *ellipse = scene.addEllipse(0, 0, 100, 100);
2553 ellipse->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
2554 QGraphicsEllipseItem *ellipse2 = scene.addEllipse(0, 0, 10, 10);
2555 ellipse2->setParentItem(ellipse);
2556 QGraphicsEllipseItem *ellipse3 = scene.addEllipse(0, 0, 10, 10);
2557 ellipse3->setParentItem(ellipse);
2558 QGraphicsEllipseItem *ellipse5 = scene.addEllipse(50, 50, 10, 10);
2559 ellipse5->setParentItem(ellipse);
2560 QGraphicsEllipseItem *ellipse4 = scene.addEllipse(0, 0, 10, 10);
2562 QVERIFY(ellipse2->collidesWithItem(ellipse3));
2563 QVERIFY(ellipse3->collidesWithItem(ellipse2));
2564 QVERIFY(!ellipse2->collidesWithItem(ellipse));
2565 QVERIFY(!ellipse->collidesWithItem(ellipse2));
2566 QVERIFY(!ellipse4->collidesWithItem(ellipse));
2567 QVERIFY(!ellipse4->collidesWithItem(ellipse2));
2568 QVERIFY(!ellipse4->collidesWithItem(ellipse3));
2569 QVERIFY(!ellipse->collidesWithItem(ellipse4));
2570 QVERIFY(!ellipse2->collidesWithItem(ellipse4));
2571 QVERIFY(!ellipse3->collidesWithItem(ellipse4));
2572 QVERIFY(ellipse->collidesWithItem(ellipse5));
2573 QVERIFY(ellipse5->collidesWithItem(ellipse));
2576 class MyItem : public QGraphicsEllipseItem
2579 bool isObscuredBy(const QGraphicsItem *item) const
2581 const MyItem *myItem = qgraphicsitem_cast<const MyItem *>(item);
2583 if (item->zValue() > zValue()) {
2585 QPointF topMid = (r.topRight()+r.topLeft())/2;
2586 QPointF botMid = (r.bottomRight()+r.bottomLeft())/2;
2587 QPointF leftMid = (r.topLeft()+r.bottomLeft())/2;
2588 QPointF rightMid = (r.topRight()+r.bottomRight())/2;
2590 QPainterPath mappedShape = item->mapToItem(this, item->opaqueArea());
2592 if (mappedShape.contains(topMid) &&
2593 mappedShape.contains(botMid) &&
2594 mappedShape.contains(leftMid) &&
2595 mappedShape.contains(rightMid))
2603 return QGraphicsItem::isObscuredBy(item);
2606 QPainterPath opaqueArea() const
2614 int type() const { return Type; }
2617 void tst_QGraphicsItem::isObscuredBy()
2619 QGraphicsScene scene;
2621 MyItem myitem1, myitem2;
2623 myitem1.setRect(QRectF(50, 50, 40, 200));
2626 myitem2.setRect(QRectF(25, 25, 20, 20));
2627 myitem2.setZValue(-1.0);
2628 scene.addItem(&myitem1);
2629 scene.addItem(&myitem2);
2631 QVERIFY(!myitem2.isObscuredBy(&myitem1));
2632 QVERIFY(!myitem1.isObscuredBy(&myitem2));
2634 myitem2.setRect(QRectF(-50, 85, 20, 20));
2635 QVERIFY(myitem2.isObscuredBy(&myitem1));
2636 QVERIFY(!myitem1.isObscuredBy(&myitem2));
2638 myitem2.setRect(QRectF(-30, 70, 20, 20));
2639 QVERIFY(!myitem2.isObscuredBy(&myitem1));
2640 QVERIFY(!myitem1.isObscuredBy(&myitem2));
2642 QGraphicsRectItem rect1, rect2;
2644 rect1.setRect(QRectF(-40, -40, 50, 50));
2645 rect1.setBrush(QBrush(Qt::red));
2646 rect2.setRect(QRectF(-30, -20, 20, 20));
2647 rect2.setZValue(-1.0);
2648 rect2.setBrush(QBrush(Qt::blue));
2650 QVERIFY(rect2.isObscuredBy(&rect1));
2651 QVERIFY(!rect1.isObscuredBy(&rect2));
2653 rect2.setPos(QPointF(-20, -25));
2655 QVERIFY(!rect2.isObscuredBy(&rect1));
2656 QVERIFY(!rect1.isObscuredBy(&rect2));
2658 rect2.setPos(QPointF(-100, -100));
2660 QVERIFY(!rect2.isObscuredBy(&rect1));
2661 QVERIFY(!rect1.isObscuredBy(&rect2));
2664 class OpaqueItem : public QGraphicsRectItem
2667 QPainterPath opaqueArea() const
2673 void tst_QGraphicsItem::isObscured()
2675 if (sizeof(qreal) != sizeof(double))
2676 QSKIP("Skipped due to rounding errors");
2678 OpaqueItem *item1 = new OpaqueItem;
2679 item1->setRect(0, 0, 100, 100);
2680 item1->setZValue(0);
2682 OpaqueItem *item2 = new OpaqueItem;
2683 item2->setZValue(1);
2684 item2->setRect(0, 0, 100, 100);
2686 QGraphicsScene scene;
2687 scene.addItem(item1);
2688 scene.addItem(item2);
2690 QVERIFY(item1->isObscured());
2691 QVERIFY(item1->isObscuredBy(item2));
2692 QVERIFY(item1->isObscured(QRectF(0, 0, 50, 50)));
2693 QVERIFY(item1->isObscured(QRectF(50, 0, 50, 50)));
2694 QVERIFY(item1->isObscured(QRectF(50, 50, 50, 50)));
2695 QVERIFY(item1->isObscured(QRectF(0, 50, 50, 50)));
2696 QVERIFY(item1->isObscured(0, 0, 50, 50));
2697 QVERIFY(item1->isObscured(50, 0, 50, 50));
2698 QVERIFY(item1->isObscured(50, 50, 50, 50));
2699 QVERIFY(item1->isObscured(0, 50, 50, 50));
2700 QVERIFY(!item2->isObscured());
2701 QVERIFY(!item2->isObscuredBy(item1));
2702 QVERIFY(!item2->isObscured(QRectF(0, 0, 50, 50)));
2703 QVERIFY(!item2->isObscured(QRectF(50, 0, 50, 50)));
2704 QVERIFY(!item2->isObscured(QRectF(50, 50, 50, 50)));
2705 QVERIFY(!item2->isObscured(QRectF(0, 50, 50, 50)));
2706 QVERIFY(!item2->isObscured(0, 0, 50, 50));
2707 QVERIFY(!item2->isObscured(50, 0, 50, 50));
2708 QVERIFY(!item2->isObscured(50, 50, 50, 50));
2709 QVERIFY(!item2->isObscured(0, 50, 50, 50));
2711 item2->moveBy(50, 0);
2713 QVERIFY(!item1->isObscured());
2714 QVERIFY(!item1->isObscuredBy(item2));
2715 QVERIFY(!item1->isObscured(QRectF(0, 0, 50, 50)));
2716 QVERIFY(item1->isObscured(QRectF(50, 0, 50, 50)));
2717 QVERIFY(item1->isObscured(QRectF(50, 50, 50, 50)));
2718 QVERIFY(!item1->isObscured(QRectF(0, 50, 50, 50)));
2719 QVERIFY(!item1->isObscured(0, 0, 50, 50));
2720 QVERIFY(item1->isObscured(50, 0, 50, 50));
2721 QVERIFY(item1->isObscured(50, 50, 50, 50));
2722 QVERIFY(!item1->isObscured(0, 50, 50, 50));
2723 QVERIFY(!item2->isObscured());
2724 QVERIFY(!item2->isObscuredBy(item1));
2725 QVERIFY(!item2->isObscured(QRectF(0, 0, 50, 50)));
2726 QVERIFY(!item2->isObscured(QRectF(50, 0, 50, 50)));
2727 QVERIFY(!item2->isObscured(QRectF(50, 50, 50, 50)));
2728 QVERIFY(!item2->isObscured(QRectF(0, 50, 50, 50)));
2729 QVERIFY(!item2->isObscured(0, 0, 50, 50));
2730 QVERIFY(!item2->isObscured(50, 0, 50, 50));
2731 QVERIFY(!item2->isObscured(50, 50, 50, 50));
2732 QVERIFY(!item2->isObscured(0, 50, 50, 50));
2735 void tst_QGraphicsItem::mapFromToParent()
2738 path1.addRect(0, 0, 200, 200);
2741 path2.addRect(0, 0, 100, 100);
2744 path3.addRect(0, 0, 50, 50);
2747 path4.addRect(0, 0, 25, 25);
2749 QGraphicsItem *item1 = new QGraphicsPathItem(path1);
2750 QGraphicsItem *item2 = new QGraphicsPathItem(path2, item1);
2751 QGraphicsItem *item3 = new QGraphicsPathItem(path3, item2);
2752 QGraphicsItem *item4 = new QGraphicsPathItem(path4, item3);
2754 item1->setPos(10, 10);
2755 item2->setPos(10, 10);
2756 item3->setPos(10, 10);
2757 item4->setPos(10, 10);
2759 for (int i = 0; i < 4; ++i) {
2761 matrix.rotate(i * 90);
2762 matrix.translate(i * 100, -i * 100);
2764 item1->setMatrix(matrix);
2766 QCOMPARE(item1->mapToParent(QPointF(0, 0)), item1->pos() + matrix.map(QPointF(0, 0)));
2767 QCOMPARE(item2->mapToParent(QPointF(0, 0)), item2->pos());
2768 QCOMPARE(item3->mapToParent(QPointF(0, 0)), item3->pos());
2769 QCOMPARE(item4->mapToParent(QPointF(0, 0)), item4->pos());
2770 QCOMPARE(item1->mapToParent(QPointF(10, -10)), item1->pos() + matrix.map(QPointF(10, -10)));
2771 QCOMPARE(item2->mapToParent(QPointF(10, -10)), item2->pos() + QPointF(10, -10));
2772 QCOMPARE(item3->mapToParent(QPointF(10, -10)), item3->pos() + QPointF(10, -10));
2773 QCOMPARE(item4->mapToParent(QPointF(10, -10)), item4->pos() + QPointF(10, -10));
2774 QCOMPARE(item1->mapToParent(QPointF(-10, 10)), item1->pos() + matrix.map(QPointF(-10, 10)));
2775 QCOMPARE(item2->mapToParent(QPointF(-10, 10)), item2->pos() + QPointF(-10, 10));
2776 QCOMPARE(item3->mapToParent(QPointF(-10, 10)), item3->pos() + QPointF(-10, 10));
2777 QCOMPARE(item4->mapToParent(QPointF(-10, 10)), item4->pos() + QPointF(-10, 10));
2778 QCOMPARE(item1->mapFromParent(item1->pos()), matrix.inverted().map(QPointF(0, 0)));
2779 QCOMPARE(item2->mapFromParent(item2->pos()), QPointF(0, 0));
2780 QCOMPARE(item3->mapFromParent(item3->pos()), QPointF(0, 0));
2781 QCOMPARE(item4->mapFromParent(item4->pos()), QPointF(0, 0));
2782 QCOMPARE(item1->mapFromParent(item1->pos() + QPointF(10, -10)),
2783 matrix.inverted().map(QPointF(10, -10)));
2784 QCOMPARE(item2->mapFromParent(item2->pos() + QPointF(10, -10)), QPointF(10, -10));
2785 QCOMPARE(item3->mapFromParent(item3->pos() + QPointF(10, -10)), QPointF(10, -10));
2786 QCOMPARE(item4->mapFromParent(item4->pos() + QPointF(10, -10)), QPointF(10, -10));
2787 QCOMPARE(item1->mapFromParent(item1->pos() + QPointF(-10, 10)),
2788 matrix.inverted().map(QPointF(-10, 10)));
2789 QCOMPARE(item2->mapFromParent(item2->pos() + QPointF(-10, 10)), QPointF(-10, 10));
2790 QCOMPARE(item3->mapFromParent(item3->pos() + QPointF(-10, 10)), QPointF(-10, 10));
2791 QCOMPARE(item4->mapFromParent(item4->pos() + QPointF(-10, 10)), QPointF(-10, 10));
2797 void tst_QGraphicsItem::mapFromToScene()
2799 QGraphicsItem *item1 = new QGraphicsPathItem(QPainterPath());
2800 QGraphicsItem *item2 = new QGraphicsPathItem(QPainterPath(), item1);
2801 QGraphicsItem *item3 = new QGraphicsPathItem(QPainterPath(), item2);
2802 QGraphicsItem *item4 = new QGraphicsPathItem(QPainterPath(), item3);
2804 item1->setPos(100, 100);
2805 item2->setPos(100, 100);
2806 item3->setPos(100, 100);
2807 item4->setPos(100, 100);
2808 QCOMPARE(item1->pos(), QPointF(100, 100));
2809 QCOMPARE(item2->pos(), QPointF(100, 100));
2810 QCOMPARE(item3->pos(), QPointF(100, 100));
2811 QCOMPARE(item4->pos(), QPointF(100, 100));
2812 QCOMPARE(item1->pos(), item1->mapToParent(0, 0));
2813 QCOMPARE(item2->pos(), item2->mapToParent(0, 0));
2814 QCOMPARE(item3->pos(), item3->mapToParent(0, 0));
2815 QCOMPARE(item4->pos(), item4->mapToParent(0, 0));
2816 QCOMPARE(item1->mapToParent(10, 10), QPointF(110, 110));
2817 QCOMPARE(item2->mapToParent(10, 10), QPointF(110, 110));
2818 QCOMPARE(item3->mapToParent(10, 10), QPointF(110, 110));
2819 QCOMPARE(item4->mapToParent(10, 10), QPointF(110, 110));
2820 QCOMPARE(item1->mapToScene(0, 0), QPointF(100, 100));
2821 QCOMPARE(item2->mapToScene(0, 0), QPointF(200, 200));
2822 QCOMPARE(item3->mapToScene(0, 0), QPointF(300, 300));
2823 QCOMPARE(item4->mapToScene(0, 0), QPointF(400, 400));
2824 QCOMPARE(item1->mapToScene(10, 0), QPointF(110, 100));
2825 QCOMPARE(item2->mapToScene(10, 0), QPointF(210, 200));
2826 QCOMPARE(item3->mapToScene(10, 0), QPointF(310, 300));
2827 QCOMPARE(item4->mapToScene(10, 0), QPointF(410, 400));
2828 QCOMPARE(item1->mapFromScene(100, 100), QPointF(0, 0));
2829 QCOMPARE(item2->mapFromScene(200, 200), QPointF(0, 0));
2830 QCOMPARE(item3->mapFromScene(300, 300), QPointF(0, 0));
2831 QCOMPARE(item4->mapFromScene(400, 400), QPointF(0, 0));
2832 QCOMPARE(item1->mapFromScene(110, 100), QPointF(10, 0));
2833 QCOMPARE(item2->mapFromScene(210, 200), QPointF(10, 0));
2834 QCOMPARE(item3->mapFromScene(310, 300), QPointF(10, 0));
2835 QCOMPARE(item4->mapFromScene(410, 400), QPointF(10, 0));
2837 // Rotate item1 90 degrees clockwise
2838 QMatrix matrix; matrix.rotate(90);
2839 item1->setMatrix(matrix);
2840 QCOMPARE(item1->pos(), item1->mapToParent(0, 0));
2841 QCOMPARE(item2->pos(), item2->mapToParent(0, 0));
2842 QCOMPARE(item3->pos(), item3->mapToParent(0, 0));
2843 QCOMPARE(item4->pos(), item4->mapToParent(0, 0));
2844 QCOMPARE(item1->mapToParent(10, 0), QPointF(100, 110));
2845 QCOMPARE(item2->mapToParent(10, 0), QPointF(110, 100));
2846 QCOMPARE(item3->mapToParent(10, 0), QPointF(110, 100));
2847 QCOMPARE(item4->mapToParent(10, 0), QPointF(110, 100));
2848 QCOMPARE(item1->mapToScene(0, 0), QPointF(100, 100));
2849 QCOMPARE(item2->mapToScene(0, 0), QPointF(0, 200));
2850 QCOMPARE(item3->mapToScene(0, 0), QPointF(-100, 300));
2851 QCOMPARE(item4->mapToScene(0, 0), QPointF(-200, 400));
2852 QCOMPARE(item1->mapToScene(10, 0), QPointF(100, 110));
2853 QCOMPARE(item2->mapToScene(10, 0), QPointF(0, 210));
2854 QCOMPARE(item3->mapToScene(10, 0), QPointF(-100, 310));
2855 QCOMPARE(item4->mapToScene(10, 0), QPointF(-200, 410));
2856 QCOMPARE(item1->mapFromScene(100, 100), QPointF(0, 0));
2857 QCOMPARE(item2->mapFromScene(0, 200), QPointF(0, 0));
2858 QCOMPARE(item3->mapFromScene(-100, 300), QPointF(0, 0));
2859 QCOMPARE(item4->mapFromScene(-200, 400), QPointF(0, 0));
2860 QCOMPARE(item1->mapFromScene(100, 110), QPointF(10, 0));
2861 QCOMPARE(item2->mapFromScene(0, 210), QPointF(10, 0));
2862 QCOMPARE(item3->mapFromScene(-100, 310), QPointF(10, 0));
2863 QCOMPARE(item4->mapFromScene(-200, 410), QPointF(10, 0));
2865 // Rotate item2 90 degrees clockwise
2866 item2->setMatrix(matrix);
2867 QCOMPARE(item1->pos(), item1->mapToParent(0, 0));
2868 QCOMPARE(item2->pos(), item2->mapToParent(0, 0));
2869 QCOMPARE(item3->pos(), item3->mapToParent(0, 0));
2870 QCOMPARE(item4->pos(), item4->mapToParent(0, 0));
2871 QCOMPARE(item1->mapToParent(10, 0), QPointF(100, 110));
2872 QCOMPARE(item2->mapToParent(10, 0), QPointF(100, 110));
2873 QCOMPARE(item3->mapToParent(10, 0), QPointF(110, 100));
2874 QCOMPARE(item4->mapToParent(10, 0), QPointF(110, 100));
2875 QCOMPARE(item1->mapToScene(0, 0), QPointF(100, 100));
2876 QCOMPARE(item2->mapToScene(0, 0), QPointF(0, 200));
2877 QCOMPARE(item3->mapToScene(0, 0), QPointF(-100, 100));
2878 QCOMPARE(item4->mapToScene(0, 0), QPointF(-200, 0));
2879 QCOMPARE(item1->mapToScene(10, 0), QPointF(100, 110));
2880 QCOMPARE(item2->mapToScene(10, 0), QPointF(-10, 200));
2881 QCOMPARE(item3->mapToScene(10, 0), QPointF(-110, 100));
2882 QCOMPARE(item4->mapToScene(10, 0), QPointF(-210, 0));
2883 QCOMPARE(item1->mapFromScene(100, 100), QPointF(0, 0));
2884 QCOMPARE(item2->mapFromScene(0, 200), QPointF(0, 0));
2885 QCOMPARE(item3->mapFromScene(-100, 100), QPointF(0, 0));
2886 QCOMPARE(item4->mapFromScene(-200, 0), QPointF(0, 0));
2887 QCOMPARE(item1->mapFromScene(100, 110), QPointF(10, 0));
2888 QCOMPARE(item2->mapFromScene(-10, 200), QPointF(10, 0));
2889 QCOMPARE(item3->mapFromScene(-110, 100), QPointF(10, 0));
2890 QCOMPARE(item4->mapFromScene(-210, 0), QPointF(10, 0));
2892 // Translate item3 50 points, then rotate 90 degrees counterclockwise
2894 matrix2.translate(50, 0);
2895 matrix2.rotate(-90);
2896 item3->setMatrix(matrix2);
2897 QCOMPARE(item1->pos(), item1->mapToParent(0, 0));
2898 QCOMPARE(item2->pos(), item2->mapToParent(0, 0));
2899 QCOMPARE(item3->pos(), item3->mapToParent(0, 0) - QPointF(50, 0));
2900 QCOMPARE(item4->pos(), item4->mapToParent(0, 0));
2901 QCOMPARE(item1->mapToParent(10, 0), QPointF(100, 110));
2902 QCOMPARE(item2->mapToParent(10, 0), QPointF(100, 110));
2903 QCOMPARE(item3->mapToParent(10, 0), QPointF(150, 90));
2904 QCOMPARE(item4->mapToParent(10, 0), QPointF(110, 100));
2905 QCOMPARE(item1->mapToScene(0, 0), QPointF(100, 100));
2906 QCOMPARE(item2->mapToScene(0, 0), QPointF(0, 200));
2907 QCOMPARE(item3->mapToScene(0, 0), QPointF(-150, 100));
2908 QCOMPARE(item4->mapToScene(0, 0), QPointF(-250, 200));
2909 QCOMPARE(item1->mapToScene(10, 0), QPointF(100, 110));
2910 QCOMPARE(item2->mapToScene(10, 0), QPointF(-10, 200));
2911 QCOMPARE(item3->mapToScene(10, 0), QPointF(-150, 110));
2912 QCOMPARE(item4->mapToScene(10, 0), QPointF(-250, 210));
2913 QCOMPARE(item1->mapFromScene(100, 100), QPointF(0, 0));
2914 QCOMPARE(item2->mapFromScene(0, 200), QPointF(0, 0));
2915 QCOMPARE(item3->mapFromScene(-150, 100), QPointF(0, 0));
2916 QCOMPARE(item4->mapFromScene(-250, 200), QPointF(0, 0));
2917 QCOMPARE(item1->mapFromScene(100, 110), QPointF(10, 0));
2918 QCOMPARE(item2->mapFromScene(-10, 200), QPointF(10, 0));
2919 QCOMPARE(item3->mapFromScene(-150, 110), QPointF(10, 0));
2920 QCOMPARE(item4->mapFromScene(-250, 210), QPointF(10, 0));
2925 void tst_QGraphicsItem::mapFromToItem()
2927 QGraphicsItem *item1 = new QGraphicsPathItem;
2928 QGraphicsItem *item2 = new QGraphicsPathItem;
2929 QGraphicsItem *item3 = new QGraphicsPathItem;
2930 QGraphicsItem *item4 = new QGraphicsPathItem;
2932 item1->setPos(-100, -100);
2933 item2->setPos(100, -100);
2934 item3->setPos(100, 100);
2935 item4->setPos(-100, 100);
2937 QCOMPARE(item1->mapFromItem(item2, 0, 0), QPointF(200, 0));
2938 QCOMPARE(item2->mapFromItem(item3, 0, 0), QPointF(0, 200));
2939 QCOMPARE(item3->mapFromItem(item4, 0, 0), QPointF(-200, 0));
2940 QCOMPARE(item4->mapFromItem(item1, 0, 0), QPointF(0, -200));
2941 QCOMPARE(item1->mapFromItem(item4, 0, 0), QPointF(0, 200));
2942 QCOMPARE(item2->mapFromItem(item1, 0, 0), QPointF(-200, 0));
2943 QCOMPARE(item3->mapFromItem(item2, 0, 0), QPointF(0, -200));
2944 QCOMPARE(item4->mapFromItem(item3, 0, 0), QPointF(200, 0));
2947 matrix.translate(100, 100);
2948 item1->setMatrix(matrix);
2950 QCOMPARE(item1->mapFromItem(item2, 0, 0), QPointF(100, -100));
2951 QCOMPARE(item2->mapFromItem(item3, 0, 0), QPointF(0, 200));
2952 QCOMPARE(item3->mapFromItem(item4, 0, 0), QPointF(-200, 0));
2953 QCOMPARE(item4->mapFromItem(item1, 0, 0), QPointF(100, -100));
2954 QCOMPARE(item1->mapFromItem(item4, 0, 0), QPointF(-100, 100));
2955 QCOMPARE(item2->mapFromItem(item1, 0, 0), QPointF(-100, 100));
2956 QCOMPARE(item3->mapFromItem(item2, 0, 0), QPointF(0, -200));
2957 QCOMPARE(item4->mapFromItem(item3, 0, 0), QPointF(200, 0));
2960 item1->setMatrix(matrix);
2961 item2->setMatrix(matrix);
2962 item3->setMatrix(matrix);
2963 item4->setMatrix(matrix);
2965 QCOMPARE(item1->mapFromItem(item2, 0, 0), QPointF(0, -200));
2966 QCOMPARE(item2->mapFromItem(item3, 0, 0), QPointF(200, 0));
2967 QCOMPARE(item3->mapFromItem(item4, 0, 0), QPointF(0, 200));
2968 QCOMPARE(item4->mapFromItem(item1, 0, 0), QPointF(-200, 0));
2969 QCOMPARE(item1->mapFromItem(item4, 0, 0), QPointF(200, 0));
2970 QCOMPARE(item2->mapFromItem(item1, 0, 0), QPointF(0, 200));
2971 QCOMPARE(item3->mapFromItem(item2, 0, 0), QPointF(-200, 0));
2972 QCOMPARE(item4->mapFromItem(item3, 0, 0), QPointF(0, -200));
2973 QCOMPARE(item1->mapFromItem(item2, 10, -5), QPointF(10, -205));
2974 QCOMPARE(item2->mapFromItem(item3, 10, -5), QPointF(210, -5));
2975 QCOMPARE(item3->mapFromItem(item4, 10, -5), QPointF(10, 195));
2976 QCOMPARE(item4->mapFromItem(item1, 10, -5), QPointF(-190, -5));
2977 QCOMPARE(item1->mapFromItem(item4, 10, -5), QPointF(210, -5));
2978 QCOMPARE(item2->mapFromItem(item1, 10, -5), QPointF(10, 195));
2979 QCOMPARE(item3->mapFromItem(item2, 10, -5), QPointF(-190, -5));
2980 QCOMPARE(item4->mapFromItem(item3, 10, -5), QPointF(10, -205));
2982 QCOMPARE(item1->mapFromItem(0, 10, -5), item1->mapFromScene(10, -5));
2983 QCOMPARE(item2->mapFromItem(0, 10, -5), item2->mapFromScene(10, -5));
2984 QCOMPARE(item3->mapFromItem(0, 10, -5), item3->mapFromScene(10, -5));
2985 QCOMPARE(item4->mapFromItem(0, 10, -5), item4->mapFromScene(10, -5));
2986 QCOMPARE(item1->mapToItem(0, 10, -5), item1->mapToScene(10, -5));
2987 QCOMPARE(item2->mapToItem(0, 10, -5), item2->mapToScene(10, -5));
2988 QCOMPARE(item3->mapToItem(0, 10, -5), item3->mapToScene(10, -5));
2989 QCOMPARE(item4->mapToItem(0, 10, -5), item4->mapToScene(10, -5));
2997 void tst_QGraphicsItem::mapRectFromToParent_data()
2999 QTest::addColumn<bool>("parent");
3000 QTest::addColumn<QPointF>("parentPos");
3001 QTest::addColumn<QTransform>("parentTransform");
3002 QTest::addColumn<QPointF>("pos");
3003 QTest::addColumn<QTransform>("transform");
3004 QTest::addColumn<QRectF>("inputRect");
3005 QTest::addColumn<QRectF>("outputRect");
3007 QTest::newRow("nil") << false << QPointF() << QTransform() << QPointF() << QTransform() << QRectF() << QRectF();
3008 QTest::newRow("simple") << false << QPointF() << QTransform() << QPointF() << QTransform()
3009 << QRectF(0, 0, 10, 10) << QRectF(0, 0, 10, 10);
3010 QTest::newRow("simple w/parent") << true
3011 << QPointF() << QTransform()
3012 << QPointF() << QTransform()
3013 << QRectF(0, 0, 10, 10) << QRectF(0, 0, 10, 10);
3014 QTest::newRow("simple w/parent parentPos") << true
3015 << QPointF(50, 50) << QTransform()
3016 << QPointF() << QTransform()
3017 << QRectF(0, 0, 10, 10) << QRectF(0, 0, 10, 10);
3018 QTest::newRow("simple w/parent parentPos parentRotation") << true
3019 << QPointF(50, 50) << QTransform().rotate(45)
3020 << QPointF() << QTransform()
3021 << QRectF(0, 0, 10, 10) << QRectF(0, 0, 10, 10);
3022 QTest::newRow("pos w/parent") << true
3023 << QPointF() << QTransform()
3024 << QPointF(50, 50) << QTransform()
3025 << QRectF(0, 0, 10, 10) << QRectF(50, 50, 10, 10);
3026 QTest::newRow("rotation w/parent") << true
3027 << QPointF() << QTransform()
3028 << QPointF() << QTransform().rotate(90)
3029 << QRectF(0, 0, 10, 10) << QRectF(-10, 0, 10, 10);
3030 QTest::newRow("pos rotation w/parent") << true
3031 << QPointF() << QTransform()
3032 << QPointF(50, 50) << QTransform().rotate(90)
3033 << QRectF(0, 0, 10, 10) << QRectF(40, 50, 10, 10);
3034 QTest::newRow("pos rotation w/parent parentPos parentRotation") << true
3035 << QPointF(-170, -190) << QTransform().rotate(90)
3036 << QPointF(50, 50) << QTransform().rotate(90)
3037 << QRectF(0, 0, 10, 10) << QRectF(40, 50, 10, 10);
3040 void tst_QGraphicsItem::mapRectFromToParent()
3042 QFETCH(bool, parent);
3043 QFETCH(QPointF, parentPos);
3044 QFETCH(QTransform, parentTransform);
3045 QFETCH(QPointF, pos);
3046 QFETCH(QTransform, transform);
3047 QFETCH(QRectF, inputRect);
3048 QFETCH(QRectF, outputRect);
3050 QGraphicsRectItem *rect = new QGraphicsRectItem;
3052 rect->setTransform(transform);
3055 QGraphicsRectItem *rectParent = new QGraphicsRectItem;
3056 rect->setParentItem(rectParent);
3057 rectParent->setPos(parentPos);
3058 rectParent->setTransform(parentTransform);
3061 // Make sure we use non-destructive transform operations (e.g., 90 degree
3063 QCOMPARE(rect->mapRectToParent(inputRect), outputRect);
3064 QCOMPARE(rect->mapRectFromParent(outputRect), inputRect);
3065 QCOMPARE(rect->itemTransform(rect->parentItem()).mapRect(inputRect), outputRect);
3066 QCOMPARE(rect->mapToParent(inputRect).boundingRect(), outputRect);
3067 QCOMPARE(rect->mapToParent(QPolygonF(inputRect)).boundingRect(), outputRect);
3068 QCOMPARE(rect->mapFromParent(outputRect).boundingRect(), inputRect);
3069 QCOMPARE(rect->mapFromParent(QPolygonF(outputRect)).boundingRect(), inputRect);
3070 QPainterPath inputPath;
3071 inputPath.addRect(inputRect);
3072 QPainterPath outputPath;
3073 outputPath.addRect(outputRect);
3074 QCOMPARE(rect->mapToParent(inputPath).boundingRect(), outputPath.boundingRect());
3075 QCOMPARE(rect->mapFromParent(outputPath).boundingRect(), inputPath.boundingRect());
3078 void tst_QGraphicsItem::isAncestorOf()
3080 QGraphicsItem *grandPa = new QGraphicsRectItem;
3081 QGraphicsItem *parent = new QGraphicsRectItem;
3082 QGraphicsItem *child = new QGraphicsRectItem;
3084 QVERIFY(!parent->isAncestorOf(0));
3085 QVERIFY(!child->isAncestorOf(0));
3086 QVERIFY(!parent->isAncestorOf(child));
3087 QVERIFY(!child->isAncestorOf(parent));
3088 QVERIFY(!parent->isAncestorOf(parent));
3090 child->setParentItem(parent);
3091 parent->setParentItem(grandPa);
3093 QVERIFY(parent->isAncestorOf(child));
3094 QVERIFY(grandPa->isAncestorOf(parent));
3095 QVERIFY(grandPa->isAncestorOf(child));
3096 QVERIFY(!child->isAncestorOf(parent));
3097 QVERIFY(!parent->isAncestorOf(grandPa));
3098 QVERIFY(!child->isAncestorOf(grandPa));
3099 QVERIFY(!child->isAncestorOf(child));
3100 QVERIFY(!parent->isAncestorOf(parent));
3101 QVERIFY(!grandPa->isAncestorOf(grandPa));
3103 parent->setParentItem(0);
3110 void tst_QGraphicsItem::commonAncestorItem()
3112 QGraphicsItem *ancestor = new QGraphicsRectItem;
3113 QGraphicsItem *grandMa = new QGraphicsRectItem;
3114 QGraphicsItem *grandPa = new QGraphicsRectItem;
3115 QGraphicsItem *brotherInLaw = new QGraphicsRectItem;
3116 QGraphicsItem *cousin = new QGraphicsRectItem;
3117 QGraphicsItem *husband = new QGraphicsRectItem;
3118 QGraphicsItem *child = new QGraphicsRectItem;
3119 QGraphicsItem *wife = new QGraphicsRectItem;
3121 child->setParentItem(husband);
3122 husband->setParentItem(grandPa);
3123 brotherInLaw->setParentItem(grandPa);
3124 cousin->setParentItem(brotherInLaw);
3125 wife->setParentItem(grandMa);
3126 grandMa->setParentItem(ancestor);
3127 grandPa->setParentItem(ancestor);
3129 QCOMPARE(grandMa->commonAncestorItem(grandMa), grandMa);
3130 QCOMPARE(grandMa->commonAncestorItem(0), (QGraphicsItem *)0);
3131 QCOMPARE(grandMa->commonAncestorItem(grandPa), ancestor);
3132 QCOMPARE(grandPa->commonAncestorItem(grandMa), ancestor);
3133 QCOMPARE(grandPa->commonAncestorItem(husband), grandPa);
3134 QCOMPARE(grandPa->commonAncestorItem(wife), ancestor);
3135 QCOMPARE(grandMa->commonAncestorItem(husband), ancestor);
3136 QCOMPARE(grandMa->commonAncestorItem(wife), grandMa);
3137 QCOMPARE(wife->commonAncestorItem(grandMa), grandMa);
3138 QCOMPARE(child->commonAncestorItem(cousin), grandPa);
3139 QCOMPARE(cousin->commonAncestorItem(child), grandPa);
3140 QCOMPARE(wife->commonAncestorItem(child), ancestor);
3141 QCOMPARE(child->commonAncestorItem(wife), ancestor);
3144 void tst_QGraphicsItem::data()
3146 QGraphicsTextItem text;
3148 QCOMPARE(text.data(0), QVariant());
3149 text.setData(0, "TextItem");
3150 QCOMPARE(text.data(0), QVariant(QString("TextItem")));
3151 text.setData(0, QVariant());
3152 QCOMPARE(text.data(0), QVariant());
3155 void tst_QGraphicsItem::type()
3157 QCOMPARE(int(QGraphicsItem::Type), 1);
3158 QCOMPARE(int(QGraphicsPathItem::Type), 2);
3159 QCOMPARE(int(QGraphicsRectItem::Type), 3);
3160 QCOMPARE(int(QGraphicsEllipseItem::Type), 4);
3161 QCOMPARE(int(QGraphicsPolygonItem::Type), 5);
3162 QCOMPARE(int(QGraphicsLineItem::Type), 6);
3163 QCOMPARE(int(QGraphicsPixmapItem::Type), 7);
3164 QCOMPARE(int(QGraphicsTextItem::Type), 8);
3166 QCOMPARE(QGraphicsPathItem().type(), 2);
3167 QCOMPARE(QGraphicsRectItem().type(), 3);
3168 QCOMPARE(QGraphicsEllipseItem().type(), 4);
3169 QCOMPARE(QGraphicsPolygonItem().type(), 5);
3170 QCOMPARE(QGraphicsLineItem().type(), 6);
3171 QCOMPARE(QGraphicsPixmapItem().type(), 7);
3172 QCOMPARE(QGraphicsTextItem().type(), 8);
3175 void tst_QGraphicsItem::graphicsitem_cast()
3177 QGraphicsPathItem pathItem;
3178 const QGraphicsPathItem *pPathItem = &pathItem;
3179 QGraphicsRectItem rectItem;
3180 const QGraphicsRectItem *pRectItem = &rectItem;
3181 QGraphicsEllipseItem ellipseItem;
3182 const QGraphicsEllipseItem *pEllipseItem = &ellipseItem;
3183 QGraphicsPolygonItem polygonItem;
3184 const QGraphicsPolygonItem *pPolygonItem = &polygonItem;
3185 QGraphicsLineItem lineItem;
3186 const QGraphicsLineItem *pLineItem = &lineItem;
3187 QGraphicsPixmapItem pixmapItem;
3188 const QGraphicsPixmapItem *pPixmapItem = &pixmapItem;
3189 QGraphicsTextItem textItem;
3190 const QGraphicsTextItem *pTextItem = &textItem;
3192 QVERIFY(qgraphicsitem_cast<QGraphicsPathItem *>(&pathItem));
3193 //QVERIFY(qgraphicsitem_cast<QAbstractGraphicsPathItem *>(&pathItem));
3194 QVERIFY(qgraphicsitem_cast<QGraphicsItem *>(&pathItem));
3195 QVERIFY(qgraphicsitem_cast<const QGraphicsItem *>(pPathItem));
3196 QVERIFY(qgraphicsitem_cast<const QGraphicsPathItem *>(pPathItem));
3198 QVERIFY(qgraphicsitem_cast<QGraphicsRectItem *>(&rectItem));
3199 QVERIFY(qgraphicsitem_cast<QGraphicsItem *>(&rectItem));
3200 QVERIFY(qgraphicsitem_cast<const QGraphicsItem *>(pRectItem));
3201 QVERIFY(qgraphicsitem_cast<const QGraphicsRectItem *>(pRectItem));
3203 QVERIFY(qgraphicsitem_cast<QGraphicsEllipseItem *>(&ellipseItem));
3204 QVERIFY(qgraphicsitem_cast<QGraphicsItem *>(&ellipseItem));
3205 QVERIFY(qgraphicsitem_cast<const QGraphicsItem *>(pEllipseItem));
3206 QVERIFY(qgraphicsitem_cast<const QGraphicsEllipseItem *>(pEllipseItem));
3208 QVERIFY(qgraphicsitem_cast<QGraphicsPolygonItem *>(&polygonItem));
3209 //QVERIFY(qgraphicsitem_cast<QAbstractGraphicsPathItem *>(&polygonItem));
3210 QVERIFY(qgraphicsitem_cast<QGraphicsItem *>(&polygonItem));
3211 QVERIFY(qgraphicsitem_cast<const QGraphicsItem *>(pPolygonItem));
3212 QVERIFY(qgraphicsitem_cast<const QGraphicsPolygonItem *>(pPolygonItem));
3214 QVERIFY(qgraphicsitem_cast<QGraphicsLineItem *>(&lineItem));
3215 QVERIFY(qgraphicsitem_cast<QGraphicsItem *>(&lineItem));
3216 QVERIFY(qgraphicsitem_cast<const QGraphicsItem *>(pLineItem));
3217 QVERIFY(qgraphicsitem_cast<const QGraphicsLineItem *>(pLineItem));
3219 QVERIFY(qgraphicsitem_cast<QGraphicsPixmapItem *>(&pixmapItem));
3220 QVERIFY(qgraphicsitem_cast<QGraphicsItem *>(&pixmapItem));
3221 QVERIFY(qgraphicsitem_cast<const QGraphicsItem *>(pPixmapItem));
3222 QVERIFY(qgraphicsitem_cast<const QGraphicsPixmapItem *>(pPixmapItem));
3224 QVERIFY(qgraphicsitem_cast<QGraphicsTextItem *>(&textItem));
3225 QVERIFY(qgraphicsitem_cast<QGraphicsItem *>(&textItem));
3226 QVERIFY(qgraphicsitem_cast<const QGraphicsItem *>(pTextItem));
3227 QVERIFY(qgraphicsitem_cast<const QGraphicsTextItem *>(pTextItem));
3229 // and some casts that _should_ fail:
3230 QVERIFY(!qgraphicsitem_cast<QGraphicsEllipseItem *>(&pathItem));
3231 QVERIFY(!qgraphicsitem_cast<const QGraphicsTextItem *>(pPolygonItem));
3233 // and this shouldn't crash
3234 QGraphicsItem *ptr = 0;
3235 QVERIFY(!qgraphicsitem_cast<QGraphicsTextItem *>(ptr));
3236 QVERIFY(!qgraphicsitem_cast<QGraphicsItem *>(ptr));
3239 void tst_QGraphicsItem::hoverEventsGenerateRepaints()
3243 QGraphicsScene scene;
3244 QGraphicsView view(&scene);
3246 QTest::qWaitForWindowShown(&view);
3249 EventTester *tester = new EventTester;
3250 scene.addItem(tester);
3251 tester->setAcceptsHoverEvents(true);
3253 QTRY_COMPARE(tester->repaints, 1);
3255 // Send a hover enter event
3256 QGraphicsSceneHoverEvent hoverEnterEvent(QEvent::GraphicsSceneHoverEnter);
3257 hoverEnterEvent.setScenePos(QPointF(0, 0));
3258 hoverEnterEvent.setPos(QPointF(0, 0));
3259 QApplication::sendEvent(&scene, &hoverEnterEvent);
3261 // Check that we get a repaint
3262 int npaints = tester->repaints;
3263 qApp->processEvents();
3264 qApp->processEvents();
3265 QCOMPARE(tester->events.size(), 2); // enter + move
3266 QCOMPARE(tester->repaints, npaints + 1);
3267 QCOMPARE(tester->events.last(), QEvent::GraphicsSceneHoverMove);
3269 // Send a hover move event
3270 QGraphicsSceneHoverEvent hoverMoveEvent(QEvent::GraphicsSceneHoverMove);
3271 hoverMoveEvent.setScenePos(QPointF(0, 0));
3272 hoverMoveEvent.setPos(QPointF(0, 0));
3273 QApplication::sendEvent(&scene, &hoverMoveEvent);
3275 // Check that we don't get a repaint
3276 qApp->processEvents();
3277 qApp->processEvents();
3279 QCOMPARE(tester->events.size(), 3);
3280 QCOMPARE(tester->repaints, npaints + 1);
3281 QCOMPARE(tester->events.last(), QEvent::GraphicsSceneHoverMove);
3283 // Send a hover leave event
3284 QGraphicsSceneHoverEvent hoverLeaveEvent(QEvent::GraphicsSceneHoverLeave);
3285 hoverLeaveEvent.setScenePos(QPointF(-100, -100));
3286 hoverLeaveEvent.setPos(QPointF(0, 0));
3287 QApplication::sendEvent(&scene, &hoverLeaveEvent);
3289 // Check that we get a repaint
3290 qApp->processEvents();
3291 qApp->processEvents();
3293 QCOMPARE(tester->events.size(), 4);
3294 QCOMPARE(tester->repaints, npaints + 2);
3295 QCOMPARE(tester->events.last(), QEvent::GraphicsSceneHoverLeave);
3298 void tst_QGraphicsItem::boundingRects_data()
3300 QTest::addColumn<QGraphicsItem *>("item");
3301 QTest::addColumn<QRectF>("boundingRect");
3303 QRectF rect(0, 0, 100, 100);
3307 QRectF adjustedRect(-0.5, -0.5, 101, 101);
3309 QTest::newRow("path") << (QGraphicsItem *)new QGraphicsPathItem(path) << adjustedRect;
3310 QTest::newRow("rect") << (QGraphicsItem *)new QGraphicsRectItem(rect) << adjustedRect;
3311 QTest::newRow("ellipse") << (QGraphicsItem *)new QGraphicsEllipseItem(rect) << adjustedRect;
3312 QTest::newRow("polygon") << (QGraphicsItem *)new QGraphicsPolygonItem(rect) << adjustedRect;
3315 void tst_QGraphicsItem::boundingRects()
3317 QFETCH(QGraphicsItem *, item);
3318 QFETCH(QRectF, boundingRect);
3320 ((QAbstractGraphicsShapeItem *)item)->setPen(QPen(Qt::black, 1));
3321 QCOMPARE(item->boundingRect(), boundingRect);
3324 void tst_QGraphicsItem::boundingRects2()
3326 QGraphicsPixmapItem pixmap(QPixmap::fromImage(QImage(100, 100, QImage::Format_ARGB32_Premultiplied)));
3327 QCOMPARE(pixmap.boundingRect(), QRectF(0, 0, 100, 100));
3329 QGraphicsLineItem line(0, 0, 100, 0);
3330 line.setPen(QPen(Qt::black, 1));
3331 QCOMPARE(line.boundingRect(), QRectF(-0.5, -0.5, 101, 1));
3334 void tst_QGraphicsItem::sceneBoundingRect()
3336 QGraphicsScene scene;
3337 QGraphicsRectItem *item = scene.addRect(QRectF(0, 0, 100, 100), QPen(Qt::black, 0));
3338 item->setPos(100, 100);
3340 QCOMPARE(item->boundingRect(), QRectF(0, 0, 100, 100));
3341 QCOMPARE(item->sceneBoundingRect(), QRectF(100, 100, 100, 100));
3345 QCOMPARE(item->boundingRect(), QRectF(0, 0, 100, 100));
3346 QCOMPARE(item->sceneBoundingRect(), QRectF(0, 100, 100, 100));
3349 void tst_QGraphicsItem::childrenBoundingRect()
3351 QGraphicsScene scene;
3352 QGraphicsRectItem *parent = scene.addRect(QRectF(0, 0, 100, 100), QPen(Qt::black, 0));
3353 QGraphicsRectItem *child = scene.addRect(QRectF(0, 0, 100, 100), QPen(Qt::black, 0));
3354 child->setParentItem(parent);
3355 parent->setPos(100, 100);
3356 child->setPos(100, 100);
3358 QCOMPARE(parent->boundingRect(), QRectF(0, 0, 100, 100));
3359 QCOMPARE(child->boundingRect(), QRectF(0, 0, 100, 100));
3360 QCOMPARE(child->childrenBoundingRect(), QRectF());
3361 QCOMPARE(parent->childrenBoundingRect(), QRectF(100, 100, 100, 100));
3363 QGraphicsRectItem *child2 = scene.addRect(QRectF(0, 0, 100, 100), QPen(Qt::black, 0));
3364 child2->setParentItem(parent);
3365 child2->setPos(-100, -100);
3366 QCOMPARE(parent->childrenBoundingRect(), QRectF(-100, -100, 300, 300));
3368 QGraphicsRectItem *childChild = scene.addRect(QRectF(0, 0, 100, 100), QPen(Qt::black, 0));
3369 childChild->setParentItem(child);
3370 childChild->setPos(500, 500);
3373 scene.addPolygon(parent->mapToScene(parent->boundingRect() | parent->childrenBoundingRect()))->setPen(QPen(Qt::red));;
3375 QGraphicsView view(&scene);
3378 QTest::qWaitForWindowShown(&view);
3381 QCOMPARE(parent->childrenBoundingRect(), QRectF(-500, -100, 600, 800));
3384 void tst_QGraphicsItem::childrenBoundingRectTransformed()
3386 QGraphicsScene scene;
3388 QGraphicsRectItem *rect = scene.addRect(QRectF(0, 0, 100, 100));
3389 QGraphicsRectItem *rect2 = scene.addRect(QRectF(0, 0, 100, 100));
3390 QGraphicsRectItem *rect3 = scene.addRect(QRectF(0, 0, 100, 100));
3391 QGraphicsRectItem *rect4 = scene.addRect(QRectF(0, 0, 100, 100));
3392 QGraphicsRectItem *rect5 = scene.addRect(QRectF(0, 0, 100, 100));
3393 rect2->setParentItem(rect);
3394 rect3->setParentItem(rect2);
3395 rect4->setParentItem(rect3);
3396 rect5->setParentItem(rect4);
3398 rect2->setTransform(QTransform().translate(50, 50).rotate(45));
3399 rect2->setPos(25, 25);
3400 rect3->setTransform(QTransform().translate(50, 50).rotate(45));
3401 rect3->setPos(25, 25);
3402 rect4->setTransform(QTransform().translate(50, 50).rotate(45));
3403 rect4->setPos(25, 25);
3404 rect5->setTransform(QTransform().translate(50, 50).rotate(45));
3405 rect5->setPos(25, 25);
3407 QRectF subTreeRect = rect->childrenBoundingRect();
3408 QCOMPARE(subTreeRect.left(), qreal(-206.0660171779821));
3409 QCOMPARE(subTreeRect.top(), qreal(75.0));
3410 QCOMPARE(subTreeRect.width(), qreal(351.7766952966369));
3411 QCOMPARE(subTreeRect.height(), qreal(251.7766952966369));
3419 subTreeRect = rect->childrenBoundingRect();
3420 QCOMPARE(rect->childrenBoundingRect(), QRectF(-100, 75, 275, 250));
3423 void tst_QGraphicsItem::childrenBoundingRect2()
3425 QGraphicsItemGroup box;
3426 QGraphicsLineItem l1(0, 0, 100, 0, &box);
3427 QGraphicsLineItem l2(100, 0, 100, 100, &box);
3428 QGraphicsLineItem l3(0, 0, 0, 100, &box);
3429 // Make sure lines (zero with/height) are included in the childrenBoundingRect.
3430 QCOMPARE(box.childrenBoundingRect(), QRectF(0, 0, 100, 100));
3433 void tst_QGraphicsItem::childrenBoundingRect3()
3435 QGraphicsScene scene;
3437 QGraphicsRectItem *rect = scene.addRect(QRectF(0, 0, 100, 100));
3438 QGraphicsRectItem *rect2 = scene.addRect(QRectF(0, 0, 100, 100));
3439 QGraphicsRectItem *rect3 = scene.addRect(QRectF(0, 0, 100, 100));
3440 QGraphicsRectItem *rect4 = scene.addRect(QRectF(0, 0, 100, 100));
3441 QGraphicsRectItem *rect5 = scene.addRect(QRectF(0, 0, 100, 100));
3442 rect2->setParentItem(rect);
3443 rect3->setParentItem(rect2);
3444 rect4->setParentItem(rect3);
3445 rect5->setParentItem(rect4);
3447 rect2->setTransform(QTransform().translate(50, 50).rotate(45));
3448 rect2->setPos(25, 25);
3449 rect3->setTransform(QTransform().translate(50, 50).rotate(45));
3450 rect3->setPos(25, 25);
3451 rect4->setTransform(QTransform().translate(50, 50).rotate(45));
3452 rect4->setPos(25, 25);
3453 rect5->setTransform(QTransform().translate(50, 50).rotate(45));
3454 rect5->setPos(25, 25);
3456 // Try to mess up the cached bounding rect.
3457 (void)rect2->childrenBoundingRect();
3459 QRectF subTreeRect = rect->childrenBoundingRect();
3460 QCOMPARE(subTreeRect.left(), qreal(-206.0660171779821));
3461 QCOMPARE(subTreeRect.top(), qreal(75.0));
3462 QCOMPARE(subTreeRect.width(), qreal(351.7766952966369));
3463 QCOMPARE(subTreeRect.height(), qreal(251.7766952966369));
3466 void tst_QGraphicsItem::childrenBoundingRect4()
3468 QGraphicsScene scene;
3470 QGraphicsRectItem *rect = scene.addRect(QRectF(0, 0, 10, 10));
3471 QGraphicsRectItem *rect2 = scene.addRect(QRectF(0, 0, 20, 20));
3472 QGraphicsRectItem *rect3 = scene.addRect(QRectF(0, 0, 30, 30));
3473 rect2->setParentItem(rect);
3474 rect3->setParentItem(rect);
3476 QGraphicsView view(&scene);
3479 QTest::qWaitForWindowShown(&view);
3481 // Try to mess up the cached bounding rect.
3482 rect->childrenBoundingRect();
3483 rect2->childrenBoundingRect();
3485 rect3->setOpacity(0.0);
3486 rect3->setParentItem(rect2);
3488 QCOMPARE(rect->childrenBoundingRect(), rect3->boundingRect());
3489 QCOMPARE(rect2->childrenBoundingRect(), rect3->boundingRect());
3492 void tst_QGraphicsItem::childrenBoundingRect5()
3494 QGraphicsScene scene;
3496 QGraphicsRectItem *parent = scene.addRect(QRectF(0, 0, 100, 100));
3497 QGraphicsRectItem *child = scene.addRect(QRectF(0, 0, 100, 100));
3498 child->setParentItem(parent);
3500 QGraphicsView view(&scene);
3503 QTest::qWaitForWindowShown(&view);
3505 // Try to mess up the cached bounding rect.
3506 QRectF expectedChildrenBoundingRect = parent->boundingRect();
3507 QCOMPARE(parent->childrenBoundingRect(), expectedChildrenBoundingRect);
3509 // Apply some effects.
3510 QGraphicsDropShadowEffect *dropShadow = new QGraphicsDropShadowEffect;
3511 dropShadow->setOffset(25, 25);
3512 child->setGraphicsEffect(dropShadow);
3513 parent->setGraphicsEffect(new QGraphicsOpacityEffect);
3515 QVERIFY(parent->childrenBoundingRect() != expectedChildrenBoundingRect);
3516 expectedChildrenBoundingRect |= dropShadow->boundingRect();
3517 QCOMPARE(parent->childrenBoundingRect(), expectedChildrenBoundingRect);
3520 void tst_QGraphicsItem::group()
3522 QGraphicsScene scene;
3523 QGraphicsRectItem *parent = scene.addRect(QRectF(0, 0, 50, 50), QPen(Qt::black, 0), QBrush(Qt::green));
3524 QGraphicsRectItem *child = scene.addRect(QRectF(0, 0, 50, 50), QPen(Qt::black, 0), QBrush(Qt::blue));
3525 QGraphicsRectItem *parent2 = scene.addRect(QRectF(0, 0, 50, 50), QPen(Qt::black, 0), QBrush(Qt::red));
3526 parent2->setPos(-50, 50);
3528 child->setParentItem(parent);
3529 parent->setPos(25, 25);
3530 child->setPos(25, 25);
3532 QCOMPARE(parent->group(), (QGraphicsItemGroup *)0);
3533 QCOMPARE(parent2->group(), (QGraphicsItemGroup *)0);
3534 QCOMPARE(child->group(), (QGraphicsItemGroup *)0);
3536 QGraphicsView view(&scene);
3538 QTest::qWaitForWindowShown(&view);
3539 QApplication::processEvents();
3541 QGraphicsItemGroup *group = new QGraphicsItemGroup;
3542 group->setSelected(true);
3543 scene.addItem(group);
3545 QRectF parentSceneBoundingRect = parent->sceneBoundingRect();
3546 group->addToGroup(parent);
3547 QCOMPARE(parent->group(), group);
3548 QCOMPARE(parent->sceneBoundingRect(), parentSceneBoundingRect);
3550 QCOMPARE(parent->parentItem(), (QGraphicsItem *)group);
3551 QCOMPARE(group->children().size(), 1);
3552 QCOMPARE(scene.items().size(), 4);
3553 QCOMPARE(scene.items(group->sceneBoundingRect()).size(), 3);
3557 QRectF parent2SceneBoundingRect = parent2->sceneBoundingRect();
3558 group->addToGroup(parent2);
3559 QCOMPARE(parent2->group(), group);
3560 QCOMPARE(parent2->sceneBoundingRect(), parent2SceneBoundingRect);
3562 QCOMPARE(parent2->parentItem(), (QGraphicsItem *)group);
3563 QCOMPARE(group->children().size(), 2);
3564 QCOMPARE(scene.items().size(), 4);
3565 QCOMPARE(scene.items(group->sceneBoundingRect()).size(), 4);
3569 QList<QGraphicsItem *> newItems;
3570 for (int i = 0; i < 100; ++i) {
3571 QGraphicsItem *item = scene.addRect(QRectF(-25, -25, 50, 50), QPen(Qt::black, 0),
3572 QBrush(QColor(rand() % 255, rand() % 255,
3573 rand() % 255, rand() % 255)));
3575 item->setPos(-1000 + rand() % 2000,
3576 -1000 + rand() % 2000);
3577 item->rotate(rand() % 90);
3580 view.fitInView(scene.itemsBoundingRect());
3583 foreach (QGraphicsItem *item, newItems) {
3584 group->addToGroup(item);
3585 QCOMPARE(item->group(), group);
3586 if ((n++ % 100) == 0)
3591 void tst_QGraphicsItem::setGroup()
3593 QGraphicsItemGroup group1;
3594 QGraphicsItemGroup group2;
3596 QGraphicsRectItem *rect = new QGraphicsRectItem;
3597 QCOMPARE(rect->group(), (QGraphicsItemGroup *)0);
3598 QCOMPARE(rect->parentItem(), (QGraphicsItem *)0);
3599 rect->setGroup(&group1);
3600 QCOMPARE(rect->group(), &group1);
3601 QCOMPARE(rect->parentItem(), (QGraphicsItem *)&group1);
3602 rect->setGroup(&group2);
3603 QCOMPARE(rect->group(), &group2);
3604 QCOMPARE(rect->parentItem(), (QGraphicsItem *)&group2);
3606 QCOMPARE(rect->group(), (QGraphicsItemGroup *)0);
3607 QCOMPARE(rect->parentItem(), (QGraphicsItem *)0);
3610 void tst_QGraphicsItem::setGroup2()
3612 QGraphicsScene scene;
3613 QGraphicsItemGroup group;
3614 scene.addItem(&group);
3616 QGraphicsRectItem *rect = scene.addRect(50,50,50,50,Qt::NoPen,Qt::black);
3617 rect->setTransformOriginPoint(50,50);
3618 rect->setRotation(45);
3619 rect->setScale(1.5);
3620 rect->translate(20,20);
3621 group.translate(-30,-40);
3622 group.setRotation(180);
3623 group.setScale(0.5);
3625 QTransform oldSceneTransform = rect->sceneTransform();
3626 rect->setGroup(&group);
3627 QCOMPARE(rect->sceneTransform(), oldSceneTransform);
3629 group.setRotation(20);
3631 rect->setRotation(90);
3632 rect->setScale(0.8);
3634 oldSceneTransform = rect->sceneTransform();
3636 QCOMPARE(rect->sceneTransform(), oldSceneTransform);
3639 void tst_QGraphicsItem::nestedGroups()
3641 QGraphicsItemGroup *group1 = new QGraphicsItemGroup;
3642 QGraphicsItemGroup *group2 = new QGraphicsItemGroup;
3644 QGraphicsRectItem *rect = new QGraphicsRectItem;
3645 QGraphicsRectItem *rect2 = new QGraphicsRectItem;
3646 rect2->setParentItem(rect);
3648 group1->addToGroup(rect);
3649 QCOMPARE(rect->group(), group1);
3650 QCOMPARE(rect2->group(), group1);
3652 group2->addToGroup(group1);
3653 QCOMPARE(rect->group(), group1);
3654 QCOMPARE(rect2->group(), group1);
3655 QCOMPARE(group1->group(), group2);
3656 QCOMPARE(group2->group(), (QGraphicsItemGroup *)0);
3658 QGraphicsScene scene;
3659 scene.addItem(group1);
3661 QCOMPARE(rect->group(), group1);
3662 QCOMPARE(rect2->group(), group1);
3663 QCOMPARE(group1->group(), (QGraphicsItemGroup *)0);
3664 QVERIFY(group2->children().isEmpty());
3669 void tst_QGraphicsItem::warpChildrenIntoGroup()
3671 QGraphicsScene scene;
3672 QGraphicsRectItem *parentRectItem = scene.addRect(QRectF(0, 0, 100, 100));
3673 QGraphicsRectItem *childRectItem = scene.addRect(QRectF(0, 0, 100, 100));
3674 parentRectItem->rotate(90);
3675 childRectItem->setPos(-50, -25);
3676 childRectItem->setParentItem(parentRectItem);
3678 QCOMPARE(childRectItem->mapToScene(50, 0), QPointF(25, 0));
3679 QCOMPARE(childRectItem->scenePos(), QPointF(25, -50));
3681 QGraphicsRectItem *parentOfGroup = scene.addRect(QRectF(0, 0, 100, 100));
3682 parentOfGroup->setPos(-200, -200);
3683 parentOfGroup->scale(2, 2);
3685 QGraphicsItemGroup *group = new QGraphicsItemGroup;
3686 group->setPos(50, 50);
3687 group->setParentItem(parentOfGroup);
3689 QCOMPARE(group->scenePos(), QPointF(-100, -100));
3691 group->addToGroup(childRectItem);
3693 QCOMPARE(childRectItem->mapToScene(50, 0), QPointF(25, 0));
3694 QCOMPARE(childRectItem->scenePos(), QPointF(25, -50));
3697 void tst_QGraphicsItem::removeFromGroup()
3699 QGraphicsScene scene;
3700 QGraphicsRectItem *rect1 = scene.addRect(QRectF(-100, -100, 200, 200));
3701 QGraphicsRectItem *rect2 = scene.addRect(QRectF(100, 100, 200, 200));
3702 rect1->setFlag(QGraphicsItem::ItemIsSelectable);
3703 rect2->setFlag(QGraphicsItem::ItemIsSelectable);
3704 rect1->setSelected(true);
3705 rect2->setSelected(true);
3707 QGraphicsView view(&scene);
3710 qApp->processEvents(); // index items
3711 qApp->processEvents(); // emit changed
3713 QGraphicsItemGroup *group = scene.createItemGroup(scene.selectedItems());
3715 QCOMPARE(group->children().size(), 2);
3716 qApp->processEvents(); // index items
3717 qApp->processEvents(); // emit changed
3719 scene.destroyItemGroup(group); // calls removeFromGroup.
3721 qApp->processEvents(); // index items
3722 qApp->processEvents(); // emit changed
3724 QCOMPARE(scene.items().size(), 2);
3725 QVERIFY(!rect1->group());
3726 QVERIFY(!rect2->group());
3729 class ChildEventTester : public QGraphicsRectItem
3732 ChildEventTester(const QRectF &rect, QGraphicsItem *parent = 0)
3733 : QGraphicsRectItem(rect, parent), counter(0)
3739 void focusInEvent(QFocusEvent *event)
3740 { ++counter; QGraphicsRectItem::focusInEvent(event); }
3741 void mousePressEvent(QGraphicsSceneMouseEvent *)
3743 void mouseMoveEvent(QGraphicsSceneMouseEvent *)
3745 void mouseReleaseEvent(QGraphicsSceneMouseEvent *)
3749 void tst_QGraphicsItem::handlesChildEvents()
3751 ChildEventTester *blue = new ChildEventTester(QRectF(0, 0, 100, 100));
3752 ChildEventTester *red = new ChildEventTester(QRectF(0, 0, 50, 50));
3753 ChildEventTester *green = new ChildEventTester(QRectF(0, 0, 25, 25));
3754 ChildEventTester *gray = new ChildEventTester(QRectF(0, 0, 25, 25));
3755 ChildEventTester *yellow = new ChildEventTester(QRectF(0, 0, 50, 50));
3757 blue->setBrush(QBrush(Qt::blue));
3758 red->setBrush(QBrush(Qt::red));
3759 yellow->setBrush(QBrush(Qt::yellow));
3760 green->setBrush(QBrush(Qt::green));
3761 gray->setBrush(QBrush(Qt::gray));
3763 yellow->setPos(50, 50);
3764 green->setPos(25, 0);
3765 gray->setPos(25, 25);
3766 red->setParentItem(blue);
3767 yellow->setParentItem(blue);
3768 green->setParentItem(red);
3769 gray->setParentItem(red);
3771 QGraphicsScene scene;
3772 scene.addItem(blue);
3774 QGraphicsView view(&scene);
3776 QTest::qWaitForWindowShown(&view);
3779 // Pull out the items, closest item first
3780 QList<QGraphicsItem *> items = scene.items(scene.itemsBoundingRect());
3781 QCOMPARE(items.at(0), (QGraphicsItem *)yellow);
3782 QCOMPARE(items.at(1), (QGraphicsItem *)gray);
3783 QCOMPARE(items.at(2), (QGraphicsItem *)green);
3784 QCOMPARE(items.at(3), (QGraphicsItem *)red);
3785 QCOMPARE(items.at(4), (QGraphicsItem *)blue);
3787 QCOMPARE(blue->counter, 0);
3789 // Send events to the toplevel item
3790 QGraphicsSceneMouseEvent pressEvent(QEvent::GraphicsSceneMousePress);
3791 QGraphicsSceneMouseEvent releaseEvent(QEvent::GraphicsSceneMouseRelease);
3793 pressEvent.setButton(Qt::LeftButton);
3794 pressEvent.setScenePos(blue->mapToScene(5, 5));
3795 pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
3796 releaseEvent.setButton(Qt::LeftButton);
3797 releaseEvent.setScenePos(blue->mapToScene(5, 5));
3798 releaseEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
3799 QApplication::sendEvent(&scene, &pressEvent);
3800 QApplication::sendEvent(&scene, &releaseEvent);
3802 QCOMPARE(blue->counter, 2);
3804 // Send events to a level1 item
3805 pressEvent.setScenePos(red->mapToScene(5, 5));
3806 pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
3807 releaseEvent.setScenePos(red->mapToScene(5, 5));
3808 releaseEvent.setScreenPos(view.mapFromScene(releaseEvent.scenePos()));
3809 QApplication::sendEvent(&scene, &pressEvent);
3810 QApplication::sendEvent(&scene, &releaseEvent);
3812 QCOMPARE(blue->counter, 2);
3813 QCOMPARE(red->counter, 2);
3815 // Send events to a level2 item
3816 pressEvent.setScenePos(green->mapToScene(5, 5));
3817 pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
3818 releaseEvent.setScenePos(green->mapToScene(5, 5));
3819 releaseEvent.setScreenPos(view.mapFromScene(releaseEvent.scenePos()));
3820 QApplication::sendEvent(&scene, &pressEvent);
3821 QApplication::sendEvent(&scene, &releaseEvent);
3823 QCOMPARE(blue->counter, 2);
3824 QCOMPARE(red->counter, 2);
3825 QCOMPARE(green->counter, 2);
3827 blue->setHandlesChildEvents(true);
3829 // Send events to a level1 item
3830 pressEvent.setScenePos(red->mapToScene(5, 5));
3831 pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
3832 releaseEvent.setScenePos(red->mapToScene(5, 5));
3833 releaseEvent.setScreenPos(view.mapFromScene(releaseEvent.scenePos()));
3834 QApplication::sendEvent(&scene, &pressEvent);
3835 QApplication::sendEvent(&scene, &releaseEvent);
3837 QCOMPARE(blue->counter, 4);
3838 QCOMPARE(red->counter, 2);
3840 // Send events to a level2 item
3841 pressEvent.setScenePos(green->mapToScene(5, 5));
3842 pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
3843 releaseEvent.setScenePos(green->mapToScene(5, 5));
3844 releaseEvent.setScreenPos(view.mapFromScene(releaseEvent.scenePos()));
3845 QApplication::sendEvent(&scene, &pressEvent);
3846 QApplication::sendEvent(&scene, &releaseEvent);
3848 QCOMPARE(blue->counter, 6);
3849 QCOMPARE(red->counter, 2);
3850 QCOMPARE(green->counter, 2);
3852 blue->setHandlesChildEvents(false);
3854 // Send events to a level1 item
3855 pressEvent.setScenePos(red->mapToScene(5, 5));
3856 pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
3857 releaseEvent.setScenePos(red->mapToScene(5, 5));
3858 releaseEvent.setScreenPos(view.mapFromScene(releaseEvent.scenePos()));
3859 QApplication::sendEvent(&scene, &pressEvent);
3860 QApplication::sendEvent(&scene, &releaseEvent);
3862 QCOMPARE(blue->counter, 6);
3863 QCOMPARE(red->counter, 4);
3865 // Send events to a level2 item
3866 pressEvent.setScenePos(green->mapToScene(5, 5));
3867 pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
3868 releaseEvent.setScenePos(green->mapToScene(5, 5));
3869 releaseEvent.setScreenPos(view.mapFromScene(releaseEvent.scenePos()));
3870 QApplication::sendEvent(&scene, &pressEvent);
3871 QApplication::sendEvent(&scene, &releaseEvent);
3873 QCOMPARE(blue->counter, 6);
3874 QCOMPARE(red->counter, 4);
3875 QCOMPARE(green->counter, 4);
3878 void tst_QGraphicsItem::handlesChildEvents2()
3880 ChildEventTester *root = new ChildEventTester(QRectF(0, 0, 10, 10));
3881 root->setHandlesChildEvents(true);
3882 QVERIFY(root->handlesChildEvents());
3884 ChildEventTester *child = new ChildEventTester(QRectF(0, 0, 10, 10), root);
3885 QVERIFY(!child->handlesChildEvents());
3887 ChildEventTester *child2 = new ChildEventTester(QRectF(0, 0, 10, 10));
3888 ChildEventTester *child3 = new ChildEventTester(QRectF(0, 0, 10, 10), child2);
3889 ChildEventTester *child4 = new ChildEventTester(QRectF(0, 0, 10, 10), child3);
3890 child2->setParentItem(root);
3891 QVERIFY(!child2->handlesChildEvents());
3892 QVERIFY(!child3->handlesChildEvents());
3893 QVERIFY(!child4->handlesChildEvents());
3895 QGraphicsScene scene;
3896 scene.addItem(root);
3898 QGraphicsView view(&scene);
3900 QTest::qWaitForWindowShown(&view);
3901 QApplication::processEvents();
3903 QMouseEvent event(QEvent::MouseButtonPress, view.mapFromScene(5, 5),
3904 view.viewport()->mapToGlobal(view.mapFromScene(5, 5)), Qt::LeftButton, 0, 0);
3905 QApplication::sendEvent(view.viewport(), &event);
3907 QTRY_COMPARE(root->counter, 1);
3910 void tst_QGraphicsItem::handlesChildEvents3()
3912 QGraphicsScene scene;
3913 QEvent activate(QEvent::WindowActivate);
3914 QApplication::sendEvent(&scene, &activate);
3916 ChildEventTester *group2 = new ChildEventTester(QRectF(), 0);
3917 ChildEventTester *group1 = new ChildEventTester(QRectF(), group2);
3918 ChildEventTester *leaf = new ChildEventTester(QRectF(), group1);
3919 scene.addItem(group2);
3921 leaf->setFlag(QGraphicsItem::ItemIsFocusable);
3922 group1->setFlag(QGraphicsItem::ItemIsFocusable);
3923 group1->setHandlesChildEvents(true);
3924 group2->setFlag(QGraphicsItem::ItemIsFocusable);
3925 group2->setHandlesChildEvents(true);
3928 QVERIFY(leaf->hasFocus()); // group2 stole the event, but leaf still got focus
3929 QVERIFY(!group1->hasFocus());
3930 QVERIFY(!group2->hasFocus());
3931 QCOMPARE(leaf->counter, 0);
3932 QCOMPARE(group1->counter, 0);
3933 QCOMPARE(group2->counter, 1);
3936 QVERIFY(group1->hasFocus()); // group2 stole the event, but group1 still got focus
3937 QVERIFY(!leaf->hasFocus());
3938 QVERIFY(!group2->hasFocus());
3939 QCOMPARE(leaf->counter, 0);
3940 QCOMPARE(group1->counter, 0);
3941 QCOMPARE(group2->counter, 2);
3944 QVERIFY(group2->hasFocus()); // group2 stole the event, and now group2 also has focus
3945 QVERIFY(!leaf->hasFocus());
3946 QVERIFY(!group1->hasFocus());
3947 QCOMPARE(leaf->counter, 0);
3948 QCOMPARE(group1->counter, 0);
3949 QCOMPARE(group2->counter, 3);
3953 class ChildEventFilterTester : public ChildEventTester
3956 ChildEventFilterTester(const QRectF &rect, QGraphicsItem *parent = 0)
3957 : ChildEventTester(rect, parent), filter(QEvent::None)
3960 QEvent::Type filter;
3963 bool sceneEventFilter(QGraphicsItem *item, QEvent *event)
3966 if (event->type() == filter) {
3974 void tst_QGraphicsItem::filtersChildEvents()
3976 QGraphicsScene scene;
3977 ChildEventFilterTester *root = new ChildEventFilterTester(QRectF(0, 0, 10, 10));
3978 ChildEventFilterTester *filter = new ChildEventFilterTester(QRectF(10, 10, 10, 10), root);
3979 ChildEventTester *child = new ChildEventTester(QRectF(20, 20, 10, 10), filter);
3982 filter->setFiltersChildEvents(true);
3983 filter->filter = QEvent::GraphicsSceneMousePress;
3985 scene.addItem(root);
3987 QGraphicsView view(&scene);
3989 QTest::qWaitForWindowShown(&view);
3992 QGraphicsSceneMouseEvent pressEvent(QEvent::GraphicsSceneMousePress);
3993 QGraphicsSceneMouseEvent releaseEvent(QEvent::GraphicsSceneMouseRelease);
3995 // send event to child
3996 pressEvent.setButton(Qt::LeftButton);
3997 pressEvent.setScenePos(QPointF(25, 25));//child->mapToScene(5, 5));
3998 pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
3999 releaseEvent.setButton(Qt::LeftButton);
4000 releaseEvent.setScenePos(QPointF(25, 25));//child->mapToScene(5, 5));
4001 releaseEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
4002 QApplication::sendEvent(&scene, &pressEvent);
4003 QApplication::sendEvent(&scene, &releaseEvent);
4005 QTRY_COMPARE(child->counter, 1); // mouse release is not filtered
4006 QCOMPARE(filter->counter, 1); // mouse press is filtered
4007 QCOMPARE(root->counter, 0);
4009 // add another filter
4010 root->setFiltersChildEvents(true);
4011 root->filter = QEvent::GraphicsSceneMouseRelease;
4013 // send event to child
4014 QApplication::sendEvent(&scene, &pressEvent);
4015 QApplication::sendEvent(&scene, &releaseEvent);
4017 QCOMPARE(child->counter, 1);
4018 QCOMPARE(filter->counter, 2); // mouse press is filtered
4019 QCOMPARE(root->counter, 1); // mouse release is filtered
4021 // reparent to another sub-graph
4022 ChildEventTester *parent = new ChildEventTester(QRectF(10, 10, 10, 10), root);
4023 child->setParentItem(parent);
4025 // send event to child
4026 QApplication::sendEvent(&scene, &pressEvent);
4027 QApplication::sendEvent(&scene, &releaseEvent);
4029 QCOMPARE(child->counter, 2); // mouse press is _not_ filtered
4030 QCOMPARE(parent->counter, 0);
4031 QCOMPARE(filter->counter, 2);
4032 QCOMPARE(root->counter, 2); // mouse release is filtered
4035 void tst_QGraphicsItem::filtersChildEvents2()
4037 ChildEventFilterTester *root = new ChildEventFilterTester(QRectF(0, 0, 10, 10));
4038 root->setFiltersChildEvents(true);
4039 root->filter = QEvent::GraphicsSceneMousePress;
4040 QVERIFY(root->filtersChildEvents());
4042 ChildEventTester *child = new ChildEventTester(QRectF(0, 0, 10, 10), root);
4043 QVERIFY(!child->filtersChildEvents());
4045 ChildEventTester *child2 = new ChildEventTester(QRectF(0, 0, 10, 10));
4046 ChildEventTester *child3 = new ChildEventTester(QRectF(0, 0, 10, 10), child2);
4047 ChildEventTester *child4 = new ChildEventTester(QRectF(0, 0, 10, 10), child3);
4049 child2->setParentItem(root);
4050 QVERIFY(!child2->filtersChildEvents());
4051 QVERIFY(!child3->filtersChildEvents());
4052 QVERIFY(!child4->filtersChildEvents());
4054 QGraphicsScene scene;
4055 scene.addItem(root);
4057 QGraphicsView view(&scene);
4060 QTest::qWaitForWindowShown(&view);
4061 QApplication::processEvents();
4063 QMouseEvent event(QEvent::MouseButtonPress, view.mapFromScene(5, 5),
4064 view.viewport()->mapToGlobal(view.mapFromScene(5, 5)), Qt::LeftButton, 0, 0);
4065 QApplication::sendEvent(view.viewport(), &event);
4067 QTRY_COMPARE(root->counter, 1);
4068 QCOMPARE(child->counter, 0);
4069 QCOMPARE(child2->counter, 0);
4070 QCOMPARE(child3->counter, 0);
4071 QCOMPARE(child4->counter, 0);
4074 class CustomItem : public QGraphicsItem
4077 QRectF boundingRect() const
4078 { return QRectF(-110, -110, 220, 220); }
4080 void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
4082 for (int x = -100; x <= 100; x += 25)
4083 painter->drawLine(x, -100, x, 100);
4084 for (int y = -100; y <= 100; y += 25)
4085 painter->drawLine(-100, y, 100, y);
4087 QFont font = painter->font();
4088 font.setPointSize(4);
4089 painter->setFont(font);
4090 for (int x = -100; x < 100; x += 25) {
4091 for (int y = -100; y < 100; y += 25) {
4092 painter->drawText(QRectF(x, y, 25, 25), Qt::AlignCenter, QString("%1x%2").arg(x).arg(y));
4098 void tst_QGraphicsItem::ensureVisible()
4100 QGraphicsScene scene;
4101 scene.setSceneRect(-200, -200, 400, 400);
4102 QGraphicsItem *item = new CustomItem;
4103 scene.addItem(item);
4105 QGraphicsView view(&scene);
4106 view.setFixedSize(300, 300);
4108 QTest::qWaitForWindowShown(&view);
4110 for (int i = 0; i < 25; ++i) {
4111 view.scale(qreal(1.06), qreal(1.06));
4112 QApplication::processEvents();
4115 item->ensureVisible(-100, -100, 25, 25);
4118 for (int x = -100; x < 100; x += 25) {
4119 for (int y = -100; y < 100; y += 25) {
4120 int xmargin = rand() % 75;
4121 int ymargin = rand() % 75;
4122 item->ensureVisible(x, y, 25, 25, xmargin, ymargin);
4123 QApplication::processEvents();
4125 QPolygonF viewScenePoly;
4126 viewScenePoly << view.mapToScene(view.rect().topLeft())
4127 << view.mapToScene(view.rect().topRight())
4128 << view.mapToScene(view.rect().bottomRight())
4129 << view.mapToScene(view.rect().bottomLeft());
4131 QVERIFY(scene.items(viewScenePoly).contains(item));
4134 path.addPolygon(viewScenePoly);
4135 QVERIFY(path.contains(item->mapToScene(x + 12, y + 12)));
4137 QPolygonF viewScenePolyMinusMargins;
4138 viewScenePolyMinusMargins << view.mapToScene(view.rect().topLeft() + QPoint(xmargin, ymargin))
4139 << view.mapToScene(view.rect().topRight() + QPoint(-xmargin, ymargin))
4140 << view.mapToScene(view.rect().bottomRight() + QPoint(-xmargin, -ymargin))
4141 << view.mapToScene(view.rect().bottomLeft() + QPoint(xmargin, -ymargin));
4144 path2.addPolygon(viewScenePolyMinusMargins);
4145 QVERIFY(path2.contains(item->mapToScene(x + 12, y + 12)));
4149 item->ensureVisible(100, 100, 25, 25);
4153 void tst_QGraphicsItem::cursor()
4155 #ifndef QT_NO_CURSOR
4156 QGraphicsScene scene;
4157 QGraphicsRectItem *item1 = scene.addRect(QRectF(0, 0, 50, 50));
4158 QGraphicsRectItem *item2 = scene.addRect(QRectF(0, 0, 50, 50));
4159 item1->setPos(-100, 0);
4160 item2->setPos(50, 0);
4162 QVERIFY(!item1->hasCursor());
4163 QVERIFY(!item2->hasCursor());
4165 item1->setCursor(Qt::IBeamCursor);
4166 item2->setCursor(Qt::PointingHandCursor);
4168 QVERIFY(item1->hasCursor());
4169 QVERIFY(item2->hasCursor());
4171 item1->setCursor(QCursor());
4172 item2->setCursor(QCursor());
4174 QVERIFY(item1->hasCursor());
4175 QVERIFY(item2->hasCursor());
4177 item1->unsetCursor();
4178 item2->unsetCursor();
4180 QVERIFY(!item1->hasCursor());
4181 QVERIFY(!item2->hasCursor());
4183 item1->setCursor(Qt::IBeamCursor);
4184 item2->setCursor(Qt::PointingHandCursor);
4187 QGraphicsView view(&scene,&topLevel);
4188 view.setFixedSize(200, 100);
4190 QTest::mouseMove(&view, view.rect().center());
4194 QCursor cursor = view.viewport()->cursor();
4197 QMouseEvent event(QEvent::MouseMove, QPoint(100, 50), Qt::NoButton, 0, 0);
4198 QApplication::sendEvent(view.viewport(), &event);
4203 QCOMPARE(view.viewport()->cursor().shape(), cursor.shape());
4206 QTest::mouseMove(view.viewport(), view.mapFromScene(item1->sceneBoundingRect().center()));
4207 QMouseEvent event(QEvent::MouseMove, view.mapFromScene(item1->sceneBoundingRect().center()), Qt::NoButton, 0, 0);
4208 QApplication::sendEvent(view.viewport(), &event);
4211 if (!PlatformQuirks::haveMouseCursor())
4213 #if !defined(Q_OS_WINCE)
4216 // Test environment does not have any cursor, therefore no shape
4220 QCOMPARE(view.viewport()->cursor().shape(), item1->cursor().shape());
4223 QTest::mouseMove(view.viewport(), view.mapFromScene(item2->sceneBoundingRect().center()));
4224 QMouseEvent event(QEvent::MouseMove, view.mapFromScene(item2->sceneBoundingRect().center()), Qt::NoButton, 0, 0);
4225 QApplication::sendEvent(view.viewport(), &event);
4230 QCOMPARE(view.viewport()->cursor().shape(), item2->cursor().shape());
4233 QTest::mouseMove(view.viewport(), view.rect().center());
4234 QMouseEvent event(QEvent::MouseMove, QPoint(100, 25), Qt::NoButton, 0, 0);
4235 QApplication::sendEvent(view.viewport(), &event);
4240 QCOMPARE(view.viewport()->cursor().shape(), cursor.shape());
4244 void tst_QGraphicsItem::textControlGetterSetter()
4246 QGraphicsTextItem *item = new QGraphicsTextItem;
4247 QVERIFY(item->textControl()->parent() == item);
4248 QPointer<QTextControl> control = item->textControl();
4252 item = new QGraphicsTextItem;
4254 QPointer<QTextControl> oldControl = control;
4255 control = new QTextControl;
4257 item->setTextControl(control);
4258 QVERIFY(item->textControl() == control);
4259 QVERIFY(!control->parent());
4260 QVERIFY(!oldControl);
4262 // set some text to give it a size, to test that
4263 // setTextControl (re)connects signals
4264 const QRectF oldBoundingRect = item->boundingRect();
4265 QVERIFY(oldBoundingRect.isValid());
4266 item->setPlainText("Some text");
4268 QVERIFY(item->boundingRect().isValid());
4269 QVERIFY(item->boundingRect() != oldBoundingRect);
4271 // test that on setting a control the item size
4273 oldControl = control;
4274 control = new QTextControl;
4275 control->setPlainText("foo!");
4276 item->setTextControl(control);
4277 QCOMPARE(item->boundingRect().size(), control->document()->documentLayout()->documentSize());
4279 QVERIFY(oldControl);
4288 void tst_QGraphicsItem::defaultItemTest_QGraphicsLineItem()
4290 QGraphicsLineItem item;
4291 QCOMPARE(item.line(), QLineF());
4292 QCOMPARE(item.pen(), QPen());
4293 QCOMPARE(item.shape(), QPainterPath());
4295 item.setPen(QPen(Qt::black, 1));
4296 QCOMPARE(item.pen(), QPen(Qt::black, 1));
4297 item.setLine(QLineF(0, 0, 10, 0));
4298 QCOMPARE(item.line(), QLineF(0, 0, 10, 0));
4299 QCOMPARE(item.boundingRect(), QRectF(-0.5, -0.5, 11, 1));
4300 QCOMPARE(item.shape().elementCount(), 11);
4303 path.moveTo(0, -0.5);
4304 path.lineTo(10, -0.5);
4305 path.lineTo(10.5, -0.5);
4306 path.lineTo(10.5, 0.5);
4307 path.lineTo(10, 0.5);
4308 path.lineTo(0, 0.5);
4309 path.lineTo(-0.5, 0.5);
4310 path.lineTo(-0.5, -0.5);
4311 path.lineTo(0, -0.5);
4314 path.closeSubpath();
4316 for (int i = 0; i < 11; ++i)
4317 QCOMPARE(QPointF(item.shape().elementAt(i)), QPointF(path.elementAt(i)));
4320 void tst_QGraphicsItem::defaultItemTest_QGraphicsPixmapItem()
4322 QGraphicsPixmapItem item;
4323 QVERIFY(item.pixmap().isNull());
4324 QCOMPARE(item.offset(), QPointF());
4325 QCOMPARE(item.transformationMode(), Qt::FastTransformation);
4327 QPixmap pixmap(300, 200);
4328 pixmap.fill(Qt::red);
4329 item.setPixmap(pixmap);
4330 QCOMPARE(item.pixmap(), pixmap);
4332 item.setTransformationMode(Qt::FastTransformation);
4333 QCOMPARE(item.transformationMode(), Qt::FastTransformation);
4334 item.setTransformationMode(Qt::SmoothTransformation);
4335 QCOMPARE(item.transformationMode(), Qt::SmoothTransformation);
4337 item.setOffset(-15, -15);
4338 QCOMPARE(item.offset(), QPointF(-15, -15));
4339 item.setOffset(QPointF(-10, -10));
4340 QCOMPARE(item.offset(), QPointF(-10, -10));
4342 QCOMPARE(item.boundingRect(), QRectF(-10, -10, 300, 200));
4345 void tst_QGraphicsItem::defaultItemTest_QGraphicsTextItem()
4347 QGraphicsTextItem *text = new QGraphicsTextItem;
4348 QVERIFY(!text->openExternalLinks());
4349 QVERIFY(text->textCursor().isNull());
4350 QCOMPARE(text->defaultTextColor(), QPalette().color(QPalette::Text));
4351 QVERIFY(text->document() != 0);
4352 QCOMPARE(text->font(), QApplication::font());
4353 QCOMPARE(text->textInteractionFlags(), Qt::TextInteractionFlags(Qt::NoTextInteraction));
4354 QCOMPARE(text->textWidth(), -1.0);
4355 QCOMPARE(text->toPlainText(), QString(""));
4357 QGraphicsScene scene;
4358 scene.addItem(text);
4359 text->setPlainText("Hello world");
4360 text->setFlag(QGraphicsItem::ItemIsMovable);
4363 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
4364 event.setScenePos(QPointF(1, 1));
4365 event.setButton(Qt::LeftButton);
4366 event.setButtons(Qt::LeftButton);
4367 QApplication::sendEvent(&scene, &event);
4368 QGraphicsSceneMouseEvent event2(QEvent::GraphicsSceneMouseMove);
4369 event2.setScenePos(QPointF(11, 11));
4370 event2.setButton(Qt::LeftButton);
4371 event2.setButtons(Qt::LeftButton);
4372 QApplication::sendEvent(&scene, &event2);
4375 QCOMPARE(text->pos(), QPointF(10, 10));
4377 text->setTextInteractionFlags(Qt::NoTextInteraction);
4378 QVERIFY(!(text->flags() & QGraphicsItem::ItemAcceptsInputMethod));
4379 text->setTextInteractionFlags(Qt::TextEditorInteraction);
4380 QCOMPARE(text->textInteractionFlags(), Qt::TextInteractionFlags(Qt::TextEditorInteraction));
4381 QVERIFY(text->flags() & QGraphicsItem::ItemAcceptsInputMethod);
4384 QGraphicsSceneMouseEvent event2(QEvent::GraphicsSceneMouseMove);
4385 event2.setScenePos(QPointF(21, 21));
4386 event2.setButton(Qt::LeftButton);
4387 event2.setButtons(Qt::LeftButton);
4388 QApplication::sendEvent(&scene, &event2);
4391 QCOMPARE(text->pos(), QPointF(20, 20)); // clicked on edge, item moved
4394 void tst_QGraphicsItem::defaultItemTest_QGraphicsEllipseItem()
4396 QGraphicsEllipseItem item;
4397 QVERIFY(item.rect().isNull());
4398 QVERIFY(item.boundingRect().isNull());
4399 QVERIFY(item.shape().isEmpty());
4400 QCOMPARE(item.spanAngle(), 360 * 16);
4401 QCOMPARE(item.startAngle(), 0);
4403 item.setRect(0, 0, 100, 100);
4404 QCOMPARE(item.boundingRect(), QRectF(0, 0, 100, 100));
4406 item.setSpanAngle(90 * 16);
4407 qFuzzyCompare(item.boundingRect().left(), qreal(50.0));
4408 qFuzzyCompare(item.boundingRect().top(), qreal(0.0));
4409 qFuzzyCompare(item.boundingRect().width(), qreal(50.0));
4410 qFuzzyCompare(item.boundingRect().height(), qreal(50.0));
4412 item.setPen(QPen(Qt::black, 1));
4413 QCOMPARE(item.boundingRect(), QRectF(49.5, -0.5, 51, 51));
4415 item.setSpanAngle(180 * 16);
4416 QCOMPARE(item.boundingRect(), QRectF(-0.5, -0.5, 101, 51));
4418 item.setSpanAngle(360 * 16);
4419 QCOMPARE(item.boundingRect(), QRectF(-0.5, -0.5, 101, 101));
4422 class ItemChangeTester : public QGraphicsRectItem
4426 { setFlag(ItemSendsGeometryChanges); clear(); }
4427 ItemChangeTester(QGraphicsItem *parent) : QGraphicsRectItem(parent)
4428 { setFlag(ItemSendsGeometryChanges); clear(); }
4432 itemChangeReturnValue = QVariant();
4433 itemSceneChangeTargetScene = 0;
4439 QVariant itemChangeReturnValue;
4440 QGraphicsScene *itemSceneChangeTargetScene;
4442 QList<GraphicsItemChange> changes;
4443 QList<QVariant> values;
4444 QList<QVariant> oldValues;
4446 QVariant itemChange(GraphicsItemChange change, const QVariant &value)
4451 case QGraphicsItem::ItemPositionChange:
4454 case QGraphicsItem::ItemPositionHasChanged:
4456 case QGraphicsItem::ItemMatrixChange: {
4458 qVariantSetValue<QMatrix>(variant, matrix());
4459 oldValues << variant;
4462 case QGraphicsItem::ItemTransformChange: {
4464 qVariantSetValue<QTransform>(variant, transform());
4465 oldValues << variant;
4468 case QGraphicsItem::ItemTransformHasChanged:
4470 case QGraphicsItem::ItemVisibleChange:
4471 oldValues << isVisible();
4473 case QGraphicsItem::ItemVisibleHasChanged:
4475 case QGraphicsItem::ItemEnabledChange:
4476 oldValues << isEnabled();
4478 case QGraphicsItem::ItemEnabledHasChanged:
4480 case QGraphicsItem::ItemSelectedChange:
4481 oldValues << isSelected();
4483 case QGraphicsItem::ItemSelectedHasChanged:
4485 case QGraphicsItem::ItemParentChange:
4486 oldValues << qVariantFromValue<void *>(parentItem());
4488 case QGraphicsItem::ItemParentHasChanged:
4490 case QGraphicsItem::ItemChildAddedChange:
4491 oldValues << children().size();
4493 case QGraphicsItem::ItemChildRemovedChange:
4494 oldValues << children().size();
4496 case QGraphicsItem::ItemSceneChange:
4497 oldValues << qVariantFromValue<QGraphicsScene *>(scene());
4498 if (itemSceneChangeTargetScene
4499 && qVariantValue<QGraphicsScene *>(value)
4500 && itemSceneChangeTargetScene != qVariantValue<QGraphicsScene *>(value)) {
4501 return qVariantFromValue<QGraphicsScene *>(itemSceneChangeTargetScene);
4504 case QGraphicsItem::ItemSceneHasChanged:
4506 case QGraphicsItem::ItemCursorChange:
4507 #ifndef QT_NO_CURSOR
4508 oldValues << cursor();
4511 case QGraphicsItem::ItemCursorHasChanged:
4513 case QGraphicsItem::ItemToolTipChange:
4514 oldValues << toolTip();
4516 case QGraphicsItem::ItemToolTipHasChanged:
4518 case QGraphicsItem::ItemFlagsChange:
4519 oldValues << quint32(flags());
4521 case QGraphicsItem::ItemFlagsHaveChanged:
4523 case QGraphicsItem::ItemZValueChange:
4524 oldValues << zValue();
4526 case QGraphicsItem::ItemZValueHasChanged:
4528 case QGraphicsItem::ItemOpacityChange:
4529 oldValues << opacity();
4531 case QGraphicsItem::ItemOpacityHasChanged:
4533 case QGraphicsItem::ItemScenePositionHasChanged:
4535 case QGraphicsItem::ItemRotationChange:
4536 oldValues << rotation();
4538 case QGraphicsItem::ItemRotationHasChanged:
4540 case QGraphicsItem::ItemScaleChange:
4541 oldValues << scale();
4543 case QGraphicsItem::ItemScaleHasChanged:
4545 case QGraphicsItem::ItemTransformOriginPointChange:
4546 oldValues << transformOriginPoint();
4548 case QGraphicsItem::ItemTransformOriginPointHasChanged:
4551 return itemChangeReturnValue.isValid() ? itemChangeReturnValue : value;
4555 void tst_QGraphicsItem::itemChange()
4557 ItemChangeTester tester;
4558 tester.itemSceneChangeTargetScene = 0;
4560 ItemChangeTester testerHelper;
4561 QVERIFY(tester.changes.isEmpty());
4562 QVERIFY(tester.values.isEmpty());
4564 int changeCount = 0;
4566 // ItemEnabledChange
4567 tester.itemChangeReturnValue = true;
4568 tester.setEnabled(false);
4570 ++changeCount; // HasChanged
4571 QCOMPARE(tester.changes.size(), changeCount);
4572 QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemEnabledChange);
4573 QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemEnabledHasChanged);
4574 QCOMPARE(tester.values.at(tester.values.size() - 2), QVariant(false));
4575 QCOMPARE(tester.values.at(tester.values.size() - 1), QVariant(true));
4576 QCOMPARE(tester.oldValues.last(), QVariant(true));
4577 QCOMPARE(tester.isEnabled(), true);
4580 // ItemMatrixChange / ItemTransformHasChanged
4581 qVariantSetValue<QMatrix>(tester.itemChangeReturnValue, QMatrix().rotate(90));
4582 tester.setMatrix(QMatrix().translate(50, 0), true);
4583 ++changeCount; // notification sent too
4584 QCOMPARE(tester.changes.size(), ++changeCount);
4585 QCOMPARE(int(tester.changes.at(tester.changes.size() - 2)), int(QGraphicsItem::ItemMatrixChange));
4586 QCOMPARE(int(tester.changes.last()), int(QGraphicsItem::ItemTransformHasChanged));
4587 QCOMPARE(qVariantValue<QMatrix>(tester.values.at(tester.values.size() - 2)),
4588 QMatrix().translate(50, 0));
4589 QCOMPARE(tester.values.last(), QVariant(QTransform(QMatrix().rotate(90))));
4591 qVariantSetValue<QMatrix>(variant, QMatrix());
4592 QCOMPARE(tester.oldValues.last(), variant);
4593 QCOMPARE(tester.matrix(), QMatrix().rotate(90));
4596 tester.resetTransform();
4598 ++changeCount; // notification sent too
4600 // ItemTransformChange / ItemTransformHasChanged
4601 qVariantSetValue<QTransform>(tester.itemChangeReturnValue, QTransform().rotate(90));
4602 tester.translate(50, 0);
4603 ++changeCount; // notification sent too
4605 QCOMPARE(tester.changes.size(), changeCount);
4606 QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemTransformChange);
4607 QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemTransformHasChanged);
4608 QCOMPARE(qVariantValue<QTransform>(tester.values.at(tester.values.size() - 2)),
4609 QTransform().translate(50, 0));
4610 QCOMPARE(qVariantValue<QTransform>(tester.values.at(tester.values.size() - 1)),
4611 QTransform().rotate(90));
4613 qVariantSetValue<QTransform>(variant, QTransform());
4614 QCOMPARE(tester.oldValues.last(), variant);
4615 QCOMPARE(tester.transform(), QTransform().rotate(90));
4618 // ItemPositionChange / ItemPositionHasChanged
4619 tester.itemChangeReturnValue = QPointF(42, 0);
4620 tester.setPos(0, 42);
4621 ++changeCount; // notification sent too
4623 QCOMPARE(tester.changes.size(), changeCount);
4624 QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemPositionChange);
4625 QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemPositionHasChanged);
4626 QCOMPARE(tester.values.at(tester.changes.size() - 2), QVariant(QPointF(0, 42)));
4627 QCOMPARE(tester.values.at(tester.changes.size() - 1), QVariant(QPointF(42, 0)));
4628 QCOMPARE(tester.oldValues.last(), QVariant(QPointF()));
4629 QCOMPARE(tester.pos(), QPointF(42, 0));
4632 // ItemZValueChange / ItemZValueHasChanged
4633 tester.itemChangeReturnValue = qreal(2.0);
4634 tester.setZValue(1.0);
4635 ++changeCount; // notification sent too
4637 QCOMPARE(tester.changes.size(), changeCount);
4638 QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemZValueChange);
4639 QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemZValueHasChanged);
4640 QCOMPARE(tester.values.at(tester.changes.size() - 2), QVariant(qreal(1.0)));
4641 QCOMPARE(tester.values.at(tester.changes.size() - 1), QVariant(qreal(2.0)));
4642 QCOMPARE(tester.oldValues.last(), QVariant(qreal(0.0)));
4643 QCOMPARE(tester.zValue(), qreal(2.0));
4646 // ItemRotationChange / ItemRotationHasChanged
4647 tester.itemChangeReturnValue = qreal(15.0);
4648 tester.setRotation(10.0);
4649 ++changeCount; // notification sent too
4651 QCOMPARE(tester.changes.size(), changeCount);
4652 QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemRotationChange);
4653 QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemRotationHasChanged);
4654 QCOMPARE(tester.values.at(tester.changes.size() - 2), QVariant(qreal(10.0)));
4655 QCOMPARE(tester.values.at(tester.changes.size() - 1), QVariant(qreal(15.0)));
4656 QCOMPARE(tester.oldValues.last(), QVariant(qreal(0.0)));
4657 QCOMPARE(tester.rotation(), qreal(15.0));
4660 // ItemScaleChange / ItemScaleHasChanged
4661 tester.itemChangeReturnValue = qreal(2.0);
4662 tester.setScale(1.5);
4663 ++changeCount; // notification sent too
4665 QCOMPARE(tester.changes.size(), changeCount);
4666 QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemScaleChange);
4667 QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemScaleHasChanged);
4668 QCOMPARE(tester.values.at(tester.changes.size() - 2), QVariant(qreal(1.5)));
4669 QCOMPARE(tester.values.at(tester.changes.size() - 1), QVariant(qreal(2.0)));
4670 QCOMPARE(tester.oldValues.last(), QVariant(qreal(1.0)));
4671 QCOMPARE(tester.scale(), qreal(2.0));
4674 // ItemTransformOriginPointChange / ItemTransformOriginPointHasChanged
4675 tester.itemChangeReturnValue = QPointF(2.0, 2.0);
4676 tester.setTransformOriginPoint(1.0, 1.0);
4677 ++changeCount; // notification sent too
4679 QCOMPARE(tester.changes.size(), changeCount);
4680 QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemTransformOriginPointChange);
4681 QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemTransformOriginPointHasChanged);
4682 QCOMPARE(tester.values.at(tester.changes.size() - 2), QVariant(QPointF(1.0, 1.0)));
4683 QCOMPARE(tester.values.at(tester.changes.size() - 1), QVariant(QPointF(2.0, 2.0)));
4684 QCOMPARE(tester.oldValues.last(), QVariant(QPointF(0.0, 0.0)));
4685 QCOMPARE(tester.transformOriginPoint(), QPointF(2.0, 2.0));
4689 tester.itemChangeReturnValue = QGraphicsItem::ItemIsSelectable;
4690 tester.setFlag(QGraphicsItem::ItemIsSelectable, false);
4691 QCOMPARE(tester.changes.size(), changeCount); // No change
4692 tester.setFlag(QGraphicsItem::ItemIsSelectable, true);
4694 ++changeCount; // ItemFlagsHasChanged
4695 QCOMPARE(tester.changes.size(), changeCount);
4696 QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemFlagsChange);
4697 QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemFlagsHaveChanged);
4698 QVariant expectedFlags = qVariantFromValue<quint32>(QGraphicsItem::GraphicsItemFlags(QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemSendsGeometryChanges));
4699 QCOMPARE(tester.values.at(tester.values.size() - 2), expectedFlags);
4700 QCOMPARE(tester.values.at(tester.values.size() - 1), qVariantFromValue<quint32>((quint32)QGraphicsItem::ItemIsSelectable));
4703 // ItemSelectedChange
4704 tester.setSelected(false);
4705 QCOMPARE(tester.changes.size(), changeCount); // No change :-)
4706 tester.itemChangeReturnValue = true;
4707 tester.setSelected(true);
4709 ++changeCount; // ItemSelectedHasChanged
4710 QCOMPARE(tester.changes.size(), changeCount);
4711 QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemSelectedChange);
4712 QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemSelectedHasChanged);
4713 QCOMPARE(tester.values.at(tester.values.size() - 2), QVariant(true));
4714 QCOMPARE(tester.values.at(tester.values.size() - 1), QVariant(true));
4715 QCOMPARE(tester.oldValues.last(), QVariant(false));
4716 QCOMPARE(tester.isSelected(), true);
4718 tester.itemChangeReturnValue = false;
4719 tester.setSelected(true);
4721 // the value hasn't changed to the itemChange return value
4722 // bacause itemChange is never called (true -> true is a noop).
4723 QCOMPARE(tester.isSelected(), true);
4726 // ItemVisibleChange
4727 tester.itemChangeReturnValue = false;
4728 QVERIFY(tester.isVisible());
4729 tester.setVisible(false);
4730 ++changeCount; // ItemVisibleChange
4731 ++changeCount; // ItemSelectedChange
4732 ++changeCount; // ItemSelectedHasChanged
4733 ++changeCount; // ItemVisibleHasChanged
4734 QCOMPARE(tester.changes.size(), changeCount);
4735 QCOMPARE(tester.changes.at(tester.changes.size() - 4), QGraphicsItem::ItemVisibleChange);
4736 QCOMPARE(tester.changes.at(tester.changes.size() - 3), QGraphicsItem::ItemSelectedChange);
4737 QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemSelectedHasChanged);
4738 QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemVisibleHasChanged);
4739 QCOMPARE(tester.values.at(tester.values.size() - 4), QVariant(false));
4740 QCOMPARE(tester.values.at(tester.values.size() - 3), QVariant(false));
4741 QCOMPARE(tester.values.at(tester.values.size() - 2), QVariant(false));
4742 QCOMPARE(tester.values.at(tester.values.size() - 1), QVariant(false));
4743 QCOMPARE(tester.isVisible(), false);
4747 qVariantSetValue<QGraphicsItem *>(tester.itemChangeReturnValue, 0);
4748 tester.setParentItem(&testerHelper);
4749 QCOMPARE(tester.changes.size(), ++changeCount);
4750 QCOMPARE(tester.changes.last(), QGraphicsItem::ItemParentChange);
4751 QCOMPARE(qVariantValue<QGraphicsItem *>(tester.values.last()), (QGraphicsItem *)&testerHelper);
4752 QCOMPARE(qVariantValue<QGraphicsItem *>(tester.oldValues.last()), (QGraphicsItem *)0);
4753 QCOMPARE(tester.parentItem(), (QGraphicsItem *)0);
4756 // ItemOpacityChange
4757 tester.itemChangeReturnValue = 1.0;
4758 tester.setOpacity(0.7);
4759 QCOMPARE(tester.changes.size(), ++changeCount);
4760 QCOMPARE(tester.changes.last(), QGraphicsItem::ItemOpacityChange);
4761 QVERIFY(qFuzzyCompare(qreal(tester.values.last().toDouble()), qreal(0.7)));
4762 QCOMPARE(tester.oldValues.last().toDouble(), double(1.0));
4763 QCOMPARE(tester.opacity(), qreal(1.0));
4764 tester.itemChangeReturnValue = 0.7;
4765 tester.setOpacity(0.7);
4766 ++changeCount; // ItemOpacityChange
4767 ++changeCount; // ItemOpacityHasChanged
4768 QCOMPARE(tester.changes.size(), changeCount);
4769 QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemOpacityChange);
4770 QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemOpacityHasChanged);
4771 QCOMPARE(tester.opacity(), qreal(0.7));
4774 // ItemChildAddedChange
4775 tester.itemChangeReturnValue.clear();
4776 testerHelper.setParentItem(&tester);
4777 QCOMPARE(tester.changes.size(), ++changeCount);
4778 QCOMPARE(tester.changes.last(), QGraphicsItem::ItemChildAddedChange);
4779 QCOMPARE(qVariantValue<QGraphicsItem *>(tester.values.last()), (QGraphicsItem *)&testerHelper);
4782 // ItemChildRemovedChange 1
4783 testerHelper.setParentItem(0);
4784 QCOMPARE(tester.changes.size(), ++changeCount);
4785 QCOMPARE(tester.changes.last(), QGraphicsItem::ItemChildRemovedChange);
4786 QCOMPARE(qVariantValue<QGraphicsItem *>(tester.values.last()), (QGraphicsItem *)&testerHelper);
4788 // ItemChildRemovedChange 1
4789 ItemChangeTester *test = new ItemChangeTester;
4790 test->itemSceneChangeTargetScene = 0;
4792 QGraphicsScene *scene = new QGraphicsScene;
4793 scene->addItem(test);
4794 count = test->changes.size();
4795 //We test here the fact that when a child is deleted the parent receive only one ItemChildRemovedChange
4796 QGraphicsRectItem *child = new QGraphicsRectItem(test);
4797 //We received ItemChildAddedChange
4798 QCOMPARE(test->changes.size(), ++count);
4799 QCOMPARE(test->changes.last(), QGraphicsItem::ItemChildAddedChange);
4802 QCOMPARE(test->changes.size(), ++count);
4803 QCOMPARE(test->changes.last(), QGraphicsItem::ItemChildRemovedChange);
4805 ItemChangeTester *childTester = new ItemChangeTester(test);
4806 //Changes contains all sceneHasChanged and so on, we don't want to test that
4807 int childCount = childTester->changes.size();
4808 //We received ItemChildAddedChange
4809 QCOMPARE(test->changes.size(), ++count);
4810 child = new QGraphicsRectItem(childTester);
4811 //We received ItemChildAddedChange
4812 QCOMPARE(childTester->changes.size(), ++childCount);
4813 QCOMPARE(childTester->changes.last(), QGraphicsItem::ItemChildAddedChange);
4814 //Delete the child of the top level with all its children
4817 QCOMPARE(test->changes.size(), ++count);
4818 QCOMPARE(test->changes.last(), QGraphicsItem::ItemChildRemovedChange);
4822 // ItemChildRemovedChange 2
4823 ItemChangeTester parent;
4824 ItemChangeTester *child = new ItemChangeTester;
4825 child->setParentItem(&parent);
4826 QCOMPARE(parent.changes.last(), QGraphicsItem::ItemChildAddedChange);
4827 QCOMPARE(qVariantValue<QGraphicsItem *>(parent.values.last()), (QGraphicsItem *)child);
4829 QCOMPARE(parent.changes.last(), QGraphicsItem::ItemChildRemovedChange);
4830 QCOMPARE(qVariantValue<QGraphicsItem *>(parent.values.last()), (QGraphicsItem *)child);
4833 // !!! Note: If this test crashes because of double-deletion, there's
4834 // a bug somewhere in QGraphicsScene or QGraphicsItem.
4837 QGraphicsScene scene;
4838 QGraphicsScene scene2;
4839 scene.addItem(&tester);
4840 ++changeCount; // ItemSceneChange (scene)
4841 ++changeCount; // ItemSceneHasChanged (scene)
4842 QCOMPARE(tester.changes.size(), changeCount);
4844 QCOMPARE(tester.scene(), &scene);
4845 QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemSceneChange);
4846 QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemSceneHasChanged);
4847 // Item's old value was 0
4848 // Item's current value is scene
4849 QCOMPARE(qVariantValue<QGraphicsScene *>(tester.oldValues.last()), (QGraphicsScene *)0);
4850 QCOMPARE(qVariantValue<QGraphicsScene *>(tester.values.last()), (QGraphicsScene *)&scene);
4851 scene2.addItem(&tester);
4852 ++changeCount; // ItemSceneChange (0) was: (scene)
4853 ++changeCount; // ItemSceneHasChanged (0)
4854 ++changeCount; // ItemSceneChange (scene2) was: (0)
4855 ++changeCount; // ItemSceneHasChanged (scene2)
4856 QCOMPARE(tester.changes.size(), changeCount);
4858 QCOMPARE(tester.scene(), &scene2);
4859 QCOMPARE(tester.changes.at(tester.changes.size() - 4), QGraphicsItem::ItemSceneChange);
4860 QCOMPARE(tester.changes.at(tester.changes.size() - 3), QGraphicsItem::ItemSceneHasChanged);
4861 QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemSceneChange);
4862 QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemSceneHasChanged);
4863 // Item's last old value was scene
4864 // Item's last current value is 0
4866 QCOMPARE(qVariantValue<QGraphicsScene *>(tester.oldValues.at(tester.oldValues.size() - 2)), (QGraphicsScene *)&scene);
4867 QCOMPARE(qVariantValue<QGraphicsScene *>(tester.oldValues.at(tester.oldValues.size() - 1)), (QGraphicsScene *)0);
4868 QCOMPARE(qVariantValue<QGraphicsScene *>(tester.values.at(tester.values.size() - 4)), (QGraphicsScene *)0);
4869 QCOMPARE(qVariantValue<QGraphicsScene *>(tester.values.at(tester.values.size() - 3)), (QGraphicsScene *)0);
4870 QCOMPARE(qVariantValue<QGraphicsScene *>(tester.values.at(tester.values.size() - 2)), (QGraphicsScene *)&scene2);
4871 QCOMPARE(qVariantValue<QGraphicsScene *>(tester.values.at(tester.values.size() - 1)), (QGraphicsScene *)&scene2);
4872 // Item's last old value was 0
4873 // Item's last current value is scene2
4874 QCOMPARE(qVariantValue<QGraphicsScene *>(tester.oldValues.last()), (QGraphicsScene *)0);
4875 QCOMPARE(qVariantValue<QGraphicsScene *>(tester.values.last()), (QGraphicsScene *)&scene2);
4877 scene2.removeItem(&tester);
4878 ++changeCount; // ItemSceneChange (0) was: (scene2)
4879 ++changeCount; // ItemSceneHasChanged (0)
4880 QCOMPARE(tester.changes.size(), changeCount);
4882 QCOMPARE(tester.scene(), (QGraphicsScene *)0);
4883 QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemSceneChange);
4884 QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemSceneHasChanged);
4885 // Item's last old value was scene2
4886 // Item's last current value is 0
4887 QCOMPARE(qVariantValue<QGraphicsScene *>(tester.oldValues.last()), (QGraphicsScene *)&scene2);
4888 QCOMPARE(qVariantValue<QGraphicsScene *>(tester.values.at(tester.values.size() - 2)), (QGraphicsScene *)0);
4889 QCOMPARE(qVariantValue<QGraphicsScene *>(tester.values.at(tester.values.size() - 1)), (QGraphicsScene *)0);
4891 tester.itemSceneChangeTargetScene = &scene;
4892 scene2.addItem(&tester);
4893 ++changeCount; // ItemSceneChange (scene2) was: (0)
4894 ++changeCount; // ItemSceneChange (scene) was: (0)
4895 ++changeCount; // ItemSceneHasChanged (scene)
4896 QCOMPARE(tester.values.size(), changeCount);
4898 QCOMPARE(qVariantValue<QGraphicsScene *>(tester.values.at(tester.values.size() - 3)), (QGraphicsScene *)&scene2);
4899 QCOMPARE(qVariantValue<QGraphicsScene *>(tester.values.at(tester.values.size() - 2)), (QGraphicsScene *)&scene);
4900 QCOMPARE(qVariantValue<QGraphicsScene *>(tester.values.at(tester.values.size() - 1)), (QGraphicsScene *)&scene);
4902 QCOMPARE(tester.scene(), &scene);
4903 tester.itemSceneChangeTargetScene = 0;
4904 tester.itemChangeReturnValue = QVariant();
4905 scene.removeItem(&tester);
4906 ++changeCount; // ItemSceneChange
4907 ++changeCount; // ItemSceneHasChanged
4908 QCOMPARE(tester.scene(), (QGraphicsScene *)0);
4911 // ItemToolTipChange/ItemToolTipHasChanged
4912 const QString toolTip(QLatin1String("I'm soo cool"));
4913 const QString overridenToolTip(QLatin1String("No, you are not soo cool"));
4914 tester.itemChangeReturnValue = overridenToolTip;
4915 tester.setToolTip(toolTip);
4916 ++changeCount; // ItemToolTipChange
4917 ++changeCount; // ItemToolTipHasChanged
4918 QCOMPARE(tester.changes.size(), changeCount);
4919 QCOMPARE(tester.changes.at(changeCount - 2), QGraphicsItem::ItemToolTipChange);
4920 QCOMPARE(tester.values.at(changeCount - 2).toString(), toolTip);
4921 QCOMPARE(tester.changes.at(changeCount - 1), QGraphicsItem::ItemToolTipHasChanged);
4922 QCOMPARE(tester.values.at(changeCount - 1).toString(), overridenToolTip);
4923 QCOMPARE(tester.toolTip(), overridenToolTip);
4924 tester.itemChangeReturnValue = QVariant();
4928 class EventFilterTesterItem : public QGraphicsLineItem
4931 QList<QEvent::Type> filteredEvents;
4932 QList<QGraphicsItem *> filteredEventReceivers;
4933 bool handlesSceneEvents;
4935 QList<QEvent::Type> receivedEvents;
4937 EventFilterTesterItem() : handlesSceneEvents(false) {}
4940 bool sceneEventFilter(QGraphicsItem *watched, QEvent *event)
4942 filteredEvents << event->type();
4943 filteredEventReceivers << watched;
4944 return handlesSceneEvents;
4947 bool sceneEvent(QEvent *event)
4949 return QGraphicsLineItem::sceneEvent(event);
4953 void tst_QGraphicsItem::sceneEventFilter()
4955 QGraphicsScene scene;
4957 QGraphicsView view(&scene);
4959 QApplication::setActiveWindow(&view);
4960 QTest::qWaitForWindowShown(&view);
4963 QGraphicsTextItem *text1 = scene.addText(QLatin1String("Text1"));
4964 QGraphicsTextItem *text2 = scene.addText(QLatin1String("Text2"));
4965 QGraphicsTextItem *text3 = scene.addText(QLatin1String("Text3"));
4966 text1->setFlag(QGraphicsItem::ItemIsFocusable);
4967 text2->setFlag(QGraphicsItem::ItemIsFocusable);
4968 text3->setFlag(QGraphicsItem::ItemIsFocusable);
4970 EventFilterTesterItem *tester = new EventFilterTesterItem;
4971 scene.addItem(tester);
4973 QTRY_VERIFY(!text1->hasFocus());
4974 text1->installSceneEventFilter(tester);
4976 QTRY_VERIFY(text1->hasFocus());
4978 QCOMPARE(tester->filteredEvents.size(), 1);
4979 QCOMPARE(tester->filteredEvents.at(0), QEvent::FocusIn);
4980 QCOMPARE(tester->filteredEventReceivers.at(0), static_cast<QGraphicsItem *>(text1));
4982 text2->installSceneEventFilter(tester);
4983 text3->installSceneEventFilter(tester);
4988 QCOMPARE(tester->filteredEvents.size(), 5);
4989 QCOMPARE(tester->filteredEvents.at(1), QEvent::FocusOut);
4990 QCOMPARE(tester->filteredEventReceivers.at(1), static_cast<QGraphicsItem *>(text1));
4991 QCOMPARE(tester->filteredEvents.at(2), QEvent::FocusIn);
4992 QCOMPARE(tester->filteredEventReceivers.at(2), static_cast<QGraphicsItem *>(text2));
4993 QCOMPARE(tester->filteredEvents.at(3), QEvent::FocusOut);
4994 QCOMPARE(tester->filteredEventReceivers.at(3), static_cast<QGraphicsItem *>(text2));
4995 QCOMPARE(tester->filteredEvents.at(4), QEvent::FocusIn);
4996 QCOMPARE(tester->filteredEventReceivers.at(4), static_cast<QGraphicsItem *>(text3));
4998 text1->removeSceneEventFilter(tester);
5001 QCOMPARE(tester->filteredEvents.size(), 6);
5002 QCOMPARE(tester->filteredEvents.at(5), QEvent::FocusOut);
5003 QCOMPARE(tester->filteredEventReceivers.at(5), static_cast<QGraphicsItem *>(text3));
5005 tester->handlesSceneEvents = true;
5008 QCOMPARE(tester->filteredEvents.size(), 7);
5009 QCOMPARE(tester->filteredEvents.at(6), QEvent::FocusIn);
5010 QCOMPARE(tester->filteredEventReceivers.at(6), static_cast<QGraphicsItem *>(text2));
5012 QVERIFY(text2->hasFocus());
5014 //Let check if the items are correctly removed from the sceneEventFilters array
5015 //to avoid stale pointers.
5017 QGraphicsScene *anotherScene = new QGraphicsScene;
5018 QGraphicsTextItem *ti = anotherScene->addText("This is a test #1");
5020 QGraphicsTextItem *ti2 = anotherScene->addText("This is a test #2");
5021 QGraphicsTextItem *ti3 = anotherScene->addText("This is a test #3");
5022 gv.setScene(anotherScene);
5024 QTest::qWaitForWindowShown(&gv);
5026 ti->installSceneEventFilter(ti2);
5027 ti3->installSceneEventFilter(ti);
5030 QTest::mouseMove(gv.viewport(), gv.mapFromScene(ti->scenePos()));
5035 class GeometryChanger : public QGraphicsItem
5038 void changeGeometry()
5039 { prepareGeometryChange(); }
5042 void tst_QGraphicsItem::prepareGeometryChange()
5045 QGraphicsScene scene;
5046 QGraphicsItem *item = scene.addRect(QRectF(0, 0, 100, 100));
5047 QVERIFY(scene.items(QRectF(0, 0, 100, 100)).contains(item));
5048 ((GeometryChanger *)item)->changeGeometry();
5049 QVERIFY(scene.items(QRectF(0, 0, 100, 100)).contains(item));
5054 class PaintTester : public QGraphicsRectItem
5057 PaintTester() : widget(NULL), painted(0) { setRect(QRectF(10, 10, 20, 20));}
5059 void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *w)
5069 void tst_QGraphicsItem::paint()
5071 QGraphicsScene scene;
5073 PaintTester paintTester;
5074 scene.addItem(&paintTester);
5076 QGraphicsView view(&scene);
5078 if(PlatformQuirks::isAutoMaximizing())
5079 view.showFullScreen();
5082 QTest::qWaitForWindowShown(&view);
5083 QApplication::processEvents();
5085 //we try to switch the desktop: if it fails, we skip the test
5086 if (::SwitchDesktop( ::GetThreadDesktop( ::GetCurrentThreadId() ) ) == 0) {
5087 QSKIP("The Graphics View doesn't get the paint events");
5091 QTRY_COMPARE(paintTester.widget, view.viewport());
5095 QGraphicsScene scene2;
5096 QGraphicsView view2(&scene2);
5098 QTest::qWaitForWindowShown(&view2);
5101 PaintTester tester2;
5102 scene2.addItem(&tester2);
5103 qApp->processEvents();
5105 //First show one paint
5106 QTRY_COMPARE(tester2.painted, 1);
5108 //nominal case, update call paint
5110 qApp->processEvents();
5111 QTRY_VERIFY(tester2.painted == 2);
5113 //we remove the item from the scene, number of updates is still the same
5115 scene2.removeItem(&tester2);
5116 qApp->processEvents();
5117 QTRY_VERIFY(tester2.painted == 2);
5119 //We re-add the item, the number of paint should increase
5120 scene2.addItem(&tester2);
5122 qApp->processEvents();
5123 QTRY_VERIFY(tester2.painted == 3);
5126 class HarakiriItem : public QGraphicsRectItem
5129 HarakiriItem(int harakiriPoint)
5130 : QGraphicsRectItem(QRectF(0, 0, 100, 100)), harakiri(harakiriPoint)
5135 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
5137 QGraphicsRectItem::paint(painter, option, widget);
5138 if (harakiri == 0) {
5139 // delete unsupported since 4.5
5149 if (harakiri == 1 && n == 0) {
5150 // delete unsupported
5156 if (harakiri == 2 && n == 1) {
5163 void contextMenuEvent(QGraphicsSceneContextMenuEvent *)
5165 if (harakiri == 3) {
5171 void dragEnterEvent(QGraphicsSceneDragDropEvent *event)
5174 QGraphicsRectItem::dragEnterEvent(event);
5177 void dragLeaveEvent(QGraphicsSceneDragDropEvent *event)
5180 QGraphicsRectItem::dragLeaveEvent(event);
5183 void dragMoveEvent(QGraphicsSceneDragDropEvent *event)
5186 QGraphicsRectItem::dragMoveEvent(event);
5189 void dropEvent(QGraphicsSceneDragDropEvent *event)
5192 QGraphicsRectItem::dropEvent(event);
5195 void focusInEvent(QFocusEvent *)
5197 if (harakiri == 4) {
5203 void focusOutEvent(QFocusEvent *)
5205 if (harakiri == 5) {
5211 void hoverEnterEvent(QGraphicsSceneHoverEvent *)
5213 if (harakiri == 6) {
5219 void hoverLeaveEvent(QGraphicsSceneHoverEvent *)
5221 if (harakiri == 7) {
5227 void hoverMoveEvent(QGraphicsSceneHoverEvent *)
5229 if (harakiri == 8) {
5235 void inputMethodEvent(QInputMethodEvent *event)
5238 QGraphicsRectItem::inputMethodEvent(event);
5241 QVariant inputMethodQuery(Qt::InputMethodQuery query) const
5244 return QGraphicsRectItem::inputMethodQuery(query);
5247 QVariant itemChange(GraphicsItemChange change, const QVariant &value)
5249 // deletion not supported
5250 return QGraphicsRectItem::itemChange(change, value);
5253 void keyPressEvent(QKeyEvent *)
5255 if (harakiri == 9) {
5261 void keyReleaseEvent(QKeyEvent *)
5263 if (harakiri == 10) {
5269 void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *)
5271 if (harakiri == 11) {
5277 void mouseMoveEvent(QGraphicsSceneMouseEvent *)
5279 if (harakiri == 12) {
5285 void mousePressEvent(QGraphicsSceneMouseEvent *)
5287 if (harakiri == 13) {
5293 void mouseReleaseEvent(QGraphicsSceneMouseEvent *)
5295 if (harakiri == 14) {
5301 bool sceneEvent(QEvent *event)
5303 // deletion not supported
5304 return QGraphicsRectItem::sceneEvent(event);
5307 bool sceneEventFilter(QGraphicsItem *watched, QEvent *event)
5309 // deletion not supported
5310 return QGraphicsRectItem::sceneEventFilter(watched, event);
5313 void wheelEvent(QGraphicsSceneWheelEvent *)
5315 if (harakiri == 16) {
5325 int HarakiriItem::dead;
5327 void tst_QGraphicsItem::deleteItemInEventHandlers()
5329 for (int i = 0; i < 17; ++i) {
5330 QGraphicsScene scene;
5331 HarakiriItem *item = new HarakiriItem(i);
5332 item->setAcceptsHoverEvents(true);
5333 item->setFlag(QGraphicsItem::ItemIsFocusable);
5335 scene.addItem(item);
5337 item->installSceneEventFilter(item); // <- ehey!
5339 QGraphicsView view(&scene);
5342 qApp->processEvents();
5343 qApp->processEvents();
5349 QContextMenuEvent event(QContextMenuEvent::Other,
5350 view.mapFromScene(item->scenePos()));
5351 QCoreApplication::sendEvent(view.viewport(), &event);
5354 QTest::mouseMove(view.viewport(), view.mapFromScene(item->scenePos()));
5356 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item->scenePos()));
5358 QTest::mouseDClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item->scenePos()));
5360 QTest::mouseClick(view.viewport(), Qt::RightButton, 0, view.mapFromScene(item->scenePos()));
5362 QTest::mouseMove(view.viewport(), view.mapFromScene(item->scenePos() + QPointF(20, -20)));
5370 QTest::keyPress(view.viewport(), Qt::Key_A);
5372 QTest::keyRelease(view.viewport(), Qt::Key_A);
5374 QTest::keyPress(view.viewport(), Qt::Key_A);
5376 QTest::keyRelease(view.viewport(), Qt::Key_A);
5380 class ItemPaintsOutsideShape : public QGraphicsItem
5383 QRectF boundingRect() const
5385 return QRectF(0, 0, 100, 100);
5388 void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
5390 painter->fillRect(-50, -50, 200, 200, Qt::red);
5391 painter->fillRect(0, 0, 100, 100, Qt::blue);
5395 void tst_QGraphicsItem::itemClipsToShape()
5397 QGraphicsItem *clippedItem = new ItemPaintsOutsideShape;
5398 clippedItem->setFlag(QGraphicsItem::ItemClipsToShape);
5400 QGraphicsItem *unclippedItem = new ItemPaintsOutsideShape;
5401 unclippedItem->setPos(200, 0);
5403 QGraphicsScene scene(-50, -50, 400, 200);
5404 scene.addItem(clippedItem);
5405 scene.addItem(unclippedItem);
5407 QImage image(400, 200, QImage::Format_ARGB32_Premultiplied);
5409 QPainter painter(&image);
5410 painter.setRenderHint(QPainter::Antialiasing);
5411 scene.render(&painter);
5414 QCOMPARE(image.pixel(45, 100), QRgb(0));
5415 QCOMPARE(image.pixel(100, 45), QRgb(0));
5416 QCOMPARE(image.pixel(155, 100), QRgb(0));
5417 QCOMPARE(image.pixel(45, 155), QRgb(0));
5418 QCOMPARE(image.pixel(55, 100), QColor(Qt::blue).rgba());
5419 QCOMPARE(image.pixel(100, 55), QColor(Qt::blue).rgba());
5420 QCOMPARE(image.pixel(145, 100), QColor(Qt::blue).rgba());
5421 QCOMPARE(image.pixel(55, 145), QColor(Qt::blue).rgba());
5422 QCOMPARE(image.pixel(245, 100), QColor(Qt::red).rgba());
5423 QCOMPARE(image.pixel(300, 45), QColor(Qt::red).rgba());
5424 QCOMPARE(image.pixel(355, 100), QColor(Qt::red).rgba());
5425 QCOMPARE(image.pixel(245, 155), QColor(Qt::red).rgba());
5426 QCOMPARE(image.pixel(255, 100), QColor(Qt::blue).rgba());
5427 QCOMPARE(image.pixel(300, 55), QColor(Qt::blue).rgba());
5428 QCOMPARE(image.pixel(345, 100), QColor(Qt::blue).rgba());
5429 QCOMPARE(image.pixel(255, 145), QColor(Qt::blue).rgba());
5432 void tst_QGraphicsItem::itemClipsChildrenToShape()
5434 QGraphicsScene scene;
5435 QGraphicsItem *rect = scene.addRect(0, 0, 50, 50, QPen(Qt::NoPen), QBrush(Qt::yellow));
5437 QGraphicsItem *ellipse = scene.addEllipse(0, 0, 100, 100, QPen(Qt::NoPen), QBrush(Qt::green));
5438 ellipse->setParentItem(rect);
5440 QGraphicsItem *clippedEllipse = scene.addEllipse(0, 0, 50, 50, QPen(Qt::NoPen), QBrush(Qt::blue));
5441 clippedEllipse->setParentItem(ellipse);
5443 QGraphicsItem *clippedEllipse2 = scene.addEllipse(0, 0, 25, 25, QPen(Qt::NoPen), QBrush(Qt::red));
5444 clippedEllipse2->setParentItem(clippedEllipse);
5446 QGraphicsItem *clippedEllipse3 = scene.addEllipse(50, 50, 25, 25, QPen(Qt::NoPen), QBrush(Qt::red));
5447 clippedEllipse3->setParentItem(clippedEllipse);
5449 QVERIFY(!(ellipse->flags() & QGraphicsItem::ItemClipsChildrenToShape));
5450 ellipse->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
5451 QVERIFY((ellipse->flags() & QGraphicsItem::ItemClipsChildrenToShape));
5453 QImage image(100, 100, QImage::Format_ARGB32_Premultiplied);
5455 QPainter painter(&image);
5456 painter.setRenderHint(QPainter::Antialiasing);
5457 scene.render(&painter);
5460 QCOMPARE(image.pixel(16, 16), QColor(255, 0, 0).rgba());
5461 QCOMPARE(image.pixel(32, 32), QColor(0, 0, 255).rgba());
5462 QCOMPARE(image.pixel(50, 50), QColor(0, 255, 0).rgba());
5463 QCOMPARE(image.pixel(12, 12), QColor(255, 255, 0).rgba());
5464 QCOMPARE(image.pixel(60, 60), QColor(255, 0, 0).rgba());
5467 void tst_QGraphicsItem::itemClipsChildrenToShape2()
5469 QGraphicsRectItem *parent = new QGraphicsRectItem(QRectF(0, 0, 10, 10));
5470 QGraphicsEllipseItem *child1 = new QGraphicsEllipseItem(QRectF(50, 50, 100, 100));
5471 QGraphicsRectItem *child2 = new QGraphicsRectItem(QRectF(15, 15, 80, 80));
5473 child1->setParentItem(parent);
5474 child1->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
5475 child2->setParentItem(child1);
5477 parent->setBrush(Qt::blue);
5478 child1->setBrush(Qt::green);
5479 child2->setBrush(Qt::red);
5481 QGraphicsScene scene;
5482 scene.addItem(parent);
5484 QCOMPARE(scene.itemAt(5, 5), (QGraphicsItem *)parent);
5485 QCOMPARE(scene.itemAt(15, 5), (QGraphicsItem *)0);
5486 QCOMPARE(scene.itemAt(5, 15), (QGraphicsItem *)0);
5487 QCOMPARE(scene.itemAt(60, 60), (QGraphicsItem *)0);
5488 QCOMPARE(scene.itemAt(140, 60), (QGraphicsItem *)0);
5489 QCOMPARE(scene.itemAt(60, 140), (QGraphicsItem *)0);
5490 QCOMPARE(scene.itemAt(140, 140), (QGraphicsItem *)0);
5491 QCOMPARE(scene.itemAt(75, 75), (QGraphicsItem *)child2);
5492 QCOMPARE(scene.itemAt(75, 100), (QGraphicsItem *)child1);
5493 QCOMPARE(scene.itemAt(100, 75), (QGraphicsItem *)child1);
5496 QImage image(100, 100, QImage::Format_ARGB32_Premultiplied);
5498 QPainter painter(&image);
5499 scene.render(&painter);
5502 QCOMPARE(image.pixel(5, 5), QColor(0, 0, 255).rgba());
5503 QCOMPARE(image.pixel(5, 10), QRgb(0));
5504 QCOMPARE(image.pixel(10, 5), QRgb(0));
5505 QCOMPARE(image.pixel(40, 40), QRgb(0));
5506 QCOMPARE(image.pixel(90, 40), QRgb(0));
5507 QCOMPARE(image.pixel(40, 90), QRgb(0));
5508 QCOMPARE(image.pixel(95, 95), QRgb(0));
5509 QCOMPARE(image.pixel(50, 70), QColor(0, 255, 0).rgba());
5510 QCOMPARE(image.pixel(70, 50), QColor(0, 255, 0).rgba());
5511 QCOMPARE(image.pixel(50, 60), QColor(255, 0, 0).rgba());
5512 QCOMPARE(image.pixel(60, 50), QColor(255, 0, 0).rgba());
5514 QGraphicsView view(&scene);
5520 void tst_QGraphicsItem::itemClipsChildrenToShape3()
5522 // Construct a scene with nested children, each 50 pixels offset from the elder.
5523 // Set a top-level clipping flag
5524 QGraphicsScene scene;
5525 QGraphicsRectItem *parent = scene.addRect( 0, 0, 150, 150 );
5526 QGraphicsRectItem *child = scene.addRect( 0, 0, 150, 150 );
5527 QGraphicsRectItem *grandchild = scene.addRect( 0, 0, 150, 150 );
5528 child->setParentItem(parent);
5529 grandchild->setParentItem(child);
5530 child->setPos( 50, 50 );
5531 grandchild->setPos( 50, 50 );
5532 parent->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
5534 QCOMPARE(scene.itemAt(25,25), (QGraphicsItem *)parent);
5535 QCOMPARE(scene.itemAt(75,75), (QGraphicsItem *)child);
5536 QCOMPARE(scene.itemAt(125,125), (QGraphicsItem *)grandchild);
5537 QCOMPARE(scene.itemAt(175,175), (QGraphicsItem *)0);
5539 // Move child to fully overlap the parent. The grandchild should
5540 // now occupy two-thirds of the scene
5541 child->prepareGeometryChange();
5542 child->setPos( 0, 0 );
5544 QCOMPARE(scene.itemAt(25,25), (QGraphicsItem *)child);
5545 QCOMPARE(scene.itemAt(75,75), (QGraphicsItem *)grandchild);
5546 QCOMPARE(scene.itemAt(125,125), (QGraphicsItem *)grandchild);
5547 QCOMPARE(scene.itemAt(175,175), (QGraphicsItem *)0);
5550 class MyProxyWidget : public QGraphicsProxyWidget
5553 MyProxyWidget(QGraphicsItem *parent) : QGraphicsProxyWidget(parent)
5558 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
5560 QGraphicsProxyWidget::paint(painter, option, widget);
5566 void tst_QGraphicsItem::itemClipsChildrenToShape4()
5568 QGraphicsScene scene;
5569 QGraphicsView view(&scene);
5571 QGraphicsWidget * outerWidget = new QGraphicsWidget();
5572 outerWidget->setFlag(QGraphicsItem::ItemClipsChildrenToShape, true);
5573 MyProxyWidget * innerWidget = new MyProxyWidget(outerWidget);
5574 QLabel * label = new QLabel();
5575 label->setText("Welcome back my friends to the show that never ends...");
5576 innerWidget->setWidget(label);
5577 view.resize(300, 300);
5578 scene.addItem(outerWidget);
5579 outerWidget->resize( 200, 100 );
5580 scene.addEllipse( 100, 100, 100, 50 ); // <-- this is important to trigger the right codepath*
5581 //now the label is shown
5582 outerWidget->setFlag(QGraphicsItem::ItemClipsChildrenToShape, false );
5583 QApplication::setActiveWindow(&view);
5585 QTRY_COMPARE(QApplication::activeWindow(), (QWidget *)&view);
5586 QTRY_COMPARE(innerWidget->painted, true);
5589 //#define DEBUG_ITEM_CLIPS_CHILDREN_TO_SHAPE_5
5590 static inline void renderSceneToImage(QGraphicsScene *scene, QImage *image, const QString &filename)
5593 QPainter painter(image);
5594 scene->render(&painter);
5596 #ifdef DEBUG_ITEM_CLIPS_CHILDREN_TO_SHAPE_5
5597 image->save(filename);
5603 void tst_QGraphicsItem::itemClipsChildrenToShape5()
5605 class ParentItem : public QGraphicsRectItem
5608 ParentItem(qreal x, qreal y, qreal width, qreal height)
5609 : QGraphicsRectItem(x, y, width, height) {}
5611 QPainterPath shape() const
5614 path.addRect(50, 50, 200, 200);
5619 ParentItem *parent = new ParentItem(0, 0, 300, 300);
5620 parent->setBrush(Qt::blue);
5621 parent->setOpacity(0.5);
5623 const QRegion parentRegion(0, 0, 300, 300);
5624 const QRegion clippedParentRegion = parentRegion & QRect(50, 50, 200, 200);
5625 QRegion childRegion;
5626 QRegion grandChildRegion;
5628 QGraphicsRectItem *topLeftChild = new QGraphicsRectItem(0, 0, 100, 100);
5629 topLeftChild->setBrush(Qt::red);
5630 topLeftChild->setParentItem(parent);
5631 childRegion += QRect(0, 0, 100, 100);
5633 QGraphicsRectItem *topRightChild = new QGraphicsRectItem(0, 0, 100, 100);
5634 topRightChild->setBrush(Qt::red);
5635 topRightChild->setParentItem(parent);
5636 topRightChild->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
5637 topRightChild->setPos(200, 0);
5638 childRegion += QRect(200, 0, 100, 100);
5640 QGraphicsRectItem *topRightGrandChild = new QGraphicsRectItem(0, 0, 100, 100);
5641 topRightGrandChild->setBrush(Qt::green);
5642 topRightGrandChild->setParentItem(topRightChild);
5643 topRightGrandChild->setPos(-40, 40);
5644 grandChildRegion += QRect(200 - 40, 0 + 40, 100, 100) & QRect(200, 0, 100, 100);
5646 QGraphicsRectItem *bottomLeftChild = new QGraphicsRectItem(0, 0, 100, 100);
5647 bottomLeftChild->setBrush(Qt::red);
5648 bottomLeftChild->setParentItem(parent);
5649 bottomLeftChild->setFlag(QGraphicsItem::ItemClipsToShape);
5650 bottomLeftChild->setPos(0, 200);
5651 childRegion += QRect(0, 200, 100, 100);
5653 QGraphicsRectItem *bottomLeftGrandChild = new QGraphicsRectItem(0, 0, 160, 160);
5654 bottomLeftGrandChild->setBrush(Qt::green);
5655 bottomLeftGrandChild->setParentItem(bottomLeftChild);
5656 bottomLeftGrandChild->setFlag(QGraphicsItem::ItemClipsToShape);
5657 bottomLeftGrandChild->setPos(0, -60);
5658 grandChildRegion += QRect(0, 200 - 60, 160, 160);
5660 QGraphicsRectItem *bottomRightChild = new QGraphicsRectItem(0, 0, 100, 100);
5661 bottomRightChild->setBrush(Qt::red);
5662 bottomRightChild->setParentItem(parent);
5663 bottomRightChild->setPos(200, 200);
5664 childRegion += QRect(200, 200, 100, 100);
5666 QPoint controlPoints[17] = {
5667 QPoint(5, 5) , QPoint(95, 5) , QPoint(205, 5) , QPoint(295, 5) ,
5668 QPoint(5, 95) , QPoint(95, 95) , QPoint(205, 95) , QPoint(295, 95) ,
5670 QPoint(5, 205), QPoint(95, 205), QPoint(205, 205), QPoint(295, 205),
5671 QPoint(5, 295), QPoint(95, 295), QPoint(205, 295), QPoint(295, 295),
5674 const QRegion clippedChildRegion = childRegion & QRect(50, 50, 200, 200);
5675 const QRegion clippedGrandChildRegion = grandChildRegion & QRect(50, 50, 200, 200);
5677 QGraphicsScene scene;
5678 scene.addItem(parent);
5679 QImage sceneImage(300, 300, QImage::Format_ARGB32);
5681 #define VERIFY_CONTROL_POINTS(pRegion, cRegion, gRegion) \
5682 for (int i = 0; i < 17; ++i) { \
5683 QPoint controlPoint = controlPoints[i]; \
5684 QRgb pixel = sceneImage.pixel(controlPoint.x(), controlPoint.y()); \
5685 if (pRegion.contains(controlPoint)) \
5686 QVERIFY(qBlue(pixel) != 0); \
5688 QVERIFY(qBlue(pixel) == 0); \
5689 if (cRegion.contains(controlPoint)) \
5690 QVERIFY(qRed(pixel) != 0); \
5692 QVERIFY(qRed(pixel) == 0); \
5693 if (gRegion.contains(controlPoint)) \
5694 QVERIFY(qGreen(pixel) != 0); \
5696 QVERIFY(qGreen(pixel) == 0); \
5699 const QList<QGraphicsItem *> children = parent->childItems();
5700 const int childrenCount = children.count();
5702 for (int i = 0; i < 5; ++i) {
5704 QString childString;
5707 // All children stacked in front.
5708 childString = QLatin1String("ChildrenInFront.png");
5709 foreach (QGraphicsItem *child, children)
5710 child->setFlag(QGraphicsItem::ItemStacksBehindParent, false);
5713 // All children stacked behind.
5714 childString = QLatin1String("ChildrenBehind.png");
5715 foreach (QGraphicsItem *child, children)
5716 child->setFlag(QGraphicsItem::ItemStacksBehindParent, true);
5719 // First half of the children behind, second half in front.
5720 childString = QLatin1String("FirstHalfBehind_SecondHalfInFront.png");
5721 for (int j = 0; j < childrenCount; ++j) {
5722 QGraphicsItem *child = children.at(j);
5723 child->setFlag(QGraphicsItem::ItemStacksBehindParent, (j < childrenCount / 2));
5727 // First half of the children in front, second half behind.
5728 childString = QLatin1String("FirstHalfInFront_SecondHalfBehind.png");
5729 for (int j = 0; j < childrenCount; ++j) {
5730 QGraphicsItem *child = children.at(j);
5731 child->setFlag(QGraphicsItem::ItemStacksBehindParent, (j >= childrenCount / 2));
5735 // Child2 and child4 behind, rest in front.
5736 childString = QLatin1String("Child2And4Behind_RestInFront.png");
5737 for (int j = 0; j < childrenCount; ++j) {
5738 QGraphicsItem *child = children.at(j);
5739 if (j == 1 || j == 3)
5740 child->setFlag(QGraphicsItem::ItemStacksBehindParent, true);
5742 child->setFlag(QGraphicsItem::ItemStacksBehindParent, false);
5746 qFatal("internal error");
5749 // Nothing is clipped.
5750 parent->setFlag(QGraphicsItem::ItemClipsChildrenToShape, false);
5751 parent->setFlag(QGraphicsItem::ItemClipsToShape, false);
5752 clipString = QLatin1String("nothingClipped_");
5753 renderSceneToImage(&scene, &sceneImage, clipString + childString);
5754 VERIFY_CONTROL_POINTS(parentRegion, childRegion, grandChildRegion);
5756 // Parent clips children to shape.
5757 parent->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
5758 clipString = QLatin1String("parentClipsChildrenToShape_");
5759 renderSceneToImage(&scene, &sceneImage, clipString + childString);
5760 VERIFY_CONTROL_POINTS(parentRegion, clippedChildRegion, clippedGrandChildRegion);
5762 // Parent clips itself and children to shape.
5763 parent->setFlag(QGraphicsItem::ItemClipsToShape);
5764 clipString = QLatin1String("parentClipsItselfAndChildrenToShape_");
5765 renderSceneToImage(&scene, &sceneImage, clipString + childString);
5766 VERIFY_CONTROL_POINTS(clippedParentRegion, clippedChildRegion, clippedGrandChildRegion);
5768 // Parent clips itself to shape.
5769 parent->setFlag(QGraphicsItem::ItemClipsChildrenToShape, false);
5770 clipString = QLatin1String("parentClipsItselfToShape_");
5771 renderSceneToImage(&scene, &sceneImage, clipString + childString);
5772 VERIFY_CONTROL_POINTS(clippedParentRegion, childRegion, grandChildRegion);
5776 void tst_QGraphicsItem::itemClipsTextChildToShape()
5778 // Construct a scene with a rect that clips its children, with one text
5779 // child that has text that exceeds the size of the rect.
5780 QGraphicsScene scene;
5781 QGraphicsItem *rect = scene.addRect(0, 0, 50, 50, QPen(Qt::black), Qt::black);
5782 rect->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
5783 QGraphicsTextItem *text = new QGraphicsTextItem("This is a long sentence that's wider than 50 pixels.");
5784 text->setParentItem(rect);
5786 // Render this scene to a transparent image.
5787 QRectF sr = scene.itemsBoundingRect();
5788 QImage image(sr.size().toSize(), QImage::Format_ARGB32_Premultiplied);
5790 QPainter painter(&image);
5791 scene.render(&painter);
5793 // Erase the area immediately underneath the rect.
5794 painter.setCompositionMode(QPainter::CompositionMode_Source);
5795 painter.fillRect(rect->sceneBoundingRect().translated(-sr.topLeft()).adjusted(-0.5, -0.5, 0.5, 0.5),
5799 // Check that you get a truly transparent image back (i.e., the text was
5800 // clipped away, so there should be no trails left after erasing only the
5802 QImage emptyImage(scene.itemsBoundingRect().size().toSize(), QImage::Format_ARGB32_Premultiplied);
5804 QCOMPARE(image, emptyImage);
5807 void tst_QGraphicsItem::itemClippingDiscovery()
5809 // A simple scene with an ellipse parent and two rect children, one a
5810 // child of the other.
5811 QGraphicsScene scene;
5812 QGraphicsEllipseItem *clipItem = scene.addEllipse(0, 0, 100, 100);
5813 QGraphicsRectItem *leftRectItem = scene.addRect(0, 0, 50, 100);
5814 QGraphicsRectItem *rightRectItem = scene.addRect(50, 0, 50, 100);
5815 leftRectItem->setParentItem(clipItem);
5816 rightRectItem->setParentItem(clipItem);
5818 // The rects item are both visible at these points.
5819 QCOMPARE(scene.itemAt(10, 10), (QGraphicsItem *)leftRectItem);
5820 QCOMPARE(scene.itemAt(90, 90), (QGraphicsItem *)rightRectItem);
5822 // The ellipse clips the rects now.
5823 clipItem->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
5825 // The rect items are no longer visible at these points.
5826 QCOMPARE(scene.itemAt(10, 10), (QGraphicsItem *)0);
5827 if (sizeof(qreal) != sizeof(double))
5828 QSKIP("This fails due to internal rounding errors");
5829 QCOMPARE(scene.itemAt(90, 90), (QGraphicsItem *)0);
5832 void tst_QGraphicsItem::ancestorFlags()
5834 QGraphicsItem *level1 = new QGraphicsRectItem;
5835 QGraphicsItem *level21 = new QGraphicsRectItem;
5836 level21->setParentItem(level1);
5837 QGraphicsItem *level22 = new QGraphicsRectItem;
5838 level22->setParentItem(level1);
5839 QGraphicsItem *level31 = new QGraphicsRectItem;
5840 level31->setParentItem(level21);
5841 QGraphicsItem *level32 = new QGraphicsRectItem;
5842 level32->setParentItem(level21);
5844 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
5845 QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
5846 QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
5847 QCOMPARE(int(level31->d_ptr->ancestorFlags), 0);
5848 QCOMPARE(int(level32->d_ptr->ancestorFlags), 0);
5850 // HandlesChildEvents: 1) Root level sets a flag
5851 level1->setHandlesChildEvents(true);
5852 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
5853 QCOMPARE(int(level21->d_ptr->ancestorFlags), 1);
5854 QCOMPARE(int(level22->d_ptr->ancestorFlags), 1);
5855 QCOMPARE(int(level31->d_ptr->ancestorFlags), 1);
5856 QCOMPARE(int(level32->d_ptr->ancestorFlags), 1);
5858 // HandlesChildEvents: 2) Root level set it again
5859 level1->setHandlesChildEvents(true);
5860 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
5861 QCOMPARE(int(level21->d_ptr->ancestorFlags), 1);
5862 QCOMPARE(int(level22->d_ptr->ancestorFlags), 1);
5863 QCOMPARE(int(level31->d_ptr->ancestorFlags), 1);
5864 QCOMPARE(int(level32->d_ptr->ancestorFlags), 1);
5866 // HandlesChildEvents: 3) Root level unsets a flag
5867 level1->setHandlesChildEvents(false);
5868 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
5869 QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
5870 QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
5871 QCOMPARE(int(level31->d_ptr->ancestorFlags), 0);
5872 QCOMPARE(int(level32->d_ptr->ancestorFlags), 0);
5874 // HandlesChildEvents: 4) Child item sets a flag
5875 level21->setHandlesChildEvents(true);
5876 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
5877 QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
5878 QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
5879 QCOMPARE(int(level31->d_ptr->ancestorFlags), 1);
5880 QCOMPARE(int(level32->d_ptr->ancestorFlags), 1);
5882 // HandlesChildEvents: 5) Parent item sets a flag
5883 level1->setHandlesChildEvents(true);
5884 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
5885 QCOMPARE(int(level21->d_ptr->ancestorFlags), 1);
5886 QCOMPARE(int(level22->d_ptr->ancestorFlags), 1);
5887 QCOMPARE(int(level31->d_ptr->ancestorFlags), 1);
5888 QCOMPARE(int(level32->d_ptr->ancestorFlags), 1);
5890 // HandlesChildEvents: 6) Child item unsets a flag
5891 level21->setHandlesChildEvents(false);
5892 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
5893 QCOMPARE(int(level21->d_ptr->ancestorFlags), 1);
5894 QCOMPARE(int(level22->d_ptr->ancestorFlags), 1);
5895 QCOMPARE(int(level31->d_ptr->ancestorFlags), 1);
5896 QCOMPARE(int(level32->d_ptr->ancestorFlags), 1);
5898 // HandlesChildEvents: 7) Parent item unsets a flag
5899 level21->setHandlesChildEvents(true);
5900 level1->setHandlesChildEvents(false);
5901 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
5902 QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
5903 QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
5904 QCOMPARE(int(level31->d_ptr->ancestorFlags), 1);
5905 QCOMPARE(int(level32->d_ptr->ancestorFlags), 1);
5907 // Reparent the child to root
5908 level21->setParentItem(0);
5909 QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
5910 QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
5911 QCOMPARE(int(level31->d_ptr->ancestorFlags), 1);
5912 QCOMPARE(int(level32->d_ptr->ancestorFlags), 1);
5914 // Reparent the child to level1 again.
5915 level1->setHandlesChildEvents(true);
5916 level21->setParentItem(level1);
5917 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
5918 QCOMPARE(int(level21->d_ptr->ancestorFlags), 1);
5919 QCOMPARE(int(level22->d_ptr->ancestorFlags), 1);
5920 QCOMPARE(int(level31->d_ptr->ancestorFlags), 1);
5921 QCOMPARE(int(level32->d_ptr->ancestorFlags), 1);
5923 // Reparenting level31 back to level1.
5924 level31->setParentItem(level1);
5925 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
5926 QCOMPARE(int(level21->d_ptr->ancestorFlags), 1);
5927 QCOMPARE(int(level22->d_ptr->ancestorFlags), 1);
5928 QCOMPARE(int(level31->d_ptr->ancestorFlags), 1);
5929 QCOMPARE(int(level32->d_ptr->ancestorFlags), 1);
5931 // Reparenting level31 back to level21.
5932 level31->setParentItem(0);
5933 QCOMPARE(int(level31->d_ptr->ancestorFlags), 0);
5934 level31->setParentItem(level21);
5935 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
5936 QCOMPARE(int(level21->d_ptr->ancestorFlags), 1);
5937 QCOMPARE(int(level22->d_ptr->ancestorFlags), 1);
5938 QCOMPARE(int(level31->d_ptr->ancestorFlags), 1);
5939 QCOMPARE(int(level32->d_ptr->ancestorFlags), 1);
5941 // Level1 doesn't handle child events
5942 level1->setHandlesChildEvents(false);
5943 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
5944 QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
5945 QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
5946 QCOMPARE(int(level31->d_ptr->ancestorFlags), 1);
5947 QCOMPARE(int(level32->d_ptr->ancestorFlags), 1);
5949 // Nobody handles child events
5950 level21->setHandlesChildEvents(false);
5952 for (int i = 0; i < 2; ++i) {
5953 QGraphicsItem::GraphicsItemFlag flag = !i ? QGraphicsItem::ItemClipsChildrenToShape
5954 : QGraphicsItem::ItemIgnoresTransformations;
5955 int ancestorFlag = !i ? QGraphicsItemPrivate::AncestorClipsChildren
5956 : QGraphicsItemPrivate::AncestorIgnoresTransformations;
5958 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
5959 QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
5960 QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
5961 QCOMPARE(int(level31->d_ptr->ancestorFlags), 0);
5962 QCOMPARE(int(level32->d_ptr->ancestorFlags), 0);
5964 // HandlesChildEvents: 1) Root level sets a flag
5965 level1->setFlag(flag, true);
5966 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
5967 QCOMPARE(int(level21->d_ptr->ancestorFlags), ancestorFlag);
5968 QCOMPARE(int(level22->d_ptr->ancestorFlags), ancestorFlag);
5969 QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag);
5970 QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag);
5972 // HandlesChildEvents: 2) Root level set it again
5973 level1->setFlag(flag, true);
5974 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
5975 QCOMPARE(int(level21->d_ptr->ancestorFlags), ancestorFlag);
5976 QCOMPARE(int(level22->d_ptr->ancestorFlags), ancestorFlag);
5977 QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag);
5978 QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag);
5980 // HandlesChildEvents: 3) Root level unsets a flag
5981 level1->setFlag(flag, false);
5982 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
5983 QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
5984 QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
5985 QCOMPARE(int(level31->d_ptr->ancestorFlags), 0);
5986 QCOMPARE(int(level32->d_ptr->ancestorFlags), 0);
5988 // HandlesChildEvents: 4) Child item sets a flag
5989 level21->setFlag(flag, true);
5990 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
5991 QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
5992 QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
5993 QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag);
5994 QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag);
5996 // HandlesChildEvents: 5) Parent item sets a flag
5997 level1->setFlag(flag, true);
5998 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
5999 QCOMPARE(int(level21->d_ptr->ancestorFlags), ancestorFlag);
6000 QCOMPARE(int(level22->d_ptr->ancestorFlags), ancestorFlag);
6001 QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag);
6002 QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag);
6004 // HandlesChildEvents: 6) Child item unsets a flag
6005 level21->setFlag(flag, false);
6006 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
6007 QCOMPARE(int(level21->d_ptr->ancestorFlags), ancestorFlag);
6008 QCOMPARE(int(level22->d_ptr->ancestorFlags), ancestorFlag);
6009 QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag);
6010 QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag);
6012 // HandlesChildEvents: 7) Parent item unsets a flag
6013 level21->setFlag(flag, true);
6014 level1->setFlag(flag, false);
6015 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
6016 QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
6017 QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
6018 QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag);
6019 QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag);
6021 // Reparent the child to root
6022 level21->setParentItem(0);
6023 QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
6024 QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
6025 QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag);
6026 QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag);
6028 // Reparent the child to level1 again.
6029 level1->setFlag(flag, true);
6030 level21->setParentItem(level1);
6031 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
6032 QCOMPARE(int(level21->d_ptr->ancestorFlags), ancestorFlag);
6033 QCOMPARE(int(level22->d_ptr->ancestorFlags), ancestorFlag);
6034 QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag);
6035 QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag);
6037 // Reparenting level31 back to level1.
6038 level31->setParentItem(level1);
6039 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
6040 QCOMPARE(int(level21->d_ptr->ancestorFlags), ancestorFlag);
6041 QCOMPARE(int(level22->d_ptr->ancestorFlags), ancestorFlag);
6042 QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag);
6043 QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag);
6045 // Reparenting level31 back to level21.
6046 level31->setParentItem(0);
6047 QCOMPARE(int(level31->d_ptr->ancestorFlags), 0);
6048 level31->setParentItem(level21);
6049 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
6050 QCOMPARE(int(level21->d_ptr->ancestorFlags), ancestorFlag);
6051 QCOMPARE(int(level22->d_ptr->ancestorFlags), ancestorFlag);
6052 QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag);
6053 QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag);
6055 // Level1 doesn't handle child events
6056 level1->setFlag(flag, false);
6057 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
6058 QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
6059 QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
6060 QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag);
6061 QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag);
6063 // Nobody handles child events
6064 level21->setFlag(flag, false);
6065 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
6066 QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
6067 QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
6068 QCOMPARE(int(level31->d_ptr->ancestorFlags), 0);
6069 QCOMPARE(int(level32->d_ptr->ancestorFlags), 0);
6075 void tst_QGraphicsItem::untransformable()
6077 QGraphicsItem *item1 = new QGraphicsEllipseItem(QRectF(-50, -50, 100, 100));
6078 item1->setZValue(1);
6079 item1->setFlag(QGraphicsItem::ItemIgnoresTransformations);
6081 ((QGraphicsEllipseItem *)item1)->setBrush(Qt::red);
6083 QGraphicsItem *item2 = new QGraphicsEllipseItem(QRectF(-50, -50, 100, 100));
6084 item2->setParentItem(item1);
6086 item2->setPos(100, 0);
6087 ((QGraphicsEllipseItem *)item2)->setBrush(Qt::green);
6089 QGraphicsItem *item3 = new QGraphicsEllipseItem(QRectF(-50, -50, 100, 100));
6090 item3->setParentItem(item2);
6091 item3->setPos(100, 0);
6092 ((QGraphicsEllipseItem *)item3)->setBrush(Qt::blue);
6094 QGraphicsScene scene(-500, -500, 1000, 1000);
6095 scene.addItem(item1);
6098 QGraphicsView view(&scene,&topLevel);
6099 view.resize(300, 300);
6102 view.centerOn(0, 0);
6104 // Painting with the DiagCrossPattern is really slow on Mac
6105 // when zoomed out. (The test times out). Task to fix is 155567.
6106 #if !defined(Q_WS_MAC) || 1
6107 view.setBackgroundBrush(QBrush(Qt::black, Qt::DiagCrossPattern));
6110 QTest::qWaitForWindowShown(&view);
6112 for (int i = 0; i < 10; ++i) {
6113 QPoint center = view.viewport()->rect().center();
6114 QCOMPARE(view.itemAt(center), item1);
6115 QCOMPARE(view.itemAt(center - QPoint(40, 0)), item1);
6116 QCOMPARE(view.itemAt(center - QPoint(-40, 0)), item1);
6117 QCOMPARE(view.itemAt(center - QPoint(0, 40)), item1);
6118 QCOMPARE(view.itemAt(center - QPoint(0, -40)), item1);
6120 center += QPoint(70, 70);
6121 QCOMPARE(view.itemAt(center - QPoint(40, 0)), item2);
6122 QCOMPARE(view.itemAt(center - QPoint(-40, 0)), item2);
6123 QCOMPARE(view.itemAt(center - QPoint(0, 40)), item2);
6124 QCOMPARE(view.itemAt(center - QPoint(0, -40)), item2);
6126 center += QPoint(0, 100);
6127 QCOMPARE(view.itemAt(center - QPoint(40, 0)), item3);
6128 QCOMPARE(view.itemAt(center - QPoint(-40, 0)), item3);
6129 QCOMPARE(view.itemAt(center - QPoint(0, 40)), item3);
6130 QCOMPARE(view.itemAt(center - QPoint(0, -40)), item3);
6132 view.scale(0.5, 0.5);
6134 view.shear(qreal(0.01), qreal(0.01));
6135 view.translate(10, 10);
6140 class ContextMenuItem : public QGraphicsRectItem
6144 : ignoreEvent(true), gotEvent(false), eventWasAccepted(false)
6148 bool eventWasAccepted;
6150 void contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
6153 eventWasAccepted = event->isAccepted();
6159 void tst_QGraphicsItem::contextMenuEventPropagation()
6161 ContextMenuItem *bottomItem = new ContextMenuItem;
6162 bottomItem->setRect(0, 0, 100, 100);
6163 ContextMenuItem *topItem = new ContextMenuItem;
6164 topItem->setParentItem(bottomItem);
6165 topItem->setRect(0, 0, 100, 100);
6167 QGraphicsScene scene;
6169 QGraphicsView view(&scene);
6170 view.setAlignment(Qt::AlignLeft | Qt::AlignTop);
6172 view.resize(200, 200);
6173 QTest::qWaitForWindowShown(&view);
6176 QContextMenuEvent event(QContextMenuEvent::Mouse, QPoint(10, 10),
6177 view.viewport()->mapToGlobal(QPoint(10, 10)));
6179 QApplication::sendEvent(view.viewport(), &event);
6180 QVERIFY(!event.isAccepted());
6182 scene.addItem(bottomItem);
6183 topItem->ignoreEvent = true;
6184 bottomItem->ignoreEvent = true;
6186 QApplication::sendEvent(view.viewport(), &event);
6187 QVERIFY(!event.isAccepted());
6188 QCOMPARE(topItem->gotEvent, true);
6189 QCOMPARE(topItem->eventWasAccepted, true);
6190 QCOMPARE(bottomItem->gotEvent, true);
6191 QCOMPARE(bottomItem->eventWasAccepted, true);
6193 topItem->ignoreEvent = false;
6194 topItem->gotEvent = false;
6195 bottomItem->gotEvent = false;
6197 QApplication::sendEvent(view.viewport(), &event);
6198 QVERIFY(event.isAccepted());
6199 QCOMPARE(topItem->gotEvent, true);
6200 QCOMPARE(bottomItem->gotEvent, false);
6201 QCOMPARE(topItem->eventWasAccepted, true);
6204 void tst_QGraphicsItem::itemIsMovable()
6206 QGraphicsRectItem *rect = new QGraphicsRectItem(-50, -50, 100, 100);
6207 rect->setFlag(QGraphicsItem::ItemIsMovable);
6209 QGraphicsScene scene;
6210 scene.addItem(rect);
6213 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
6214 event.setButton(Qt::LeftButton);
6215 event.setButtons(Qt::LeftButton);
6216 qApp->sendEvent(&scene, &event);
6219 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseMove);
6220 event.setButton(Qt::LeftButton);
6221 event.setButtons(Qt::LeftButton);
6222 qApp->sendEvent(&scene, &event);
6224 QCOMPARE(rect->pos(), QPointF(0, 0));
6226 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseMove);
6227 event.setButtons(Qt::LeftButton);
6228 event.setScenePos(QPointF(10, 10));
6229 qApp->sendEvent(&scene, &event);
6231 QCOMPARE(rect->pos(), QPointF(10, 10));
6233 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseMove);
6234 event.setButtons(Qt::RightButton);
6235 event.setScenePos(QPointF(20, 20));
6236 qApp->sendEvent(&scene, &event);
6238 QCOMPARE(rect->pos(), QPointF(10, 10));
6240 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseMove);
6241 event.setButtons(Qt::LeftButton);
6242 event.setScenePos(QPointF(30, 30));
6243 qApp->sendEvent(&scene, &event);
6245 QCOMPARE(rect->pos(), QPointF(30, 30));
6248 class ItemAddScene : public QGraphicsScene
6254 QTimer::singleShot(500, this, SLOT(newTextItem()));
6261 QGraphicsItem *item = new QGraphicsTextItem("This item will not ensure that it's visible", 0, this);
6262 item->setPos(.0, .0);
6267 void tst_QGraphicsItem::task141694_textItemEnsureVisible()
6270 scene.setSceneRect(-1000, -1000, 2000, 2000);
6272 QGraphicsView view(&scene);
6273 view.setFixedSize(200, 200);
6275 QTest::qWaitForWindowShown(&view);
6277 view.ensureVisible(-1000, -1000, 5, 5);
6278 int hscroll = view.horizontalScrollBar()->value();
6279 int vscroll = view.verticalScrollBar()->value();
6283 // This should not cause the view to scroll
6284 QTRY_COMPARE(view.horizontalScrollBar()->value(), hscroll);
6285 QCOMPARE(view.verticalScrollBar()->value(), vscroll);
6288 void tst_QGraphicsItem::task128696_textItemEnsureMovable()
6290 QGraphicsTextItem *item = new QGraphicsTextItem;
6291 item->setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
6292 item->setTextInteractionFlags(Qt::TextEditorInteraction);
6293 item->setPlainText("abc de\nf ghi\n j k l");
6295 QGraphicsScene scene;
6296 scene.setSceneRect(-100, -100, 200, 200);
6297 scene.addItem(item);
6299 QGraphicsView view(&scene);
6300 view.setFixedSize(200, 200);
6303 QGraphicsSceneMouseEvent event1(QEvent::GraphicsSceneMousePress);
6304 event1.setScenePos(QPointF(0, 0));
6305 event1.setButton(Qt::LeftButton);
6306 event1.setButtons(Qt::LeftButton);
6307 QApplication::sendEvent(&scene, &event1);
6308 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)item);
6310 QGraphicsSceneMouseEvent event2(QEvent::GraphicsSceneMouseMove);
6311 event2.setScenePos(QPointF(10, 10));
6312 event2.setButton(Qt::LeftButton);
6313 event2.setButtons(Qt::LeftButton);
6314 QApplication::sendEvent(&scene, &event2);
6315 QCOMPARE(item->pos(), QPointF(10, 10));
6318 void tst_QGraphicsItem::task177918_lineItemUndetected()
6320 QGraphicsScene scene;
6321 QGraphicsLineItem *line = scene.addLine(10, 10, 10, 10);
6322 QCOMPARE(line->boundingRect(), QRectF(10, 10, 0, 0));
6324 QVERIFY(!scene.items(9, 9, 2, 2, Qt::IntersectsItemShape).isEmpty());
6325 QVERIFY(!scene.items(9, 9, 2, 2, Qt::ContainsItemShape).isEmpty());
6326 QVERIFY(!scene.items(9, 9, 2, 2, Qt::IntersectsItemBoundingRect).isEmpty());
6327 QVERIFY(!scene.items(9, 9, 2, 2, Qt::ContainsItemBoundingRect).isEmpty());
6330 void tst_QGraphicsItem::task240400_clickOnTextItem_data()
6332 QTest::addColumn<int>("flags");
6333 QTest::addColumn<int>("textFlags");
6334 QTest::newRow("editor, noflags") << 0 << int(Qt::TextEditorInteraction);
6335 QTest::newRow("editor, movable") << int(QGraphicsItem::ItemIsMovable) << int(Qt::TextEditorInteraction);
6336 QTest::newRow("editor, selectable") << int(QGraphicsItem::ItemIsSelectable) << int(Qt::TextEditorInteraction);
6337 QTest::newRow("editor, movable | selectable") << int(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable)
6338 << int(Qt::TextEditorInteraction);
6339 QTest::newRow("noninteractive, noflags") << 0 << int(Qt::NoTextInteraction);
6340 QTest::newRow("noninteractive, movable") << int(QGraphicsItem::ItemIsMovable) << int(Qt::NoTextInteraction);
6341 QTest::newRow("noninteractive, selectable") << int(QGraphicsItem::ItemIsSelectable) << int(Qt::NoTextInteraction);
6342 QTest::newRow("noninteractive, movable | selectable") << int(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable)
6343 << int(Qt::NoTextInteraction);
6346 void tst_QGraphicsItem::task240400_clickOnTextItem()
6349 QFETCH(int, textFlags);
6351 QGraphicsScene scene;
6352 QEvent activate(QEvent::WindowActivate);
6353 QApplication::sendEvent(&scene, &activate);
6355 QGraphicsTextItem *item = scene.addText("Hello");
6356 item->setFlags(QGraphicsItem::GraphicsItemFlags(flags));
6357 item->setTextInteractionFlags(Qt::TextInteractionFlags(textFlags));
6358 bool focusable = (item->flags() & QGraphicsItem::ItemIsFocusable);
6359 QVERIFY(textFlags ? focusable : !focusable);
6361 int column = item->textCursor().columnNumber();
6362 QCOMPARE(column, 0);
6364 QVERIFY(!item->hasFocus());
6366 // Click in the top-left corner of the item
6368 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
6369 event.setScenePos(item->sceneBoundingRect().topLeft() + QPointF(0.1, 0.1));
6370 event.setButton(Qt::LeftButton);
6371 event.setButtons(Qt::LeftButton);
6372 QApplication::sendEvent(&scene, &event);
6374 if (flags || textFlags)
6375 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)item);
6377 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
6379 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseRelease);
6380 event.setScenePos(item->sceneBoundingRect().topLeft() + QPointF(0.1, 0.1));
6381 event.setButton(Qt::LeftButton);
6382 event.setButtons(0);
6383 QApplication::sendEvent(&scene, &event);
6386 QVERIFY(item->hasFocus());
6388 QVERIFY(!item->hasFocus());
6389 QVERIFY(!scene.mouseGrabberItem());
6390 bool selectable = (flags & QGraphicsItem::ItemIsSelectable);
6391 QVERIFY(selectable ? item->isSelected() : !item->isSelected());
6393 // Now click in the middle and check that the cursor moved.
6395 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
6396 event.setScenePos(item->sceneBoundingRect().center());
6397 event.setButton(Qt::LeftButton);
6398 event.setButtons(Qt::LeftButton);
6399 QApplication::sendEvent(&scene, &event);
6401 if (flags || textFlags)
6402 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)item);
6404 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
6406 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseRelease);
6407 event.setScenePos(item->sceneBoundingRect().center());
6408 event.setButton(Qt::LeftButton);
6409 event.setButtons(0);
6410 QApplication::sendEvent(&scene, &event);
6413 QVERIFY(item->hasFocus());
6415 QVERIFY(!item->hasFocus());
6416 QVERIFY(!scene.mouseGrabberItem());
6418 QVERIFY(selectable ? item->isSelected() : !item->isSelected());
6421 if (textFlags & Qt::TextEditorInteraction)
6422 QVERIFY(item->textCursor().columnNumber() > column);
6424 QCOMPARE(item->textCursor().columnNumber(), 0);
6427 class TextItem : public QGraphicsSimpleTextItem
6430 TextItem(const QString& text) : QGraphicsSimpleTextItem(text)
6435 void paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget)
6438 QGraphicsSimpleTextItem::paint(painter, option, widget);
6444 void tst_QGraphicsItem::ensureUpdateOnTextItem()
6446 QGraphicsScene scene;
6447 QGraphicsView view(&scene);
6449 QTest::qWaitForWindowShown(&view);
6451 TextItem *text1 = new TextItem(QLatin1String("123"));
6452 scene.addItem(text1);
6453 qApp->processEvents();
6454 QTRY_COMPARE(text1->updates,1);
6456 //same bouding rect but we have to update
6457 text1->setText(QLatin1String("321"));
6458 qApp->processEvents();
6459 QTRY_COMPARE(text1->updates,2);
6462 void tst_QGraphicsItem::task243707_addChildBeforeParent()
6464 // Task reports that adding the child before the parent leads to an
6465 // inconsistent internal state that can cause a crash. This test shows
6467 QGraphicsScene scene;
6468 QGraphicsWidget *widget = new QGraphicsWidget;
6469 QGraphicsWidget *widget2 = new QGraphicsWidget(widget);
6470 scene.addItem(widget2);
6471 QVERIFY(!widget2->parentItem());
6472 scene.addItem(widget);
6473 QVERIFY(!widget->commonAncestorItem(widget2));
6474 QVERIFY(!widget2->commonAncestorItem(widget));
6477 void tst_QGraphicsItem::task197802_childrenVisibility()
6479 QGraphicsScene scene;
6480 QGraphicsRectItem item(QRectF(0,0,20,20));
6482 QGraphicsRectItem *item2 = new QGraphicsRectItem(QRectF(0,0,10,10), &item);
6483 scene.addItem(&item);
6485 //freshly created: both visible
6486 QVERIFY(item.isVisible());
6487 QVERIFY(item2->isVisible());
6489 //hide child: parent visible, child not
6491 QVERIFY(item.isVisible());
6492 QVERIFY(!item2->isVisible());
6494 //hide parent: parent and child invisible
6496 QVERIFY(!item.isVisible());
6497 QVERIFY(!item2->isVisible());
6499 //ask to show the child: parent and child invisible anyways
6501 QVERIFY(!item.isVisible());
6502 QVERIFY(!item2->isVisible());
6504 //show the parent: both parent and child visible
6506 QVERIFY(item.isVisible());
6507 QVERIFY(item2->isVisible());
6512 void tst_QGraphicsItem::boundingRegion_data()
6514 QTest::addColumn<QLineF>("line");
6515 QTest::addColumn<qreal>("granularity");
6516 QTest::addColumn<QTransform>("transform");
6517 QTest::addColumn<QRegion>("expectedRegion");
6519 QTest::newRow("(0, 0, 10, 10) | 0.0 | identity | {(0, 0, 10, 10)}") << QLineF(0, 0, 10, 10) << qreal(0.0) << QTransform()
6520 << QRegion(QRect(0, 0, 10, 10));
6521 QTest::newRow("(0, 0, 10, 0) | 0.0 | identity | {(0, 0, 10, 10)}") << QLineF(0, 0, 10, 0) << qreal(0.0) << QTransform()
6522 << QRegion(QRect(0, 0, 10, 1));
6523 QTest::newRow("(0, 0, 10, 0) | 0.5 | identity | {(0, 0, 10, 1)}") << QLineF(0, 0, 10, 0) << qreal(0.5) << QTransform()
6524 << QRegion(QRect(0, 0, 10, 1));
6525 QTest::newRow("(0, 0, 10, 0) | 1.0 | identity | {(0, 0, 10, 1)}") << QLineF(0, 0, 10, 0) << qreal(1.0) << QTransform()
6526 << QRegion(QRect(0, 0, 10, 1));
6527 QTest::newRow("(0, 0, 0, 10) | 0.0 | identity | {(0, 0, 10, 10)}") << QLineF(0, 0, 0, 10) << qreal(0.0) << QTransform()
6528 << QRegion(QRect(0, 0, 1, 10));
6529 QTest::newRow("(0, 0, 0, 10) | 0.5 | identity | {(0, 0, 1, 10)}") << QLineF(0, 0, 0, 10) << qreal(0.5) << QTransform()
6530 << QRegion(QRect(0, 0, 1, 10));
6531 QTest::newRow("(0, 0, 0, 10) | 1.0 | identity | {(0, 0, 1, 10)}") << QLineF(0, 0, 0, 10) << qreal(1.0) << QTransform()
6532 << QRegion(QRect(0, 0, 1, 10));
6535 void tst_QGraphicsItem::boundingRegion()
6537 QFETCH(QLineF, line);
6538 QFETCH(qreal, granularity);
6539 QFETCH(QTransform, transform);
6540 QFETCH(QRegion, expectedRegion);
6542 QGraphicsLineItem item(line);
6543 QCOMPARE(item.boundingRegionGranularity(), qreal(0.0));
6544 item.setBoundingRegionGranularity(granularity);
6545 QCOMPARE(item.boundingRegionGranularity(), granularity);
6546 QCOMPARE(item.boundingRegion(transform), expectedRegion);
6549 void tst_QGraphicsItem::itemTransform_parentChild()
6551 QGraphicsScene scene;
6552 QGraphicsItem *parent = scene.addRect(0, 0, 100, 100);
6553 QGraphicsItem *child = scene.addRect(0, 0, 100, 100);
6554 child->setParentItem(parent);
6555 child->setPos(10, 10);
6559 QCOMPARE(child->itemTransform(parent).map(QPointF(10, 10)), QPointF(-10, 30));
6560 QCOMPARE(parent->itemTransform(child).map(QPointF(-10, 30)), QPointF(10, 10));
6563 void tst_QGraphicsItem::itemTransform_siblings()
6565 QGraphicsScene scene;
6566 QGraphicsItem *parent = scene.addRect(0, 0, 100, 100);
6567 QGraphicsItem *brother = scene.addRect(0, 0, 100, 100);
6568 QGraphicsItem *sister = scene.addRect(0, 0, 100, 100);
6569 parent->scale(10, 5);
6570 parent->rotate(-180);
6571 parent->shear(2, 3);
6573 brother->setParentItem(parent);
6574 sister->setParentItem(parent);
6576 brother->setPos(10, 10);
6577 brother->scale(2, 2);
6578 brother->rotate(90);
6579 sister->setPos(10, 10);
6580 sister->scale(2, 2);
6583 QCOMPARE(brother->itemTransform(sister).map(QPointF(10, 10)), QPointF(10, 10));
6584 QCOMPARE(sister->itemTransform(brother).map(QPointF(10, 10)), QPointF(10, 10));
6587 void tst_QGraphicsItem::itemTransform_unrelated()
6589 QGraphicsScene scene;
6590 QGraphicsItem *stranger1 = scene.addRect(0, 0, 100, 100);
6591 QGraphicsItem *stranger2 = scene.addRect(0, 0, 100, 100);
6592 stranger1->setPos(10, 10);
6593 stranger1->scale(2, 2);
6594 stranger1->rotate(90);
6595 stranger2->setPos(10, 10);
6596 stranger2->scale(2, 2);
6597 stranger2->rotate(90);
6599 QCOMPARE(stranger1->itemTransform(stranger2).map(QPointF(10, 10)), QPointF(10, 10));
6600 QCOMPARE(stranger2->itemTransform(stranger1).map(QPointF(10, 10)), QPointF(10, 10));
6603 void tst_QGraphicsItem::opacity_data()
6605 QTest::addColumn<qreal>("p_opacity");
6606 QTest::addColumn<int>("p_opacityFlags");
6607 QTest::addColumn<qreal>("c1_opacity");
6608 QTest::addColumn<int>("c1_opacityFlags");
6609 QTest::addColumn<qreal>("c2_opacity");
6610 QTest::addColumn<int>("c2_opacityFlags");
6611 QTest::addColumn<qreal>("p_effectiveOpacity");
6612 QTest::addColumn<qreal>("c1_effectiveOpacity");
6613 QTest::addColumn<qreal>("c2_effectiveOpacity");
6614 QTest::addColumn<qreal>("c3_effectiveOpacity");
6616 // Modify the opacity and see how it propagates
6617 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
6618 << qreal(1.0) << qreal(1.0) << qreal(1.0) << qreal(1.0);
6619 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
6620 << qreal(0.5) << qreal(0.5) << qreal(0.5) << qreal(0.5);
6621 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
6622 << qreal(0.5) << qreal(0.05) << qreal(0.05) << qreal(0.05);
6623 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
6624 << qreal(0.0) << qreal(0.0) << qreal(0.0) << qreal(0.0);
6626 // Parent doesn't propagate to children - now modify the opacity and see how it propagates
6627 int flags = QGraphicsItem::ItemDoesntPropagateOpacityToChildren;
6628 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
6629 << qreal(1.0) << qreal(1.0) << qreal(1.0) << qreal(1.0);
6630 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
6631 << qreal(0.5) << qreal(1.0) << qreal(1.0) << qreal(1.0);
6632 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
6633 << qreal(0.5) << qreal(0.1) << qreal(0.1) << qreal(0.1);
6634 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
6635 << qreal(0.0) << qreal(1.0) << qreal(1.0) << qreal(1.0);
6637 // Child ignores parent - now modify the opacity and see how it propagates
6638 flags = QGraphicsItem::ItemIgnoresParentOpacity;
6639 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
6640 << qreal(1.0) << qreal(1.0) << qreal(1.0) << qreal(1.0);
6641 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
6642 << qreal(0.5) << qreal(0.5) << qreal(0.25) << qreal(0.25);
6643 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
6644 << qreal(0.2) << qreal(0.2) << qreal(0.04) << qreal(0.04);
6645 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
6646 << qreal(0.0) << qreal(0.0) << qreal(0.0) << qreal(0.0);
6648 // Child ignores parent and doesn't propagate - now modify the opacity and see how it propagates
6649 flags = QGraphicsItem::ItemIgnoresParentOpacity | QGraphicsItem::ItemDoesntPropagateOpacityToChildren;
6650 QTest::newRow("M: 1.0 0 1.0 1 1.0 1.0 1.0 1.0 1.0") << qreal(1.0) << 0 // p
6651 << qreal(1.0) << flags // c1 (no prop)
6652 << qreal(1.0) << 0 // c2
6653 << qreal(1.0) << qreal(1.0) << qreal(1.0) << qreal(1.0);
6654 QTest::newRow("M: 0.5 0 1.0 1 1.0 1.0 1.0 1.0 1.0") << qreal(0.5) << 0 // p
6655 << qreal(1.0) << flags // c1 (no prop)
6656 << qreal(1.0) << 0 // c2
6657 << qreal(0.5) << qreal(1.0) << qreal(1.0) << qreal(1.0);
6658 QTest::newRow("M: 0.5 0 0.5 1 1.0 1.0 1.0 1.0 1.0") << qreal(0.5) << 0 // p
6659 << qreal(0.5) << flags // c1 (no prop)
6660 << qreal(1.0) << 0 // c2
6661 << qreal(0.5) << qreal(0.5) << qreal(1.0) << qreal(1.0);
6662 QTest::newRow("M: 0.5 0 0.5 1 0.5 1.0 1.0 1.0 1.0") << qreal(0.5) << 0 // p
6663 << qreal(0.5) << flags // c1 (no prop)
6664 << qreal(0.5) << 0 // c2
6665 << qreal(0.5) << qreal(0.5) << qreal(0.5) << qreal(0.5);
6666 QTest::newRow("M: 1.0 0 0.5 1 0.5 1.0 1.0 1.0 1.0") << qreal(1.0) << 0 // p
6667 << qreal(0.5) << flags // c1 (no prop)
6668 << qreal(0.5) << 0 // c2
6669 << qreal(1.0) << qreal(0.5) << qreal(0.5) << qreal(0.5);
6672 void tst_QGraphicsItem::opacity()
6674 QFETCH(qreal, p_opacity);
6675 QFETCH(int, p_opacityFlags);
6676 QFETCH(qreal, p_effectiveOpacity);
6677 QFETCH(qreal, c1_opacity);
6678 QFETCH(int, c1_opacityFlags);
6679 QFETCH(qreal, c1_effectiveOpacity);
6680 QFETCH(qreal, c2_opacity);
6681 QFETCH(int, c2_opacityFlags);
6682 QFETCH(qreal, c2_effectiveOpacity);
6683 QFETCH(qreal, c3_effectiveOpacity);
6685 QGraphicsRectItem *p = new QGraphicsRectItem;
6686 QGraphicsRectItem *c1 = new QGraphicsRectItem(p);
6687 QGraphicsRectItem *c2 = new QGraphicsRectItem(c1);
6688 QGraphicsRectItem *c3 = new QGraphicsRectItem(c2);
6690 QCOMPARE(p->opacity(), qreal(1.0));
6691 QCOMPARE(p->effectiveOpacity(), qreal(1.0));
6692 int opacityMask = QGraphicsItem::ItemIgnoresParentOpacity | QGraphicsItem::ItemDoesntPropagateOpacityToChildren;
6693 QVERIFY(!(p->flags() & opacityMask));
6695 p->setOpacity(p_opacity);
6696 c1->setOpacity(c1_opacity);
6697 c2->setOpacity(c2_opacity);
6698 p->setFlags(QGraphicsItem::GraphicsItemFlags(p->flags() | p_opacityFlags));
6699 c1->setFlags(QGraphicsItem::GraphicsItemFlags(c1->flags() | c1_opacityFlags));
6700 c2->setFlags(QGraphicsItem::GraphicsItemFlags(c2->flags() | c2_opacityFlags));
6702 QCOMPARE(int(p->flags() & opacityMask), p_opacityFlags);
6703 QCOMPARE(int(c1->flags() & opacityMask), c1_opacityFlags);
6704 QCOMPARE(int(c2->flags() & opacityMask), c2_opacityFlags);
6705 QCOMPARE(p->opacity(), p_opacity);
6706 QCOMPARE(p->effectiveOpacity(), p_effectiveOpacity);
6707 QCOMPARE(c1->effectiveOpacity(), c1_effectiveOpacity);
6708 QCOMPARE(c2->effectiveOpacity(), c2_effectiveOpacity);
6709 QCOMPARE(c3->effectiveOpacity(), c3_effectiveOpacity);
6712 void tst_QGraphicsItem::opacity2()
6714 EventTester *parent = new EventTester;
6715 EventTester *child = new EventTester(parent);
6716 EventTester *grandChild = new EventTester(child);
6718 QGraphicsScene scene;
6719 scene.addItem(parent);
6721 MyGraphicsView view(&scene);
6722 if(PlatformQuirks::isAutoMaximizing())
6723 view.showFullScreen();
6726 QTest::qWaitForWindowShown(&view);
6727 QTRY_VERIFY(view.repaints >= 1);
6729 #define RESET_REPAINT_COUNTERS \
6730 parent->repaints = 0; \
6731 child->repaints = 0; \
6732 grandChild->repaints = 0; \
6735 RESET_REPAINT_COUNTERS
6737 child->setOpacity(0.0);
6739 QTRY_COMPARE(view.repaints, 1);
6740 QCOMPARE(parent->repaints, 1);
6741 QCOMPARE(child->repaints, 0);
6742 QCOMPARE(grandChild->repaints, 0);
6744 RESET_REPAINT_COUNTERS
6746 child->setOpacity(1.0);
6748 QTRY_COMPARE(view.repaints, 1);
6749 QCOMPARE(parent->repaints, 1);
6750 QCOMPARE(child->repaints, 1);
6751 QCOMPARE(grandChild->repaints, 1);
6753 RESET_REPAINT_COUNTERS
6755 parent->setOpacity(0.0);
6757 QTRY_COMPARE(view.repaints, 1);
6758 QCOMPARE(parent->repaints, 0);
6759 QCOMPARE(child->repaints, 0);
6760 QCOMPARE(grandChild->repaints, 0);
6762 RESET_REPAINT_COUNTERS
6764 parent->setOpacity(1.0);
6766 QTRY_COMPARE(view.repaints, 1);
6767 QCOMPARE(parent->repaints, 1);
6768 QCOMPARE(child->repaints, 1);
6769 QCOMPARE(grandChild->repaints, 1);
6771 grandChild->setFlag(QGraphicsItem::ItemIgnoresParentOpacity);
6772 RESET_REPAINT_COUNTERS
6774 child->setOpacity(0.0);
6776 QTRY_COMPARE(view.repaints, 1);
6777 QCOMPARE(parent->repaints, 1);
6778 QCOMPARE(child->repaints, 0);
6779 QCOMPARE(grandChild->repaints, 1);
6781 RESET_REPAINT_COUNTERS
6783 child->setOpacity(0.0); // Already 0.0; no change.
6785 QTRY_COMPARE(view.repaints, 0);
6786 QCOMPARE(parent->repaints, 0);
6787 QCOMPARE(child->repaints, 0);
6788 QCOMPARE(grandChild->repaints, 0);
6791 void tst_QGraphicsItem::opacityZeroUpdates()
6793 EventTester *parent = new EventTester;
6794 EventTester *child = new EventTester(parent);
6796 child->setPos(10, 10);
6798 QGraphicsScene scene;
6799 scene.addItem(parent);
6801 MyGraphicsView view(&scene);
6803 QTest::qWaitForWindowShown(&view);
6804 QTRY_VERIFY(view.repaints > 0);
6807 parent->setOpacity(0.0);
6811 // transforming items bounding rect to view coordinates
6812 const QRect childDeviceBoundingRect = child->deviceTransform(view.viewportTransform())
6813 .mapRect(child->boundingRect()).toRect();
6814 const QRect parentDeviceBoundingRect = parent->deviceTransform(view.viewportTransform())
6815 .mapRect(parent->boundingRect()).toRect();
6817 QRegion expectedRegion = parentDeviceBoundingRect.adjusted(-2, -2, 2, 2);
6818 expectedRegion += childDeviceBoundingRect.adjusted(-2, -2, 2, 2);
6820 COMPARE_REGIONS(view.paintedRegion, expectedRegion);
6823 class StacksBehindParentHelper : public QGraphicsRectItem
6826 StacksBehindParentHelper(QList<QGraphicsItem *> *paintedItems, const QRectF &rect, QGraphicsItem *parent = 0)
6827 : QGraphicsRectItem(rect, parent), paintedItems(paintedItems)
6830 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
6832 QGraphicsRectItem::paint(painter, option, widget);
6833 paintedItems->append(this);
6837 QList<QGraphicsItem *> *paintedItems;
6840 void tst_QGraphicsItem::itemStacksBehindParent()
6842 StacksBehindParentHelper *parent1 = new StacksBehindParentHelper(&paintedItems, QRectF(0, 0, 100, 50));
6843 StacksBehindParentHelper *child11 = new StacksBehindParentHelper(&paintedItems, QRectF(-10, 10, 50, 50), parent1);
6844 StacksBehindParentHelper *grandChild111 = new StacksBehindParentHelper(&paintedItems, QRectF(-20, 20, 50, 50), child11);
6845 StacksBehindParentHelper *child12 = new StacksBehindParentHelper(&paintedItems, QRectF(60, 10, 50, 50), parent1);
6846 StacksBehindParentHelper *grandChild121 = new StacksBehindParentHelper(&paintedItems, QRectF(70, 20, 50, 50), child12);
6848 StacksBehindParentHelper *parent2 = new StacksBehindParentHelper(&paintedItems, QRectF(0, 0, 100, 50));
6849 StacksBehindParentHelper *child21 = new StacksBehindParentHelper(&paintedItems, QRectF(-10, 10, 50, 50), parent2);
6850 StacksBehindParentHelper *grandChild211 = new StacksBehindParentHelper(&paintedItems, QRectF(-20, 20, 50, 50), child21);
6851 StacksBehindParentHelper *child22 = new StacksBehindParentHelper(&paintedItems, QRectF(60, 10, 50, 50), parent2);
6852 StacksBehindParentHelper *grandChild221 = new StacksBehindParentHelper(&paintedItems, QRectF(70, 20, 50, 50), child22);
6854 parent1->setData(0, "parent1");
6855 child11->setData(0, "child11");
6856 grandChild111->setData(0, "grandChild111");
6857 child12->setData(0, "child12");
6858 grandChild121->setData(0, "grandChild121");
6859 parent2->setData(0, "parent2");
6860 child21->setData(0, "child21");
6861 grandChild211->setData(0, "grandChild211");
6862 child22->setData(0, "child22");
6863 grandChild221->setData(0, "grandChild221");
6865 // Disambiguate siblings
6866 parent1->setZValue(1);
6867 child11->setZValue(1);
6868 child21->setZValue(1);
6870 QGraphicsScene scene;
6871 scene.addItem(parent1);
6872 scene.addItem(parent2);
6874 QGraphicsView view(&scene);
6876 QTest::qWaitForWindowShown(&view);
6877 QTRY_VERIFY(!paintedItems.isEmpty());
6879 paintedItems.clear();
6880 view.viewport()->update();
6881 QApplication::processEvents();
6882 QTRY_COMPARE(scene.items(0, 0, 100, 100), (QList<QGraphicsItem *>()
6883 << grandChild111 << child11
6884 << grandChild121 << child12 << parent1
6885 << grandChild211 << child21
6886 << grandChild221 << child22 << parent2));
6887 QTRY_COMPARE(paintedItems, QList<QGraphicsItem *>()
6888 << parent2 << child22 << grandChild221
6889 << child21 << grandChild211
6890 << parent1 << child12 << grandChild121
6891 << child11 << grandChild111);
6893 child11->setFlag(QGraphicsItem::ItemStacksBehindParent);
6895 paintedItems.clear();
6896 QApplication::processEvents();
6898 QTRY_COMPARE(scene.items(0, 0, 100, 100), (QList<QGraphicsItem *>()
6899 << grandChild121 << child12 << parent1
6900 << grandChild111 << child11
6901 << grandChild211 << child21
6902 << grandChild221 << child22 << parent2));
6903 QCOMPARE(paintedItems, QList<QGraphicsItem *>()
6904 << parent2 << child22 << grandChild221
6905 << child21 << grandChild211
6906 << child11 << grandChild111
6907 << parent1 << child12 << grandChild121);
6909 child12->setFlag(QGraphicsItem::ItemStacksBehindParent);
6910 paintedItems.clear();
6912 QApplication::processEvents();
6914 QTRY_COMPARE(scene.items(0, 0, 100, 100), (QList<QGraphicsItem *>()
6915 << parent1 << grandChild111 << child11
6916 << grandChild121 << child12
6917 << grandChild211 << child21
6918 << grandChild221 << child22 << parent2));
6919 QCOMPARE(paintedItems, QList<QGraphicsItem *>()
6920 << parent2 << child22 << grandChild221
6921 << child21 << grandChild211
6922 << child12 << grandChild121
6923 << child11 << grandChild111 << parent1);
6926 class ClippingAndTransformsScene : public QGraphicsScene
6929 QList<QGraphicsItem *> drawnItems;
6931 void drawItems(QPainter *painter, int numItems, QGraphicsItem *items[],
6932 const QStyleOptionGraphicsItem options[], QWidget *widget = 0)
6935 for (int i = 0; i < numItems; ++i)
6936 drawnItems << items[i];
6937 QGraphicsScene::drawItems(painter, numItems, items, options, widget);
6941 void tst_QGraphicsItem::nestedClipping()
6943 ClippingAndTransformsScene scene;
6944 scene.setSceneRect(-50, -50, 200, 200);
6946 QGraphicsRectItem *root = new QGraphicsRectItem(QRectF(0, 0, 100, 100));
6947 root->setBrush(QColor(0, 0, 255));
6948 root->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
6949 QGraphicsRectItem *l1 = new QGraphicsRectItem(QRectF(0, 0, 100, 100));
6950 l1->setParentItem(root);
6952 l1->setBrush(QColor(255, 0, 0));
6953 l1->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
6954 QGraphicsEllipseItem *l2 = new QGraphicsEllipseItem(QRectF(0, 0, 100, 100));
6955 l2->setParentItem(l1);
6957 l2->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
6958 l2->setBrush(QColor(255, 255, 0));
6959 QGraphicsRectItem *l3 = new QGraphicsRectItem(QRectF(0, 0, 25, 25));
6960 l3->setParentItem(l2);
6961 l3->setBrush(QColor(0, 255, 0));
6962 l3->setPos(50 - 12, -12);
6964 scene.addItem(root);
6966 root->setData(0, "root");
6967 l1->setData(0, "l1");
6968 l2->setData(0, "l2");
6969 l3->setData(0, "l3");
6971 QGraphicsView view(&scene);
6972 view.setOptimizationFlag(QGraphicsView::IndirectPainting);
6974 QTest::qWaitForWindowShown(&view);
6977 QList<QGraphicsItem *> expected;
6978 expected << root << l1 << l2 << l3;
6979 QTRY_COMPARE(scene.drawnItems, expected);
6981 QImage image(200, 200, QImage::Format_ARGB32_Premultiplied);
6984 QPainter painter(&image);
6985 scene.render(&painter);
6988 // Check transparent areas
6989 QCOMPARE(image.pixel(100, 25), qRgba(0, 0, 0, 0));
6990 QCOMPARE(image.pixel(100, 175), qRgba(0, 0, 0, 0));
6991 QCOMPARE(image.pixel(25, 100), qRgba(0, 0, 0, 0));
6992 QCOMPARE(image.pixel(175, 100), qRgba(0, 0, 0, 0));
6993 QCOMPARE(image.pixel(70, 80), qRgba(255, 0, 0, 255));
6994 QCOMPARE(image.pixel(80, 130), qRgba(255, 255, 0, 255));
6995 QCOMPARE(image.pixel(92, 105), qRgba(0, 255, 0, 255));
6996 QCOMPARE(image.pixel(105, 105), qRgba(0, 0, 255, 255));
6998 // Enable this to compare if the test starts failing.
6999 image.save("nestedClipping_reference.png");
7003 class TransformDebugItem : public QGraphicsRectItem
7006 TransformDebugItem()
7007 : QGraphicsRectItem(QRectF(-10, -10, 20, 20))
7009 setBrush(QColor(qrand() % 256, qrand() % 256, qrand() % 256));
7014 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
7015 QWidget *widget = 0)
7017 x = painter->worldTransform();
7018 QGraphicsRectItem::paint(painter, option, widget);
7022 void tst_QGraphicsItem::nestedClippingTransforms()
7024 TransformDebugItem *rootClipper = new TransformDebugItem;
7025 rootClipper->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
7026 TransformDebugItem *child = new TransformDebugItem;
7027 child->setParentItem(rootClipper);
7028 child->setPos(2, 2);
7029 TransformDebugItem *grandChildClipper = new TransformDebugItem;
7030 grandChildClipper->setParentItem(child);
7031 grandChildClipper->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
7032 grandChildClipper->setPos(4, 4);
7033 TransformDebugItem *greatGrandChild = new TransformDebugItem;
7034 greatGrandChild->setPos(2, 2);
7035 greatGrandChild->setParentItem(grandChildClipper);
7036 TransformDebugItem *grandChildClipper2 = new TransformDebugItem;
7037 grandChildClipper2->setParentItem(child);
7038 grandChildClipper2->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
7039 grandChildClipper2->setPos(8, 8);
7040 TransformDebugItem *greatGrandChild2 = new TransformDebugItem;
7041 greatGrandChild2->setPos(2, 2);
7042 greatGrandChild2->setParentItem(grandChildClipper2);
7043 TransformDebugItem *grandChildClipper3 = new TransformDebugItem;
7044 grandChildClipper3->setParentItem(child);
7045 grandChildClipper3->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
7046 grandChildClipper3->setPos(12, 12);
7047 TransformDebugItem *greatGrandChild3 = new TransformDebugItem;
7048 greatGrandChild3->setPos(2, 2);
7049 greatGrandChild3->setParentItem(grandChildClipper3);
7051 QGraphicsScene scene;
7052 scene.addItem(rootClipper);
7054 QImage image(scene.itemsBoundingRect().size().toSize(), QImage::Format_ARGB32_Premultiplied);
7060 QCOMPARE(rootClipper->x, QTransform(1, 0, 0, 0, 1, 0, 10, 10, 1));
7061 QCOMPARE(child->x, QTransform(1, 0, 0, 0, 1, 0, 12, 12, 1));
7062 QCOMPARE(grandChildClipper->x, QTransform(1, 0, 0, 0, 1, 0, 16, 16, 1));
7063 QCOMPARE(greatGrandChild->x, QTransform(1, 0, 0, 0, 1, 0, 18, 18, 1));
7064 QCOMPARE(grandChildClipper2->x, QTransform(1, 0, 0, 0, 1, 0, 20, 20, 1));
7065 QCOMPARE(greatGrandChild2->x, QTransform(1, 0, 0, 0, 1, 0, 22, 22, 1));
7066 QCOMPARE(grandChildClipper3->x, QTransform(1, 0, 0, 0, 1, 0, 24, 24, 1));
7067 QCOMPARE(greatGrandChild3->x, QTransform(1, 0, 0, 0, 1, 0, 26, 26, 1));
7070 void tst_QGraphicsItem::sceneTransformCache()
7072 // Test that an item's scene transform is updated correctly when the
7073 // parent is transformed.
7074 QGraphicsScene scene;
7075 QGraphicsRectItem *rect = scene.addRect(0, 0, 100, 100);
7076 QGraphicsRectItem *rect2 = scene.addRect(0, 0, 100, 100);
7077 rect2->setParentItem(rect);
7079 rect->translate(0, 50);
7080 QGraphicsView view(&scene);
7083 qt_x11_wait_for_window_manager(&view);
7086 rect->translate(0, 100);
7088 x.translate(0, 150);
7090 QCOMPARE(rect2->sceneTransform(), x);
7092 scene.removeItem(rect);
7094 //Crazy use case : rect4 child of rect3 so the transformation of rect4 will be cached.Good!
7095 //We remove rect4 from the scene, then the validTransform bit flag is set to 0 and the index of the cache
7096 //add to the freeTransformSlots. The problem was that sceneTransformIndex was not set to -1 so if a new item arrive
7097 //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
7098 //added back to the scene then it will set the transform to his old sceneTransformIndex value that will erase the new
7099 //value of rect6 so rect6 transform will be wrong.
7100 QGraphicsRectItem *rect3 = scene.addRect(0, 0, 100, 100);
7101 QGraphicsRectItem *rect4 = scene.addRect(0, 0, 100, 100);
7102 rect3->setPos(QPointF(10,10));
7104 rect4->setParentItem(rect3);
7105 rect4->setPos(QPointF(10,10));
7107 QCOMPARE(rect4->mapToScene(rect4->boundingRect().topLeft()), QPointF(20,20));
7109 scene.removeItem(rect4);
7110 //rect4 transform is local only
7111 QCOMPARE(rect4->mapToScene(rect4->boundingRect().topLeft()), QPointF(10,10));
7113 QGraphicsRectItem *rect5 = scene.addRect(0, 0, 100, 100);
7114 QGraphicsRectItem *rect6 = scene.addRect(0, 0, 100, 100);
7115 rect5->setPos(QPointF(20,20));
7117 rect6->setParentItem(rect5);
7118 rect6->setPos(QPointF(10,10));
7119 //test if rect6 transform is ok
7120 QCOMPARE(rect6->mapToScene(rect6->boundingRect().topLeft()), QPointF(30,30));
7122 scene.addItem(rect4);
7124 QCOMPARE(rect4->mapToScene(rect4->boundingRect().topLeft()), QPointF(10,10));
7125 //test if rect6 transform is still correct
7126 QCOMPARE(rect6->mapToScene(rect6->boundingRect().topLeft()), QPointF(30,30));
7129 void tst_QGraphicsItem::tabChangesFocus_data()
7131 QTest::addColumn<bool>("tabChangesFocus");
7132 QTest::newRow("tab changes focus") << true;
7133 QTest::newRow("tab doesn't change focus") << false;
7136 void tst_QGraphicsItem::tabChangesFocus()
7138 QFETCH(bool, tabChangesFocus);
7140 QGraphicsScene scene;
7141 QGraphicsTextItem *item = scene.addText("Hello");
7142 item->setTabChangesFocus(tabChangesFocus);
7143 item->setTextInteractionFlags(Qt::TextEditorInteraction);
7146 QDial *dial1 = new QDial;
7147 QGraphicsView *view = new QGraphicsView(&scene);
7149 QDial *dial2 = new QDial;
7150 QVBoxLayout *layout = new QVBoxLayout;
7151 layout->addWidget(dial1);
7152 layout->addWidget(view);
7153 layout->addWidget(dial2);
7156 widget.setLayout(layout);
7158 QTest::qWaitForWindowShown(&widget);
7161 QTRY_VERIFY(scene.isActive());
7165 QTRY_VERIFY(dial1->hasFocus());
7167 QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
7169 QTRY_VERIFY(view->hasFocus());
7170 QTRY_VERIFY(item->hasFocus());
7172 QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
7175 if (tabChangesFocus) {
7176 QTRY_VERIFY(!view->hasFocus());
7177 QTRY_VERIFY(!item->hasFocus());
7178 QTRY_VERIFY(dial2->hasFocus());
7180 QTRY_VERIFY(view->hasFocus());
7181 QTRY_VERIFY(item->hasFocus());
7182 QCOMPARE(item->toPlainText(), QString("\tHello"));
7186 void tst_QGraphicsItem::cacheMode()
7188 QGraphicsScene scene(0, 0, 100, 100);
7189 QGraphicsView view(&scene);
7190 view.resize(150, 150);
7192 QApplication::setActiveWindow(&view);
7193 QTest::qWaitForWindowShown(&view);
7195 // Increase the probability of window activation
7196 // not causing another repaint of test items.
7199 EventTester *tester = new EventTester;
7200 EventTester *testerChild = new EventTester;
7201 testerChild->setParentItem(tester);
7202 EventTester *testerChild2 = new EventTester;
7203 testerChild2->setParentItem(testerChild);
7204 testerChild2->setFlag(QGraphicsItem::ItemIgnoresTransformations);
7206 scene.addItem(tester);
7209 for (int i = 0; i < 2; ++i) {
7210 // No visual change.
7211 QTRY_COMPARE(tester->repaints, 1);
7212 QCOMPARE(testerChild->repaints, 1);
7213 QCOMPARE(testerChild2->repaints, 1);
7214 tester->setCacheMode(QGraphicsItem::NoCache);
7215 testerChild->setCacheMode(QGraphicsItem::NoCache);
7216 testerChild2->setCacheMode(QGraphicsItem::NoCache);
7218 QTRY_COMPARE(tester->repaints, 1);
7219 QCOMPARE(testerChild->repaints, 1);
7220 QCOMPARE(testerChild2->repaints, 1);
7221 tester->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
7222 testerChild->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
7223 testerChild2->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
7227 // The first move causes a repaint as the item is painted into its pixmap.
7228 // (Only occurs if the item has previously been painted without cache).
7229 tester->setPos(10, 10);
7230 testerChild->setPos(10, 10);
7231 testerChild2->setPos(10, 10);
7233 QTRY_COMPARE(tester->repaints, 2);
7234 QCOMPARE(testerChild->repaints, 2);
7235 QCOMPARE(testerChild2->repaints, 2);
7237 // Consecutive moves should not repaint.
7238 tester->setPos(20, 20);
7239 testerChild->setPos(20, 20);
7240 testerChild2->setPos(20, 20);
7242 QCOMPARE(tester->repaints, 2);
7243 QCOMPARE(testerChild->repaints, 2);
7244 QCOMPARE(testerChild2->repaints, 2);
7246 // Translating does not result in a repaint.
7247 tester->translate(10, 10);
7249 QTRY_COMPARE(tester->repaints, 2);
7250 QCOMPARE(testerChild->repaints, 2);
7251 QCOMPARE(testerChild2->repaints, 2);
7253 // Rotating results in a repaint.
7256 QTRY_COMPARE(tester->repaints, 3);
7257 QCOMPARE(testerChild->repaints, 3);
7258 QCOMPARE(testerChild2->repaints, 2);
7260 // Change to ItemCoordinateCache (triggers repaint).
7261 tester->setCacheMode(QGraphicsItem::ItemCoordinateCache); // autosize
7262 testerChild->setCacheMode(QGraphicsItem::ItemCoordinateCache); // autosize
7263 testerChild2->setCacheMode(QGraphicsItem::ItemCoordinateCache); // autosize
7265 QTRY_COMPARE(tester->repaints, 4);
7266 QCOMPARE(testerChild->repaints, 4);
7267 QCOMPARE(testerChild2->repaints, 3);
7269 // Rotating items with ItemCoordinateCache doesn't cause a repaint.
7271 testerChild->rotate(22);
7272 testerChild2->rotate(22);
7274 QTRY_COMPARE(tester->repaints, 4);
7275 QTRY_COMPARE(testerChild->repaints, 4);
7276 QTRY_COMPARE(testerChild2->repaints, 3);
7277 tester->resetTransform();
7278 testerChild->resetTransform();
7279 testerChild2->resetTransform();
7281 // Explicit update causes a repaint.
7282 tester->update(0, 0, 5, 5);
7284 QTRY_COMPARE(tester->repaints, 5);
7285 QCOMPARE(testerChild->repaints, 4);
7286 QCOMPARE(testerChild2->repaints, 3);
7288 // Updating outside the item's bounds does not cause a repaint.
7289 tester->update(10, 10, 5, 5);
7291 QTRY_COMPARE(tester->repaints, 5);
7292 QCOMPARE(testerChild->repaints, 4);
7293 QCOMPARE(testerChild2->repaints, 3);
7295 // Resizing an item should cause a repaint of that item. (because of
7297 tester->setGeometry(QRectF(-15, -15, 30, 30));
7299 QTRY_COMPARE(tester->repaints, 6);
7300 QCOMPARE(testerChild->repaints, 4);
7301 QCOMPARE(testerChild2->repaints, 3);
7304 tester->setCacheMode(QGraphicsItem::ItemCoordinateCache, QSize(30, 30));
7305 testerChild->setCacheMode(QGraphicsItem::ItemCoordinateCache, QSize(30, 30));
7306 testerChild2->setCacheMode(QGraphicsItem::ItemCoordinateCache, QSize(30, 30));
7308 QTRY_COMPARE(tester->repaints, 7);
7309 QCOMPARE(testerChild->repaints, 5);
7310 QCOMPARE(testerChild2->repaints, 4);
7312 // Resizing the item should cause a repaint.
7313 testerChild->setGeometry(QRectF(-15, -15, 30, 30));
7315 QTRY_COMPARE(tester->repaints, 7);
7316 QCOMPARE(testerChild->repaints, 6);
7317 QCOMPARE(testerChild2->repaints, 4);
7319 // Scaling the view does not cause a repaint.
7320 view.scale(0.7, 0.7);
7322 QTRY_COMPARE(tester->repaints, 7);
7323 QCOMPARE(testerChild->repaints, 6);
7324 QCOMPARE(testerChild2->repaints, 4);
7326 // Switch to device coordinate cache.
7327 tester->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
7328 testerChild->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
7329 testerChild2->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
7331 QTRY_COMPARE(tester->repaints, 8);
7332 QCOMPARE(testerChild->repaints, 7);
7333 QCOMPARE(testerChild2->repaints, 5);
7335 // Scaling the view back should cause repaints for two of the items.
7336 view.setTransform(QTransform());
7338 QTRY_COMPARE(tester->repaints, 9);
7339 QCOMPARE(testerChild->repaints, 8);
7340 QCOMPARE(testerChild2->repaints, 5);
7342 // Rotating the base item (perspective) should repaint two items.
7343 tester->setTransform(QTransform().rotate(10, Qt::XAxis));
7345 QTRY_COMPARE(tester->repaints, 10);
7346 QCOMPARE(testerChild->repaints, 9);
7347 QCOMPARE(testerChild2->repaints, 5);
7349 // Moving the middle item should case a repaint even if it's a move,
7350 // because the parent is rotated with a perspective.
7351 testerChild->setPos(1, 1);
7353 QTRY_COMPARE(tester->repaints, 11);
7354 QTRY_COMPARE(testerChild->repaints, 10);
7355 QTRY_COMPARE(testerChild2->repaints, 5);
7356 tester->resetTransform();
7359 tester->setGeometry(QRectF(-4000, -4000, 8000, 8000));
7360 QTRY_COMPARE(tester->repaints, 12);
7361 QTRY_COMPARE(testerChild->repaints, 11);
7362 QTRY_COMPARE(testerChild2->repaints, 5);
7364 // Move the large item - will cause a repaint as the
7365 // cache is clipped.
7366 tester->setPos(5, 0);
7367 QTRY_COMPARE(tester->repaints, 13);
7368 QTRY_COMPARE(testerChild->repaints, 11);
7369 QTRY_COMPARE(testerChild2->repaints, 5);
7371 // Hiding and showing should invalidate the cache
7375 QTRY_COMPARE(tester->repaints, 14);
7376 QTRY_COMPARE(testerChild->repaints, 12);
7377 QTRY_COMPARE(testerChild2->repaints, 6);
7380 void tst_QGraphicsItem::cacheMode2()
7382 QGraphicsScene scene(0, 0, 100, 100);
7383 QGraphicsView view(&scene);
7384 view.resize(150, 150);
7386 QApplication::setActiveWindow(&view);
7387 QTest::qWaitForWindowShown(&view);
7389 // Increase the probability of window activation
7390 // not causing another repaint of test items.
7393 EventTester *tester = new EventTester;
7394 scene.addItem(tester);
7396 QTRY_COMPARE(tester->repaints, 1);
7398 // Switching from NoCache to NoCache (no repaint)
7399 tester->setCacheMode(QGraphicsItem::NoCache);
7401 QTRY_COMPARE(tester->repaints, 1);
7403 // Switching from NoCache to DeviceCoordinateCache (no repaint)
7404 tester->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
7406 QTRY_COMPARE(tester->repaints, 1);
7408 // Switching from DeviceCoordinateCache to DeviceCoordinateCache (no repaint)
7409 tester->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
7411 QTRY_COMPARE(tester->repaints, 1);
7413 // Switching from DeviceCoordinateCache to NoCache (no repaint)
7414 tester->setCacheMode(QGraphicsItem::NoCache);
7416 QTRY_COMPARE(tester->repaints, 1);
7418 // Switching from NoCache to ItemCoordinateCache (repaint)
7419 tester->setCacheMode(QGraphicsItem::ItemCoordinateCache);
7421 QTRY_COMPARE(tester->repaints, 2);
7423 // Switching from ItemCoordinateCache to ItemCoordinateCache (no repaint)
7424 tester->setCacheMode(QGraphicsItem::ItemCoordinateCache);
7426 QTRY_COMPARE(tester->repaints, 2);
7428 // Switching from ItemCoordinateCache to ItemCoordinateCache with different size (repaint)
7429 tester->setCacheMode(QGraphicsItem::ItemCoordinateCache, QSize(100, 100));
7431 QTRY_COMPARE(tester->repaints, 3);
7433 // Switching from ItemCoordinateCache to NoCache (repaint)
7434 tester->setCacheMode(QGraphicsItem::NoCache);
7436 QTRY_COMPARE(tester->repaints, 4);
7438 // Switching from DeviceCoordinateCache to ItemCoordinateCache (repaint)
7439 tester->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
7441 QTRY_COMPARE(tester->repaints, 4);
7442 tester->setCacheMode(QGraphicsItem::ItemCoordinateCache);
7444 QTRY_COMPARE(tester->repaints, 5);
7446 // Switching from ItemCoordinateCache to DeviceCoordinateCache (repaint)
7447 tester->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
7449 QTRY_COMPARE(tester->repaints, 6);
7452 void tst_QGraphicsItem::updateCachedItemAfterMove()
7454 // A simple item that uses ItemCoordinateCache
7455 EventTester *tester = new EventTester;
7456 tester->setCacheMode(QGraphicsItem::ItemCoordinateCache);
7458 // Add to a scene, show in a view, ensure it's painted and reset its
7460 QGraphicsScene scene;
7461 scene.addItem(tester);
7462 QGraphicsView view(&scene);
7464 QTest::qWaitForWindowShown(&view);
7467 QTRY_VERIFY(tester->repaints > 0);
7468 tester->repaints = 0;
7470 // Move the item, should not cause repaints
7471 tester->setPos(10, 0);
7473 QCOMPARE(tester->repaints, 0);
7475 // Move then update, should cause one repaint
7476 tester->setPos(20, 0);
7479 QCOMPARE(tester->repaints, 1);
7481 // Hiding the item doesn't cause a repaint
7484 QCOMPARE(tester->repaints, 1);
7486 // Moving a hidden item doesn't cause a repaint
7487 tester->setPos(30, 0);
7490 QCOMPARE(tester->repaints, 1);
7493 class Track : public QGraphicsRectItem
7496 Track(const QRectF &rect)
7497 : QGraphicsRectItem(rect)
7499 setAcceptHoverEvents(true);
7502 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0)
7504 QGraphicsRectItem::paint(painter, option, widget);
7505 painter->drawText(boundingRect(), Qt::AlignCenter, QString("%1x%2\n%3x%4").arg(p.x()).arg(p.y()).arg(sp.x()).arg(sp.y()));
7509 void hoverMoveEvent(QGraphicsSceneHoverEvent *event)
7512 sp = event->widget()->mapFromGlobal(event->screenPos());
7520 void tst_QGraphicsItem::deviceTransform_data()
7522 QTest::addColumn<bool>("untransformable1");
7523 QTest::addColumn<bool>("untransformable2");
7524 QTest::addColumn<bool>("untransformable3");
7525 QTest::addColumn<qreal>("rotation1");
7526 QTest::addColumn<qreal>("rotation2");
7527 QTest::addColumn<qreal>("rotation3");
7528 QTest::addColumn<QTransform>("deviceX");
7529 QTest::addColumn<QPointF>("mapResult1");
7530 QTest::addColumn<QPointF>("mapResult2");
7531 QTest::addColumn<QPointF>("mapResult3");
7533 QTest::newRow("nil") << false << false << false
7534 << qreal(0.0) << qreal(0.0) << qreal(0.0)
7536 << QPointF(150, 150) << QPointF(250, 250) << QPointF(350, 350);
7537 QTest::newRow("deviceX rot 90") << false << false << false
7538 << qreal(0.0) << qreal(0.0) << qreal(0.0)
7539 << QTransform().rotate(90)
7540 << QPointF(-150, 150) << QPointF(-250, 250) << QPointF(-350, 350);
7541 QTest::newRow("deviceX rot 90 100") << true << false << false
7542 << qreal(0.0) << qreal(0.0) << qreal(0.0)
7543 << QTransform().rotate(90)
7544 << QPointF(-50, 150) << QPointF(50, 250) << QPointF(150, 350);
7545 QTest::newRow("deviceX rot 90 010") << false << true << false
7546 << qreal(0.0) << qreal(0.0) << qreal(0.0)
7547 << QTransform().rotate(90)
7548 << QPointF(-150, 150) << QPointF(-150, 250) << QPointF(-50, 350);
7549 QTest::newRow("deviceX rot 90 001") << false << false << true
7550 << qreal(0.0) << qreal(0.0) << qreal(0.0)
7551 << QTransform().rotate(90)
7552 << QPointF(-150, 150) << QPointF(-250, 250) << QPointF(-250, 350);
7553 QTest::newRow("deviceX rot 90 111") << true << true << true
7554 << qreal(0.0) << qreal(0.0) << qreal(0.0)
7555 << QTransform().rotate(90)
7556 << QPointF(-50, 150) << QPointF(50, 250) << QPointF(150, 350);
7557 QTest::newRow("deviceX rot 90 101") << true << false << true
7558 << qreal(0.0) << qreal(0.0) << qreal(0.0)
7559 << QTransform().rotate(90)
7560 << QPointF(-50, 150) << QPointF(50, 250) << QPointF(150, 350);
7563 void tst_QGraphicsItem::deviceTransform()
7565 QFETCH(bool, untransformable1);
7566 QFETCH(bool, untransformable2);
7567 QFETCH(bool, untransformable3);
7568 QFETCH(qreal, rotation1);
7569 QFETCH(qreal, rotation2);
7570 QFETCH(qreal, rotation3);
7571 QFETCH(QTransform, deviceX);
7572 QFETCH(QPointF, mapResult1);
7573 QFETCH(QPointF, mapResult2);
7574 QFETCH(QPointF, mapResult3);
7576 QGraphicsScene scene;
7577 Track *rect1 = new Track(QRectF(0, 0, 100, 100));
7578 Track *rect2 = new Track(QRectF(0, 0, 100, 100));
7579 Track *rect3 = new Track(QRectF(0, 0, 100, 100));
7580 rect2->setParentItem(rect1);
7581 rect3->setParentItem(rect2);
7582 rect1->setPos(100, 100);
7583 rect2->setPos(100, 100);
7584 rect3->setPos(100, 100);
7585 rect1->rotate(rotation1);
7586 rect2->rotate(rotation2);
7587 rect3->rotate(rotation3);
7588 rect1->setFlag(QGraphicsItem::ItemIgnoresTransformations, untransformable1);
7589 rect2->setFlag(QGraphicsItem::ItemIgnoresTransformations, untransformable2);
7590 rect3->setFlag(QGraphicsItem::ItemIgnoresTransformations, untransformable3);
7591 rect1->setBrush(Qt::red);
7592 rect2->setBrush(Qt::green);
7593 rect3->setBrush(Qt::blue);
7594 scene.addItem(rect1);
7596 QCOMPARE(rect1->deviceTransform(deviceX).map(QPointF(50, 50)), mapResult1);
7597 QCOMPARE(rect2->deviceTransform(deviceX).map(QPointF(50, 50)), mapResult2);
7598 QCOMPARE(rect3->deviceTransform(deviceX).map(QPointF(50, 50)), mapResult3);
7601 void tst_QGraphicsItem::update()
7603 QGraphicsScene scene;
7604 scene.setSceneRect(-100, -100, 200, 200);
7606 MyGraphicsView view(&scene,&topLevel);
7608 topLevel.resize(300, 300);
7611 qt_x11_wait_for_window_manager(&view);
7615 EventTester *item = new EventTester;
7616 scene.addItem(item);
7617 QTest::qWait(100); // Make sure all pending updates are processed.
7620 item->update(); // Item marked as dirty
7621 scene.update(); // Entire scene marked as dirty
7622 qApp->processEvents();
7623 QCOMPARE(item->repaints, 1);
7625 // Make sure the dirty state from the previous update is reset so that
7626 // the item don't think it is already dirty and discards this update.
7628 qApp->processEvents();
7629 QCOMPARE(item->repaints, 2);
7631 // Make sure a partial update doesn't cause a full update to be discarded.
7634 item->update(QRectF(0, 0, 5, 5));
7636 qApp->processEvents();
7637 QCOMPARE(item->repaints, 1);
7638 QCOMPARE(view.repaints, 1);
7639 QRect itemDeviceBoundingRect = item->deviceTransform(view.viewportTransform())
7640 .mapRect(item->boundingRect()).toAlignedRect();
7641 QRegion expectedRegion = itemDeviceBoundingRect.adjusted(-2, -2, 2, 2);
7642 // The entire item's bounding rect (adjusted for antialiasing) should have been painted.
7643 QCOMPARE(view.paintedRegion, expectedRegion);
7645 // Make sure update requests outside the bounding rect are discarded.
7648 item->update(-15, -15, 5, 5); // Item's brect: (-10, -10, 20, 20)
7649 qApp->processEvents();
7650 QCOMPARE(item->repaints, 0);
7651 QCOMPARE(view.repaints, 0);
7653 // Make sure the area occupied by an item is repainted when hiding it.
7656 item->update(); // Full update; all sub-sequent update requests are discarded.
7657 item->hide(); // visible set to 0. ignoreVisible must be set to 1; the item won't be processed otherwise.
7658 qApp->processEvents();
7659 QCOMPARE(item->repaints, 0);
7660 QCOMPARE(view.repaints, 1);
7661 // The entire item's bounding rect (adjusted for antialiasing) should have been painted.
7662 QCOMPARE(view.paintedRegion, expectedRegion);
7664 // Make sure item is repainted when shown (after being hidden).
7668 qApp->processEvents();
7669 QCOMPARE(item->repaints, 1);
7670 QCOMPARE(view.repaints, 1);
7671 // The entire item's bounding rect (adjusted for antialiasing) should have been painted.
7672 QCOMPARE(view.paintedRegion, expectedRegion);
7676 qApp->processEvents();
7678 const QPointF originalPos = item->pos();
7679 item->setPos(5000, 5000);
7680 qApp->processEvents();
7681 QCOMPARE(item->repaints, 0);
7682 QCOMPARE(view.repaints, 0);
7683 qApp->processEvents();
7685 item->setPos(originalPos);
7686 qApp->processEvents();
7687 QCOMPARE(item->repaints, 0);
7688 QCOMPARE(view.repaints, 0);
7690 qApp->processEvents();
7691 QCOMPARE(item->repaints, 1);
7692 QCOMPARE(view.repaints, 1);
7693 // The entire item's bounding rect (adjusted for antialiasing) should have been painted.
7694 QCOMPARE(view.paintedRegion, expectedRegion);
7696 QGraphicsViewPrivate *viewPrivate = static_cast<QGraphicsViewPrivate *>(qt_widget_private(&view));
7697 item->setPos(originalPos + QPoint(50, 50));
7698 viewPrivate->updateAll();
7699 QVERIFY(viewPrivate->fullUpdatePending);
7703 item->setPos(originalPos);
7705 qApp->processEvents();
7706 QCOMPARE(item->repaints, 1);
7707 QCOMPARE(view.repaints, 1);
7708 COMPARE_REGIONS(view.paintedRegion, expectedRegion + expectedRegion.translated(50, 50));
7710 // Make sure moving a parent item triggers an update on the children
7711 // (even though the parent itself is outside the viewport).
7712 QGraphicsRectItem *parent = new QGraphicsRectItem(0, 0, 10, 10);
7713 parent->setPos(-400, 0);
7714 item->setParentItem(parent);
7715 item->setPos(400, 0);
7716 scene.addItem(parent);
7718 itemDeviceBoundingRect = item->deviceTransform(view.viewportTransform())
7719 .mapRect(item->boundingRect()).toAlignedRect();
7720 expectedRegion = itemDeviceBoundingRect.adjusted(-2, -2, 2, 2);
7723 parent->translate(-400, 0);
7724 qApp->processEvents();
7725 QCOMPARE(item->repaints, 0);
7726 QCOMPARE(view.repaints, 1);
7727 QCOMPARE(view.paintedRegion, expectedRegion);
7730 parent->translate(400, 0);
7731 qApp->processEvents();
7732 QCOMPARE(item->repaints, 1);
7733 QCOMPARE(view.repaints, 1);
7734 QCOMPARE(view.paintedRegion, expectedRegion);
7735 QCOMPARE(view.paintedRegion, expectedRegion);
7738 void tst_QGraphicsItem::setTransformProperties_data()
7740 QTest::addColumn<QPointF>("origin");
7741 QTest::addColumn<qreal>("rotation");
7742 QTest::addColumn<qreal>("scale");
7744 QTest::newRow("nothing") << QPointF() << qreal(0.0) << qreal(1.0);
7746 QTest::newRow("rotation") << QPointF() << qreal(42.2) << qreal(1.0);
7748 QTest::newRow("rotation dicentred") << QPointF(qreal(22.3), qreal(-56.2))
7752 QTest::newRow("Scale") << QPointF() << qreal(0.0)
7755 QTest::newRow("Everything dicentred") << QPointF(qreal(22.3), qreal(-56.2)) << qreal(-175) << qreal(196);
7759 * the normal QCOMPARE doesn't work because it doesn't use qFuzzyCompare
7761 #define QCOMPARE_TRANSFORM(X1, X2) QVERIFY(((X1)*(X2).inverted()).isIdentity())
7763 void tst_QGraphicsItem::setTransformProperties()
7765 QFETCH(QPointF,origin);
7766 QFETCH(qreal,rotation);
7767 QFETCH(qreal,scale);
7770 result.translate(origin.x(), origin.y());
7771 result.rotate(rotation, Qt::ZAxis);
7772 result.scale(scale, scale);
7773 result.translate(-origin.x(), -origin.y());
7775 QGraphicsScene scene;
7776 QGraphicsRectItem *item = new QGraphicsRectItem(QRectF(0, 0, 100, 100));
7777 scene.addItem(item);
7779 item->setRotation(rotation);
7780 item->setScale(scale);
7781 item->setTransformOriginPoint(origin);
7783 QCOMPARE(item->rotation(), rotation);
7784 QCOMPARE(item->scale(), scale);
7785 QCOMPARE(item->transformOriginPoint(), origin);
7787 QCOMPARE(QTransform(), item->transform());
7788 QCOMPARE(result, item->sceneTransform());
7790 //-----------------------------------------------------------------
7791 //Change the rotation Z
7792 item->setRotation(45);
7794 result2.translate(origin.x(), origin.y());
7796 result2.scale(scale, scale);
7797 result2.translate(-origin.x(), -origin.y());
7799 QCOMPARE(item->rotation(), 45.);
7800 QCOMPARE(item->scale(), scale);
7801 QCOMPARE(item->transformOriginPoint(), origin);
7803 QCOMPARE(QTransform(), item->transform());
7804 QCOMPARE(result2, item->sceneTransform());
7806 //-----------------------------------------------------------------
7807 // calling setTransform() and setPos should change the sceneTransform
7808 item->setTransform(result);
7809 item->setPos(100, -150.5);
7811 QCOMPARE(item->rotation(), 45.);
7812 QCOMPARE(item->scale(), scale);
7813 QCOMPARE(item->transformOriginPoint(), origin);
7814 QCOMPARE(result, item->transform());
7816 QTransform result3(result);
7818 result3.translate(origin.x(), origin.y());
7820 result3.scale(scale, scale);
7821 result3.translate(-origin.x(), -origin.y());
7823 result3 *= QTransform::fromTranslate(100, -150.5); //the pos;
7825 QCOMPARE(result3, item->sceneTransform());
7827 //-----------------------------------------------------
7828 // setting the propertiees should be the same as setting a transform
7829 {//with center origin on the matrix
7830 QGraphicsRectItem *item1 = new QGraphicsRectItem(QRectF(50.2, -150, 230.5, 119));
7831 scene.addItem(item1);
7832 QGraphicsRectItem *item2 = new QGraphicsRectItem(QRectF(50.2, -150, 230.5, 119));
7833 scene.addItem(item2);
7835 item1->setPos(12.3, -5);
7836 item2->setPos(12.3, -5);
7837 item1->setRotation(rotation);
7838 item1->setScale(scale);
7839 item1->setTransformOriginPoint(origin);
7841 item2->setTransform(result);
7843 QCOMPARE_TRANSFORM(item1->sceneTransform(), item2->sceneTransform());
7845 QCOMPARE_TRANSFORM(item1->itemTransform(item2), QTransform());
7846 QCOMPARE_TRANSFORM(item2->itemTransform(item1), QTransform());
7850 class MyStyleOptionTester : public QGraphicsRectItem
7853 MyStyleOptionTester(const QRectF &rect)
7854 : QGraphicsRectItem(rect), startTrack(false)
7857 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0)
7860 //Doesn't use the extended style option so the exposed rect is the boundingRect
7861 if (!(flags() & QGraphicsItem::ItemUsesExtendedStyleOption)) {
7862 QCOMPARE(option->exposedRect, boundingRect());
7863 QCOMPARE(option->matrix, QMatrix());
7865 QVERIFY(option->exposedRect != QRect());
7866 QVERIFY(option->exposedRect != boundingRect());
7867 QCOMPARE(option->matrix, sceneTransform().toAffine());
7870 QGraphicsRectItem::paint(painter, option, widget);
7875 void tst_QGraphicsItem::itemUsesExtendedStyleOption()
7877 QGraphicsScene scene(0, 0, 300, 300);
7878 QGraphicsPixmapItem item;
7879 item.setFlag(QGraphicsItem::ItemUsesExtendedStyleOption, true);
7880 QCOMPARE(item.flags(), QGraphicsItem::GraphicsItemFlags(QGraphicsItem::ItemUsesExtendedStyleOption));
7881 item.setFlag(QGraphicsItem::ItemUsesExtendedStyleOption, false);
7882 QCOMPARE(item.flags(), 0);
7884 //We now test the content of the style option
7885 MyStyleOptionTester *rect = new MyStyleOptionTester(QRect(0, 0, 100, 100));
7886 scene.addItem(rect);
7887 rect->setPos(200, 200);
7889 QGraphicsView view(&scene, &topLevel);
7890 topLevel.setWindowFlags(Qt::X11BypassWindowManagerHint);
7891 rect->startTrack = false;
7893 QTest::qWaitForWindowShown(&view);
7895 rect->startTrack = true;
7896 rect->update(10, 10, 10, 10);
7898 rect->startTrack = false;
7899 rect->setFlag(QGraphicsItem::ItemUsesExtendedStyleOption, true);
7900 QVERIFY((rect->flags() & QGraphicsItem::ItemUsesExtendedStyleOption));
7902 rect->startTrack = true;
7903 rect->update(10, 10, 10, 10);
7907 void tst_QGraphicsItem::itemSendsGeometryChanges()
7909 ItemChangeTester item;
7913 QTransform x = QTransform().rotate(45);
7914 QPointF pos(10, 10);
7918 QPointF origin(1.0, 1.0);
7919 item.setTransform(x);
7921 item.setRotation(r);
7923 item.setTransformOriginPoint(origin);
7924 QCOMPARE(item.transform(), x);
7925 QCOMPARE(item.pos(), pos);
7926 QCOMPARE(item.rotation(), r);
7927 QCOMPARE(item.scale(), s);
7928 QCOMPARE(item.transformOriginPoint(), origin);
7929 QCOMPARE(item.changes.size(), 0);
7932 QCOMPARE(item.changes.size(), 2); // opacity
7934 item.setFlag(QGraphicsItem::ItemSendsGeometryChanges);
7935 QCOMPARE(item.changes.size(), 4); // flags
7936 item.setTransform(QTransform());
7937 item.setPos(QPointF());
7938 QCOMPARE(item.changes.size(), 8); // transform + pos
7939 QCOMPARE(item.transform(), QTransform());
7940 QCOMPARE(item.pos(), QPointF());
7941 QCOMPARE(item.opacity(), o);
7942 item.setRotation(0.0);
7944 item.setTransformOriginPoint(0.0, 0.0);
7945 QCOMPARE(item.changes.size(), 14); // rotation + scale + origin
7946 QCOMPARE(item.rotation(), qreal(0.0));
7947 QCOMPARE(item.scale(), qreal(1.0));
7948 QCOMPARE(item.transformOriginPoint(), QPointF(0.0, 0.0));
7950 QCOMPARE(item.changes, QList<QGraphicsItem::GraphicsItemChange>()
7951 << QGraphicsItem::ItemOpacityChange
7952 << QGraphicsItem::ItemOpacityHasChanged
7953 << QGraphicsItem::ItemFlagsChange
7954 << QGraphicsItem::ItemFlagsHaveChanged
7955 << QGraphicsItem::ItemTransformChange
7956 << QGraphicsItem::ItemTransformHasChanged
7957 << QGraphicsItem::ItemPositionChange
7958 << QGraphicsItem::ItemPositionHasChanged
7959 << QGraphicsItem::ItemRotationChange
7960 << QGraphicsItem::ItemRotationHasChanged
7961 << QGraphicsItem::ItemScaleChange
7962 << QGraphicsItem::ItemScaleHasChanged
7963 << QGraphicsItem::ItemTransformOriginPointChange
7964 << QGraphicsItem::ItemTransformOriginPointHasChanged);
7967 // Make sure we update moved items correctly.
7968 void tst_QGraphicsItem::moveItem()
7970 QGraphicsScene scene;
7971 scene.setSceneRect(-50, -50, 200, 200);
7973 MyGraphicsView view(&scene);
7976 qt_x11_wait_for_window_manager(&view);
7980 EventTester *parent = new EventTester;
7981 EventTester *child = new EventTester(parent);
7982 EventTester *grandChild = new EventTester(child);
7984 #define RESET_COUNTERS \
7985 parent->repaints = 0; \
7986 child->repaints = 0; \
7987 grandChild->repaints = 0; \
7990 scene.addItem(parent);
7995 // Item's boundingRect: (-10, -10, 20, 20).
7996 QRect parentDeviceBoundingRect = parent->deviceTransform(view.viewportTransform())
7997 .mapRect(parent->boundingRect()).toAlignedRect()
7998 .adjusted(-2, -2, 2, 2); // Adjusted for antialiasing.
8000 parent->setPos(20, 20);
8001 qApp->processEvents();
8002 QCOMPARE(parent->repaints, 1);
8003 QCOMPARE(view.repaints, 1);
8004 QRegion expectedParentRegion = parentDeviceBoundingRect; // old position
8005 parentDeviceBoundingRect.translate(20, 20);
8006 expectedParentRegion += parentDeviceBoundingRect; // new position
8007 COMPARE_REGIONS(view.paintedRegion, expectedParentRegion);
8011 child->setPos(20, 20);
8012 qApp->processEvents();
8013 QCOMPARE(parent->repaints, 1);
8014 QCOMPARE(child->repaints, 1);
8015 QCOMPARE(view.repaints, 1);
8016 const QRegion expectedChildRegion = expectedParentRegion.translated(20, 20);
8017 COMPARE_REGIONS(view.paintedRegion, expectedChildRegion);
8021 grandChild->setPos(20, 20);
8022 qApp->processEvents();
8023 QCOMPARE(parent->repaints, 1);
8024 QCOMPARE(child->repaints, 1);
8025 QCOMPARE(grandChild->repaints, 1);
8026 QCOMPARE(view.repaints, 1);
8027 const QRegion expectedGrandChildRegion = expectedParentRegion.translated(40, 40);
8028 COMPARE_REGIONS(view.paintedRegion, expectedGrandChildRegion);
8032 parent->translate(20, 20);
8033 qApp->processEvents();
8034 QCOMPARE(parent->repaints, 1);
8035 QCOMPARE(child->repaints, 1);
8036 QCOMPARE(grandChild->repaints, 1);
8037 QCOMPARE(view.repaints, 1);
8038 expectedParentRegion.translate(20, 20);
8039 expectedParentRegion += expectedChildRegion.translated(20, 20);
8040 expectedParentRegion += expectedGrandChildRegion.translated(20, 20);
8041 COMPARE_REGIONS(view.paintedRegion, expectedParentRegion);
8044 void tst_QGraphicsItem::moveLineItem()
8046 QGraphicsScene scene;
8047 scene.setSceneRect(0, 0, 200, 200);
8048 QGraphicsLineItem *item = new QGraphicsLineItem(0, 0, 100, 0);
8049 item->setPos(50, 50);
8050 scene.addItem(item);
8052 MyGraphicsView view(&scene);
8055 qt_x11_wait_for_window_manager(&view);
8060 QRectF brect = item->boundingRect();
8061 // Do same adjustments as in qgraphicsscene.cpp
8063 brect.adjust(qreal(-0.00001), 0, qreal(0.00001), 0);
8064 if (!brect.height())
8065 brect.adjust(0, qreal(-0.00001), 0, qreal(0.00001));
8066 const QRect itemDeviceBoundingRect = item->deviceTransform(view.viewportTransform())
8067 .mapRect(brect).toAlignedRect();
8068 QRegion expectedRegion = itemDeviceBoundingRect.adjusted(-2, -2, 2, 2); // antialiasing
8070 // Make sure the calculated region is correct.
8073 QTRY_COMPARE(view.paintedRegion, expectedRegion);
8076 // Old position: (50, 50)
8077 item->setPos(50, 100);
8078 expectedRegion += expectedRegion.translated(0, 50);
8080 QCOMPARE(view.paintedRegion, expectedRegion);
8083 void tst_QGraphicsItem::sorting_data()
8085 QTest::addColumn<int>("index");
8087 QTest::newRow("NoIndex") << int(QGraphicsScene::NoIndex);
8088 QTest::newRow("BspTreeIndex") << int(QGraphicsScene::BspTreeIndex);
8091 void tst_QGraphicsItem::sorting()
8093 if (PlatformQuirks::isAutoMaximizing())
8094 QSKIP("Skipped because Platform is auto maximizing");
8096 _paintedItems.clear();
8098 QGraphicsScene scene;
8099 QGraphicsItem *grid[100][100];
8100 for (int x = 0; x < 100; ++x) {
8101 for (int y = 0; y < 100; ++y) {
8102 PainterItem *item = new PainterItem;
8103 item->setPos(x * 25, y * 25);
8104 item->setData(0, QString("%1x%2").arg(x).arg(y));
8106 scene.addItem(item);
8110 PainterItem *item1 = new PainterItem;
8111 PainterItem *item2 = new PainterItem;
8112 item1->setData(0, "item1");
8113 item2->setData(0, "item2");
8114 scene.addItem(item1);
8115 scene.addItem(item2);
8117 QGraphicsView view(&scene);
8118 view.setResizeAnchor(QGraphicsView::NoAnchor);
8119 view.setTransformationAnchor(QGraphicsView::NoAnchor);
8120 view.resize(120, 100);
8121 view.setFrameStyle(0);
8124 qt_x11_wait_for_window_manager(&view);
8128 _paintedItems.clear();
8130 view.viewport()->repaint();
8131 #if defined(Q_WS_MAC)
8132 // There's no difference between repaint and update on the Mac,
8133 // so we have to process events here to make sure we get the event.
8137 QCOMPARE(_paintedItems, QList<QGraphicsItem *>()
8138 << grid[0][0] << grid[0][1] << grid[0][2] << grid[0][3]
8139 << grid[1][0] << grid[1][1] << grid[1][2] << grid[1][3]
8140 << grid[2][0] << grid[2][1] << grid[2][2] << grid[2][3]
8141 << grid[3][0] << grid[3][1] << grid[3][2] << grid[3][3]
8142 << grid[4][0] << grid[4][1] << grid[4][2] << grid[4][3]
8146 void tst_QGraphicsItem::itemHasNoContents()
8148 PainterItem *item1 = new PainterItem;
8149 PainterItem *item2 = new PainterItem;
8150 item2->setParentItem(item1);
8151 item2->setPos(50, 50);
8152 item1->setFlag(QGraphicsItem::ItemHasNoContents);
8153 item1->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
8155 QGraphicsScene scene;
8156 scene.addItem(item1);
8158 QGraphicsView view(&scene);
8160 QTest::qWaitForWindowShown(&view);
8161 QTRY_VERIFY(!_paintedItems.isEmpty());
8163 _paintedItems.clear();
8165 view.viewport()->repaint();
8167 // There's no difference between update() and repaint() on the Mac,
8168 // so we have to process events here to make sure we get the event.
8172 QTRY_COMPARE(_paintedItems, QList<QGraphicsItem *>() << item2);
8175 void tst_QGraphicsItem::hitTestUntransformableItem()
8177 QGraphicsScene scene;
8178 scene.setSceneRect(-100, -100, 200, 200);
8180 QGraphicsView view(&scene);
8183 qt_x11_wait_for_window_manager(&view);
8187 // Confuse the BSP with dummy items.
8188 QGraphicsRectItem *dummy = new QGraphicsRectItem(0, 0, 20, 20);
8189 dummy->setPos(-100, -100);
8190 scene.addItem(dummy);
8191 for (int i = 0; i < 100; ++i) {
8192 QGraphicsItem *parent = dummy;
8193 dummy = new QGraphicsRectItem(0, 0, 20, 20);
8194 dummy->setPos(-100 + i, -100 + i);
8195 dummy->setParentItem(parent);
8198 QGraphicsRectItem *item1 = new QGraphicsRectItem(0, 0, 20, 20);
8199 item1->setPos(-200, -200);
8201 QGraphicsRectItem *item2 = new QGraphicsRectItem(0, 0, 20, 20);
8202 item2->setFlag(QGraphicsItem::ItemIgnoresTransformations);
8203 item2->setParentItem(item1);
8204 item2->setPos(200, 200);
8206 QGraphicsRectItem *item3 = new QGraphicsRectItem(0, 0, 20, 20);
8207 item3->setParentItem(item2);
8208 item3->setPos(80, 80);
8210 scene.addItem(item1);
8213 QList<QGraphicsItem *> items = scene.items(QPointF(80, 80));
8214 QCOMPARE(items.size(), 1);
8215 QCOMPARE(items.at(0), static_cast<QGraphicsItem*>(item3));
8217 scene.setItemIndexMethod(QGraphicsScene::NoIndex);
8220 items = scene.items(QPointF(80, 80));
8221 QCOMPARE(items.size(), 1);
8222 QCOMPARE(items.at(0), static_cast<QGraphicsItem*>(item3));
8225 void tst_QGraphicsItem::hitTestGraphicsEffectItem()
8227 QGraphicsScene scene;
8228 scene.setSceneRect(-100, -100, 200, 200);
8232 QGraphicsView view(&scene, &toplevel);
8233 toplevel.resize(300, 300);
8236 qt_x11_wait_for_window_manager(&toplevel);
8240 // Confuse the BSP with dummy items.
8241 QGraphicsRectItem *dummy = new QGraphicsRectItem(0, 0, 20, 20);
8242 dummy->setPos(-100, -100);
8243 scene.addItem(dummy);
8244 for (int i = 0; i < 100; ++i) {
8245 QGraphicsItem *parent = dummy;
8246 dummy = new QGraphicsRectItem(0, 0, 20, 20);
8247 dummy->setPos(-100 + i, -100 + i);
8248 dummy->setParentItem(parent);
8251 const QRectF itemBoundingRect(0, 0, 20, 20);
8252 EventTester *item1 = new EventTester;
8253 item1->br = itemBoundingRect;
8254 item1->setPos(-200, -200);
8255 item1->brush = Qt::red;
8257 EventTester *item2 = new EventTester;
8258 item2->br = itemBoundingRect;
8259 item2->setFlag(QGraphicsItem::ItemIgnoresTransformations);
8260 item2->setParentItem(item1);
8261 item2->setPos(200, 200);
8262 item2->brush = Qt::green;
8264 EventTester *item3 = new EventTester;
8265 item3->br = itemBoundingRect;
8266 item3->setParentItem(item2);
8267 item3->setPos(80, 80);
8268 item3->brush = Qt::blue;
8270 scene.addItem(item1);
8273 item1->repaints = 0;
8274 item2->repaints = 0;
8275 item3->repaints = 0;
8277 // Apply shadow effect to the entire sub-tree.
8278 QGraphicsDropShadowEffect *shadow = new QGraphicsDropShadowEffect;
8279 shadow->setOffset(-20, -20);
8280 item1->setGraphicsEffect(shadow);
8283 // Make sure all visible items are repainted.
8284 QCOMPARE(item1->repaints, 1);
8285 QCOMPARE(item2->repaints, 1);
8286 QCOMPARE(item3->repaints, 1);
8288 // Make sure an item doesn't respond to a click on its shadow.
8289 QList<QGraphicsItem *> items = scene.items(QPointF(75, 75));
8290 QVERIFY(items.isEmpty());
8291 items = scene.items(QPointF(80, 80));
8292 QCOMPARE(items.size(), 1);
8293 QCOMPARE(items.at(0), static_cast<QGraphicsItem *>(item3));
8295 scene.setItemIndexMethod(QGraphicsScene::NoIndex);
8298 items = scene.items(QPointF(75, 75));
8299 QVERIFY(items.isEmpty());
8300 items = scene.items(QPointF(80, 80));
8301 QCOMPARE(items.size(), 1);
8302 QCOMPARE(items.at(0), static_cast<QGraphicsItem *>(item3));
8305 void tst_QGraphicsItem::focusProxy()
8307 QGraphicsScene scene;
8308 QEvent activate(QEvent::WindowActivate);
8309 QApplication::sendEvent(&scene, &activate);
8311 QGraphicsItem *item = scene.addRect(0, 0, 10, 10);
8312 item->setFlag(QGraphicsItem::ItemIsFocusable);
8313 QVERIFY(!item->focusProxy());
8315 QGraphicsItem *item2 = scene.addRect(0, 0, 10, 10);
8316 item2->setFlag(QGraphicsItem::ItemIsFocusable);
8317 item->setFocusProxy(item2);
8318 QCOMPARE(item->focusProxy(), item2);
8321 QVERIFY(item->hasFocus());
8322 QVERIFY(item2->hasFocus());
8324 // Try to make a focus chain loop
8326 QTextStream stream(&err);
8327 stream << "QGraphicsItem::setFocusProxy: "
8328 << (void*)item << " is already in the focus proxy chain" << flush;
8329 QTest::ignoreMessage(QtWarningMsg, err.toLatin1().constData());
8330 item2->setFocusProxy(item); // fails
8331 QCOMPARE(item->focusProxy(), (QGraphicsItem *)item2);
8332 QCOMPARE(item2->focusProxy(), (QGraphicsItem *)0);
8334 // Try to assign self as focus proxy
8335 QTest::ignoreMessage(QtWarningMsg, "QGraphicsItem::setFocusProxy: cannot assign self as focus proxy");
8336 item->setFocusProxy(item); // fails
8337 QCOMPARE(item->focusProxy(), (QGraphicsItem *)item2);
8338 QCOMPARE(item2->focusProxy(), (QGraphicsItem *)0);
8340 // Reset the focus proxy
8341 item->setFocusProxy(0);
8342 QCOMPARE(item->focusProxy(), (QGraphicsItem *)0);
8343 QVERIFY(!item->hasFocus());
8344 QVERIFY(item2->hasFocus());
8347 item->setFocusProxy(item2);
8348 QCOMPARE(item->focusProxy(), (QGraphicsItem *)item2);
8350 QCOMPARE(item->focusProxy(), (QGraphicsItem *)0);
8352 // Test event delivery
8353 item2 = scene.addRect(0, 0, 10, 10);
8354 item2->setFlag(QGraphicsItem::ItemIsFocusable);
8355 item->setFocusProxy(item2);
8358 EventSpy focusInSpy(&scene, item, QEvent::FocusIn);
8359 EventSpy focusOutSpy(&scene, item, QEvent::FocusOut);
8360 EventSpy focusInSpy2(&scene, item2, QEvent::FocusIn);
8361 EventSpy focusOutSpy2(&scene, item2, QEvent::FocusOut);
8362 QCOMPARE(focusInSpy.count(), 0);
8363 QCOMPARE(focusOutSpy.count(), 0);
8364 QCOMPARE(focusInSpy2.count(), 0);
8365 QCOMPARE(focusOutSpy2.count(), 0);
8368 QCOMPARE(focusInSpy.count(), 0);
8369 QCOMPARE(focusInSpy2.count(), 1);
8371 QCOMPARE(focusOutSpy.count(), 0);
8372 QCOMPARE(focusOutSpy2.count(), 1);
8374 // Test two items proxying one item.
8375 QGraphicsItem *item3 = scene.addRect(0, 0, 10, 10);
8376 item3->setFlag(QGraphicsItem::ItemIsFocusable);
8377 item3->setFocusProxy(item2); // item and item3 use item2 as proxy
8379 QCOMPARE(item->focusProxy(), item2);
8380 QCOMPARE(item2->focusProxy(), (QGraphicsItem *)0);
8381 QCOMPARE(item3->focusProxy(), item2);
8383 QCOMPARE(item->focusProxy(), (QGraphicsItem *)0);
8384 QCOMPARE(item3->focusProxy(), (QGraphicsItem *)0);
8387 void tst_QGraphicsItem::subFocus()
8389 // Construct a text item that's not part of a scene (yet)
8390 // and has no parent. Setting focus on it will not make
8391 // the item gain input focus; that requires a scene. But
8392 // it does set subfocus, indicating that the item wishes
8393 // to gain focus later.
8394 QGraphicsTextItem *text = new QGraphicsTextItem("Hello");
8395 text->setTextInteractionFlags(Qt::TextEditorInteraction);
8396 QVERIFY(!text->hasFocus());
8398 QVERIFY(!text->hasFocus());
8399 QCOMPARE(text->focusItem(), (QGraphicsItem *)text);
8402 QGraphicsTextItem *text2 = new QGraphicsTextItem("Hi");
8403 text2->setTextInteractionFlags(Qt::TextEditorInteraction);
8404 text2->setPos(30, 30);
8406 // Add both items to a scene and check that it's text that
8408 QGraphicsScene scene;
8409 QEvent activate(QEvent::WindowActivate);
8410 QApplication::sendEvent(&scene, &activate);
8412 scene.addItem(text);
8413 scene.addItem(text2);
8414 QVERIFY(text->hasFocus());
8416 text->setData(0, "text");
8417 text2->setData(0, "text2");
8419 // Remove text2 and set subfocus on it. Then readd. Reparent it onto the
8420 // other item and see that it gains input focus.
8421 scene.removeItem(text2);
8423 scene.addItem(text2);
8424 QCOMPARE(text2->focusItem(), (QGraphicsItem *)text2);
8425 text2->setParentItem(text);
8426 QCOMPARE(text->focusItem(), (QGraphicsItem *)text2);
8427 QCOMPARE(text2->focusItem(), (QGraphicsItem *)text2);
8428 QVERIFY(!text->hasFocus());
8429 QVERIFY(text2->hasFocus());
8431 // Remove both items from the scene, restore subfocus and
8432 // readd them. Now the subfocus should kick in and give
8434 scene.removeItem(text);
8435 QCOMPARE(text->focusItem(), (QGraphicsItem *)0);
8436 QCOMPARE(text2->focusItem(), (QGraphicsItem *)0);
8438 QCOMPARE(text->focusItem(), (QGraphicsItem *)text2);
8439 QCOMPARE(text2->focusItem(), (QGraphicsItem *)text2);
8440 scene.addItem(text);
8442 // Hiding and showing text should pass focus to text2.
8443 QCOMPARE(text->focusItem(), (QGraphicsItem *)text2);
8444 QVERIFY(text2->hasFocus());
8446 // Subfocus should repropagate to root when reparenting.
8447 QGraphicsRectItem *rect = new QGraphicsRectItem;
8448 QGraphicsRectItem *rect2 = new QGraphicsRectItem(rect);
8449 QGraphicsRectItem *rect3 = new QGraphicsRectItem(rect2);
8450 rect3->setFlag(QGraphicsItem::ItemIsFocusable);
8452 text->setData(0, "text");
8453 text2->setData(0, "text2");
8454 rect->setData(0, "rect");
8455 rect2->setData(0, "rect2");
8456 rect3->setData(0, "rect3");
8459 QVERIFY(!rect3->hasFocus());
8460 QCOMPARE(rect->focusItem(), (QGraphicsItem *)rect3);
8461 QCOMPARE(rect2->focusItem(), (QGraphicsItem *)rect3);
8462 QCOMPARE(rect3->focusItem(), (QGraphicsItem *)rect3);
8463 rect->setParentItem(text2);
8464 QCOMPARE(text->focusItem(), (QGraphicsItem *)rect3);
8465 QCOMPARE(text2->focusItem(), (QGraphicsItem *)rect3);
8466 QCOMPARE(rect->focusItem(), (QGraphicsItem *)rect3);
8467 QCOMPARE(rect2->focusItem(), (QGraphicsItem *)rect3);
8468 QCOMPARE(rect3->focusItem(), (QGraphicsItem *)rect3);
8469 QVERIFY(!rect->hasFocus());
8470 QVERIFY(!rect2->hasFocus());
8471 QVERIFY(rect3->hasFocus());
8474 QCOMPARE(text->focusItem(), (QGraphicsItem *)0);
8475 QCOMPARE(text2->focusItem(), (QGraphicsItem *)0);
8476 QCOMPARE(rect->focusItem(), (QGraphicsItem *)0);
8479 void tst_QGraphicsItem::focusProxyDeletion()
8481 QGraphicsRectItem *rect = new QGraphicsRectItem;
8482 QGraphicsRectItem *rect2 = new QGraphicsRectItem;
8483 rect->setFocusProxy(rect2);
8484 QCOMPARE(rect->focusProxy(), (QGraphicsItem *)rect2);
8487 QCOMPARE(rect->focusProxy(), (QGraphicsItem *)0);
8489 rect2 = new QGraphicsRectItem;
8490 rect->setFocusProxy(rect2);
8491 delete rect; // don't crash
8493 rect = new QGraphicsRectItem;
8494 rect->setFocusProxy(rect2);
8495 QGraphicsScene *scene = new QGraphicsScene;
8496 scene->addItem(rect);
8497 scene->addItem(rect2);
8499 QCOMPARE(rect->focusProxy(), (QGraphicsItem *)0);
8501 rect2 = new QGraphicsRectItem;
8502 QTest::ignoreMessage(QtWarningMsg, "QGraphicsItem::setFocusProxy: focus proxy must be in same scene");
8503 rect->setFocusProxy(rect2);
8504 QCOMPARE(rect->focusProxy(), (QGraphicsItem *)0);
8505 scene->addItem(rect2);
8506 rect->setFocusProxy(rect2);
8507 QCOMPARE(rect->focusProxy(), (QGraphicsItem *)rect2);
8508 delete rect; // don't crash
8510 rect = new QGraphicsRectItem;
8511 rect2 = new QGraphicsRectItem;
8512 rect->setFocusProxy(rect2);
8513 QCOMPARE(rect->focusProxy(), (QGraphicsItem *)rect2);
8514 scene->addItem(rect);
8515 scene->addItem(rect2);
8516 rect->setFocusProxy(rect2);
8517 delete scene; // don't crash
8520 void tst_QGraphicsItem::negativeZStacksBehindParent()
8522 QGraphicsRectItem rect;
8523 QCOMPARE(rect.zValue(), qreal(0.0));
8524 QVERIFY(!(rect.flags() & QGraphicsItem::ItemNegativeZStacksBehindParent));
8525 QVERIFY(!(rect.flags() & QGraphicsItem::ItemStacksBehindParent));
8527 QCOMPARE(rect.zValue(), qreal(-1.0));
8528 QVERIFY(!(rect.flags() & QGraphicsItem::ItemStacksBehindParent));
8530 rect.setFlag(QGraphicsItem::ItemNegativeZStacksBehindParent);
8531 QVERIFY(rect.flags() & QGraphicsItem::ItemNegativeZStacksBehindParent);
8532 QVERIFY(!(rect.flags() & QGraphicsItem::ItemStacksBehindParent));
8534 QVERIFY(rect.flags() & QGraphicsItem::ItemStacksBehindParent);
8536 QVERIFY(!(rect.flags() & QGraphicsItem::ItemStacksBehindParent));
8537 rect.setFlag(QGraphicsItem::ItemNegativeZStacksBehindParent, false);
8539 rect.setFlag(QGraphicsItem::ItemNegativeZStacksBehindParent, true);
8540 QVERIFY(rect.flags() & QGraphicsItem::ItemStacksBehindParent);
8541 rect.setFlag(QGraphicsItem::ItemNegativeZStacksBehindParent, false);
8542 QVERIFY(rect.flags() & QGraphicsItem::ItemStacksBehindParent);
8545 void tst_QGraphicsItem::setGraphicsEffect()
8547 // Check that we don't have any effect by default.
8548 QGraphicsItem *item = new QGraphicsRectItem(0, 0, 10, 10);
8549 QVERIFY(!item->graphicsEffect());
8552 QPointer<QGraphicsEffect> blurEffect = new QGraphicsBlurEffect;
8553 item->setGraphicsEffect(blurEffect);
8554 QCOMPARE(item->graphicsEffect(), static_cast<QGraphicsEffect *>(blurEffect));
8556 // Ensure the existing effect is deleted when setting a new one.
8557 QPointer<QGraphicsEffect> shadowEffect = new QGraphicsDropShadowEffect;
8558 item->setGraphicsEffect(shadowEffect);
8559 QVERIFY(!blurEffect);
8560 QCOMPARE(item->graphicsEffect(), static_cast<QGraphicsEffect *>(shadowEffect));
8561 blurEffect = new QGraphicsBlurEffect;
8563 // Ensure the effect is uninstalled when setting it on a new target.
8564 QGraphicsItem *anotherItem = new QGraphicsRectItem(0, 0, 10, 10);
8565 anotherItem->setGraphicsEffect(blurEffect);
8566 item->setGraphicsEffect(blurEffect);
8567 QVERIFY(!anotherItem->graphicsEffect());
8568 QVERIFY(!shadowEffect);
8570 // Ensure the existing effect is deleted when deleting the item.
8572 QVERIFY(!blurEffect);
8575 // Ensure the effect is uninstalled when deleting it
8576 item = new QGraphicsRectItem(0, 0, 10, 10);
8577 blurEffect = new QGraphicsBlurEffect;
8578 item->setGraphicsEffect(blurEffect);
8580 QVERIFY(!item->graphicsEffect());
8582 // Ensure the existing effect is uninstalled and deleted when setting a null effect
8583 blurEffect = new QGraphicsBlurEffect;
8584 item->setGraphicsEffect(blurEffect);
8585 item->setGraphicsEffect(0);
8586 QVERIFY(!item->graphicsEffect());
8587 QVERIFY(!blurEffect);
8592 void tst_QGraphicsItem::panel()
8594 QGraphicsScene scene;
8596 QGraphicsRectItem *panel1 = new QGraphicsRectItem;
8597 QGraphicsRectItem *panel2 = new QGraphicsRectItem;
8598 QGraphicsRectItem *panel3 = new QGraphicsRectItem;
8599 QGraphicsRectItem *panel4 = new QGraphicsRectItem;
8600 QGraphicsRectItem *notPanel1 = new QGraphicsRectItem;
8601 QGraphicsRectItem *notPanel2 = new QGraphicsRectItem;
8602 panel1->setFlag(QGraphicsItem::ItemIsPanel);
8603 panel2->setFlag(QGraphicsItem::ItemIsPanel);
8604 panel3->setFlag(QGraphicsItem::ItemIsPanel);
8605 panel4->setFlag(QGraphicsItem::ItemIsPanel);
8606 scene.addItem(panel1);
8607 scene.addItem(panel2);
8608 scene.addItem(panel3);
8609 scene.addItem(panel4);
8610 scene.addItem(notPanel1);
8611 scene.addItem(notPanel2);
8613 EventSpy spy_activate_panel1(&scene, panel1, QEvent::WindowActivate);
8614 EventSpy spy_deactivate_panel1(&scene, panel1, QEvent::WindowDeactivate);
8615 EventSpy spy_activate_panel2(&scene, panel2, QEvent::WindowActivate);
8616 EventSpy spy_deactivate_panel2(&scene, panel2, QEvent::WindowDeactivate);
8617 EventSpy spy_activate_panel3(&scene, panel3, QEvent::WindowActivate);
8618 EventSpy spy_deactivate_panel3(&scene, panel3, QEvent::WindowDeactivate);
8619 EventSpy spy_activate_panel4(&scene, panel4, QEvent::WindowActivate);
8620 EventSpy spy_deactivate_panel4(&scene, panel4, QEvent::WindowDeactivate);
8621 EventSpy spy_activate_notPanel1(&scene, notPanel1, QEvent::WindowActivate);
8622 EventSpy spy_deactivate_notPanel1(&scene, notPanel1, QEvent::WindowDeactivate);
8623 EventSpy spy_activate_notPanel2(&scene, notPanel1, QEvent::WindowActivate);
8624 EventSpy spy_deactivate_notPanel2(&scene, notPanel1, QEvent::WindowDeactivate);
8626 QCOMPARE(spy_activate_panel1.count(), 0);
8627 QCOMPARE(spy_deactivate_panel1.count(), 0);
8628 QCOMPARE(spy_activate_panel2.count(), 0);
8629 QCOMPARE(spy_deactivate_panel2.count(), 0);
8630 QCOMPARE(spy_activate_panel3.count(), 0);
8631 QCOMPARE(spy_deactivate_panel3.count(), 0);
8632 QCOMPARE(spy_activate_panel4.count(), 0);
8633 QCOMPARE(spy_deactivate_panel4.count(), 0);
8634 QCOMPARE(spy_activate_notPanel1.count(), 0);
8635 QCOMPARE(spy_deactivate_notPanel1.count(), 0);
8636 QCOMPARE(spy_activate_notPanel2.count(), 0);
8637 QCOMPARE(spy_deactivate_notPanel2.count(), 0);
8639 QVERIFY(!scene.activePanel());
8640 QVERIFY(!scene.isActive());
8642 QEvent activate(QEvent::WindowActivate);
8643 QEvent deactivate(QEvent::WindowDeactivate);
8645 QApplication::sendEvent(&scene, &activate);
8647 // No previous activation, so the scene is active.
8648 QVERIFY(scene.isActive());
8649 QCOMPARE(scene.activePanel(), (QGraphicsItem *)panel1);
8650 QVERIFY(panel1->isActive());
8651 QVERIFY(!panel2->isActive());
8652 QVERIFY(!panel3->isActive());
8653 QVERIFY(!panel4->isActive());
8654 QVERIFY(!notPanel1->isActive());
8655 QVERIFY(!notPanel2->isActive());
8656 QCOMPARE(spy_deactivate_notPanel1.count(), 0);
8657 QCOMPARE(spy_deactivate_notPanel2.count(), 0);
8658 QCOMPARE(spy_activate_panel1.count(), 1);
8659 QCOMPARE(spy_activate_panel2.count(), 0);
8660 QCOMPARE(spy_activate_panel3.count(), 0);
8661 QCOMPARE(spy_activate_panel4.count(), 0);
8663 // Switch back to scene.
8664 scene.setActivePanel(0);
8665 QVERIFY(!scene.activePanel());
8666 QVERIFY(!panel1->isActive());
8667 QVERIFY(!panel2->isActive());
8668 QVERIFY(!panel3->isActive());
8669 QVERIFY(!panel4->isActive());
8670 QVERIFY(notPanel1->isActive());
8671 QVERIFY(notPanel2->isActive());
8672 QCOMPARE(spy_activate_notPanel1.count(), 1);
8673 QCOMPARE(spy_activate_notPanel2.count(), 1);
8675 // Deactivate the scene
8676 QApplication::sendEvent(&scene, &deactivate);
8677 QVERIFY(!scene.activePanel());
8678 QVERIFY(!panel1->isActive());
8679 QVERIFY(!panel2->isActive());
8680 QVERIFY(!panel3->isActive());
8681 QVERIFY(!panel4->isActive());
8682 QVERIFY(!notPanel1->isActive());
8683 QVERIFY(!notPanel2->isActive());
8684 QCOMPARE(spy_deactivate_notPanel1.count(), 1);
8685 QCOMPARE(spy_deactivate_notPanel2.count(), 1);
8687 // Reactivate the scene
8688 QApplication::sendEvent(&scene, &activate);
8689 QVERIFY(!scene.activePanel());
8690 QVERIFY(!panel1->isActive());
8691 QVERIFY(!panel2->isActive());
8692 QVERIFY(!panel3->isActive());
8693 QVERIFY(!panel4->isActive());
8694 QVERIFY(notPanel1->isActive());
8695 QVERIFY(notPanel2->isActive());
8696 QCOMPARE(spy_activate_notPanel1.count(), 2);
8697 QCOMPARE(spy_activate_notPanel2.count(), 2);
8700 scene.setActivePanel(panel1);
8701 QVERIFY(panel1->isActive());
8702 QCOMPARE(spy_deactivate_notPanel1.count(), 2);
8703 QCOMPARE(spy_deactivate_notPanel2.count(), 2);
8704 QCOMPARE(spy_activate_panel1.count(), 2);
8706 // Deactivate the scene
8707 QApplication::sendEvent(&scene, &deactivate);
8708 QVERIFY(!panel1->isActive());
8709 QCOMPARE(spy_deactivate_panel1.count(), 2);
8711 // Reactivate the scene
8712 QApplication::sendEvent(&scene, &activate);
8713 QVERIFY(panel1->isActive());
8714 QCOMPARE(spy_activate_panel1.count(), 3);
8716 // Deactivate the scene
8717 QApplication::sendEvent(&scene, &deactivate);
8718 QVERIFY(!panel1->isActive());
8719 QVERIFY(!scene.activePanel());
8720 scene.setActivePanel(0);
8722 // Reactivate the scene
8723 QApplication::sendEvent(&scene, &activate);
8724 QVERIFY(!panel1->isActive());
8727 void tst_QGraphicsItem::panelWithFocusItem()
8729 QGraphicsScene scene;
8730 QEvent activate(QEvent::WindowActivate);
8731 QApplication::sendEvent(&scene, &activate);
8733 QGraphicsRectItem *parentPanel = new QGraphicsRectItem;
8734 QGraphicsRectItem *parentPanelFocusItem = new QGraphicsRectItem(parentPanel);
8735 parentPanel->setFlag(QGraphicsItem::ItemIsPanel);
8736 parentPanelFocusItem->setFlag(QGraphicsItem::ItemIsFocusable);
8737 parentPanelFocusItem->setFocus();
8738 scene.addItem(parentPanel);
8740 QVERIFY(parentPanel->isActive());
8741 QVERIFY(parentPanelFocusItem->hasFocus());
8742 QCOMPARE(parentPanel->focusItem(), (QGraphicsItem *)parentPanelFocusItem);
8743 QCOMPARE(parentPanelFocusItem->focusItem(), (QGraphicsItem *)parentPanelFocusItem);
8745 QGraphicsRectItem *childPanel = new QGraphicsRectItem;
8746 QGraphicsRectItem *childPanelFocusItem = new QGraphicsRectItem(childPanel);
8747 childPanel->setFlag(QGraphicsItem::ItemIsPanel);
8748 childPanelFocusItem->setFlag(QGraphicsItem::ItemIsFocusable);
8749 childPanelFocusItem->setFocus();
8751 QVERIFY(!childPanelFocusItem->hasFocus());
8752 QCOMPARE(childPanel->focusItem(), (QGraphicsItem *)childPanelFocusItem);
8753 QCOMPARE(childPanelFocusItem->focusItem(), (QGraphicsItem *)childPanelFocusItem);
8755 childPanel->setParentItem(parentPanel);
8757 QVERIFY(!parentPanel->isActive());
8758 QVERIFY(!parentPanelFocusItem->hasFocus());
8759 QCOMPARE(parentPanel->focusItem(), (QGraphicsItem *)parentPanelFocusItem);
8760 QCOMPARE(parentPanelFocusItem->focusItem(), (QGraphicsItem *)parentPanelFocusItem);
8762 QVERIFY(childPanel->isActive());
8763 QVERIFY(childPanelFocusItem->hasFocus());
8764 QCOMPARE(childPanel->focusItem(), (QGraphicsItem *)childPanelFocusItem);
8765 QCOMPARE(childPanelFocusItem->focusItem(), (QGraphicsItem *)childPanelFocusItem);
8769 QVERIFY(parentPanel->isActive());
8770 QVERIFY(parentPanelFocusItem->hasFocus());
8771 QCOMPARE(parentPanel->focusItem(), (QGraphicsItem *)parentPanelFocusItem);
8772 QCOMPARE(parentPanelFocusItem->focusItem(), (QGraphicsItem *)parentPanelFocusItem);
8775 void tst_QGraphicsItem::addPanelToActiveScene()
8777 QGraphicsScene scene;
8778 QVERIFY(!scene.isActive());
8780 QGraphicsRectItem *rect = new QGraphicsRectItem;
8781 scene.addItem(rect);
8782 QVERIFY(!rect->isActive());
8783 scene.removeItem(rect);
8785 QEvent activate(QEvent::WindowActivate);
8786 QEvent deactivate(QEvent::WindowDeactivate);
8788 QApplication::sendEvent(&scene, &activate);
8789 QVERIFY(scene.isActive());
8790 scene.addItem(rect);
8791 QVERIFY(rect->isActive());
8792 scene.removeItem(rect);
8794 rect->setFlag(QGraphicsItem::ItemIsPanel);
8795 scene.addItem(rect);
8796 QVERIFY(rect->isActive());
8797 QCOMPARE(scene.activePanel(), (QGraphicsItem *)rect);
8799 QGraphicsRectItem *rect2 = new QGraphicsRectItem;
8800 scene.addItem(rect2);
8801 QVERIFY(rect->isActive());
8802 QCOMPARE(scene.activePanel(), (QGraphicsItem *)rect);
8805 void tst_QGraphicsItem::activate()
8807 QGraphicsScene scene;
8808 QGraphicsRectItem *rect = scene.addRect(-10, -10, 20, 20);
8809 QVERIFY(!rect->isActive());
8811 QEvent activate(QEvent::WindowActivate);
8812 QEvent deactivate(QEvent::WindowDeactivate);
8814 QApplication::sendEvent(&scene, &activate);
8816 // Non-panel item (active when scene is active).
8817 QVERIFY(rect->isActive());
8819 QGraphicsRectItem *rect2 = new QGraphicsRectItem;
8820 rect2->setFlag(QGraphicsItem::ItemIsPanel);
8821 QGraphicsRectItem *rect3 = new QGraphicsRectItem;
8822 rect3->setFlag(QGraphicsItem::ItemIsPanel);
8824 // Test normal activation.
8825 QVERIFY(!rect2->isActive());
8826 scene.addItem(rect2);
8827 QVERIFY(rect2->isActive()); // first panel item is activated
8828 scene.addItem(rect3);
8829 QVERIFY(!rect3->isActive()); // second panel item is _not_ activated
8830 rect3->setActive(true);
8831 QVERIFY(rect3->isActive());
8832 scene.removeItem(rect3);
8833 QVERIFY(!rect3->isActive()); // no panel is active anymore
8834 QCOMPARE(scene.activePanel(), (QGraphicsItem *)0);
8835 scene.addItem(rect3);
8836 QVERIFY(rect3->isActive()); // second panel item is activated
8838 // Test pending activation.
8839 scene.removeItem(rect3);
8840 rect2->setActive(true);
8841 QVERIFY(rect2->isActive()); // first panel item is activated
8842 rect3->setActive(true);
8843 QVERIFY(!rect3->isActive()); // not active (yet)
8844 scene.addItem(rect3);
8845 QVERIFY(rect3->isActive()); // now becomes active
8847 // Test pending deactivation.
8848 scene.removeItem(rect3);
8849 rect3->setActive(false);
8850 scene.addItem(rect3);
8851 QVERIFY(!rect3->isActive()); // doesn't become active
8853 // Child of panel activation.
8854 rect3->setActive(true);
8855 QGraphicsRectItem *rect4 = new QGraphicsRectItem;
8856 rect4->setFlag(QGraphicsItem::ItemIsPanel);
8857 QGraphicsRectItem *rect5 = new QGraphicsRectItem(rect4);
8858 QGraphicsRectItem *rect6 = new QGraphicsRectItem(rect5);
8859 scene.addItem(rect4);
8860 QCOMPARE(scene.activePanel(), (QGraphicsItem *)rect3);
8861 scene.removeItem(rect4);
8862 rect6->setActive(true);
8863 scene.addItem(rect4);
8864 QVERIFY(rect4->isActive());
8865 QVERIFY(rect5->isActive());
8866 QVERIFY(rect6->isActive());
8867 QCOMPARE(scene.activePanel(), (QGraphicsItem *)rect4);
8868 scene.removeItem(rect4); // no active panel
8869 rect6->setActive(false);
8870 scene.addItem(rect4);
8871 QVERIFY(!rect4->isActive());
8872 QVERIFY(!rect5->isActive());
8873 QVERIFY(!rect6->isActive());
8874 QCOMPARE(scene.activePanel(), (QGraphicsItem *)0);
8876 // Controlling auto-activation when the scene changes activation.
8877 rect4->setActive(true);
8878 QApplication::sendEvent(&scene, &deactivate);
8879 QVERIFY(!scene.isActive());
8880 QVERIFY(!rect4->isActive());
8881 rect4->setActive(false);
8882 QApplication::sendEvent(&scene, &activate);
8883 QVERIFY(scene.isActive());
8884 QVERIFY(!scene.activePanel());
8885 QVERIFY(!rect4->isActive());
8888 void tst_QGraphicsItem::setActivePanelOnInactiveScene()
8890 QGraphicsScene scene;
8891 QGraphicsRectItem *item = scene.addRect(QRectF());
8892 QGraphicsRectItem *panel = scene.addRect(QRectF());
8893 panel->setFlag(QGraphicsItem::ItemIsPanel);
8895 EventSpy itemActivateSpy(&scene, item, QEvent::WindowActivate);
8896 EventSpy itemDeactivateSpy(&scene, item, QEvent::WindowDeactivate);
8897 EventSpy panelActivateSpy(&scene, panel, QEvent::WindowActivate);
8898 EventSpy panelDeactivateSpy(&scene, panel, QEvent::WindowDeactivate);
8899 EventSpy sceneActivationChangeSpy(&scene, QEvent::ActivationChange);
8901 scene.setActivePanel(panel);
8902 QCOMPARE(scene.activePanel(), (QGraphicsItem *)0);
8903 QCOMPARE(itemActivateSpy.count(), 0);
8904 QCOMPARE(itemDeactivateSpy.count(), 0);
8905 QCOMPARE(panelActivateSpy.count(), 0);
8906 QCOMPARE(panelDeactivateSpy.count(), 0);
8907 QCOMPARE(sceneActivationChangeSpy.count(), 0);
8910 void tst_QGraphicsItem::activationOnShowHide()
8912 QGraphicsScene scene;
8913 QEvent activate(QEvent::WindowActivate);
8914 QApplication::sendEvent(&scene, &activate);
8916 QGraphicsRectItem *rootPanel = scene.addRect(QRectF());
8917 rootPanel->setFlag(QGraphicsItem::ItemIsPanel);
8918 rootPanel->setActive(true);
8920 QGraphicsRectItem *subPanel = new QGraphicsRectItem;
8921 subPanel->setFlag(QGraphicsItem::ItemIsPanel);
8923 // Reparenting onto an active panel auto-activates the child panel.
8924 subPanel->setParentItem(rootPanel);
8925 QVERIFY(subPanel->isActive());
8926 QVERIFY(!rootPanel->isActive());
8928 // Hiding an active child panel will reactivate the parent panel.
8930 QVERIFY(rootPanel->isActive());
8932 // Showing a child panel will auto-activate it.
8934 QVERIFY(subPanel->isActive());
8935 QVERIFY(!rootPanel->isActive());
8937 // Adding an unrelated panel doesn't affect activation.
8938 QGraphicsRectItem *otherPanel = new QGraphicsRectItem;
8939 otherPanel->setFlag(QGraphicsItem::ItemIsPanel);
8940 scene.addItem(otherPanel);
8941 QVERIFY(subPanel->isActive());
8943 // Showing an unrelated panel doesn't affect activation.
8946 QVERIFY(subPanel->isActive());
8948 // Add a non-panel item.
8949 QGraphicsRectItem *otherItem = new QGraphicsRectItem;
8950 scene.addItem(otherItem);
8951 otherItem->setActive(true);
8952 QVERIFY(otherItem->isActive());
8954 // Reparent a panel onto an active non-panel item.
8955 subPanel->setParentItem(otherItem);
8956 QVERIFY(subPanel->isActive());
8958 // Showing a child panel of a non-panel item will activate it.
8960 QVERIFY(!subPanel->isActive());
8961 QVERIFY(otherItem->isActive());
8963 QVERIFY(subPanel->isActive());
8965 // Hiding a toplevel active panel will pass activation back
8966 // to the non-panel items.
8967 rootPanel->setActive(true);
8969 QVERIFY(!rootPanel->isActive());
8970 QVERIFY(otherItem->isActive());
8973 class MoveWhileDying : public QGraphicsRectItem
8976 MoveWhileDying(QGraphicsItem *parent = 0)
8977 : QGraphicsRectItem(parent)
8981 foreach (QGraphicsItem *c, childItems()) {
8982 foreach (QGraphicsItem *cc, c->childItems()) {
8987 if (QGraphicsItem *p = parentItem()) { p->moveBy(10, 10); }
8991 void tst_QGraphicsItem::moveWhileDeleting()
8993 QGraphicsScene scene;
8994 QGraphicsRectItem *rect = new QGraphicsRectItem;
8995 MoveWhileDying *silly = new MoveWhileDying(rect);
8996 QGraphicsRectItem *child = new QGraphicsRectItem(silly);
8997 scene.addItem(rect);
8998 delete rect; // don't crash!
9000 rect = new QGraphicsRectItem;
9001 silly = new MoveWhileDying(rect);
9002 child = new QGraphicsRectItem(silly);
9004 QGraphicsView view(&scene);
9007 qt_x11_wait_for_window_manager(&view);
9013 rect = new QGraphicsRectItem;
9014 rect->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
9015 silly = new MoveWhileDying(rect);
9016 child = new QGraphicsRectItem(silly);
9022 rect = new MoveWhileDying;
9023 rect->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
9024 child = new QGraphicsRectItem(rect);
9025 silly = new MoveWhileDying(child);
9032 class MyRectItem : public QGraphicsWidget
9036 MyRectItem(QGraphicsItem *parent = 0) : QGraphicsWidget(parent)
9041 void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
9043 painter->setBrush(brush);
9044 painter->drawRect(boundingRect());
9049 topLevel->collidingItems(Qt::IntersectsItemBoundingRect);
9052 QGraphicsItem *topLevel;
9057 void tst_QGraphicsItem::ensureDirtySceneTransform()
9059 QGraphicsScene scene;
9061 MyRectItem *topLevel = new MyRectItem;
9062 topLevel->setGeometry(0, 0, 100, 100);
9063 topLevel->setPos(-50, -50);
9064 topLevel->brush = QBrush(QColor(Qt::black));
9065 scene.addItem(topLevel);
9067 MyRectItem *parent = new MyRectItem;
9068 parent->topLevel = topLevel;
9069 parent->setGeometry(0, 0, 100, 100);
9070 parent->setPos(0, 0);
9071 parent->brush = QBrush(QColor(Qt::magenta));
9072 parent->setObjectName("parent");
9073 scene.addItem(parent);
9075 MyRectItem *child = new MyRectItem(parent);
9076 child->setGeometry(0, 0, 80, 80);
9077 child->setPos(10, 10);
9078 child->setObjectName("child");
9079 child->brush = QBrush(QColor(Qt::blue));
9081 MyRectItem *child2 = new MyRectItem(parent);
9082 child2->setGeometry(0, 0, 80, 80);
9083 child2->setPos(15, 15);
9084 child2->setObjectName("child2");
9085 child2->brush = QBrush(QColor(Qt::green));
9087 MyRectItem *child3 = new MyRectItem(parent);
9088 child3->setGeometry(0, 0, 80, 80);
9089 child3->setPos(20, 20);
9090 child3->setObjectName("child3");
9091 child3->brush = QBrush(QColor(Qt::gray));
9093 QGraphicsView view(&scene);
9095 QTest::qWaitForWindowShown(&view);
9096 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
9098 //We move the parent
9100 QApplication::processEvents();
9102 //We check if all items moved
9103 QCOMPARE(child->pos(), QPointF(10, 10));
9104 QCOMPARE(child2->pos(), QPointF(15, 15));
9105 QCOMPARE(child3->pos(), QPointF(20, 20));
9107 QCOMPARE(child->sceneBoundingRect(), QRectF(-90, -90, 80, 80));
9108 QCOMPARE(child2->sceneBoundingRect(), QRectF(-85, -85, 80, 80));
9109 QCOMPARE(child3->sceneBoundingRect(), QRectF(-80, -80, 80, 80));
9111 QCOMPARE(child->sceneTransform(), QTransform::fromTranslate(-90, -90));
9112 QCOMPARE(child2->sceneTransform(), QTransform::fromTranslate(-85, -85));
9113 QCOMPARE(child3->sceneTransform(), QTransform::fromTranslate(-80, -80));
9116 void tst_QGraphicsItem::focusScope()
9118 // ItemIsFocusScope is an internal feature (for now).
9119 QGraphicsScene scene;
9121 QGraphicsRectItem *scope3 = new QGraphicsRectItem;
9122 scope3->setData(0, "scope3");
9123 scope3->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsFocusScope);
9125 QVERIFY(!scope3->focusScopeItem());
9126 QCOMPARE(scope3->focusItem(), (QGraphicsItem *)scope3);
9128 QGraphicsRectItem *scope2 = new QGraphicsRectItem;
9129 scope2->setData(0, "scope2");
9130 scope2->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsFocusScope);
9132 QVERIFY(!scope2->focusScopeItem());
9133 scope3->setParentItem(scope2);
9134 QCOMPARE(scope2->focusScopeItem(), (QGraphicsItem *)scope3);
9135 QCOMPARE(scope2->focusItem(), (QGraphicsItem *)scope3);
9137 QGraphicsRectItem *scope1 = new QGraphicsRectItem;
9138 scope1->setData(0, "scope1");
9139 scope1->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsFocusScope);
9141 QVERIFY(!scope1->focusScopeItem());
9142 scope2->setParentItem(scope1);
9144 QCOMPARE(scope1->focusItem(), (QGraphicsItem *)scope3);
9145 QCOMPARE(scope2->focusItem(), (QGraphicsItem *)scope3);
9146 QCOMPARE(scope3->focusItem(), (QGraphicsItem *)scope3);
9147 QCOMPARE(scope1->focusScopeItem(), (QGraphicsItem *)scope2);
9148 QCOMPARE(scope2->focusScopeItem(), (QGraphicsItem *)scope3);
9149 QCOMPARE(scope3->focusScopeItem(), (QGraphicsItem *)0);
9151 scene.addItem(scope1);
9153 QEvent windowActivate(QEvent::WindowActivate);
9154 qApp->sendEvent(&scene, &windowActivate);
9157 QCOMPARE(scope1->focusItem(), (QGraphicsItem *)scope3);
9158 QCOMPARE(scope2->focusItem(), (QGraphicsItem *)scope3);
9159 QCOMPARE(scope3->focusItem(), (QGraphicsItem *)scope3);
9160 QCOMPARE(scope1->focusScopeItem(), (QGraphicsItem *)scope2);
9161 QCOMPARE(scope2->focusScopeItem(), (QGraphicsItem *)scope3);
9162 QCOMPARE(scope3->focusScopeItem(), (QGraphicsItem *)0);
9164 QVERIFY(scope3->hasFocus());
9167 QVERIFY(scope2->hasFocus());
9169 QVERIFY(scope1->hasFocus());
9171 QVERIFY(scope2->hasFocus());
9173 QVERIFY(scope3->hasFocus());
9175 QVERIFY(!scope3->hasFocus());
9177 QVERIFY(scope3->hasFocus());
9178 scope3->clearFocus();
9179 QVERIFY(scope2->hasFocus());
9180 scope2->clearFocus();
9181 QVERIFY(scope1->hasFocus());
9184 QVERIFY(!scope2->hasFocus());
9185 QVERIFY(scope1->hasFocus());
9187 QVERIFY(scope2->hasFocus());
9189 QVERIFY(scope3->hasFocus());
9191 QGraphicsRectItem *rect4 = new QGraphicsRectItem;
9192 rect4->setData(0, "rect4");
9193 rect4->setParentItem(scope3);
9195 QGraphicsRectItem *rect5 = new QGraphicsRectItem;
9196 rect5->setData(0, "rect5");
9197 rect5->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsFocusScope);
9199 rect5->setParentItem(rect4);
9200 QCOMPARE(scope3->focusScopeItem(), (QGraphicsItem *)rect5);
9201 QVERIFY(rect5->hasFocus());
9203 rect4->setParentItem(0);
9204 QVERIFY(rect5->hasFocus());
9205 QCOMPARE(scope3->focusScopeItem(), (QGraphicsItem *)0);
9206 QCOMPARE(scope3->focusItem(), (QGraphicsItem *)0);
9207 QVERIFY(!scope3->hasFocus());
9209 QGraphicsRectItem *rectA = new QGraphicsRectItem;
9210 QGraphicsRectItem *scopeA = new QGraphicsRectItem(rectA);
9211 scopeA->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsFocusScope);
9213 QGraphicsRectItem *scopeB = new QGraphicsRectItem(scopeA);
9214 scopeB->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsFocusScope);
9217 scene.addItem(rectA);
9218 QVERIFY(rect5->hasFocus());
9219 QVERIFY(!scopeB->hasFocus());
9222 QVERIFY(scopeB->hasFocus());
9223 QCOMPARE(scopeB->focusItem(), (QGraphicsItem *)scopeB);
9226 void tst_QGraphicsItem::focusScope2()
9228 QGraphicsRectItem *child1 = new QGraphicsRectItem;
9229 child1->setFlags(QGraphicsItem::ItemIsFocusable);
9231 QCOMPARE(child1->focusItem(), (QGraphicsItem *)child1);
9233 QGraphicsRectItem *child2 = new QGraphicsRectItem;
9234 child2->setFlags(QGraphicsItem::ItemIsFocusable);
9236 QGraphicsRectItem *rootFocusScope = new QGraphicsRectItem;
9237 rootFocusScope->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsFocusScope);
9238 rootFocusScope->setFocus();
9239 QCOMPARE(rootFocusScope->focusItem(), (QGraphicsItem *)rootFocusScope);
9241 child1->setParentItem(rootFocusScope);
9242 child2->setParentItem(rootFocusScope);
9244 QCOMPARE(rootFocusScope->focusScopeItem(), (QGraphicsItem *)child1);
9245 QCOMPARE(rootFocusScope->focusItem(), (QGraphicsItem *)child1);
9247 QGraphicsRectItem *siblingChild1 = new QGraphicsRectItem;
9248 siblingChild1->setFlags(QGraphicsItem::ItemIsFocusable);
9249 siblingChild1->setFocus();
9251 QGraphicsRectItem *siblingChild2 = new QGraphicsRectItem;
9252 siblingChild2->setFlags(QGraphicsItem::ItemIsFocusable);
9254 QGraphicsRectItem *siblingFocusScope = new QGraphicsRectItem;
9255 siblingFocusScope->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsFocusScope);
9257 siblingChild1->setParentItem(siblingFocusScope);
9258 siblingChild2->setParentItem(siblingFocusScope);
9260 QCOMPARE(siblingFocusScope->focusScopeItem(), (QGraphicsItem *)siblingChild1);
9261 QCOMPARE(siblingFocusScope->focusItem(), (QGraphicsItem *)0);
9263 QGraphicsItem *root = new QGraphicsRectItem;
9264 rootFocusScope->setParentItem(root);
9265 siblingFocusScope->setParentItem(root);
9267 QCOMPARE(root->focusItem(), (QGraphicsItem *)child1);
9269 QGraphicsScene scene;
9270 scene.addItem(root);
9272 QEvent activate(QEvent::WindowActivate);
9273 qApp->sendEvent(&scene, &activate);
9276 QCOMPARE(scene.focusItem(), (QGraphicsItem *)child1);
9278 // You cannot set focus on a descendant of a focus scope directly;
9279 // this will only change the scope's focus scope item pointer. If
9280 // you want to give true input focus, you must set it directly on
9282 siblingChild2->setFocus();
9283 QVERIFY(!siblingChild2->hasFocus());
9284 QVERIFY(!siblingChild2->focusItem());
9285 QCOMPARE(siblingFocusScope->focusScopeItem(), (QGraphicsItem *)siblingChild2);
9286 QCOMPARE(siblingFocusScope->focusItem(), (QGraphicsItem *)0);
9288 // Set focus on the scope; focus is forwarded to the focus scope item.
9289 siblingFocusScope->setFocus();
9290 QVERIFY(siblingChild2->hasFocus());
9291 QVERIFY(siblingChild2->focusItem());
9292 QCOMPARE(siblingFocusScope->focusScopeItem(), (QGraphicsItem *)siblingChild2);
9293 QCOMPARE(siblingFocusScope->focusItem(), (QGraphicsItem *)siblingChild2);
9296 void tst_QGraphicsItem::stackBefore()
9298 QGraphicsRectItem parent;
9299 QGraphicsRectItem *child1 = new QGraphicsRectItem(QRectF(0, 0, 5, 5), &parent);
9300 QGraphicsRectItem *child2 = new QGraphicsRectItem(QRectF(0, 0, 5, 5), &parent);
9301 QGraphicsRectItem *child3 = new QGraphicsRectItem(QRectF(0, 0, 5, 5), &parent);
9302 QGraphicsRectItem *child4 = new QGraphicsRectItem(QRectF(0, 0, 5, 5), &parent);
9303 QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child1 << child2 << child3 << child4));
9304 child1->setData(0, "child1");
9305 child2->setData(0, "child2");
9306 child3->setData(0, "child3");
9307 child4->setData(0, "child4");
9309 // Remove and append
9310 child2->setParentItem(0);
9311 child2->setParentItem(&parent);
9312 QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child1 << child3 << child4 << child2));
9314 // Move child2 before child1
9315 child2->stackBefore(child1); // 2134
9316 QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child2 << child1 << child3 << child4));
9317 child2->stackBefore(child2); // 2134
9318 QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child2 << child1 << child3 << child4));
9319 child1->setZValue(1); // 2341
9320 QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child2 << child3 << child4 << child1));
9321 child1->stackBefore(child2); // 2341
9322 QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child2 << child3 << child4 << child1));
9323 child1->setZValue(0); // 1234
9324 QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child1 << child2 << child3 << child4));
9325 child4->stackBefore(child1); // 4123
9326 QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child4 << child1 << child2 << child3));
9327 child4->setZValue(1); // 1234 (4123)
9328 QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child1 << child2 << child3 << child4));
9329 child3->stackBefore(child1); // 3124 (4312)
9330 QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child3 << child1 << child2 << child4));
9331 child4->setZValue(0); // 4312
9332 QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child4 << child3 << child1 << child2));
9334 // Make them all toplevels
9335 child1->setParentItem(0);
9336 child2->setParentItem(0);
9337 child3->setParentItem(0);
9338 child4->setParentItem(0);
9340 QGraphicsScene scene;
9341 scene.addItem(child1);
9342 scene.addItem(child2);
9343 scene.addItem(child3);
9344 scene.addItem(child4);
9345 QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder),
9346 (QList<QGraphicsItem *>() << child1 << child2 << child3 << child4));
9348 // Remove and append
9349 scene.removeItem(child2);
9350 scene.addItem(child2);
9351 QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child1 << child3 << child4 << child2));
9353 // Move child2 before child1
9354 child2->stackBefore(child1); // 2134
9355 QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child2 << child1 << child3 << child4));
9356 child2->stackBefore(child2); // 2134
9357 QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child2 << child1 << child3 << child4));
9358 child1->setZValue(1); // 2341
9359 QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child2 << child3 << child4 << child1));
9360 child1->stackBefore(child2); // 2341
9361 QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child2 << child3 << child4 << child1));
9362 child1->setZValue(0); // 1234
9363 QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child1 << child2 << child3 << child4));
9364 child4->stackBefore(child1); // 4123
9365 QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child4 << child1 << child2 << child3));
9366 child4->setZValue(1); // 1234 (4123)
9367 QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child1 << child2 << child3 << child4));
9368 child3->stackBefore(child1); // 3124 (4312)
9369 QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child3 << child1 << child2 << child4));
9370 child4->setZValue(0); // 4312
9371 QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child4 << child3 << child1 << child2));
9374 void tst_QGraphicsItem::QTBUG_4233_updateCachedWithSceneRect()
9376 EventTester *tester = new EventTester;
9377 tester->setCacheMode(QGraphicsItem::ItemCoordinateCache);
9379 QGraphicsScene scene;
9380 scene.addItem(tester);
9381 scene.setSceneRect(-100, -100, 200, 200); // contains the tester item
9383 QGraphicsView view(&scene);
9385 QTest::qWaitForWindowShown(&view);
9386 QTRY_COMPARE(QApplication::activeWindow(), (QWidget *)&view);
9388 QTRY_COMPARE(tester->repaints, 1);
9390 scene.update(); // triggers "updateAll" optimization
9391 qApp->processEvents();
9392 qApp->processEvents(); // in 4.6 only one processEvents is necessary
9394 QCOMPARE(tester->repaints, 1);
9396 scene.update(); // triggers "updateAll" optimization
9398 qApp->processEvents();
9399 qApp->processEvents(); // in 4.6 only one processEvents is necessary
9401 QCOMPARE(tester->repaints, 2);
9404 void tst_QGraphicsItem::sceneModality()
9406 // 1) Test mouse events (delivery/propagation/redirection)
9407 // 2) Test hover events (incl. leave on block, enter on unblock)
9408 // 3) Test cursor stuff (incl. unset on block, set on unblock)
9409 // 4) Test clickfocus
9410 // 5) Test grab/ungrab events (possibly ungrab on block, regrab on unblock)
9411 // 6) ### modality for non-panels is unsupported for now
9412 QGraphicsScene scene;
9414 QGraphicsRectItem *bottomItem = scene.addRect(-150, -100, 300, 200);
9415 bottomItem->setFlag(QGraphicsItem::ItemIsFocusable);
9416 bottomItem->setBrush(Qt::yellow);
9418 QGraphicsRectItem *leftParent = scene.addRect(-50, -50, 100, 100);
9419 leftParent->setFlag(QGraphicsItem::ItemIsPanel);
9420 leftParent->setBrush(Qt::blue);
9422 QGraphicsRectItem *leftChild = scene.addRect(-25, -25, 50, 50);
9423 leftChild->setFlag(QGraphicsItem::ItemIsPanel);
9424 leftChild->setBrush(Qt::green);
9425 leftChild->setParentItem(leftParent);
9427 QGraphicsRectItem *rightParent = scene.addRect(-50, -50, 100, 100);
9428 rightParent->setFlag(QGraphicsItem::ItemIsPanel);
9429 rightParent->setBrush(Qt::red);
9430 QGraphicsRectItem *rightChild = scene.addRect(-25, -25, 50, 50);
9431 rightChild->setFlag(QGraphicsItem::ItemIsPanel);
9432 rightChild->setBrush(Qt::gray);
9433 rightChild->setParentItem(rightParent);
9435 leftParent->setPos(-75, 0);
9436 rightParent->setPos(75, 0);
9438 bottomItem->setData(0, "bottomItem");
9439 leftParent->setData(0, "leftParent");
9440 leftChild->setData(0, "leftChild");
9441 rightParent->setData(0, "rightParent");
9442 rightChild->setData(0, "rightChild");
9444 scene.setSceneRect(scene.itemsBoundingRect().adjusted(-50, -50, 50, 50));
9446 EventSpy2 leftParentSpy(&scene, leftParent);
9447 EventSpy2 leftChildSpy(&scene, leftChild);
9448 EventSpy2 rightParentSpy(&scene, rightParent);
9449 EventSpy2 rightChildSpy(&scene, rightChild);
9450 EventSpy2 bottomItemSpy(&scene, bottomItem);
9452 // Scene modality, also test multiple scene modal items
9453 leftChild->setPanelModality(QGraphicsItem::SceneModal);
9454 QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0);
9455 QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1);
9456 QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 1);
9457 QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 1);
9458 QCOMPARE(bottomItemSpy.counts[QEvent::WindowBlocked], 0); // not a panel
9460 // Click inside left child
9461 sendMouseClick(&scene, leftChild->scenePos(), Qt::LeftButton);
9462 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 1);
9463 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMouseRelease], 0); // no grab
9464 QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9465 QCOMPARE(rightParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9466 QCOMPARE(rightChildSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9467 QCOMPARE(bottomItemSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9469 // Click on left parent, event goes to modal child
9470 sendMouseClick(&scene, leftParent->sceneBoundingRect().topLeft() + QPointF(5, 5), Qt::LeftButton);
9471 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 2);
9472 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMouseRelease], 0); // no grab
9473 QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9474 QCOMPARE(rightParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9475 QCOMPARE(rightChildSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9476 QCOMPARE(bottomItemSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9478 // Click on all other items and outside the items
9479 sendMouseClick(&scene, rightParent->sceneBoundingRect().topLeft() + QPointF(5, 5), Qt::LeftButton);
9480 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 3);
9481 sendMouseClick(&scene, rightChild->scenePos(), Qt::LeftButton);
9482 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 4);
9483 sendMouseClick(&scene, bottomItem->scenePos(), Qt::LeftButton);
9484 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 5);
9485 sendMouseClick(&scene, QPointF(10000, 10000), Qt::LeftButton);
9486 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 6);
9487 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMouseRelease], 0); // no grab
9488 QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9489 QCOMPARE(rightParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9490 QCOMPARE(rightChildSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9491 QCOMPARE(bottomItemSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9493 leftChildSpy.counts.clear();
9494 rightChildSpy.counts.clear();
9495 leftParentSpy.counts.clear();
9496 rightParentSpy.counts.clear();
9497 bottomItemSpy.counts.clear();
9499 leftChild->setPanelModality(QGraphicsItem::NonModal);
9500 QCOMPARE(leftChildSpy.counts[QEvent::WindowUnblocked], 0);
9501 QCOMPARE(rightChildSpy.counts[QEvent::WindowUnblocked], 1);
9502 QCOMPARE(leftParentSpy.counts[QEvent::WindowUnblocked], 1);
9503 QCOMPARE(rightParentSpy.counts[QEvent::WindowUnblocked], 1);
9504 QCOMPARE(bottomItemSpy.counts[QEvent::WindowUnblocked], 0);
9506 // Left parent enters scene modality.
9507 leftParent->setPanelModality(QGraphicsItem::SceneModal);
9508 QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0);
9509 QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 1);
9510 QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 0);
9511 QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 1);
9512 QCOMPARE(bottomItemSpy.counts[QEvent::WindowBlocked], 0);
9514 // Click inside left child.
9515 sendMouseClick(&scene, leftChild->scenePos(), Qt::LeftButton);
9516 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 1);
9517 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMouseRelease], 0);
9518 QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // panel stops propagation
9519 QCOMPARE(rightParentSpy.counts[QEvent::GraphicsSceneMousePress], 0);
9520 QCOMPARE(rightChildSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9521 QCOMPARE(bottomItemSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9523 // Click on left parent.
9524 sendMouseClick(&scene, leftParent->sceneBoundingRect().topLeft() + QPointF(5, 5), Qt::LeftButton);
9525 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 1);
9526 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMouseRelease], 0);
9527 QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 1);
9528 QCOMPARE(rightParentSpy.counts[QEvent::GraphicsSceneMousePress], 0);
9529 QCOMPARE(rightChildSpy.counts[QEvent::GraphicsSceneMousePress], 0);
9530 QCOMPARE(bottomItemSpy.counts[QEvent::GraphicsSceneMousePress], 0);
9532 // Click on all other items and outside the items
9533 sendMouseClick(&scene, rightParent->sceneBoundingRect().topLeft() + QPointF(5, 5), Qt::LeftButton);
9534 QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 2);
9535 sendMouseClick(&scene, rightChild->scenePos(), Qt::LeftButton);
9536 QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 3);
9537 sendMouseClick(&scene, bottomItem->scenePos(), Qt::LeftButton);
9538 QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 4);
9539 sendMouseClick(&scene, QPointF(10000, 10000), Qt::LeftButton);
9540 QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 5);
9541 QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMouseRelease], 0);
9542 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 1);
9543 QCOMPARE(rightParentSpy.counts[QEvent::GraphicsSceneMousePress], 0);
9544 QCOMPARE(rightChildSpy.counts[QEvent::GraphicsSceneMousePress], 0);
9545 QCOMPARE(bottomItemSpy.counts[QEvent::GraphicsSceneMousePress], 0);
9547 leftChildSpy.counts.clear();
9548 rightChildSpy.counts.clear();
9549 leftParentSpy.counts.clear();
9550 rightParentSpy.counts.clear();
9551 bottomItemSpy.counts.clear();
9553 // Now both left parent and child are scene modal. Left parent is blocked.
9554 leftChild->setPanelModality(QGraphicsItem::SceneModal);
9555 QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0);
9556 QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 0);
9557 QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1);
9558 QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 0);
9559 QCOMPARE(bottomItemSpy.counts[QEvent::WindowBlocked], 0);
9561 // Click inside left child
9562 sendMouseClick(&scene, leftChild->scenePos(), Qt::LeftButton);
9563 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 1);
9564 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMouseRelease], 0); // no grab
9565 QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9566 QCOMPARE(rightParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9567 QCOMPARE(rightChildSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9568 QCOMPARE(bottomItemSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9570 // Click on left parent, event goes to modal child
9571 sendMouseClick(&scene, leftParent->sceneBoundingRect().topLeft() + QPointF(5, 5), Qt::LeftButton);
9572 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 2);
9573 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMouseRelease], 0); // no grab
9574 QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9575 QCOMPARE(rightParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9576 QCOMPARE(rightChildSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9577 QCOMPARE(bottomItemSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9579 // Click on all other items and outside the items
9580 sendMouseClick(&scene, rightParent->sceneBoundingRect().topLeft() + QPointF(5, 5), Qt::LeftButton);
9581 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 3);
9582 sendMouseClick(&scene, rightChild->scenePos(), Qt::LeftButton);
9583 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 4);
9584 sendMouseClick(&scene, bottomItem->scenePos(), Qt::LeftButton);
9585 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 5);
9586 sendMouseClick(&scene, QPointF(10000, 10000), Qt::LeftButton);
9587 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 6);
9588 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMouseRelease], 0); // no grab
9589 QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9590 QCOMPARE(rightParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9591 QCOMPARE(rightChildSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9592 QCOMPARE(bottomItemSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9594 leftChildSpy.counts.clear();
9595 rightChildSpy.counts.clear();
9596 leftParentSpy.counts.clear();
9597 rightParentSpy.counts.clear();
9598 bottomItemSpy.counts.clear();
9600 // Right child enters scene modality, only left child is blocked.
9601 rightChild->setPanelModality(QGraphicsItem::SceneModal);
9602 QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 1);
9603 QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 0);
9604 QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 0);
9605 QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 0);
9606 QCOMPARE(bottomItemSpy.counts[QEvent::WindowBlocked], 0);
9609 void tst_QGraphicsItem::panelModality()
9611 // 1) Test mouse events (delivery/propagation/redirection)
9612 // 2) Test hover events (incl. leave on block, enter on unblock)
9613 // 3) Test cursor stuff (incl. unset on block, set on unblock)
9614 // 4) Test clickfocus
9615 // 5) Test grab/ungrab events (possibly ungrab on block, regrab on unblock)
9616 // 6) ### modality for non-panels is unsupported for now
9617 QGraphicsScene scene;
9619 QGraphicsRectItem *bottomItem = scene.addRect(-150, -100, 300, 200);
9620 bottomItem->setFlag(QGraphicsItem::ItemIsFocusable);
9621 bottomItem->setBrush(Qt::yellow);
9623 QGraphicsRectItem *leftParent = scene.addRect(-50, -50, 100, 100);
9624 leftParent->setFlag(QGraphicsItem::ItemIsPanel);
9625 leftParent->setBrush(Qt::blue);
9627 QGraphicsRectItem *leftChild = scene.addRect(-25, -25, 50, 50);
9628 leftChild->setFlag(QGraphicsItem::ItemIsPanel);
9629 leftChild->setBrush(Qt::green);
9630 leftChild->setParentItem(leftParent);
9632 QGraphicsRectItem *rightParent = scene.addRect(-50, -50, 100, 100);
9633 rightParent->setFlag(QGraphicsItem::ItemIsPanel);
9634 rightParent->setBrush(Qt::red);
9635 QGraphicsRectItem *rightChild = scene.addRect(-25, -25, 50, 50);
9636 rightChild->setFlag(QGraphicsItem::ItemIsPanel);
9637 rightChild->setBrush(Qt::gray);
9638 rightChild->setParentItem(rightParent);
9640 leftParent->setPos(-75, 0);
9641 rightParent->setPos(75, 0);
9643 bottomItem->setData(0, "bottomItem");
9644 leftParent->setData(0, "leftParent");
9645 leftChild->setData(0, "leftChild");
9646 rightParent->setData(0, "rightParent");
9647 rightChild->setData(0, "rightChild");
9649 scene.setSceneRect(scene.itemsBoundingRect().adjusted(-50, -50, 50, 50));
9651 EventSpy2 leftParentSpy(&scene, leftParent);
9652 EventSpy2 leftChildSpy(&scene, leftChild);
9653 EventSpy2 rightParentSpy(&scene, rightParent);
9654 EventSpy2 rightChildSpy(&scene, rightChild);
9655 EventSpy2 bottomItemSpy(&scene, bottomItem);
9657 // Left Child enters panel modality, only left parent is blocked.
9658 leftChild->setPanelModality(QGraphicsItem::PanelModal);
9659 QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0);
9660 QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 0);
9661 QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1);
9662 QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 0);
9663 QCOMPARE(bottomItemSpy.counts[QEvent::WindowBlocked], 0);
9665 leftChild->setPanelModality(QGraphicsItem::NonModal);
9666 leftChildSpy.counts.clear();
9667 rightChildSpy.counts.clear();
9668 leftParentSpy.counts.clear();
9669 rightParentSpy.counts.clear();
9670 bottomItemSpy.counts.clear();
9672 // Left parent enter panel modality, nothing is blocked.
9673 leftParent->setPanelModality(QGraphicsItem::PanelModal);
9674 QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0);
9675 QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 0);
9676 QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 0);
9677 QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 0);
9678 QCOMPARE(bottomItemSpy.counts[QEvent::WindowBlocked], 0);
9680 // Left child enters panel modality, left parent is blocked again.
9681 leftChild->setPanelModality(QGraphicsItem::PanelModal);
9682 QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0);
9683 QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 0);
9684 QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1);
9685 QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 0);
9686 QCOMPARE(bottomItemSpy.counts[QEvent::WindowBlocked], 0);
9688 leftChildSpy.counts.clear();
9689 rightChildSpy.counts.clear();
9690 leftParentSpy.counts.clear();
9691 rightParentSpy.counts.clear();
9692 bottomItemSpy.counts.clear();
9694 leftChild->setPanelModality(QGraphicsItem::NonModal);
9695 QCOMPARE(leftParentSpy.counts[QEvent::WindowUnblocked], 1);
9696 leftParent->setPanelModality(QGraphicsItem::NonModal);
9697 QCOMPARE(leftChildSpy.counts[QEvent::WindowUnblocked], 0);
9698 QCOMPARE(rightChildSpy.counts[QEvent::WindowUnblocked], 0);
9699 QCOMPARE(leftParentSpy.counts[QEvent::WindowUnblocked], 1);
9700 QCOMPARE(rightParentSpy.counts[QEvent::WindowUnblocked], 0);
9701 QCOMPARE(bottomItemSpy.counts[QEvent::WindowUnblocked], 0);
9703 leftChildSpy.counts.clear();
9704 rightChildSpy.counts.clear();
9705 leftParentSpy.counts.clear();
9706 rightParentSpy.counts.clear();
9707 bottomItemSpy.counts.clear();
9709 // Left and right child enter panel modality, both parents are blocked.
9710 rightChild->setPanelModality(QGraphicsItem::PanelModal);
9711 QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 0);
9712 QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 1);
9713 leftChild->setPanelModality(QGraphicsItem::PanelModal);
9714 QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1);
9715 QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 1);
9718 void tst_QGraphicsItem::mixedModality()
9720 // 1) Test mouse events (delivery/propagation/redirection)
9721 // 2) Test hover events (incl. leave on block, enter on unblock)
9722 // 3) Test cursor stuff (incl. unset on block, set on unblock)
9723 // 4) Test clickfocus
9724 // 5) Test grab/ungrab events (possibly ungrab on block, regrab on unblock)
9725 // 6) ### modality for non-panels is unsupported for now
9726 QGraphicsScene scene;
9728 QGraphicsRectItem *bottomItem = scene.addRect(-150, -100, 300, 200);
9729 bottomItem->setFlag(QGraphicsItem::ItemIsFocusable);
9730 bottomItem->setBrush(Qt::yellow);
9732 QGraphicsRectItem *leftParent = scene.addRect(-50, -50, 100, 100);
9733 leftParent->setFlag(QGraphicsItem::ItemIsPanel);
9734 leftParent->setBrush(Qt::blue);
9736 QGraphicsRectItem *leftChild = scene.addRect(-25, -25, 50, 50);
9737 leftChild->setFlag(QGraphicsItem::ItemIsPanel);
9738 leftChild->setBrush(Qt::green);
9739 leftChild->setParentItem(leftParent);
9741 QGraphicsRectItem *rightParent = scene.addRect(-50, -50, 100, 100);
9742 rightParent->setFlag(QGraphicsItem::ItemIsPanel);
9743 rightParent->setBrush(Qt::red);
9744 QGraphicsRectItem *rightChild = scene.addRect(-25, -25, 50, 50);
9745 rightChild->setFlag(QGraphicsItem::ItemIsPanel);
9746 rightChild->setBrush(Qt::gray);
9747 rightChild->setParentItem(rightParent);
9749 leftParent->setPos(-75, 0);
9750 rightParent->setPos(75, 0);
9752 bottomItem->setData(0, "bottomItem");
9753 leftParent->setData(0, "leftParent");
9754 leftChild->setData(0, "leftChild");
9755 rightParent->setData(0, "rightParent");
9756 rightChild->setData(0, "rightChild");
9758 scene.setSceneRect(scene.itemsBoundingRect().adjusted(-50, -50, 50, 50));
9760 EventSpy2 leftParentSpy(&scene, leftParent);
9761 EventSpy2 leftChildSpy(&scene, leftChild);
9762 EventSpy2 rightParentSpy(&scene, rightParent);
9763 EventSpy2 rightChildSpy(&scene, rightChild);
9764 EventSpy2 bottomItemSpy(&scene, bottomItem);
9766 // Left Child enters panel modality, only left parent is blocked.
9767 leftChild->setPanelModality(QGraphicsItem::PanelModal);
9768 QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0);
9769 QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 0);
9770 QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1);
9771 QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 0);
9773 // Left parent enters scene modality, which blocks everything except the child.
9774 leftParent->setPanelModality(QGraphicsItem::SceneModal);
9775 QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0);
9776 QCOMPARE(leftChildSpy.counts[QEvent::WindowUnblocked], 0);
9777 QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 1);
9778 QCOMPARE(rightChildSpy.counts[QEvent::WindowUnblocked], 0);
9779 QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1);
9780 QCOMPARE(leftParentSpy.counts[QEvent::WindowUnblocked], 0);
9781 QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 1);
9782 QCOMPARE(rightParentSpy.counts[QEvent::WindowUnblocked], 0);
9784 // Right child enters panel modality (changes nothing).
9785 rightChild->setPanelModality(QGraphicsItem::PanelModal);
9786 QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0);
9787 QCOMPARE(leftChildSpy.counts[QEvent::WindowUnblocked], 0);
9788 QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 1);
9789 QCOMPARE(rightChildSpy.counts[QEvent::WindowUnblocked], 0);
9790 QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1);
9791 QCOMPARE(leftParentSpy.counts[QEvent::WindowUnblocked], 0);
9792 QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 1);
9793 QCOMPARE(rightParentSpy.counts[QEvent::WindowUnblocked], 0);
9795 // Left parent leaves modality. Right child is unblocked.
9796 leftParent->setPanelModality(QGraphicsItem::NonModal);
9797 QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0);
9798 QCOMPARE(leftChildSpy.counts[QEvent::WindowUnblocked], 0);
9799 QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 1);
9800 QCOMPARE(rightChildSpy.counts[QEvent::WindowUnblocked], 1);
9801 QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1);
9802 QCOMPARE(leftParentSpy.counts[QEvent::WindowUnblocked], 0);
9803 QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 1);
9804 QCOMPARE(rightParentSpy.counts[QEvent::WindowUnblocked], 0);
9806 // Right child "upgrades" its modality to scene modal. Left child is blocked.
9807 // Right parent is unaffected.
9808 rightChild->setPanelModality(QGraphicsItem::SceneModal);
9809 QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 1);
9810 QCOMPARE(leftChildSpy.counts[QEvent::WindowUnblocked], 0);
9811 QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 1);
9812 QCOMPARE(rightChildSpy.counts[QEvent::WindowUnblocked], 1);
9813 QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1);
9814 QCOMPARE(leftParentSpy.counts[QEvent::WindowUnblocked], 0);
9815 QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 1);
9816 QCOMPARE(rightParentSpy.counts[QEvent::WindowUnblocked], 0);
9818 // "downgrade" right child back to panel modal, left child is unblocked
9819 rightChild->setPanelModality(QGraphicsItem::PanelModal);
9820 QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 1);
9821 QCOMPARE(leftChildSpy.counts[QEvent::WindowUnblocked], 1);
9822 QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 1);
9823 QCOMPARE(rightChildSpy.counts[QEvent::WindowUnblocked], 1);
9824 QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1);
9825 QCOMPARE(leftParentSpy.counts[QEvent::WindowUnblocked], 0);
9826 QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 1);
9827 QCOMPARE(rightParentSpy.counts[QEvent::WindowUnblocked], 0);
9830 void tst_QGraphicsItem::modality_hover()
9832 QGraphicsScene scene;
9833 QGraphicsRectItem *rect1 = scene.addRect(-50, -50, 100, 100);
9834 rect1->setFlag(QGraphicsItem::ItemIsPanel);
9835 rect1->setAcceptHoverEvents(true);
9836 rect1->setData(0, "rect1");
9838 QGraphicsRectItem *rect2 = scene.addRect(-50, -50, 100, 100);
9839 rect2->setParentItem(rect1);
9840 rect2->setFlag(QGraphicsItem::ItemIsPanel);
9841 rect2->setAcceptHoverEvents(true);
9842 rect2->setPos(50, 50);
9843 rect2->setPanelModality(QGraphicsItem::SceneModal);
9844 rect2->setData(0, "rect2");
9846 EventSpy2 rect1Spy(&scene, rect1);
9847 EventSpy2 rect2Spy(&scene, rect2);
9849 sendMouseMove(&scene, QPointF(-25, -25));
9851 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverEnter], 0);
9852 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverMove], 0);
9853 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverLeave], 0);
9855 sendMouseMove(&scene, QPointF(75, 75));
9857 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverEnter], 0);
9858 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverMove], 0);
9859 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverLeave], 0);
9860 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverEnter], 1);
9861 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverMove], 1);
9862 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverLeave], 0);
9864 sendMouseMove(&scene, QPointF(-25, -25));
9866 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverLeave], 1);
9867 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverEnter], 0);
9868 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverMove], 0);
9869 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverLeave], 0);
9871 rect2->setPanelModality(QGraphicsItem::NonModal);
9873 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverEnter], 1);
9874 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverMove], 1);
9876 sendMouseMove(&scene, QPointF(75, 75));
9878 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverEnter], 2);
9879 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverMove], 2);
9881 rect2->setPanelModality(QGraphicsItem::SceneModal);
9883 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverLeave], 1);
9884 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverEnter], 2);
9885 // changing modality causes a spurious GraphicsSceneHoveMove, even though the mouse didn't
9887 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverMove], 3);
9889 sendMouseMove(&scene, QPointF(-25, -25));
9891 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverLeave], 2);
9892 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverEnter], 1);
9893 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverMove], 1);
9894 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverLeave], 1);
9896 rect2->setPanelModality(QGraphicsItem::PanelModal);
9898 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverEnter], 1);
9899 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverMove], 1);
9900 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverLeave], 1);
9901 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverEnter], 2);
9902 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverMove], 3);
9903 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverLeave], 2);
9905 rect2->setPanelModality(QGraphicsItem::NonModal);
9907 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverEnter], 2);
9908 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverMove], 2);
9909 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverEnter], 2);
9910 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverMove], 3);
9911 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverLeave], 2);
9914 void tst_QGraphicsItem::modality_mouseGrabber()
9916 QGraphicsScene scene;
9917 QGraphicsRectItem *rect1 = scene.addRect(-50, -50, 100, 100);
9918 rect1->setFlag(QGraphicsItem::ItemIsPanel);
9919 rect1->setFlag(QGraphicsItem::ItemIsMovable);
9920 rect1->setData(0, "rect1");
9922 QGraphicsRectItem *rect2 = scene.addRect(-50, -50, 100, 100);
9923 rect2->setParentItem(rect1);
9924 rect2->setFlag(QGraphicsItem::ItemIsPanel);
9925 rect2->setFlag(QGraphicsItem::ItemIsMovable);
9926 rect2->setPos(50, 50);
9927 rect2->setData(0, "rect2");
9929 EventSpy2 rect1Spy(&scene, rect1);
9930 EventSpy2 rect2Spy(&scene, rect2);
9933 // pressing mouse on rect1 starts implicit grab
9934 sendMousePress(&scene, QPoint(-25, -25));
9935 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 1);
9936 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMousePress], 1);
9937 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 0);
9938 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
9939 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
9940 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) rect1);
9942 // grab lost when rect1 is modally shadowed
9943 rect2->setPanelModality(QGraphicsItem::SceneModal);
9944 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 1);
9945 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 1);
9946 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
9947 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
9948 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
9950 // releasing goes nowhere
9951 sendMouseRelease(&scene, QPoint(-25, -25));
9952 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 1);
9953 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMouseRelease], 0);
9954 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 1);
9955 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
9956 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneMouseRelease], 0);
9957 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
9958 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
9960 // pressing mouse on rect1 starts implicit grab on rect2 (since it is modal)
9961 sendMouseClick(&scene, QPoint(-25, -25));
9962 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 1);
9963 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMousePress], 1);
9964 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMouseRelease], 0);
9965 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 1);
9966 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1);
9967 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneMousePress], 1);
9968 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneMouseRelease], 1);
9969 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1);
9971 rect2->setPanelModality(QGraphicsItem::NonModal);
9973 // pressing mouse on rect1 starts implicit grab
9974 sendMousePress(&scene, QPoint(-25, -25));
9975 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 2);
9976 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMousePress], 2);
9977 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 1);
9978 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1);
9979 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1);
9980 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) rect1);
9982 // grab lost to rect2 when rect1 is modally shadowed
9983 rect2->setPanelModality(QGraphicsItem::SceneModal);
9984 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 2);
9985 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 2);
9986 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1);
9987 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1);
9988 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
9990 // rect1 does *not* re-grab when rect2 is no longer modal
9991 rect2->setPanelModality(QGraphicsItem::NonModal);
9992 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 2);
9993 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 2);
9994 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1);
9995 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1);
9996 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
9998 // release goes nowhere
9999 sendMouseRelease(&scene, QPoint(-25, -25));
10000 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 2);
10001 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMouseRelease], 0);
10002 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 2);
10003 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1);
10004 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1);
10005 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
10008 // repeat the test using PanelModal
10009 rect2->setPanelModality(QGraphicsItem::NonModal);
10010 rect1Spy.counts.clear();
10011 rect2Spy.counts.clear();
10013 // pressing mouse on rect1 starts implicit grab
10014 sendMousePress(&scene, QPoint(-25, -25));
10015 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 1);
10016 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMousePress], 1);
10017 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 0);
10018 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
10019 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
10020 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) rect1);
10022 // grab lost when rect1 is modally shadowed
10023 rect2->setPanelModality(QGraphicsItem::PanelModal);
10024 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 1);
10025 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 1);
10026 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
10027 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
10028 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
10030 // releasing goes nowhere
10031 sendMouseRelease(&scene, QPoint(-25, -25));
10032 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 1);
10033 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMouseRelease], 0);
10034 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 1);
10035 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
10036 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneMouseRelease], 0);
10037 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
10038 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
10040 // pressing mouse on rect1 starts implicit grab on rect2 (since it is modal)
10041 sendMouseClick(&scene, QPoint(-25, -25));
10042 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 1);
10043 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMousePress], 1);
10044 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMouseRelease], 0);
10045 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 1);
10046 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1);
10047 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneMousePress], 1);
10048 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneMouseRelease], 1);
10049 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1);
10051 rect2->setPanelModality(QGraphicsItem::NonModal);
10053 // pressing mouse on rect1 starts implicit grab
10054 sendMousePress(&scene, QPoint(-25, -25));
10055 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 2);
10056 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMousePress], 2);
10057 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 1);
10058 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1);
10059 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1);
10060 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) rect1);
10062 // grab lost to rect2 when rect1 is modally shadowed
10063 rect2->setPanelModality(QGraphicsItem::PanelModal);
10064 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 2);
10065 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 2);
10066 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1);
10067 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1);
10068 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
10070 // rect1 does *not* re-grab when rect2 is no longer modal
10071 rect2->setPanelModality(QGraphicsItem::NonModal);
10072 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 2);
10073 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 2);
10074 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1);
10075 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1);
10076 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
10078 // release goes nowhere
10079 sendMouseRelease(&scene, QPoint(-25, -25));
10080 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 2);
10081 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMouseRelease], 0);
10082 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 2);
10083 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1);
10084 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1);
10085 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
10089 // repeat the PanelModal tests, but this time the mouse events will be on a non-modal item,
10090 // meaning normal grabbing should work
10091 rect2->setPanelModality(QGraphicsItem::NonModal);
10092 rect1Spy.counts.clear();
10093 rect2Spy.counts.clear();
10095 QGraphicsRectItem *rect3 = scene.addRect(-50, -50, 100, 100);
10096 rect3->setFlag(QGraphicsItem::ItemIsPanel);
10097 rect3->setFlag(QGraphicsItem::ItemIsMovable);
10098 rect3->setPos(150, 50);
10099 rect3->setData(0, "rect3");
10101 EventSpy2 rect3Spy(&scene, rect3);
10103 // pressing mouse on rect3 starts implicit grab
10104 sendMousePress(&scene, QPoint(150, 50));
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], 1);
10110 QCOMPARE(rect3Spy.counts[QEvent::GraphicsSceneMousePress], 1);
10111 QCOMPARE(rect3Spy.counts[QEvent::UngrabMouse], 0);
10112 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) rect3);
10114 // grab is *not* lost when rect1 is modally shadowed by rect2
10115 rect2->setPanelModality(QGraphicsItem::PanelModal);
10116 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 0);
10117 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 0);
10118 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
10119 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
10120 QCOMPARE(rect3Spy.counts[QEvent::GrabMouse], 1);
10121 QCOMPARE(rect3Spy.counts[QEvent::UngrabMouse], 0);
10122 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) rect3);
10124 // releasing goes to rect3
10125 sendMouseRelease(&scene, QPoint(150, 50));
10126 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 0);
10127 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 0);
10128 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
10129 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
10130 QCOMPARE(rect3Spy.counts[QEvent::GrabMouse], 1);
10131 QCOMPARE(rect3Spy.counts[QEvent::GraphicsSceneMouseRelease], 1);
10132 QCOMPARE(rect3Spy.counts[QEvent::UngrabMouse], 1);
10133 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
10135 rect2->setPanelModality(QGraphicsItem::NonModal);
10137 // pressing mouse on rect3 starts implicit grab
10138 sendMousePress(&scene, QPoint(150, 50));
10139 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 0);
10140 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 0);
10141 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
10142 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
10143 QCOMPARE(rect3Spy.counts[QEvent::GrabMouse], 2);
10144 QCOMPARE(rect3Spy.counts[QEvent::UngrabMouse], 1);
10145 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) rect3);
10147 // grab is not lost
10148 rect2->setPanelModality(QGraphicsItem::PanelModal);
10149 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 0);
10150 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 0);
10151 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
10152 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
10153 QCOMPARE(rect3Spy.counts[QEvent::GrabMouse], 2);
10154 QCOMPARE(rect3Spy.counts[QEvent::UngrabMouse], 1);
10155 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) rect3);
10157 // grab stays on rect3
10158 rect2->setPanelModality(QGraphicsItem::NonModal);
10159 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 0);
10160 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 0);
10161 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
10162 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
10163 QCOMPARE(rect3Spy.counts[QEvent::GrabMouse], 2);
10164 QCOMPARE(rect3Spy.counts[QEvent::UngrabMouse], 1);
10165 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) rect3);
10167 // release goes to rect3
10168 sendMouseRelease(&scene, QPoint(150, 50));
10169 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 0);
10170 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 0);
10171 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
10172 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
10173 QCOMPARE(rect3Spy.counts[QEvent::GrabMouse], 2);
10174 QCOMPARE(rect3Spy.counts[QEvent::UngrabMouse], 2);
10175 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
10179 void tst_QGraphicsItem::modality_clickFocus()
10181 QGraphicsScene scene;
10182 QGraphicsRectItem *rect1 = scene.addRect(-50, -50, 100, 100);
10183 rect1->setFlag(QGraphicsItem::ItemIsPanel);
10184 rect1->setFlag(QGraphicsItem::ItemIsFocusable);
10185 rect1->setData(0, "rect1");
10187 QGraphicsRectItem *rect2 = scene.addRect(-50, -50, 100, 100);
10188 rect2->setParentItem(rect1);
10189 rect2->setFlag(QGraphicsItem::ItemIsPanel);
10190 rect2->setFlag(QGraphicsItem::ItemIsFocusable);
10191 rect2->setPos(50, 50);
10192 rect2->setData(0, "rect2");
10194 QEvent windowActivateEvent(QEvent::WindowActivate);
10195 QApplication::sendEvent(&scene, &windowActivateEvent);
10197 EventSpy2 rect1Spy(&scene, rect1);
10198 EventSpy2 rect2Spy(&scene, rect2);
10200 // activate rect1, it should not get focus
10201 rect1->setActive(true);
10202 QCOMPARE(scene.focusItem(), (QGraphicsItem *) 0);
10204 // focus stays unset when rect2 becomes modal
10205 rect2->setPanelModality(QGraphicsItem::SceneModal);
10206 QCOMPARE(scene.focusItem(), (QGraphicsItem *) 0);
10207 QCOMPARE(rect1Spy.counts[QEvent::FocusIn], 0);
10208 QCOMPARE(rect1Spy.counts[QEvent::FocusOut], 0);
10209 QCOMPARE(rect2Spy.counts[QEvent::FocusIn], 0);
10210 QCOMPARE(rect2Spy.counts[QEvent::FocusOut], 0);
10212 // clicking on rect1 should not set it's focus item
10213 sendMouseClick(&scene, QPointF(-25, -25));
10214 QCOMPARE(rect1->focusItem(), (QGraphicsItem *) 0);
10215 QCOMPARE(rect1Spy.counts[QEvent::FocusIn], 0);
10216 QCOMPARE(rect1Spy.counts[QEvent::FocusOut], 0);
10217 QCOMPARE(rect2Spy.counts[QEvent::FocusIn], 0);
10218 QCOMPARE(rect2Spy.counts[QEvent::FocusOut], 0);
10220 // clicking on rect2 gives it focus
10221 rect2->setActive(true);
10222 sendMouseClick(&scene, QPointF(75, 75));
10223 QCOMPARE(scene.focusItem(), (QGraphicsItem *) rect2);
10224 QCOMPARE(rect1Spy.counts[QEvent::FocusIn], 0);
10225 QCOMPARE(rect1Spy.counts[QEvent::FocusOut], 0);
10226 QCOMPARE(rect2Spy.counts[QEvent::FocusIn], 1);
10227 QCOMPARE(rect2Spy.counts[QEvent::FocusOut], 0);
10229 // clicking on rect1 does *not* give it focus
10230 rect1->setActive(true);
10231 sendMouseClick(&scene, QPointF(-25, -25));
10232 QCOMPARE(scene.focusItem(), (QGraphicsItem *) 0);
10233 QCOMPARE(rect1Spy.counts[QEvent::FocusIn], 0);
10234 QCOMPARE(rect1Spy.counts[QEvent::FocusOut], 0);
10235 QCOMPARE(rect2Spy.counts[QEvent::FocusIn], 1);
10236 QCOMPARE(rect2Spy.counts[QEvent::FocusOut], 1);
10238 // focus doesn't change when leaving modality either
10239 rect2->setPanelModality(QGraphicsItem::NonModal);
10240 QCOMPARE(scene.focusItem(), (QGraphicsItem *) 0);
10241 QCOMPARE(rect1Spy.counts[QEvent::FocusIn], 0);
10242 QCOMPARE(rect1Spy.counts[QEvent::FocusOut], 0);
10243 QCOMPARE(rect2Spy.counts[QEvent::FocusIn], 1);
10244 QCOMPARE(rect2Spy.counts[QEvent::FocusOut], 1);
10246 // click on rect1, it should get focus now
10247 sendMouseClick(&scene, QPointF(-25, -25));
10248 QCOMPARE(scene.focusItem(), (QGraphicsItem *) rect1);
10249 QCOMPARE(rect1Spy.counts[QEvent::FocusIn], 1);
10250 QCOMPARE(rect1Spy.counts[QEvent::FocusOut], 0);
10251 QCOMPARE(rect2Spy.counts[QEvent::FocusIn], 1);
10252 QCOMPARE(rect2Spy.counts[QEvent::FocusOut], 1);
10255 void tst_QGraphicsItem::modality_keyEvents()
10257 QGraphicsScene scene;
10258 QGraphicsRectItem *rect1 = scene.addRect(-50, -50, 100, 100);
10259 rect1->setFlag(QGraphicsItem::ItemIsPanel);
10260 rect1->setFlag(QGraphicsItem::ItemIsFocusable);
10261 rect1->setData(0, "rect1");
10263 QGraphicsRectItem *rect1child = scene.addRect(-10, -10, 20, 20);
10264 rect1child->setParentItem(rect1);
10265 rect1child->setFlag(QGraphicsItem::ItemIsFocusable);
10266 rect1child->setData(0, "rect1child1");
10268 QGraphicsRectItem *rect2 = scene.addRect(-50, -50, 100, 100);
10269 rect2->setParentItem(rect1);
10270 rect2->setFlag(QGraphicsItem::ItemIsPanel);
10271 rect2->setFlag(QGraphicsItem::ItemIsFocusable);
10272 rect2->setPos(50, 50);
10273 rect2->setData(0, "rect2");
10275 QGraphicsRectItem *rect2child = scene.addRect(-10, -10, 20, 20);
10276 rect2child->setParentItem(rect2);
10277 rect2child->setFlag(QGraphicsItem::ItemIsFocusable);
10278 rect2child->setData(0, "rect2child1");
10280 QEvent windowActivateEvent(QEvent::WindowActivate);
10281 QApplication::sendEvent(&scene, &windowActivateEvent);
10283 EventSpy2 rect1Spy(&scene, rect1);
10284 EventSpy2 rect1childSpy(&scene, rect1child);
10285 EventSpy2 rect2Spy(&scene, rect2);
10286 EventSpy2 rect2childSpy(&scene, rect2child);
10288 // activate rect1 and give it rect1child focus
10289 rect1->setActive(true);
10290 rect1child->setFocus();
10291 QCOMPARE(scene.focusItem(), (QGraphicsItem *) rect1child);
10293 // focus stays on rect1child when rect2 becomes modal
10294 rect2->setPanelModality(QGraphicsItem::SceneModal);
10295 QCOMPARE(scene.focusItem(), (QGraphicsItem *) rect1child);
10297 // but key events to rect1child should be neither delivered nor propagated
10298 sendKeyClick(&scene, Qt::Key_A);
10299 sendKeyClick(&scene, Qt::Key_S);
10300 sendKeyClick(&scene, Qt::Key_D);
10301 sendKeyClick(&scene, Qt::Key_F);
10302 QCOMPARE(rect1childSpy.counts[QEvent::KeyPress], 0);
10303 QCOMPARE(rect1childSpy.counts[QEvent::KeyRelease], 0);
10304 QCOMPARE(rect1Spy.counts[QEvent::KeyPress], 0);
10305 QCOMPARE(rect1Spy.counts[QEvent::KeyRelease], 0);
10307 // change to panel modality, rect1child1 keeps focus
10308 rect2->setPanelModality(QGraphicsItem::PanelModal);
10309 QCOMPARE(scene.focusItem(), (QGraphicsItem *) rect1child);
10311 // still no key events
10312 sendKeyClick(&scene, Qt::Key_J);
10313 sendKeyClick(&scene, Qt::Key_K);
10314 sendKeyClick(&scene, Qt::Key_L);
10315 sendKeyClick(&scene, Qt::Key_Semicolon);
10316 QCOMPARE(rect1childSpy.counts[QEvent::KeyPress], 0);
10317 QCOMPARE(rect1childSpy.counts[QEvent::KeyRelease], 0);
10318 QCOMPARE(rect1Spy.counts[QEvent::KeyPress], 0);
10319 QCOMPARE(rect1Spy.counts[QEvent::KeyRelease], 0);
10322 void tst_QGraphicsItem::itemIsInFront()
10324 QGraphicsScene scene;
10325 QGraphicsRectItem *rect1 = new QGraphicsRectItem;
10326 rect1->setData(0, "rect1");
10327 scene.addItem(rect1);
10329 QGraphicsRectItem *rect1child1 = new QGraphicsRectItem(rect1);
10330 rect1child1->setZValue(1);
10331 rect1child1->setData(0, "rect1child1");
10333 QGraphicsRectItem *rect1child2 = new QGraphicsRectItem(rect1);
10334 rect1child2->setParentItem(rect1);
10335 rect1child2->setData(0, "rect1child2");
10337 QGraphicsRectItem *rect1child1_1 = new QGraphicsRectItem(rect1child1);
10338 rect1child1_1->setData(0, "rect1child1_1");
10340 QGraphicsRectItem *rect1child1_2 = new QGraphicsRectItem(rect1child1);
10341 rect1child1_2->setFlag(QGraphicsItem::ItemStacksBehindParent);
10342 rect1child1_2->setData(0, "rect1child1_2");
10344 QGraphicsRectItem *rect2 = new QGraphicsRectItem;
10345 rect2->setData(0, "rect2");
10346 scene.addItem(rect2);
10348 QGraphicsRectItem *rect2child1 = new QGraphicsRectItem(rect2);
10349 rect2child1->setData(0, "rect2child1");
10351 QCOMPARE(qt_closestItemFirst(rect1, rect1), false);
10352 QCOMPARE(qt_closestItemFirst(rect1, rect2), false);
10353 QCOMPARE(qt_closestItemFirst(rect1child1, rect2child1), false);
10354 QCOMPARE(qt_closestItemFirst(rect1child1, rect1child2), true);
10355 QCOMPARE(qt_closestItemFirst(rect1child1_1, rect1child2), true);
10356 QCOMPARE(qt_closestItemFirst(rect1child1_1, rect1child1), true);
10357 QCOMPARE(qt_closestItemFirst(rect1child1_2, rect1child2), true);
10358 QCOMPARE(qt_closestItemFirst(rect1child1_2, rect1child1), false);
10359 QCOMPARE(qt_closestItemFirst(rect1child1_2, rect1), true);
10360 QCOMPARE(qt_closestItemFirst(rect1child1_2, rect2), false);
10361 QCOMPARE(qt_closestItemFirst(rect1child1_2, rect2child1), false);
10364 class ScenePosChangeTester : public ItemChangeTester
10367 ScenePosChangeTester()
10369 ScenePosChangeTester(QGraphicsItem *parent) : ItemChangeTester(parent)
10373 void tst_QGraphicsItem::scenePosChange()
10375 ScenePosChangeTester* root = new ScenePosChangeTester;
10376 ScenePosChangeTester* child1 = new ScenePosChangeTester(root);
10377 ScenePosChangeTester* grandChild1 = new ScenePosChangeTester(child1);
10378 ScenePosChangeTester* child2 = new ScenePosChangeTester(root);
10379 ScenePosChangeTester* grandChild2 = new ScenePosChangeTester(child2);
10381 child1->setFlag(QGraphicsItem::ItemSendsScenePositionChanges, true);
10382 grandChild2->setFlag(QGraphicsItem::ItemSendsScenePositionChanges, true);
10384 QVERIFY(child1->flags() & QGraphicsItem::ItemSendsScenePositionChanges);
10385 QVERIFY(grandChild2->flags() & QGraphicsItem::ItemSendsScenePositionChanges);
10387 QGraphicsScene scene;
10388 scene.addItem(root);
10390 // ignore uninteresting changes
10393 grandChild1->clear();
10394 grandChild2->clear();
10397 root->moveBy(1.0, 1.0);
10398 QCOMPARE(child1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 1);
10399 QCOMPARE(grandChild1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 0);
10400 QCOMPARE(child2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 0);
10401 QCOMPARE(grandChild2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 1);
10404 child2->moveBy(1.0, 1.0);
10405 QCOMPARE(child1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 1);
10406 QCOMPARE(grandChild1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 0);
10407 QCOMPARE(child2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 0);
10408 QCOMPARE(grandChild2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 2);
10411 grandChild2->setParentItem(child1);
10412 child1->moveBy(1.0, 1.0);
10413 QCOMPARE(child1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 2);
10414 QCOMPARE(grandChild1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 0);
10415 QCOMPARE(child2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 0);
10416 QCOMPARE(grandChild2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 3);
10419 grandChild1->setFlag(QGraphicsItem::ItemSendsScenePositionChanges, true);
10420 grandChild2->setFlag(QGraphicsItem::ItemSendsScenePositionChanges, false);
10421 QCoreApplication::processEvents(); // QGraphicsScenePrivate::_q_updateScenePosDescendants()
10422 child1->moveBy(1.0, 1.0);
10423 QCOMPARE(child1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 3);
10424 QCOMPARE(grandChild1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 1);
10425 QCOMPARE(child2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 0);
10426 QCOMPARE(grandChild2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 3);
10429 scene.removeItem(grandChild1);
10430 delete grandChild2; grandChild2 = 0;
10431 QCoreApplication::processEvents(); // QGraphicsScenePrivate::_q_updateScenePosDescendants()
10432 root->moveBy(1.0, 1.0);
10433 QCOMPARE(child1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 4);
10434 QCOMPARE(grandChild1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 1);
10435 QCOMPARE(child2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 0);
10438 QCOMPARE(child1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 5);
10439 QCOMPARE(grandChild1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 1);
10440 QCOMPARE(child2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 0);
10443 QCOMPARE(child1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 6);
10444 QCOMPARE(grandChild1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 1);
10445 QCOMPARE(child2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 0);
10448 class MyInputContext : public QInputContext
10451 MyInputContext() : nbUpdates(0) {}
10452 ~MyInputContext() {}
10454 QString identifierName() { return QString(); }
10455 QString language() { return QString(); }
10459 bool isComposing() const { return false; }
10461 void update() { nbUpdates++; }
10466 class MyInputWidget : public QGraphicsWidget
10471 setFlag(QGraphicsItem::ItemIsFocusable, true);
10472 setFlag(QGraphicsItem::ItemAcceptsInputMethod, true);
10474 void mousePressEvent(QGraphicsSceneMouseEvent *event)
10479 void doUpdateMicroFocus()
10481 if (QWidget *fw = QApplication::focusWidget()) {
10483 for (int i = 0 ; i < scene()->views().count() ; ++i) {
10484 if (scene()->views().at(i) == fw) {
10485 if (QInputContext *inputContext = fw->inputContext()) {
10486 inputContext->update();
10495 void tst_QGraphicsItem::updateMicroFocus()
10497 #if defined Q_OS_WIN || defined Q_OS_MAC
10498 QSKIP("QTBUG-9578");
10500 QGraphicsScene scene;
10502 QGridLayout layout;
10503 parent.setLayout(&layout);
10504 QGraphicsView view(&scene);
10505 QGraphicsView view2(&scene);
10506 layout.addWidget(&view, 0, 0);
10507 layout.addWidget(&view2, 0, 1);
10508 MyInputContext *ic = new MyInputContext;
10509 qApp->setInputContext(ic);
10510 MyInputWidget input;
10511 input.setPos(0, 0);
10512 input.resize(150, 150);
10513 scene.addItem(&input);
10517 qApp->setAutoSipEnabled(true);
10518 QApplication::setActiveWindow(&parent);
10519 QTest::qWaitForWindowShown(&parent);
10520 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&parent));
10521 //We reset the number of updates that happened previously (initialisation)
10523 input.doUpdateMicroFocus();
10524 QApplication::processEvents();
10525 QTRY_COMPARE(ic->nbUpdates, 1);
10528 void tst_QGraphicsItem::textItem_shortcuts()
10533 QGraphicsScene scene;
10534 QGraphicsView view(&scene);
10535 l.addWidget(&view);
10536 QPushButton b("Push Me");
10539 QGraphicsTextItem *item = scene.addText("Troll Text");
10540 item->setFlag(QGraphicsItem::ItemIsFocusable);
10541 item->setTextInteractionFlags(Qt::TextEditorInteraction);
10543 QTest::qWaitForWindowShown(&w);
10546 QTRY_VERIFY(item->hasFocus());
10547 QVERIFY(item->textCursor().selectedText().isEmpty());
10549 // Shortcut should work (select all)
10550 QTest::keyClick(&view, Qt::Key_A, Qt::ControlModifier);
10551 QTRY_COMPARE(item->textCursor().selectedText(), item->toPlainText());
10552 QTextCursor tc = item->textCursor();
10553 tc.clearSelection();
10554 item->setTextCursor(tc);
10555 QVERIFY(item->textCursor().selectedText().isEmpty());
10557 // Shortcut should also work if the text item has the focus and another widget
10558 // has the same shortcut.
10559 b.setShortcut(QKeySequence("CTRL+A"));
10560 QTest::keyClick(&view, Qt::Key_A, Qt::ControlModifier);
10561 QTRY_COMPARE(item->textCursor().selectedText(), item->toPlainText());
10564 void tst_QGraphicsItem::scroll()
10566 // Create two overlapping rectangles in the scene:
10571 // +---| | <- item2
10575 EventTester *item1 = new EventTester;
10576 item1->br = QRectF(0, 0, 200, 200);
10577 item1->brush = Qt::red;
10578 item1->setFlag(QGraphicsItem::ItemUsesExtendedStyleOption);
10580 EventTester *item2 = new EventTester;
10581 item2->br = QRectF(0, 0, 200, 200);
10582 item2->brush = Qt::blue;
10583 item2->setFlag(QGraphicsItem::ItemUsesExtendedStyleOption);
10584 item2->setPos(100, 100);
10586 QGraphicsScene scene(0, 0, 300, 300);
10587 scene.addItem(item1);
10588 scene.addItem(item2);
10590 MyGraphicsView view(&scene);
10591 view.setFrameStyle(0);
10593 QTest::qWaitForWindowShown(&view);
10594 QTRY_VERIFY(view.repaints > 0);
10600 const QRectF item1BoundingRect = item1->boundingRect();
10601 const QRectF item2BoundingRect = item2->boundingRect();
10604 // Item1 should get full exposure
10605 // Item2 should get exposure for the part that overlaps item1.
10606 item1->scroll(0, -10);
10607 QTRY_VERIFY(view.repaints > 0);
10608 QCOMPARE(item1->lastExposedRect, item1BoundingRect);
10610 QRectF expectedItem2Expose = item2BoundingRect;
10611 // NB! Adjusted by 2 pixels for antialiasing
10612 expectedItem2Expose &= item1->mapRectToItem(item2, item1BoundingRect.adjusted(-2, -2, 2, 2));
10613 QCOMPARE(item2->lastExposedRect, expectedItem2Expose);
10615 // Enable ItemCoordinateCache on item1.
10617 item1->setCacheMode(QGraphicsItem::ItemCoordinateCache);
10618 QTRY_VERIFY(view.repaints > 0);
10624 // Item1 should only get expose for the newly exposed area (accelerated scroll).
10625 // Item2 should get exposure for the part that overlaps item1.
10626 item1->scroll(0, -10, QRectF(50, 50, 100, 100));
10627 QTRY_VERIFY(view.repaints > 0);
10628 QCOMPARE(item1->lastExposedRect, QRectF(50, 140, 100, 10));
10630 expectedItem2Expose = item2BoundingRect;
10631 // NB! Adjusted by 2 pixels for antialiasing
10632 expectedItem2Expose &= item1->mapRectToItem(item2, QRectF(50, 50, 100, 100).adjusted(-2, -2, 2, 2));
10633 QCOMPARE(item2->lastExposedRect, expectedItem2Expose);
10636 Q_DECLARE_METATYPE(QGraphicsItem::GraphicsItemFlag);
10638 void tst_QGraphicsItem::focusHandling_data()
10640 QTest::addColumn<QGraphicsItem::GraphicsItemFlag>("focusFlag");
10641 QTest::addColumn<bool>("useStickyFocus");
10642 QTest::addColumn<int>("expectedFocusItem"); // 0: none, 1: focusableUnder, 2: itemWithFocus
10644 QTest::newRow("Focus goes through.")
10645 << static_cast<QGraphicsItem::GraphicsItemFlag>(0x0) << false << 1;
10647 QTest::newRow("Focus goes through, even with sticky scene.")
10648 << static_cast<QGraphicsItem::GraphicsItemFlag>(0x0) << true << 1;
10650 QTest::newRow("With ItemStopsClickFocusPropagation, we cannot focus the item beneath the flagged one (but can still focus-out).")
10651 << QGraphicsItem::ItemStopsClickFocusPropagation << false << 0;
10653 QTest::newRow("With ItemStopsClickFocusPropagation, we cannot focus the item beneath the flagged one (and cannot focus-out if scene is sticky).")
10654 << QGraphicsItem::ItemStopsClickFocusPropagation << true << 2;
10656 QTest::newRow("With ItemStopsFocusHandling, focus cannot be changed by presses.")
10657 << QGraphicsItem::ItemStopsFocusHandling << false << 2;
10659 QTest::newRow("With ItemStopsFocusHandling, focus cannot be changed by presses (even if scene is sticky).")
10660 << QGraphicsItem::ItemStopsFocusHandling << true << 2;
10663 void tst_QGraphicsItem::focusHandling()
10665 QFETCH(QGraphicsItem::GraphicsItemFlag, focusFlag);
10666 QFETCH(bool, useStickyFocus);
10667 QFETCH(int, expectedFocusItem);
10669 class MyItem : public QGraphicsRectItem
10672 MyItem() : QGraphicsRectItem(0, 0, 100, 100) {}
10673 void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
10675 painter->fillRect(boundingRect(), hasFocus() ? QBrush(Qt::red) : brush());
10679 QGraphicsRectItem *noFocusOnTop = new MyItem;
10680 noFocusOnTop->setFlag(QGraphicsItem::ItemIsFocusable, false);
10681 noFocusOnTop->setBrush(Qt::yellow);
10683 QGraphicsRectItem *focusableUnder = new MyItem;
10684 focusableUnder->setBrush(Qt::blue);
10685 focusableUnder->setFlag(QGraphicsItem::ItemIsFocusable);
10686 focusableUnder->setPos(50, 50);
10688 QGraphicsRectItem *itemWithFocus = new MyItem;
10689 itemWithFocus->setBrush(Qt::black);
10690 itemWithFocus->setFlag(QGraphicsItem::ItemIsFocusable);
10691 itemWithFocus->setPos(250, 10);
10693 QGraphicsScene scene(-50, -50, 400, 400);
10694 scene.addItem(noFocusOnTop);
10695 scene.addItem(focusableUnder);
10696 scene.addItem(itemWithFocus);
10697 scene.setStickyFocus(useStickyFocus);
10699 noFocusOnTop->setFlag(focusFlag);
10700 focusableUnder->stackBefore(noFocusOnTop);
10701 itemWithFocus->setFocus();
10703 QGraphicsView view(&scene);
10705 QTest::qWaitForWindowShown(&view);
10707 QApplication::setActiveWindow(&view);
10708 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
10709 QVERIFY(itemWithFocus->hasFocus());
10711 const QPointF mousePressPoint = noFocusOnTop->mapToScene(noFocusOnTop->boundingRect().center());
10712 const QList<QGraphicsItem *> itemsAtMousePressPosition = scene.items(mousePressPoint);
10713 QVERIFY(itemsAtMousePressPosition.contains(noFocusOnTop));
10715 sendMousePress(&scene, mousePressPoint);
10717 switch (expectedFocusItem) {
10719 QCOMPARE(scene.focusItem(), static_cast<QGraphicsRectItem *>(0));
10722 QCOMPARE(scene.focusItem(), focusableUnder);
10725 QCOMPARE(scene.focusItem(), itemWithFocus);
10729 // Sanity check - manually setting the focus must work regardless of our
10730 // focus handling flags:
10731 focusableUnder->setFocus();
10732 QCOMPARE(scene.focusItem(), focusableUnder);
10735 void tst_QGraphicsItem::touchEventPropagation_data()
10737 QTest::addColumn<QGraphicsItem::GraphicsItemFlag>("flag");
10738 QTest::addColumn<int>("expectedCount");
10740 QTest::newRow("ItemIsPanel")
10741 << QGraphicsItem::ItemIsPanel << 0;
10742 QTest::newRow("ItemStopsClickFocusPropagation")
10743 << QGraphicsItem::ItemStopsClickFocusPropagation << 1;
10744 QTest::newRow("ItemStopsFocusHandling")
10745 << QGraphicsItem::ItemStopsFocusHandling << 1;
10748 void tst_QGraphicsItem::touchEventPropagation()
10750 QFETCH(QGraphicsItem::GraphicsItemFlag, flag);
10751 QFETCH(int, expectedCount);
10753 class Testee : public QGraphicsRectItem
10756 int touchBeginEventCount;
10759 : QGraphicsRectItem(0, 0, 100, 100)
10760 , touchBeginEventCount(0)
10762 setAcceptTouchEvents(true);
10763 setFlag(QGraphicsItem::ItemIsFocusable, false);
10766 bool sceneEvent(QEvent *ev)
10768 if (ev->type() == QEvent::TouchBegin)
10769 ++touchBeginEventCount;
10771 return QGraphicsRectItem::sceneEvent(ev);
10775 Testee *touchEventReceiver = new Testee;
10776 QGraphicsItem *topMost = new QGraphicsRectItem(touchEventReceiver->boundingRect());
10778 QGraphicsScene scene;
10779 scene.addItem(topMost);
10780 scene.addItem(touchEventReceiver);
10782 topMost->setAcceptTouchEvents(true);
10783 topMost->setZValue(FLT_MAX);
10784 topMost->setFlag(QGraphicsItem::ItemIsFocusable, false);
10785 topMost->setFlag(flag, true);
10787 QGraphicsView view(&scene);
10788 view.setSceneRect(touchEventReceiver->boundingRect());
10790 QTest::qWaitForWindowShown(&view);
10792 QCOMPARE(touchEventReceiver->touchBeginEventCount, 0);
10794 QTouchEvent::TouchPoint tp(0);
10795 tp.setState(Qt::TouchPointPressed);
10796 tp.setScenePos(view.sceneRect().center());
10797 tp.setLastScenePos(view.sceneRect().center());
10799 QList<QTouchEvent::TouchPoint> touchPoints;
10802 sendMousePress(&scene, tp.scenePos());
10803 QTouchEvent touchBegin(QEvent::TouchBegin, QTouchEvent::TouchScreen, Qt::NoModifier, Qt::TouchPointPressed, touchPoints);
10805 qApp->sendEvent(&scene, &touchBegin);
10806 QCOMPARE(touchEventReceiver->touchBeginEventCount, expectedCount);
10809 void tst_QGraphicsItem::deviceCoordinateCache_simpleRotations()
10811 // Make sure we don't invalidate the cache when applying simple
10812 // (90, 180, 270, 360) rotation transforms to the item.
10813 QGraphicsRectItem *item = new QGraphicsRectItem(0, 0, 300, 200);
10814 item->setBrush(Qt::red);
10815 item->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
10817 QGraphicsScene scene;
10818 scene.setSceneRect(0, 0, 300, 200);
10819 scene.addItem(item);
10821 MyGraphicsView view(&scene);
10823 QTest::qWaitForWindowShown(&view);
10824 QTRY_VERIFY(view.repaints > 0);
10826 QGraphicsItemCache *itemCache = QGraphicsItemPrivate::get(item)->extraItemCache();
10827 QVERIFY(itemCache);
10828 QPixmapCache::Key currentKey = itemCache->deviceData.value(view.viewport()).key;
10830 // Trigger an update and verify that the cache is unchanged.
10831 QPixmapCache::Key oldKey = currentKey;
10833 view.viewport()->update();
10834 QTRY_VERIFY(view.repaints > 0);
10835 currentKey = itemCache->deviceData.value(view.viewport()).key;
10836 QCOMPARE(currentKey, oldKey);
10838 // Check 90, 180, 270 and 360 degree rotations.
10839 for (int angle = 90; angle <= 360; angle += 90) {
10840 // Rotate item and verify that the cache was invalidated.
10841 oldKey = currentKey;
10843 QTransform transform;
10844 transform.translate(150, 100);
10845 transform.rotate(angle);
10846 transform.translate(-150, -100);
10847 item->setTransform(transform);
10848 QTRY_VERIFY(view.repaints > 0);
10849 currentKey = itemCache->deviceData.value(view.viewport()).key;
10850 QVERIFY(currentKey != oldKey);
10853 // Trigger an update and verify that the cache is unchanged.
10854 oldKey = currentKey;
10856 view.viewport()->update();
10857 QTRY_VERIFY(view.repaints > 0);
10858 currentKey = itemCache->deviceData.value(view.viewport()).key;
10859 QCOMPARE(currentKey, oldKey);
10862 // 45 degree rotation.
10863 oldKey = currentKey;
10865 QTransform transform;
10866 transform.translate(150, 100);
10867 transform.rotate(45);
10868 transform.translate(-150, -100);
10869 item->setTransform(transform);
10870 QTRY_VERIFY(view.repaints > 0);
10871 currentKey = itemCache->deviceData.value(view.viewport()).key;
10872 QVERIFY(currentKey != oldKey);
10874 // Trigger an update and verify that the cache was invalidated.
10875 // We should always invalidate the cache for non-trivial transforms.
10876 oldKey = currentKey;
10878 view.viewport()->update();
10879 QTRY_VERIFY(view.repaints > 0);
10880 currentKey = itemCache->deviceData.value(view.viewport()).key;
10881 QVERIFY(currentKey != oldKey);
10884 void tst_QGraphicsItem::QTBUG_5418_textItemSetDefaultColor()
10886 struct Item : public QGraphicsTextItem
10889 void paint(QPainter *painter, const QStyleOptionGraphicsItem *opt, QWidget *wid)
10892 QGraphicsTextItem::paint(painter, opt, wid);
10896 Item *i = new Item;
10898 i->setPlainText("I AM A TROLL");
10900 QGraphicsScene scene;
10901 QGraphicsView view(&scene);
10903 QTest::qWaitForWindowShown(&view);
10905 QApplication::processEvents();
10906 QTRY_VERIFY(i->painted);
10907 QApplication::processEvents();
10910 QColor col(Qt::red);
10911 i->setDefaultTextColor(col);
10912 QApplication::processEvents();
10913 QTRY_COMPARE(i->painted, 1); //check that changing the color force an update
10915 i->painted = false;
10916 QImage image(400, 200, QImage::Format_RGB32);
10918 QPainter painter(&image);
10919 scene.render(&painter);
10921 QCOMPARE(i->painted, 1);
10923 int numRedPixel = 0;
10924 QRgb rgb = col.rgb();
10925 for (int y = 0; y < image.height(); ++y) {
10926 for (int x = 0; x < image.width(); ++x) {
10927 // Because of antialiasing we allow a certain range of errors here.
10928 QRgb pixel = image.pixel(x, y);
10929 if (qAbs((int)(pixel & 0xff) - (int)(rgb & 0xff)) +
10930 qAbs((int)((pixel & 0xff00) >> 8) - (int)((rgb & 0xff00) >> 8)) +
10931 qAbs((int)((pixel & 0xff0000) >> 16) - (int)((rgb & 0xff0000) >> 16)) <= 50) {
10932 if (++numRedPixel >= 10) {
10938 QCOMPARE(numRedPixel, -1); //color not found, FAIL!
10941 i->setDefaultTextColor(col);
10942 QApplication::processEvents();
10943 QCOMPARE(i->painted, 0); //same color as before should not trigger an update (QTBUG-6242)
10946 void tst_QGraphicsItem::QTBUG_6738_missingUpdateWithSetParent()
10948 // In all 3 test cases below the reparented item should disappear
10949 EventTester *parent = new EventTester;
10950 EventTester *child = new EventTester(parent);
10951 EventTester *child2 = new EventTester(parent);
10952 EventTester *child3 = new EventTester(parent);
10953 EventTester *child4 = new EventTester(parent);
10955 child->setPos(10, 10);
10956 child2->setPos(20, 20);
10957 child3->setPos(30, 30);
10958 child4->setPos(40, 40);
10960 QGraphicsScene scene;
10961 scene.addItem(parent);
10963 MyGraphicsView view(&scene);
10964 if(PlatformQuirks::isAutoMaximizing())
10965 view.showFullScreen();
10968 QTest::qWaitForWindowShown(&view);
10969 QTRY_VERIFY(view.repaints > 0);
10973 child2->setVisible(false);
10974 child2->setParentItem(child);
10976 QTRY_VERIFY(view.repaints == 1);
10980 child3->setOpacity(0.0);
10981 child3->setParentItem(child);
10983 QTRY_VERIFY(view.repaints == 1);
10987 child4->setParentItem(child);
10988 child4->setVisible(false);
10990 QTRY_VERIFY(view.repaints == 1);
10993 void tst_QGraphicsItem::QT_2653_fullUpdateDiscardingOpacityUpdate()
10995 QGraphicsScene scene(0, 0, 200, 200);
10996 MyGraphicsView view(&scene);
10998 EventTester *parentGreen = new EventTester();
10999 parentGreen->setGeometry(QRectF(20, 20, 100, 100));
11000 parentGreen->brush = Qt::green;
11002 EventTester *childYellow = new EventTester(parentGreen);
11003 childYellow->setGeometry(QRectF(10, 10, 50, 50));
11004 childYellow->brush = Qt::yellow;
11006 scene.addItem(parentGreen);
11008 childYellow->setOpacity(0.0);
11009 parentGreen->setOpacity(0.0);
11011 // set any of the flags below to trigger a fullUpdate to reproduce the bug:
11012 // ItemIgnoresTransformations, ItemClipsChildrenToShape, ItemIsSelectable
11013 parentGreen->setFlag(QGraphicsItem::ItemIgnoresTransformations);
11015 if (PlatformQuirks::isAutoMaximizing())
11016 view.showFullScreen();
11019 QTest::qWaitForWindowShown(&view);
11022 parentGreen->setOpacity(1.0);
11024 QTRY_COMPARE(view.repaints, 1);
11027 childYellow->repaints = 0;
11029 childYellow->setOpacity(1.0);
11031 QTRY_COMPARE(view.repaints, 1);
11032 QTRY_COMPARE(childYellow->repaints, 1);
11035 void tst_QGraphicsItem::QTBUG_7714_fullUpdateDiscardingOpacityUpdate2()
11037 QGraphicsScene scene(0, 0, 200, 200);
11038 MyGraphicsView view(&scene);
11039 MyGraphicsView origView(&scene);
11041 EventTester *parentGreen = new EventTester();
11042 parentGreen->setGeometry(QRectF(20, 20, 100, 100));
11043 parentGreen->brush = Qt::green;
11045 EventTester *childYellow = new EventTester(parentGreen);
11046 childYellow->setGeometry(QRectF(10, 10, 50, 50));
11047 childYellow->brush = Qt::yellow;
11049 scene.addItem(parentGreen);
11052 QTest::qWaitForWindowShown(&origView);
11053 origView.setGeometry(origView.width() + 20, 20,
11054 origView.width(), origView.height());
11056 parentGreen->setFlag(QGraphicsItem::ItemIgnoresTransformations);
11059 childYellow->setOpacity(0.0);
11061 QTRY_COMPARE(origView.repaints, 1);
11065 QTest::qWaitForWindowShown(&view);
11069 childYellow->setOpacity(1.0);
11071 QTRY_COMPARE(origView.repaints, 1);
11072 QTRY_COMPARE(view.repaints, 1);
11075 void tst_QGraphicsItem::QT_2649_focusScope()
11077 QGraphicsScene *scene = new QGraphicsScene;
11079 QGraphicsRectItem *subFocusItem = new QGraphicsRectItem;
11080 subFocusItem->setFlags(QGraphicsItem::ItemIsFocusable);
11081 subFocusItem->setFocus();
11082 QCOMPARE(subFocusItem->focusItem(), (QGraphicsItem *)subFocusItem);
11084 QGraphicsRectItem *scope = new QGraphicsRectItem;
11085 scope->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsFocusScope);
11087 subFocusItem->setParentItem(scope);
11088 QCOMPARE(subFocusItem->focusItem(), (QGraphicsItem *)subFocusItem);
11089 QCOMPARE(subFocusItem->focusScopeItem(), (QGraphicsItem *)0);
11090 QCOMPARE(scope->focusItem(), (QGraphicsItem *)subFocusItem);
11091 QCOMPARE(scope->focusScopeItem(), (QGraphicsItem *)subFocusItem);
11093 QGraphicsRectItem *rootItem = new QGraphicsRectItem;
11094 rootItem->setFlags(QGraphicsItem::ItemIsFocusable);
11095 scope->setParentItem(rootItem);
11096 QCOMPARE(rootItem->focusItem(), (QGraphicsItem *)subFocusItem);
11097 QCOMPARE(rootItem->focusScopeItem(), (QGraphicsItem *)0);
11098 QCOMPARE(subFocusItem->focusItem(), (QGraphicsItem *)subFocusItem);
11099 QCOMPARE(subFocusItem->focusScopeItem(), (QGraphicsItem *)0);
11100 QCOMPARE(scope->focusItem(), (QGraphicsItem *)subFocusItem);
11101 QCOMPARE(scope->focusScopeItem(), (QGraphicsItem *)subFocusItem);
11103 scene->addItem(rootItem);
11105 QEvent windowActivate(QEvent::WindowActivate);
11106 qApp->sendEvent(scene, &windowActivate);
11109 QCOMPARE(rootItem->focusItem(), (QGraphicsItem *)subFocusItem);
11110 QCOMPARE(scope->focusItem(), (QGraphicsItem *)subFocusItem);
11111 QCOMPARE(subFocusItem->focusItem(), (QGraphicsItem *)subFocusItem);
11112 QCOMPARE(rootItem->focusScopeItem(), (QGraphicsItem *)0);
11113 QCOMPARE(scope->focusScopeItem(), (QGraphicsItem *)subFocusItem);
11114 QCOMPARE(subFocusItem->focusScopeItem(), (QGraphicsItem *)0);
11115 QVERIFY(subFocusItem->hasFocus());
11119 QCOMPARE(rootItem->focusItem(), (QGraphicsItem *)0);
11120 QCOMPARE(scope->focusItem(), (QGraphicsItem *)0);
11121 QCOMPARE(subFocusItem->focusItem(), (QGraphicsItem *)0);
11122 QCOMPARE(rootItem->focusScopeItem(), (QGraphicsItem *)0);
11123 QCOMPARE(scope->focusScopeItem(), (QGraphicsItem *)subFocusItem);
11124 QCOMPARE(subFocusItem->focusScopeItem(), (QGraphicsItem *)0);
11125 QVERIFY(!subFocusItem->hasFocus());
11129 QCOMPARE(rootItem->focusItem(), (QGraphicsItem *)subFocusItem);
11130 QCOMPARE(scope->focusItem(), (QGraphicsItem *)subFocusItem);
11131 QCOMPARE(subFocusItem->focusItem(), (QGraphicsItem *)subFocusItem);
11132 QCOMPARE(rootItem->focusScopeItem(), (QGraphicsItem *)0);
11133 QCOMPARE(scope->focusScopeItem(), (QGraphicsItem *)subFocusItem);
11134 QCOMPARE(subFocusItem->focusScopeItem(), (QGraphicsItem *)0);
11135 QVERIFY(subFocusItem->hasFocus());
11137 // This should not crash
11142 class MyGraphicsItemWithItemChange : public QGraphicsWidget
11145 MyGraphicsItemWithItemChange(QGraphicsItem *parent = 0) : QGraphicsWidget(parent)
11148 QVariant itemChange(GraphicsItemChange change, const QVariant &value)
11150 if (change == QGraphicsItem::ItemSceneHasChanged) {
11151 foreach (QGraphicsView *view, scene()->views()) {
11152 //We trigger a sort of unindexed items in the BSP
11156 return QGraphicsWidget::itemChange(change, value);
11160 void tst_QGraphicsItem::sortItemsWhileAdding()
11162 QGraphicsScene scene;
11163 QGraphicsView view(&scene);
11164 QGraphicsWidget grandGrandParent;
11165 grandGrandParent.resize(200, 200);
11166 scene.addItem(&grandGrandParent);
11167 QGraphicsWidget grandParent;
11168 grandParent.resize(200, 200);
11169 QGraphicsWidget parent(&grandParent);
11170 parent.resize(200, 200);
11171 MyGraphicsItemWithItemChange item(&parent);
11172 grandParent.setParentItem(&grandGrandParent);
11175 void tst_QGraphicsItem::doNotMarkFullUpdateIfNotInScene()
11177 struct Item : public QGraphicsTextItem
11180 void paint(QPainter *painter, const QStyleOptionGraphicsItem *opt, QWidget *wid)
11183 QGraphicsTextItem::paint(painter, opt, wid);
11186 QGraphicsScene scene;
11187 MyGraphicsView view(&scene);
11188 Item *item = new Item;
11190 item->setPlainText("Grandparent");
11191 Item *item2 = new Item;
11192 item2->setPlainText("parent");
11193 item2->painted = 0;
11194 Item *item3 = new Item;
11195 item3->setPlainText("child");
11196 item3->painted = 0;
11197 QGraphicsOpacityEffect *effect = new QGraphicsOpacityEffect;
11198 effect->setOpacity(0.5);
11199 item2->setGraphicsEffect(effect);
11200 item3->setParentItem(item2);
11201 item2->setParentItem(item);
11202 scene.addItem(item);
11203 if(PlatformQuirks::isAutoMaximizing())
11204 view.showFullScreen();
11207 QTest::qWaitForWindowShown(&view);
11208 QTRY_COMPARE(view.repaints, 1);
11209 QTRY_COMPARE(item->painted, 1);
11210 QTRY_COMPARE(item2->painted, 1);
11211 QTRY_COMPARE(item3->painted, 1);
11213 QApplication::processEvents();
11214 QTRY_COMPARE(item->painted, 2);
11215 QTRY_COMPARE(item2->painted, 2);
11216 QTRY_COMPARE(item3->painted, 2);
11218 QApplication::processEvents();
11219 QTRY_COMPARE(item->painted, 3);
11220 QTRY_COMPARE(item2->painted, 3);
11221 QTRY_COMPARE(item3->painted, 3);
11224 void tst_QGraphicsItem::itemDiesDuringDraggingOperation()
11226 QGraphicsScene scene;
11227 QGraphicsView view(&scene);
11228 QGraphicsRectItem *item = new QGraphicsRectItem(QRectF(0, 0, 100, 100));
11229 item->setFlag(QGraphicsItem::ItemIsMovable);
11230 item->setAcceptDrops(true);
11231 scene.addItem(item);
11233 QApplication::setActiveWindow(&view);
11234 QTest::qWaitForWindowShown(&view);
11235 QTRY_COMPARE(QApplication::activeWindow(), (QWidget *)&view);
11236 QGraphicsSceneDragDropEvent dragEnter(QEvent::GraphicsSceneDragEnter);
11237 dragEnter.setScenePos(item->boundingRect().center());
11238 QApplication::sendEvent(&scene, &dragEnter);
11239 QGraphicsSceneDragDropEvent event(QEvent::GraphicsSceneDragMove);
11240 event.setScenePos(item->boundingRect().center());
11241 QApplication::sendEvent(&scene, &event);
11242 QVERIFY(QGraphicsScenePrivate::get(&scene)->dragDropItem == item);
11244 QVERIFY(QGraphicsScenePrivate::get(&scene)->dragDropItem == 0);
11247 void tst_QGraphicsItem::QTBUG_12112_focusItem()
11249 QGraphicsScene scene;
11250 QGraphicsView view(&scene);
11251 QGraphicsRectItem *item1 = new QGraphicsRectItem(0, 0, 20, 20);
11252 item1->setFlag(QGraphicsItem::ItemIsFocusable);
11253 QGraphicsRectItem *item2 = new QGraphicsRectItem(20, 20, 20, 20);
11254 item2->setFlag(QGraphicsItem::ItemIsFocusable);
11256 scene.addItem(item2);
11257 scene.addItem(item1);
11260 QApplication::setActiveWindow(&view);
11261 QTest::qWaitForWindowShown(&view);
11262 QTRY_COMPARE(QApplication::activeWindow(), (QWidget *)&view);
11264 QVERIFY(item1->focusItem());
11265 QVERIFY(!item2->focusItem());
11268 QVERIFY(!item1->focusItem());
11269 QVERIFY(item2->focusItem());
11272 void tst_QGraphicsItem::QTBUG_13473_sceneposchange()
11274 ScenePosChangeTester* parent = new ScenePosChangeTester;
11275 ScenePosChangeTester* child = new ScenePosChangeTester(parent);
11277 // parent's disabled ItemSendsGeometryChanges flag must not affect
11278 // child's scene pos change notifications
11279 parent->setFlag(QGraphicsItem::ItemSendsGeometryChanges, false);
11280 child->setFlag(QGraphicsItem::ItemSendsScenePositionChanges, true);
11282 QGraphicsScene scene;
11283 scene.addItem(parent);
11285 // ignore uninteresting changes
11290 parent->moveBy(1.0, 1.0);
11291 QCOMPARE(child->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 1);
11294 parent->setTransform(QTransform::fromScale(0.5, 0.5));
11295 QCOMPARE(child->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 2);
11298 class MyGraphicsWidget : public QGraphicsWidget {
11302 : QGraphicsWidget(0)
11304 QGraphicsLinearLayout *lay = new QGraphicsLinearLayout(Qt::Vertical);
11305 QLatin1String wiseWords("AZ BUKI VEDI");
11306 QString sentence(wiseWords);
11307 QStringList words = sentence.split(QLatin1Char(' '), QString::SkipEmptyParts);
11308 for (int i = 0; i < words.count(); ++i) {
11309 QGraphicsProxyWidget *proxy = new QGraphicsProxyWidget(this);
11310 QLabel *label = new QLabel(words.at(i));
11311 proxy->setWidget(label);
11312 proxy->setFocusPolicy(Qt::StrongFocus);
11313 proxy->setFlag(QGraphicsItem::ItemAcceptsInputMethod, true);
11315 proxy->setVisible(false);
11317 lay->addItem(proxy);
11324 class MyWidgetWindow : public QGraphicsWidget
11328 : QGraphicsWidget(0, Qt::Window)
11330 QGraphicsLinearLayout *lay = new QGraphicsLinearLayout(Qt::Vertical);
11331 MyGraphicsWidget *widget = new MyGraphicsWidget();
11332 lay->addItem(widget);
11337 void tst_QGraphicsItem::QTBUG_16374_crashInDestructor()
11339 QGraphicsScene scene;
11340 QGraphicsView view(&scene);
11342 MyWidgetWindow win;
11343 scene.addItem(&win);
11346 QTest::qWaitForWindowShown(&view);
11349 void tst_QGraphicsItem::QTBUG_20699_focusScopeCrash()
11351 QGraphicsScene scene;
11352 QGraphicsView view(&scene);
11353 QGraphicsPixmapItem fs;
11354 fs.setFlags(QGraphicsItem::ItemIsFocusScope | QGraphicsItem::ItemIsFocusable);
11355 scene.addItem(&fs);
11356 QGraphicsPixmapItem* fs2 = new QGraphicsPixmapItem(&fs);
11357 fs2->setFlags(QGraphicsItem::ItemIsFocusScope | QGraphicsItem::ItemIsFocusable);
11358 QGraphicsPixmapItem* fi2 = new QGraphicsPixmapItem(&fs);
11359 fi2->setFlags(QGraphicsItem::ItemIsFocusable);
11360 QGraphicsPixmapItem* fi = new QGraphicsPixmapItem(fs2);
11361 fi->setFlags(QGraphicsItem::ItemIsFocusable);
11366 QTest::qWaitForWindowShown(&view);
11368 fi->setParentItem(fi2);
11371 fi->setParentItem(fs2);
11375 fi->setParentItem(fi2);
11380 QTEST_MAIN(tst_QGraphicsItem)
11381 #include "tst_qgraphicsitem.moc"