| /**************************************************************************** |
| ** |
| ** Copyright (C) 2016 The Qt Company Ltd. |
| ** Contact: https://www.qt.io/licensing/ |
| ** |
| ** This file is part of the test suite of the Qt Toolkit. |
| ** |
| ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ |
| ** Commercial License Usage |
| ** Licensees holding valid commercial Qt licenses may use this file in |
| ** accordance with the commercial license agreement provided with the |
| ** Software or, alternatively, in accordance with the terms contained in |
| ** a written agreement between you and The Qt Company. For licensing terms |
| ** and conditions see https://www.qt.io/terms-conditions. For further |
| ** information use the contact form at https://www.qt.io/contact-us. |
| ** |
| ** GNU General Public License Usage |
| ** Alternatively, this file may be used under the terms of the GNU |
| ** General Public License version 3 as published by the Free Software |
| ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT |
| ** included in the packaging of this file. Please review the following |
| ** information to ensure the GNU General Public License requirements will |
| ** be met: https://www.gnu.org/licenses/gpl-3.0.html. |
| ** |
| ** $QT_END_LICENSE$ |
| ** |
| ****************************************************************************/ |
| |
| |
| #include <QtTest/QtTest> |
| #include <QtTest/private/qtesthelpers_p.h> |
| |
| #include <private/qgraphicsitem_p.h> |
| #include <private/qgraphicsview_p.h> |
| #include <private/qgraphicsscene_p.h> |
| #include <QRandomGenerator> |
| #include <QStyleOptionGraphicsItem> |
| #include <QAbstractTextDocumentLayout> |
| #include <QBitmap> |
| #include <QCursor> |
| #include <QDesktopWidget> |
| #include <QScreen> |
| #include <QLabel> |
| #include <QDial> |
| #include <QGraphicsItem> |
| #include <QGraphicsScene> |
| #include <QGraphicsSceneEvent> |
| #include <QGraphicsView> |
| #include <QGraphicsWidget> |
| #include <QGraphicsProxyWidget> |
| #include <QPainter> |
| #include <QScrollBar> |
| #include <QVBoxLayout> |
| #include <QGraphicsEffect> |
| #include <QPushButton> |
| #include <QLineEdit> |
| #include <QGraphicsLinearLayout> |
| #include <QTransform> |
| #include <float.h> |
| #include <QStyleHints> |
| |
| Q_DECLARE_METATYPE(QPainterPath) |
| Q_DECLARE_METATYPE(QSizeF) |
| Q_DECLARE_METATYPE(QTransform) |
| |
| #if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) |
| #include <windows.h> |
| #define Q_CHECK_PAINTEVENTS \ |
| if (::SwitchDesktop(::GetThreadDesktop(::GetCurrentThreadId())) == 0) \ |
| QSKIP("The Graphics View doesn't get the paint events"); |
| #else |
| #define Q_CHECK_PAINTEVENTS |
| #endif |
| |
| #if defined(Q_OS_MAC) |
| // On mac (cocoa) we always get full update. |
| // So check that the expected region is contained inside the actual |
| #define COMPARE_REGIONS(ACTUAL, EXPECTED) QVERIFY((EXPECTED).subtracted(ACTUAL).isEmpty()) |
| #else |
| #define COMPARE_REGIONS QTRY_COMPARE |
| #endif |
| |
| static QGraphicsRectItem staticItem; //QTBUG-7629, we should not crash at exit. |
| |
| static void sendMousePress(QGraphicsScene *scene, const QPointF &point, Qt::MouseButton button = Qt::LeftButton) |
| { |
| QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress); |
| event.setScenePos(point); |
| event.setButton(button); |
| event.setButtons(button); |
| QApplication::sendEvent(scene, &event); |
| } |
| |
| static void sendMouseMove(QGraphicsScene *scene, const QPointF &point, |
| Qt::MouseButton button = Qt::NoButton, Qt::MouseButtons /* buttons */ = 0) |
| { |
| QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseMove); |
| event.setScenePos(point); |
| event.setButton(button); |
| event.setButtons(button); |
| QApplication::sendEvent(scene, &event); |
| } |
| |
| static void sendMouseRelease(QGraphicsScene *scene, const QPointF &point, Qt::MouseButton button = Qt::LeftButton) |
| { |
| QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseRelease); |
| event.setScenePos(point); |
| event.setButton(button); |
| QApplication::sendEvent(scene, &event); |
| } |
| |
| static void sendMouseClick(QGraphicsScene *scene, const QPointF &point, Qt::MouseButton button = Qt::LeftButton) |
| { |
| sendMousePress(scene, point, button); |
| sendMouseRelease(scene, point, button); |
| } |
| |
| static void sendKeyPress(QGraphicsScene *scene, Qt::Key key) |
| { |
| QKeyEvent keyEvent(QEvent::KeyPress, key, Qt::NoModifier); |
| QApplication::sendEvent(scene, &keyEvent); |
| } |
| |
| static void sendKeyRelease(QGraphicsScene *scene, Qt::Key key) |
| { |
| QKeyEvent keyEvent(QEvent::KeyRelease, key, Qt::NoModifier); |
| QApplication::sendEvent(scene, &keyEvent); |
| } |
| |
| static void sendKeyClick(QGraphicsScene *scene, Qt::Key key) |
| { |
| sendKeyPress(scene, key); |
| sendKeyRelease(scene, key); |
| } |
| |
| class EventSpy : public QGraphicsWidget |
| { |
| Q_OBJECT |
| public: |
| EventSpy(QObject *watched, QEvent::Type type) |
| : _count(0), spied(type) |
| { |
| watched->installEventFilter(this); |
| } |
| |
| EventSpy(QGraphicsScene *scene, QGraphicsItem *watched, QEvent::Type type) |
| : _count(0), spied(type) |
| { |
| scene->addItem(this); |
| watched->installSceneEventFilter(this); |
| } |
| |
| int count() const { return _count; } |
| |
| protected: |
| bool eventFilter(QObject *watched, QEvent *event) |
| { |
| Q_UNUSED(watched); |
| if (event->type() == spied) |
| ++_count; |
| return false; |
| } |
| |
| bool sceneEventFilter(QGraphicsItem *watched, QEvent *event) |
| { |
| Q_UNUSED(watched); |
| if (event->type() == spied) |
| ++_count; |
| return false; |
| } |
| |
| int _count; |
| QEvent::Type spied; |
| }; |
| |
| class EventSpy2 : public QGraphicsWidget |
| { |
| Q_OBJECT |
| public: |
| EventSpy2(QObject *watched) |
| { |
| watched->installEventFilter(this); |
| } |
| |
| EventSpy2(QGraphicsScene *scene, QGraphicsItem *watched) |
| { |
| scene->addItem(this); |
| watched->installSceneEventFilter(this); |
| } |
| |
| QMap<QEvent::Type, int> counts; |
| |
| protected: |
| bool eventFilter(QObject *watched, QEvent *event) |
| { |
| Q_UNUSED(watched); |
| ++counts[event->type()]; |
| return false; |
| } |
| |
| bool sceneEventFilter(QGraphicsItem *watched, QEvent *event) |
| { |
| Q_UNUSED(watched); |
| ++counts[event->type()]; |
| return false; |
| } |
| }; |
| |
| class EventTester : public QGraphicsItem |
| { |
| public: |
| EventTester(QGraphicsItem *parent = 0) : QGraphicsItem(parent), repaints(0) |
| { br = QRectF(-10, -10, 20, 20); } |
| |
| void setGeometry(const QRectF &rect) |
| { |
| prepareGeometryChange(); |
| br = rect; |
| update(); |
| } |
| |
| QRectF boundingRect() const |
| { return br; } |
| |
| void paint(QPainter *painter, const QStyleOptionGraphicsItem *o, QWidget *) |
| { |
| hints = painter->renderHints(); |
| painter->setBrush(brush); |
| painter->drawRect(boundingRect()); |
| lastExposedRect = o->exposedRect; |
| ++repaints; |
| } |
| |
| bool sceneEvent(QEvent *event) |
| { |
| events << event->type(); |
| return QGraphicsItem::sceneEvent(event); |
| } |
| |
| void reset() |
| { |
| events.clear(); |
| hints = QPainter::RenderHints(0); |
| repaints = 0; |
| lastExposedRect = QRectF(); |
| } |
| |
| QList<QEvent::Type> events; |
| QPainter::RenderHints hints; |
| int repaints; |
| QRectF br; |
| QRectF lastExposedRect; |
| QBrush brush; |
| }; |
| |
| class MyGraphicsView : public QGraphicsView |
| { |
| public: |
| int repaints; |
| QRegion paintedRegion; |
| MyGraphicsView(QGraphicsScene *scene, QWidget *parent=0) : QGraphicsView(scene,parent), repaints(0) {} |
| void paintEvent(QPaintEvent *e) |
| { |
| paintedRegion += e->region(); |
| ++repaints; |
| QGraphicsView::paintEvent(e); |
| } |
| void reset() { repaints = 0; paintedRegion = QRegion(); } |
| }; |
| |
| class tst_QGraphicsItem : public QObject |
| { |
| Q_OBJECT |
| |
| public: |
| static void initMain(); |
| |
| private slots: |
| void construction(); |
| void constructionWithParent(); |
| void destruction(); |
| void deleteChildItem(); |
| void scene(); |
| void parentItem(); |
| void setParentItem(); |
| void children(); |
| void flags(); |
| void inputMethodHints(); |
| void toolTip(); |
| void visible(); |
| void isVisibleTo(); |
| void explicitlyVisible(); |
| void enabled(); |
| void explicitlyEnabled(); |
| void selected(); |
| void selected2(); |
| void selected_group(); |
| void selected_textItem(); |
| void selected_multi(); |
| void acceptedMouseButtons(); |
| void acceptHoverEvents(); |
| void childAcceptsHoverEvents(); |
| void hasFocus(); |
| void pos(); |
| void scenePos(); |
| void matrix(); |
| void sceneTransform(); |
| void setTransform(); |
| void zValue(); |
| void shape(); |
| void contains(); |
| void collidesWith_item(); |
| void collidesWith_path_data(); |
| void collidesWith_path(); |
| void collidesWithItemWithClip(); |
| void isObscuredBy(); |
| void isObscured(); |
| void mapFromToParent(); |
| void mapFromToScene(); |
| void mapFromToItem(); |
| void mapRectFromToParent_data(); |
| void mapRectFromToParent(); |
| void isAncestorOf(); |
| void commonAncestorItem(); |
| void data(); |
| void type(); |
| void graphicsitem_cast(); |
| void hoverEventsGenerateRepaints(); |
| void boundingRects_data(); |
| void boundingRects(); |
| void boundingRects2(); |
| void sceneBoundingRect(); |
| void childrenBoundingRect(); |
| void childrenBoundingRectTransformed(); |
| void childrenBoundingRect2(); |
| void childrenBoundingRect3(); |
| void childrenBoundingRect4(); |
| void childrenBoundingRect5(); |
| void group(); |
| void setGroup(); |
| void setGroup2(); |
| void nestedGroups(); |
| void warpChildrenIntoGroup(); |
| void removeFromGroup(); |
| void handlesChildEvents(); |
| void handlesChildEvents2(); |
| void handlesChildEvents3(); |
| void filtersChildEvents(); |
| void filtersChildEvents2(); |
| void ensureVisible(); |
| #ifndef QT_NO_CURSOR |
| void cursor(); |
| #endif |
| //void textControlGetterSetter(); |
| void defaultItemTest_QGraphicsLineItem(); |
| void defaultItemTest_QGraphicsPixmapItem(); |
| void defaultItemTest_QGraphicsTextItem(); |
| void defaultItemTest_QGraphicsEllipseItem(); |
| void itemChange(); |
| void sceneEventFilter(); |
| void prepareGeometryChange(); |
| void paint(); |
| void deleteItemInEventHandlers(); |
| void itemClipsToShape(); |
| void itemClipsChildrenToShape(); |
| void itemClipsChildrenToShape2(); |
| void itemClipsChildrenToShape3(); |
| void itemClipsChildrenToShape4(); |
| void itemClipsChildrenToShape5(); |
| void itemClipsTextChildToShape(); |
| void itemClippingDiscovery(); |
| void itemContainsChildrenInShape(); |
| void itemContainsChildrenInShape2(); |
| void ancestorFlags(); |
| void untransformable(); |
| #ifndef QT_NO_CONTEXTMENU |
| void contextMenuEventPropagation(); |
| #endif // QT_NO_CONTEXTMENU |
| void itemIsMovable(); |
| void boundingRegion_data(); |
| void boundingRegion(); |
| void itemTransform_parentChild(); |
| void itemTransform_siblings(); |
| void itemTransform_unrelated(); |
| void opacity_data(); |
| void opacity(); |
| void opacity2(); |
| void opacityZeroUpdates(); |
| void itemStacksBehindParent(); |
| void nestedClipping(); |
| void nestedClippingTransforms(); |
| void sceneTransformCache(); |
| void tabChangesFocus(); |
| void tabChangesFocus_data(); |
| void cacheMode(); |
| void cacheMode2(); |
| void updateCachedItemAfterMove(); |
| void deviceTransform_data(); |
| void deviceTransform(); |
| void update(); |
| void setTransformProperties_data(); |
| void setTransformProperties(); |
| void itemUsesExtendedStyleOption(); |
| void itemSendsGeometryChanges(); |
| void moveItem(); |
| void moveLineItem(); |
| void sorting_data(); |
| void sorting(); |
| void itemHasNoContents(); |
| void hitTestUntransformableItem(); |
| void hitTestGraphicsEffectItem(); |
| void focusProxy(); |
| void subFocus(); |
| void focusProxyDeletion(); |
| void negativeZStacksBehindParent(); |
| void setGraphicsEffect(); |
| void panel(); |
| void addPanelToActiveScene(); |
| void panelWithFocusItems(); |
| void activate(); |
| void setActivePanelOnInactiveScene(); |
| void activationOnShowHide(); |
| void deactivateInactivePanel(); |
| void moveWhileDeleting(); |
| void ensureDirtySceneTransform(); |
| void focusScope(); |
| void focusScope2(); |
| void focusScopeItemChangedWhileScopeDoesntHaveFocus(); |
| void stackBefore(); |
| void sceneModality(); |
| void panelModality(); |
| void mixedModality(); |
| void modality_hover(); |
| void modality_mouseGrabber(); |
| void modality_clickFocus(); |
| void modality_keyEvents(); |
| void itemIsInFront(); |
| void scenePosChange(); |
| void textItem_shortcuts(); |
| void scroll(); |
| void focusHandling_data(); |
| void focusHandling(); |
| void touchEventPropagation_data(); |
| void touchEventPropagation(); |
| void touchEventTransformation_data(); |
| void touchEventTransformation(); |
| void deviceCoordinateCache_simpleRotations(); |
| void resolvePaletteForItemChildren(); |
| |
| // task specific tests below me |
| void task141694_textItemEnsureVisible(); |
| void task128696_textItemEnsureMovable(); |
| void ensureUpdateOnTextItem(); |
| void task177918_lineItemUndetected(); |
| void task240400_clickOnTextItem_data(); |
| void task240400_clickOnTextItem(); |
| void task243707_addChildBeforeParent(); |
| void task197802_childrenVisibility(); |
| void QTBUG_4233_updateCachedWithSceneRect(); |
| void QTBUG_5418_textItemSetDefaultColor(); |
| void QTBUG_6738_missingUpdateWithSetParent(); |
| void QTBUG_7714_fullUpdateDiscardingOpacityUpdate2(); |
| void QT_2653_fullUpdateDiscardingOpacityUpdate(); |
| void QT_2649_focusScope(); |
| void sortItemsWhileAdding(); |
| void doNotMarkFullUpdateIfNotInScene(); |
| void itemDiesDuringDraggingOperation(); |
| void QTBUG_12112_focusItem(); |
| void QTBUG_13473_sceneposchange(); |
| void QTBUG_16374_crashInDestructor(); |
| void QTBUG_20699_focusScopeCrash(); |
| void QTBUG_30990_rightClickSelection(); |
| void QTBUG_21618_untransformable_sceneTransform(); |
| |
| private: |
| QList<QGraphicsItem *> paintedItems; |
| QTouchDevice *m_touchDevice = nullptr; |
| }; |
| |
| void tst_QGraphicsItem::initMain() |
| { |
| #ifdef Q_OS_WIN |
| // Ensure minimum size constraints of framed windows on High DPI screens |
| QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); |
| #endif |
| } |
| |
| void tst_QGraphicsItem::construction() |
| { |
| for (int i = 0; i < 7; ++i) { |
| QGraphicsItem *item = nullptr; |
| switch (i) { |
| case 0: |
| item = new QGraphicsEllipseItem; |
| ((QGraphicsEllipseItem *)item)->setPen(QPen(Qt::black, 0)); |
| QCOMPARE(int(item->type()), int(QGraphicsEllipseItem::Type)); |
| QCOMPARE(qgraphicsitem_cast<QGraphicsEllipseItem *>(item), (QGraphicsEllipseItem *)item); |
| QCOMPARE(qgraphicsitem_cast<QGraphicsRectItem *>(item), nullptr); |
| QCOMPARE(item->flags(), 0); |
| break; |
| case 1: |
| item = new QGraphicsLineItem; |
| ((QGraphicsLineItem *)item)->setPen(QPen(Qt::black, 0)); |
| QCOMPARE(int(item->type()), int(QGraphicsLineItem::Type)); |
| QCOMPARE(qgraphicsitem_cast<QGraphicsLineItem *>(item), (QGraphicsLineItem *)item); |
| QCOMPARE(qgraphicsitem_cast<QGraphicsRectItem *>(item), nullptr); |
| QCOMPARE(item->flags(), 0); |
| break; |
| case 2: |
| item = new QGraphicsPathItem; |
| ((QGraphicsPathItem *)item)->setPen(QPen(Qt::black, 0)); |
| QCOMPARE(int(item->type()), int(QGraphicsPathItem::Type)); |
| QCOMPARE(qgraphicsitem_cast<QGraphicsPathItem *>(item), (QGraphicsPathItem *)item); |
| QCOMPARE(qgraphicsitem_cast<QGraphicsRectItem *>(item), nullptr); |
| QCOMPARE(item->flags(), 0); |
| break; |
| case 3: |
| item = new QGraphicsPixmapItem; |
| QCOMPARE(int(item->type()), int(QGraphicsPixmapItem::Type)); |
| QCOMPARE(qgraphicsitem_cast<QGraphicsPixmapItem *>(item), (QGraphicsPixmapItem *)item); |
| QCOMPARE(qgraphicsitem_cast<QGraphicsRectItem *>(item), nullptr); |
| QCOMPARE(item->flags(), 0); |
| break; |
| case 4: |
| item = new QGraphicsPolygonItem; |
| ((QGraphicsPolygonItem *)item)->setPen(QPen(Qt::black, 0)); |
| QCOMPARE(int(item->type()), int(QGraphicsPolygonItem::Type)); |
| QCOMPARE(qgraphicsitem_cast<QGraphicsPolygonItem *>(item), (QGraphicsPolygonItem *)item); |
| QCOMPARE(qgraphicsitem_cast<QGraphicsRectItem *>(item), nullptr); |
| QCOMPARE(item->flags(), 0); |
| break; |
| case 5: |
| item = new QGraphicsRectItem; |
| ((QGraphicsRectItem *)item)->setPen(QPen(Qt::black, 0)); |
| QCOMPARE(int(item->type()), int(QGraphicsRectItem::Type)); |
| QCOMPARE(qgraphicsitem_cast<QGraphicsRectItem *>(item), (QGraphicsRectItem *)item); |
| QCOMPARE(qgraphicsitem_cast<QGraphicsLineItem *>(item), nullptr); |
| QCOMPARE(item->flags(), 0); |
| break; |
| case 6: |
| item = new QGraphicsTextItem; |
| QCOMPARE(int(item->type()), int(QGraphicsTextItem::Type)); |
| QCOMPARE(qgraphicsitem_cast<QGraphicsTextItem *>(item), (QGraphicsTextItem *)item); |
| QCOMPARE(qgraphicsitem_cast<QGraphicsRectItem *>(item), nullptr); |
| // This is the only item that uses an extended style option. |
| QCOMPARE(item->flags(), QGraphicsItem::GraphicsItemFlags(QGraphicsItem::ItemUsesExtendedStyleOption)); |
| break; |
| default: |
| qFatal("You broke the logic, please fix!"); |
| break; |
| } |
| |
| QCOMPARE(item->scene(), nullptr); |
| QCOMPARE(item->parentItem(), nullptr); |
| QVERIFY(item->childItems().isEmpty()); |
| QVERIFY(item->isVisible()); |
| QVERIFY(item->isEnabled()); |
| QVERIFY(!item->isSelected()); |
| QCOMPARE(item->acceptedMouseButtons(), Qt::MouseButtons(0x1f)); |
| if (item->type() == QGraphicsTextItem::Type) |
| QVERIFY(item->acceptHoverEvents()); |
| else |
| QVERIFY(!item->acceptHoverEvents()); |
| QVERIFY(!item->hasFocus()); |
| QCOMPARE(item->pos(), QPointF()); |
| QCOMPARE(item->transform(), QTransform()); |
| QCOMPARE(item->sceneTransform(), QTransform()); |
| QCOMPARE(item->zValue(), qreal(0)); |
| QCOMPARE(item->sceneBoundingRect(), QRectF()); |
| QCOMPARE(item->shape(), QPainterPath()); |
| QVERIFY(!item->contains(QPointF(0, 0))); |
| QVERIFY(!item->collidesWithItem(0)); |
| QVERIFY(item->collidesWithItem(item)); |
| QVERIFY(!item->collidesWithPath(QPainterPath())); |
| QVERIFY(!item->isAncestorOf(0)); |
| QVERIFY(!item->isAncestorOf(item)); |
| QCOMPARE(item->data(0), QVariant()); |
| delete item; |
| } |
| } |
| |
| class BoundingRectItem : public QGraphicsRectItem |
| { |
| public: |
| BoundingRectItem(QGraphicsItem *parent = 0) |
| : QGraphicsRectItem(0, 0, parent ? 200 : 100, parent ? 200 : 100, |
| parent) |
| { |
| setPen(QPen(Qt::black, 0)); |
| } |
| |
| QRectF boundingRect() const |
| { |
| QRectF tmp = QGraphicsRectItem::boundingRect(); |
| foreach (QGraphicsItem *child, childItems()) |
| tmp |= child->boundingRect(); // <- might be pure virtual |
| return tmp; |
| } |
| }; |
| |
| void tst_QGraphicsItem::constructionWithParent() |
| { |
| // This test causes a crash if item1 calls item2's pure virtuals before the |
| // object has been constructed. |
| QGraphicsItem *item0 = new BoundingRectItem; |
| QGraphicsItem *item1 = new BoundingRectItem; |
| QGraphicsScene scene; |
| scene.addItem(item0); |
| scene.addItem(item1); |
| QGraphicsItem *item2 = new BoundingRectItem(item1); |
| QCOMPARE(item1->childItems(), QList<QGraphicsItem *>() << item2); |
| QCOMPARE(item1->boundingRect(), QRectF(0, 0, 200, 200)); |
| |
| item2->setParentItem(item0); |
| QCOMPARE(item0->childItems(), QList<QGraphicsItem *>() << item2); |
| QCOMPARE(item0->boundingRect(), QRectF(0, 0, 200, 200)); |
| } |
| |
| static int itemDeleted = 0; |
| class Item : public QGraphicsRectItem |
| { |
| public: |
| ~Item() |
| { ++itemDeleted; } |
| }; |
| |
| void tst_QGraphicsItem::destruction() |
| { |
| QCOMPARE(itemDeleted, 0); |
| { |
| QGraphicsItem *parent = new QGraphicsRectItem; |
| Item *child = new Item; |
| child->setParentItem(parent); |
| QCOMPARE(child->parentItem(), parent); |
| delete parent; |
| QCOMPARE(itemDeleted, 1); |
| } |
| { |
| QGraphicsItem *parent = new QGraphicsRectItem; |
| Item *child = new Item; |
| child->setParentItem(parent); |
| QCOMPARE(parent->childItems().size(), 1); |
| delete child; |
| QCOMPARE(parent->childItems().size(), 0); |
| delete parent; |
| QCOMPARE(itemDeleted, 2); |
| } |
| { |
| QGraphicsScene scene; |
| QGraphicsItem *parent = new QGraphicsRectItem; |
| Item *child = new Item; |
| QCOMPARE(child->parentItem(), nullptr); |
| child->setParentItem(parent); |
| QCOMPARE(child->parentItem(), parent); |
| scene.addItem(parent); |
| QCOMPARE(child->parentItem(), parent); |
| delete parent; |
| QCOMPARE(itemDeleted, 3); |
| } |
| { |
| QGraphicsScene scene; |
| QGraphicsItem *parent = new QGraphicsRectItem; |
| Item *child = new Item; |
| child->setParentItem(parent); |
| scene.addItem(parent); |
| QCOMPARE(child->scene(), &scene); |
| QCOMPARE(parent->childItems().size(), 1); |
| delete child; |
| QCOMPARE(parent->childItems().size(), 0); |
| delete parent; |
| QCOMPARE(itemDeleted, 4); |
| } |
| { |
| QGraphicsScene scene; |
| QGraphicsItem *parent = new QGraphicsRectItem; |
| Item *child = new Item; |
| child->setParentItem(parent); |
| scene.addItem(parent); |
| QCOMPARE(child->scene(), &scene); |
| scene.removeItem(parent); |
| QCOMPARE(child->scene(), nullptr); |
| delete parent; |
| QCOMPARE(itemDeleted, 5); |
| } |
| { |
| QGraphicsScene scene; |
| QGraphicsItem *parent = new QGraphicsRectItem; |
| Item *child = new Item; |
| child->setParentItem(parent); |
| QCOMPARE(child->scene(), nullptr); |
| QCOMPARE(parent->scene(), nullptr); |
| scene.addItem(parent); |
| QCOMPARE(child->scene(), &scene); |
| scene.removeItem(child); |
| QCOMPARE(child->scene(), nullptr); |
| QCOMPARE(parent->scene(), &scene); |
| QCOMPARE(child->parentItem(), nullptr); |
| QVERIFY(parent->childItems().isEmpty()); |
| delete parent; |
| QCOMPARE(itemDeleted, 5); |
| delete child; |
| QCOMPARE(itemDeleted, 6); |
| } |
| { |
| QGraphicsScene scene; |
| QGraphicsItem *parent = new QGraphicsRectItem; |
| Item *child = new Item; |
| child->setParentItem(parent); |
| scene.addItem(parent); |
| scene.removeItem(child); |
| scene.removeItem(parent); |
| delete child; |
| delete parent; |
| QCOMPARE(itemDeleted, 7); |
| } |
| { |
| QGraphicsScene scene; |
| QGraphicsItem *parent = new QGraphicsRectItem; |
| Item *child = new Item; |
| child->setParentItem(parent); |
| scene.addItem(parent); |
| QGraphicsScene scene2; |
| scene2.addItem(parent); |
| delete parent; |
| QCOMPARE(itemDeleted, 8); |
| } |
| { |
| QGraphicsScene scene; |
| QGraphicsItem *parent = new QGraphicsRectItem; |
| Item *child = new Item; |
| child->setParentItem(parent); |
| scene.addItem(parent); |
| QCOMPARE(child->scene(), &scene); |
| QGraphicsScene scene2; |
| scene2.addItem(parent); |
| QCOMPARE(child->scene(), &scene2); |
| scene.addItem(parent); |
| QCOMPARE(child->scene(), &scene); |
| scene2.addItem(parent); |
| QCOMPARE(child->scene(), &scene2); |
| delete parent; |
| QCOMPARE(itemDeleted, 9); |
| } |
| { |
| QGraphicsScene scene; |
| QGraphicsItem *parent = new QGraphicsRectItem; |
| Item *child = new Item; |
| child->setParentItem(parent); |
| scene.addItem(parent); |
| QCOMPARE(child->scene(), &scene); |
| QGraphicsScene scene2; |
| scene2.addItem(child); |
| QCOMPARE(child->scene(), &scene2); |
| delete parent; |
| QCOMPARE(itemDeleted, 9); |
| delete child; |
| QCOMPARE(itemDeleted, 10); |
| } |
| { |
| QGraphicsScene scene; |
| QGraphicsItem *root = new QGraphicsRectItem; |
| QGraphicsItem *parent = root; |
| QGraphicsItem *middleItem = 0; |
| for (int i = 0; i < 99; ++i) { |
| Item *child = new Item; |
| child->setParentItem(parent); |
| parent = child; |
| if (i == 50) |
| middleItem = parent; |
| } |
| scene.addItem(root); |
| |
| QCOMPARE(scene.items().size(), 100); |
| |
| QGraphicsScene scene2; |
| scene2.addItem(middleItem); |
| |
| delete middleItem; |
| QCOMPARE(itemDeleted, 59); |
| } |
| QCOMPARE(itemDeleted, 109); |
| { |
| QGraphicsScene *scene = new QGraphicsScene; |
| QGraphicsRectItem *parent = new QGraphicsRectItem; |
| Item *child = new Item; |
| child->setParentItem(parent); |
| parent->setVisible(false); |
| scene->addItem(parent); |
| QCOMPARE(child->parentItem(), static_cast<QGraphicsItem*>(parent)); |
| delete scene; |
| QCOMPARE(itemDeleted, 110); |
| } |
| } |
| |
| void tst_QGraphicsItem::deleteChildItem() |
| { |
| QGraphicsScene scene; |
| QGraphicsItem *rect = scene.addRect(QRectF()); |
| QGraphicsItem *child1 = new QGraphicsRectItem(rect); |
| QGraphicsItem *child2 = new QGraphicsRectItem(rect); |
| QGraphicsItem *child3 = new QGraphicsRectItem(rect); |
| Q_UNUSED(child3); |
| delete child1; |
| child2->setParentItem(0); |
| delete child2; |
| } |
| |
| void tst_QGraphicsItem::scene() |
| { |
| QGraphicsRectItem *item = new QGraphicsRectItem; |
| QCOMPARE(item->scene(), nullptr); |
| |
| QGraphicsScene scene; |
| scene.addItem(item); |
| QCOMPARE(item->scene(), (QGraphicsScene *)&scene); |
| |
| QGraphicsScene scene2; |
| scene2.addItem(item); |
| QCOMPARE(item->scene(), (QGraphicsScene *)&scene2); |
| |
| scene2.removeItem(item); |
| QCOMPARE(item->scene(), nullptr); |
| |
| delete item; |
| } |
| |
| void tst_QGraphicsItem::parentItem() |
| { |
| QGraphicsRectItem item; |
| QCOMPARE(item.parentItem(), nullptr); |
| |
| QGraphicsRectItem *item2 = new QGraphicsRectItem(QRectF(), &item); |
| QCOMPARE(item2->parentItem(), (QGraphicsItem *)&item); |
| item2->setParentItem(&item); |
| QCOMPARE(item2->parentItem(), (QGraphicsItem *)&item); |
| item2->setParentItem(0); |
| QCOMPARE(item2->parentItem(), nullptr); |
| |
| delete item2; |
| } |
| |
| void tst_QGraphicsItem::setParentItem() |
| { |
| QGraphicsScene scene; |
| const QScopedPointer<QGraphicsItem> item(scene.addRect(QRectF(0, 0, 10, 10))); |
| QCOMPARE(item->scene(), &scene); |
| |
| const QScopedPointer<QGraphicsRectItem> child(new QGraphicsRectItem); |
| QCOMPARE(child->scene(), nullptr); |
| |
| // This implicitly adds the item to the parent's scene |
| child->setParentItem(item.data()); |
| QCOMPARE(child->scene(), &scene); |
| |
| // This just makes it a toplevel |
| child->setParentItem(0); |
| QCOMPARE(child->scene(), &scene); |
| |
| // Add the child back to the parent, then remove the parent from the scene |
| child->setParentItem(item.data()); |
| scene.removeItem(item.data()); |
| QCOMPARE(child->scene(), nullptr); |
| } |
| |
| void tst_QGraphicsItem::children() |
| { |
| QGraphicsRectItem item; |
| QVERIFY(item.childItems().isEmpty()); |
| |
| QGraphicsRectItem *item2 = new QGraphicsRectItem(QRectF(), &item); |
| QCOMPARE(item.childItems().size(), 1); |
| QCOMPARE(item.childItems().first(), (QGraphicsItem *)item2); |
| QVERIFY(item2->childItems().isEmpty()); |
| |
| delete item2; |
| QVERIFY(item.childItems().isEmpty()); |
| } |
| |
| void tst_QGraphicsItem::flags() |
| { |
| QGraphicsRectItem *item = new QGraphicsRectItem(QRectF(-10, -10, 20, 20)); |
| QCOMPARE(item->flags(), 0); |
| |
| QGraphicsScene scene; |
| QEvent activate(QEvent::WindowActivate); |
| QApplication::sendEvent(&scene, &activate); |
| |
| scene.addItem(item); |
| |
| { |
| // Focus |
| item->setFlag(QGraphicsItem::ItemIsFocusable, false); |
| QVERIFY(!item->hasFocus()); |
| item->setFocus(); |
| QVERIFY(!item->hasFocus()); |
| |
| item->setFlag(QGraphicsItem::ItemIsFocusable, true); |
| QVERIFY(!item->hasFocus()); |
| item->setFocus(); |
| QVERIFY(item->hasFocus()); |
| QVERIFY(scene.hasFocus()); |
| |
| item->setFlag(QGraphicsItem::ItemIsFocusable, false); |
| QVERIFY(!item->hasFocus()); |
| QVERIFY(scene.hasFocus()); |
| } |
| { |
| // Selectable |
| item->setFlag(QGraphicsItem::ItemIsSelectable, false); |
| QVERIFY(!item->isSelected()); |
| item->setSelected(true); |
| QVERIFY(!item->isSelected()); |
| |
| item->setFlag(QGraphicsItem::ItemIsSelectable, true); |
| QVERIFY(!item->isSelected()); |
| item->setSelected(true); |
| QVERIFY(item->isSelected()); |
| item->setFlag(QGraphicsItem::ItemIsSelectable, false); |
| QVERIFY(!item->isSelected()); |
| } |
| { |
| // Movable |
| item->setFlag(QGraphicsItem::ItemIsMovable, false); |
| QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress); |
| event.setScenePos(QPointF(0, 0)); |
| event.setButton(Qt::LeftButton); |
| event.setButtons(Qt::LeftButton); |
| QApplication::sendEvent(&scene, &event); |
| QCOMPARE(scene.mouseGrabberItem(), nullptr); // mouse grabber is reset |
| |
| QGraphicsSceneMouseEvent event2(QEvent::GraphicsSceneMouseMove); |
| event2.setScenePos(QPointF(10, 10)); |
| event2.setButton(Qt::LeftButton); |
| event2.setButtons(Qt::LeftButton); |
| QApplication::sendEvent(&scene, &event2); |
| QCOMPARE(item->pos(), QPointF()); |
| |
| QGraphicsSceneMouseEvent event3(QEvent::GraphicsSceneMouseRelease); |
| event3.setScenePos(QPointF(10, 10)); |
| event3.setButtons(0); |
| QApplication::sendEvent(&scene, &event3); |
| QCOMPARE(scene.mouseGrabberItem(), nullptr); |
| |
| item->setFlag(QGraphicsItem::ItemIsMovable, true); |
| QGraphicsSceneMouseEvent event4(QEvent::GraphicsSceneMousePress); |
| event4.setScenePos(QPointF(0, 0)); |
| event4.setButton(Qt::LeftButton); |
| event4.setButtons(Qt::LeftButton); |
| QApplication::sendEvent(&scene, &event4); |
| QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)item); |
| QGraphicsSceneMouseEvent event5(QEvent::GraphicsSceneMouseMove); |
| event5.setScenePos(QPointF(10, 10)); |
| event5.setButton(Qt::LeftButton); |
| event5.setButtons(Qt::LeftButton); |
| QApplication::sendEvent(&scene, &event5); |
| QCOMPARE(item->pos(), QPointF(10, 10)); |
| } |
| { |
| const QScopedPointer<QGraphicsItem> clippingParent(new QGraphicsRectItem); |
| clippingParent->setFlag(QGraphicsItem::ItemClipsChildrenToShape, true); |
| |
| const QScopedPointer<QGraphicsItem> nonClippingParent(new QGraphicsRectItem); |
| nonClippingParent->setFlag(QGraphicsItem::ItemClipsChildrenToShape, false); |
| |
| QGraphicsItem* child = new QGraphicsRectItem(nonClippingParent.data()); |
| QVERIFY(!child->isClipped()); |
| |
| child->setParentItem(clippingParent.data()); |
| QVERIFY(child->isClipped()); |
| |
| child->setParentItem(nonClippingParent.data()); |
| QVERIFY(!child->isClipped()); |
| } |
| } |
| |
| class ImhTester : public QGraphicsItem |
| { |
| QRectF boundingRect() const { return QRectF(); } |
| void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *) {} |
| }; |
| |
| void tst_QGraphicsItem::inputMethodHints() |
| { |
| ImhTester *item = new ImhTester; |
| item->setFlag(QGraphicsItem::ItemAcceptsInputMethod, true); |
| item->setFlag(QGraphicsItem::ItemIsFocusable, true); |
| QCOMPARE(item->inputMethodHints(), Qt::ImhNone); |
| ImhTester *item2 = new ImhTester; |
| item2->setFlag(QGraphicsItem::ItemAcceptsInputMethod, true); |
| item2->setFlag(QGraphicsItem::ItemIsFocusable, true); |
| Qt::InputMethodHints imHints = item2->inputMethodHints(); |
| imHints |= Qt::ImhHiddenText; |
| item2->setInputMethodHints(imHints); |
| QGraphicsScene scene; |
| scene.addItem(item); |
| scene.addItem(item2); |
| QGraphicsView view(&scene); |
| QApplication::setActiveWindow(&view); |
| view.show(); |
| QVERIFY(QTest::qWaitForWindowExposed(&view)); |
| QVERIFY(QTest::qWaitForWindowActive(&view)); |
| item->setFocus(); |
| QTRY_VERIFY(item->hasFocus()); |
| QCOMPARE(view.inputMethodHints(), item->inputMethodHints()); |
| item2->setFocus(); |
| QTRY_VERIFY(item2->hasFocus()); |
| QCOMPARE(view.inputMethodHints(), item2->inputMethodHints()); |
| item->setFlag(QGraphicsItem::ItemAcceptsInputMethod, false); |
| item->setFocus(); |
| QTRY_VERIFY(item->hasFocus()); |
| //Focus has changed but the new item doesn't accept input method, no hints. |
| QCOMPARE(view.inputMethodHints(), 0); |
| item2->setFocus(); |
| QTRY_VERIFY(item2->hasFocus()); |
| QCOMPARE(view.inputMethodHints(), item2->inputMethodHints()); |
| imHints = item2->inputMethodHints(); |
| imHints |= (Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText); |
| item2->setInputMethodHints(imHints); |
| QCOMPARE(view.inputMethodHints(), item2->inputMethodHints()); |
| QGraphicsProxyWidget *widget = new QGraphicsProxyWidget; |
| QLineEdit *edit = new QLineEdit; |
| edit->setEchoMode(QLineEdit::Password); |
| scene.addItem(widget); |
| widget->setFocus(); |
| QTRY_VERIFY(widget->hasFocus()); |
| //No widget on the proxy, so no hints |
| QCOMPARE(view.inputMethodHints(), 0); |
| widget->setWidget(edit); |
| //View should match with the line edit |
| QCOMPARE(view.inputMethodHints(), edit->inputMethodHints()); |
| } |
| |
| void tst_QGraphicsItem::toolTip() |
| { |
| QString toolTip = "Qt rocks!"; |
| |
| QGraphicsRectItem *item = new QGraphicsRectItem(QRectF(0, 0, 100, 100)); |
| item->setPen(QPen(Qt::red, 1)); |
| item->setBrush(QBrush(Qt::blue)); |
| QVERIFY(item->toolTip().isEmpty()); |
| item->setToolTip(toolTip); |
| QCOMPARE(item->toolTip(), toolTip); |
| |
| QGraphicsScene scene; |
| scene.addItem(item); |
| |
| QGraphicsView view(&scene); |
| view.setFixedSize(200, 200); |
| view.show(); |
| QApplication::setActiveWindow(&view); |
| QVERIFY(QTest::qWaitForWindowExposed(&view)); |
| QVERIFY(QTest::qWaitForWindowActive(&view)); |
| { |
| QHelpEvent helpEvent(QEvent::ToolTip, view.viewport()->rect().topLeft(), |
| view.viewport()->mapToGlobal(view.viewport()->rect().topLeft())); |
| QApplication::sendEvent(view.viewport(), &helpEvent); |
| QTest::qWait(250); |
| |
| bool foundView = false; |
| bool foundTipLabel = false; |
| foreach (QWidget *widget, QApplication::topLevelWidgets()) { |
| if (widget == &view) |
| foundView = true; |
| if (widget->inherits("QTipLabel")) |
| foundTipLabel = true; |
| } |
| QVERIFY(foundView); |
| QVERIFY(!foundTipLabel); |
| } |
| |
| { |
| QHelpEvent helpEvent(QEvent::ToolTip, view.viewport()->rect().center(), |
| view.viewport()->mapToGlobal(view.viewport()->rect().center())); |
| QApplication::sendEvent(view.viewport(), &helpEvent); |
| QTest::qWait(250); |
| |
| bool foundView = false; |
| bool foundTipLabel = false; |
| foreach (QWidget *widget, QApplication::topLevelWidgets()) { |
| if (widget == &view) |
| foundView = true; |
| if (widget->inherits("QTipLabel")) |
| foundTipLabel = true; |
| } |
| QVERIFY(foundView); |
| QVERIFY(foundTipLabel); |
| } |
| |
| { |
| QHelpEvent helpEvent(QEvent::ToolTip, view.viewport()->rect().topLeft(), |
| view.viewport()->mapToGlobal(view.viewport()->rect().topLeft())); |
| QApplication::sendEvent(view.viewport(), &helpEvent); |
| QTest::qWait(1000); |
| |
| bool foundView = false; |
| bool foundTipLabel = false; |
| foreach (QWidget *widget, QApplication::topLevelWidgets()) { |
| if (widget == &view) |
| foundView = true; |
| if (widget->inherits("QTipLabel") && widget->isVisible()) |
| foundTipLabel = true; |
| } |
| QVERIFY(foundView); |
| QVERIFY(!foundTipLabel); |
| } |
| } |
| |
| void tst_QGraphicsItem::visible() |
| { |
| QGraphicsItem *item = new QGraphicsRectItem(QRectF(-10, -10, 20, 20)); |
| item->setFlag(QGraphicsItem::ItemIsMovable); |
| QVERIFY(item->isVisible()); |
| item->setVisible(false); |
| QVERIFY(!item->isVisible()); |
| item->setVisible(true); |
| QVERIFY(item->isVisible()); |
| |
| QGraphicsScene scene; |
| QEvent activate(QEvent::WindowActivate); |
| QApplication::sendEvent(&scene, &activate); |
| |
| scene.addItem(item); |
| QVERIFY(item->isVisible()); |
| QCOMPARE(scene.items(QPointF(0, 0)).value(0, nullptr), item); |
| item->setVisible(false); |
| QVERIFY(scene.items(QPointF(0, 0)).isEmpty()); |
| item->setVisible(true); |
| QCOMPARE(scene.items(QPointF(0, 0)).value(0, nullptr), item); |
| |
| QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress); |
| event.setButton(Qt::LeftButton); |
| event.setScenePos(QPointF(0, 0)); |
| QApplication::sendEvent(&scene, &event); |
| QCOMPARE(scene.mouseGrabberItem(), item); |
| item->setVisible(false); |
| QCOMPARE(scene.mouseGrabberItem(), nullptr); |
| item->setVisible(true); |
| QCOMPARE(scene.mouseGrabberItem(), nullptr); |
| |
| item->setFlag(QGraphicsItem::ItemIsFocusable); |
| item->setFocus(); |
| QVERIFY(item->hasFocus()); |
| item->setVisible(false); |
| QVERIFY(!item->hasFocus()); |
| item->setVisible(true); |
| QVERIFY(!item->hasFocus()); |
| } |
| |
| void tst_QGraphicsItem::isVisibleTo() |
| { |
| QGraphicsScene scene; |
| QGraphicsItem *parent = scene.addRect(QRectF(0, 0, 100, 100)); |
| QGraphicsItem *child = scene.addRect(QRectF(25, 25, 50, 50)); |
| QGraphicsItem *grandChild = scene.addRect(QRectF(50, 50, 50, 50)); |
| QGraphicsItem *stranger = scene.addRect(100, 100, 100, 100); |
| |
| child->setParentItem(parent); |
| grandChild->setParentItem(child); |
| |
| QVERIFY(grandChild->isVisible()); |
| QVERIFY(grandChild->isVisibleTo(grandChild)); |
| QVERIFY(grandChild->isVisibleTo(child)); |
| QVERIFY(grandChild->isVisibleTo(parent)); |
| QVERIFY(grandChild->isVisibleTo(0)); |
| QVERIFY(child->isVisible()); |
| QVERIFY(child->isVisibleTo(child)); |
| QVERIFY(child->isVisibleTo(parent)); |
| QVERIFY(child->isVisibleTo(0)); |
| QVERIFY(parent->isVisible()); |
| QVERIFY(parent->isVisibleTo(parent)); |
| QVERIFY(parent->isVisibleTo(0)); |
| QVERIFY(!parent->isVisibleTo(child)); |
| QVERIFY(!child->isVisibleTo(grandChild)); |
| QVERIFY(!grandChild->isVisibleTo(stranger)); |
| QVERIFY(!child->isVisibleTo(stranger)); |
| QVERIFY(!parent->isVisibleTo(stranger)); |
| QVERIFY(!stranger->isVisibleTo(grandChild)); |
| QVERIFY(!stranger->isVisibleTo(child)); |
| QVERIFY(!stranger->isVisibleTo(parent)); |
| |
| // Case 1: only parent is explicitly hidden |
| parent->hide(); |
| |
| QVERIFY(!grandChild->isVisible()); |
| QVERIFY(grandChild->isVisibleTo(grandChild)); |
| QVERIFY(grandChild->isVisibleTo(child)); |
| QVERIFY(grandChild->isVisibleTo(parent)); |
| QVERIFY(!grandChild->isVisibleTo(0)); |
| QVERIFY(!child->isVisible()); |
| QVERIFY(child->isVisibleTo(child)); |
| QVERIFY(child->isVisibleTo(parent)); |
| QVERIFY(!child->isVisibleTo(0)); |
| QVERIFY(!parent->isVisible()); |
| QVERIFY(!parent->isVisibleTo(parent)); |
| QVERIFY(!parent->isVisibleTo(0)); |
| QVERIFY(!parent->isVisibleTo(child)); |
| QVERIFY(!child->isVisibleTo(grandChild)); |
| QVERIFY(!grandChild->isVisibleTo(stranger)); |
| QVERIFY(!child->isVisibleTo(stranger)); |
| QVERIFY(!parent->isVisibleTo(stranger)); |
| QVERIFY(!stranger->isVisibleTo(grandChild)); |
| QVERIFY(!stranger->isVisibleTo(child)); |
| QVERIFY(!stranger->isVisibleTo(parent)); |
| |
| // Case 2: only child is hidden |
| parent->show(); |
| child->hide(); |
| |
| QVERIFY(!grandChild->isVisible()); |
| QVERIFY(grandChild->isVisibleTo(grandChild)); |
| QVERIFY(grandChild->isVisibleTo(child)); |
| QVERIFY(!grandChild->isVisibleTo(parent)); |
| QVERIFY(!grandChild->isVisibleTo(0)); |
| QVERIFY(!child->isVisible()); |
| QVERIFY(!child->isVisibleTo(child)); |
| QVERIFY(!child->isVisibleTo(parent)); |
| QVERIFY(!child->isVisibleTo(0)); |
| QVERIFY(parent->isVisible()); |
| QVERIFY(parent->isVisibleTo(parent)); |
| QVERIFY(parent->isVisibleTo(0)); |
| QVERIFY(!parent->isVisibleTo(child)); |
| QVERIFY(!child->isVisibleTo(grandChild)); |
| QVERIFY(!grandChild->isVisibleTo(stranger)); |
| QVERIFY(!child->isVisibleTo(stranger)); |
| QVERIFY(!parent->isVisibleTo(stranger)); |
| QVERIFY(!stranger->isVisibleTo(grandChild)); |
| QVERIFY(!stranger->isVisibleTo(child)); |
| QVERIFY(!stranger->isVisibleTo(parent)); |
| |
| // Case 3: only grand child is hidden |
| child->show(); |
| grandChild->hide(); |
| |
| QVERIFY(!grandChild->isVisible()); |
| QVERIFY(!grandChild->isVisibleTo(grandChild)); |
| QVERIFY(!grandChild->isVisibleTo(child)); |
| QVERIFY(!grandChild->isVisibleTo(parent)); |
| QVERIFY(!grandChild->isVisibleTo(0)); |
| QVERIFY(child->isVisible()); |
| QVERIFY(child->isVisibleTo(child)); |
| QVERIFY(child->isVisibleTo(parent)); |
| QVERIFY(child->isVisibleTo(0)); |
| QVERIFY(parent->isVisible()); |
| QVERIFY(parent->isVisibleTo(parent)); |
| QVERIFY(parent->isVisibleTo(0)); |
| QVERIFY(!parent->isVisibleTo(child)); |
| QVERIFY(!child->isVisibleTo(grandChild)); |
| QVERIFY(!grandChild->isVisibleTo(stranger)); |
| QVERIFY(!child->isVisibleTo(stranger)); |
| QVERIFY(!parent->isVisibleTo(stranger)); |
| QVERIFY(!stranger->isVisibleTo(grandChild)); |
| QVERIFY(!stranger->isVisibleTo(child)); |
| QVERIFY(!stranger->isVisibleTo(parent)); |
| } |
| |
| void tst_QGraphicsItem::explicitlyVisible() |
| { |
| QGraphicsScene scene; |
| QGraphicsItem *parent = scene.addRect(QRectF(0, 0, 100, 100)); |
| QGraphicsItem *child = scene.addRect(QRectF(25, 25, 50, 50)); |
| child->setParentItem(parent); |
| |
| QVERIFY(parent->isVisible()); |
| QVERIFY(child->isVisible()); |
| |
| parent->hide(); |
| |
| QVERIFY(!parent->isVisible()); |
| QVERIFY(!child->isVisible()); |
| |
| parent->show(); |
| child->hide(); |
| |
| QVERIFY(parent->isVisible()); |
| QVERIFY(!child->isVisible()); |
| |
| parent->hide(); |
| |
| QVERIFY(!parent->isVisible()); |
| QVERIFY(!child->isVisible()); |
| |
| parent->show(); |
| |
| QVERIFY(parent->isVisible()); |
| QVERIFY(!child->isVisible()); // <- explicitly hidden |
| |
| child->show(); |
| |
| QVERIFY(child->isVisible()); |
| |
| parent->hide(); |
| |
| QVERIFY(!parent->isVisible()); |
| QVERIFY(!child->isVisible()); // <- explicit show doesn't work |
| |
| parent->show(); |
| |
| QVERIFY(parent->isVisible()); |
| QVERIFY(child->isVisible()); // <- no longer explicitly hidden |
| |
| // ------------------- Reparenting ------------------------------ |
| |
| QGraphicsItem *parent2 = scene.addRect(-50, -50, 200, 200); |
| QVERIFY(parent2->isVisible()); |
| |
| // Reparent implicitly hidden item to a visible parent. |
| parent->hide(); |
| QVERIFY(!parent->isVisible()); |
| QVERIFY(!child->isVisible()); |
| child->setParentItem(parent2); |
| QVERIFY(parent2->isVisible()); |
| QVERIFY(child->isVisible()); |
| |
| // Reparent implicitly hidden item to a hidden parent. |
| child->setParentItem(parent); |
| parent2->hide(); |
| child->setParentItem(parent2); |
| QVERIFY(!parent2->isVisible()); |
| QVERIFY(!child->isVisible()); |
| |
| // Reparent explicitly hidden item to a visible parent. |
| child->hide(); |
| parent->show(); |
| child->setParentItem(parent); |
| QVERIFY(parent->isVisible()); |
| QVERIFY(!child->isVisible()); |
| |
| // Reparent explicitly hidden item to a hidden parent. |
| child->setParentItem(parent2); |
| QVERIFY(!parent2->isVisible()); |
| QVERIFY(!child->isVisible()); |
| |
| // Reparent explicitly hidden item to a visible parent. |
| parent->show(); |
| child->setParentItem(parent); |
| QVERIFY(parent->isVisible()); |
| QVERIFY(!child->isVisible()); |
| |
| // Reparent visible item to a hidden parent. |
| child->show(); |
| parent2->hide(); |
| child->setParentItem(parent2); |
| QVERIFY(!parent2->isVisible()); |
| QVERIFY(!child->isVisible()); |
| parent2->show(); |
| QVERIFY(parent2->isVisible()); |
| QVERIFY(child->isVisible()); |
| |
| // Reparent implicitly hidden child to root. |
| parent2->hide(); |
| QVERIFY(!child->isVisible()); |
| child->setParentItem(0); |
| QVERIFY(child->isVisible()); |
| |
| // Reparent an explicitly hidden child to root. |
| child->hide(); |
| child->setParentItem(parent2); |
| parent2->show(); |
| QVERIFY(!child->isVisible()); |
| child->setParentItem(0); |
| QVERIFY(!child->isVisible()); |
| } |
| |
| void tst_QGraphicsItem::enabled() |
| { |
| QGraphicsRectItem *item = new QGraphicsRectItem(QRectF(-10, -10, 20, 20)); |
| item->setFlag(QGraphicsItem::ItemIsMovable); |
| QVERIFY(item->isEnabled()); |
| item->setEnabled(false); |
| QVERIFY(!item->isEnabled()); |
| item->setEnabled(true); |
| QVERIFY(item->isEnabled()); |
| item->setEnabled(false); |
| item->setFlag(QGraphicsItem::ItemIsFocusable); |
| QGraphicsScene scene; |
| QEvent activate(QEvent::WindowActivate); |
| QApplication::sendEvent(&scene, &activate); |
| |
| scene.addItem(item); |
| item->setFocus(); |
| QVERIFY(!item->hasFocus()); |
| item->setEnabled(true); |
| item->setFocus(); |
| QVERIFY(item->hasFocus()); |
| item->setEnabled(false); |
| QVERIFY(!item->hasFocus()); |
| |
| QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress); |
| event.setButton(Qt::LeftButton); |
| event.setScenePos(QPointF(0, 0)); |
| QApplication::sendEvent(&scene, &event); |
| QCOMPARE(scene.mouseGrabberItem(), nullptr); |
| item->setEnabled(true); |
| QApplication::sendEvent(&scene, &event); |
| QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)item); |
| item->setEnabled(false); |
| QCOMPARE(scene.mouseGrabberItem(), nullptr); |
| } |
| |
| void tst_QGraphicsItem::explicitlyEnabled() |
| { |
| QGraphicsScene scene; |
| QGraphicsItem *parent = scene.addRect(QRectF(0, 0, 100, 100)); |
| QGraphicsItem *child = scene.addRect(QRectF(25, 25, 50, 50)); |
| child->setParentItem(parent); |
| |
| QVERIFY(parent->isEnabled()); |
| QVERIFY(child->isEnabled()); |
| |
| parent->setEnabled(false); |
| |
| QVERIFY(!parent->isEnabled()); |
| QVERIFY(!child->isEnabled()); |
| |
| parent->setEnabled(true); |
| child->setEnabled(false); |
| |
| QVERIFY(parent->isEnabled()); |
| QVERIFY(!child->isEnabled()); |
| |
| parent->setEnabled(false); |
| |
| QVERIFY(!parent->isEnabled()); |
| QVERIFY(!child->isEnabled()); |
| |
| parent->setEnabled(true); |
| |
| QVERIFY(parent->isEnabled()); |
| QVERIFY(!child->isEnabled()); // <- explicitly disabled |
| |
| child->setEnabled(true); |
| |
| QVERIFY(child->isEnabled()); |
| |
| parent->setEnabled(false); |
| |
| QVERIFY(!parent->isEnabled()); |
| QVERIFY(!child->isEnabled()); // <- explicit enabled doesn't work |
| |
| parent->setEnabled(true); |
| |
| QVERIFY(parent->isEnabled()); |
| QVERIFY(child->isEnabled()); // <- no longer explicitly disabled |
| |
| // ------------------- Reparenting ------------------------------ |
| |
| QGraphicsItem *parent2 = scene.addRect(-50, -50, 200, 200); |
| QVERIFY(parent2->isEnabled()); |
| |
| // Reparent implicitly hidden item to a enabled parent. |
| parent->setEnabled(false); |
| QVERIFY(!parent->isEnabled()); |
| QVERIFY(!child->isEnabled()); |
| child->setParentItem(parent2); |
| QVERIFY(parent2->isEnabled()); |
| QVERIFY(child->isEnabled()); |
| |
| // Reparent implicitly hidden item to a hidden parent. |
| child->setParentItem(parent); |
| parent2->setEnabled(false); |
| child->setParentItem(parent2); |
| QVERIFY(!parent2->isEnabled()); |
| QVERIFY(!child->isEnabled()); |
| |
| // Reparent explicitly hidden item to a enabled parent. |
| child->setEnabled(false); |
| parent->setEnabled(true); |
| child->setParentItem(parent); |
| QVERIFY(parent->isEnabled()); |
| QVERIFY(!child->isEnabled()); |
| |
| // Reparent explicitly hidden item to a hidden parent. |
| child->setParentItem(parent2); |
| QVERIFY(!parent2->isEnabled()); |
| QVERIFY(!child->isEnabled()); |
| |
| // Reparent explicitly hidden item to a enabled parent. |
| parent->setEnabled(true); |
| child->setParentItem(parent); |
| QVERIFY(parent->isEnabled()); |
| QVERIFY(!child->isEnabled()); |
| |
| // Reparent enabled item to a hidden parent. |
| child->setEnabled(true); |
| parent2->setEnabled(false); |
| child->setParentItem(parent2); |
| QVERIFY(!parent2->isEnabled()); |
| QVERIFY(!child->isEnabled()); |
| parent2->setEnabled(true); |
| QVERIFY(parent2->isEnabled()); |
| QVERIFY(child->isEnabled()); |
| |
| // Reparent implicitly hidden child to root. |
| parent2->setEnabled(false); |
| QVERIFY(!child->isEnabled()); |
| child->setParentItem(0); |
| QVERIFY(child->isEnabled()); |
| |
| // Reparent an explicitly hidden child to root. |
| child->setEnabled(false); |
| child->setParentItem(parent2); |
| parent2->setEnabled(true); |
| QVERIFY(!child->isEnabled()); |
| child->setParentItem(0); |
| QVERIFY(!child->isEnabled()); |
| } |
| |
| class SelectChangeItem : public QGraphicsRectItem |
| { |
| public: |
| SelectChangeItem() : QGraphicsRectItem(-50, -50, 100, 100) { setBrush(Qt::blue); } |
| QList<bool> values; |
| |
| protected: |
| QVariant itemChange(GraphicsItemChange change, const QVariant &value) |
| { |
| if (change == ItemSelectedChange) |
| values << value.toBool(); |
| return QGraphicsRectItem::itemChange(change, value); |
| } |
| }; |
| |
| void tst_QGraphicsItem::selected() |
| { |
| SelectChangeItem *item = new SelectChangeItem; |
| item->setFlag(QGraphicsItem::ItemIsSelectable); |
| QVERIFY(!item->isSelected()); |
| QVERIFY(item->values.isEmpty()); |
| item->setSelected(true); |
| QCOMPARE(item->values.size(), 1); |
| QCOMPARE(item->values.last(), true); |
| QVERIFY(item->isSelected()); |
| item->setSelected(false); |
| QCOMPARE(item->values.size(), 2); |
| QCOMPARE(item->values.last(), false); |
| QVERIFY(!item->isSelected()); |
| item->setSelected(true); |
| QCOMPARE(item->values.size(), 3); |
| item->setEnabled(false); |
| QCOMPARE(item->values.size(), 4); |
| QCOMPARE(item->values.last(), false); |
| QVERIFY(!item->isSelected()); |
| item->setEnabled(true); |
| QCOMPARE(item->values.size(), 4); |
| item->setSelected(true); |
| QCOMPARE(item->values.size(), 5); |
| QCOMPARE(item->values.last(), true); |
| QVERIFY(item->isSelected()); |
| item->setVisible(false); |
| QCOMPARE(item->values.size(), 6); |
| QCOMPARE(item->values.last(), false); |
| QVERIFY(!item->isSelected()); |
| item->setVisible(true); |
| QCOMPARE(item->values.size(), 6); |
| item->setSelected(true); |
| QCOMPARE(item->values.size(), 7); |
| QCOMPARE(item->values.last(), true); |
| QVERIFY(item->isSelected()); |
| |
| QGraphicsScene scene(-100, -100, 200, 200); |
| scene.addItem(item); |
| QCOMPARE(scene.selectedItems(), QList<QGraphicsItem *>() << item); |
| item->setSelected(false); |
| QVERIFY(scene.selectedItems().isEmpty()); |
| item->setSelected(true); |
| QCOMPARE(scene.selectedItems(), QList<QGraphicsItem *>() << item); |
| item->setSelected(false); |
| QVERIFY(scene.selectedItems().isEmpty()); |
| |
| // Interactive selection |
| QGraphicsView view(&scene); |
| view.setFixedSize(250, 250); |
| view.show(); |
| |
| QVERIFY(QTest::qWaitForWindowExposed(&view)); |
| qApp->processEvents(); |
| qApp->processEvents(); |
| |
| scene.clearSelection(); |
| QCOMPARE(item->values.size(), 10); |
| QCOMPARE(item->values.last(), false); |
| QVERIFY(!item->isSelected()); |
| |
| // Click inside and check that it's selected |
| QTest::mouseMove(view.viewport()); |
| QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item->scenePos())); |
| QCOMPARE(item->values.size(), 11); |
| QCOMPARE(item->values.last(), true); |
| QVERIFY(item->isSelected()); |
| |
| // Click outside and check that it's not selected |
| QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item->scenePos() + QPointF(item->boundingRect().width(), item->boundingRect().height()))); |
| QCOMPARE(item->values.size(), 12); |
| QCOMPARE(item->values.last(), false); |
| QVERIFY(!item->isSelected()); |
| |
| SelectChangeItem *item2 = new SelectChangeItem; |
| item2->setFlag(QGraphicsItem::ItemIsSelectable); |
| item2->setPos(100, 0); |
| scene.addItem(item2); |
| |
| // Click inside and check that it's selected |
| QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item->scenePos())); |
| QCOMPARE(item->values.size(), 13); |
| QCOMPARE(item->values.last(), true); |
| QVERIFY(item->isSelected()); |
| |
| // Click inside item2 and check that it's selected, and item is not |
| QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item2->scenePos())); |
| QCOMPARE(item->values.size(), 14); |
| QCOMPARE(item->values.last(), false); |
| QVERIFY(!item->isSelected()); |
| QCOMPARE(item2->values.size(), 1); |
| QCOMPARE(item2->values.last(), true); |
| QVERIFY(item2->isSelected()); |
| } |
| |
| void tst_QGraphicsItem::selected2() |
| { |
| // Selecting an item, then moving another previously caused a crash. |
| QGraphicsScene scene; |
| QGraphicsItem *line1 = scene.addRect(QRectF(0, 0, 100, 100)); |
| line1->setPos(-105, 0); |
| line1->setFlag(QGraphicsItem::ItemIsSelectable); |
| |
| QGraphicsItem *line2 = scene.addRect(QRectF(0, 0, 100, 100)); |
| line2->setFlag(QGraphicsItem::ItemIsMovable); |
| |
| line1->setSelected(true); |
| |
| { |
| QGraphicsSceneMouseEvent mousePress(QEvent::GraphicsSceneMousePress); |
| mousePress.setScenePos(QPointF(50, 50)); |
| mousePress.setButton(Qt::LeftButton); |
| QApplication::sendEvent(&scene, &mousePress); |
| QVERIFY(mousePress.isAccepted()); |
| } |
| { |
| QGraphicsSceneMouseEvent mouseMove(QEvent::GraphicsSceneMouseMove); |
| mouseMove.setScenePos(QPointF(60, 60)); |
| mouseMove.setButton(Qt::LeftButton); |
| mouseMove.setButtons(Qt::LeftButton); |
| QApplication::sendEvent(&scene, &mouseMove); |
| QVERIFY(mouseMove.isAccepted()); |
| } |
| } |
| |
| void tst_QGraphicsItem::selected_group() |
| { |
| QGraphicsScene scene; |
| QGraphicsItem *item1 = scene.addRect(QRectF()); |
| QGraphicsItem *item2 = scene.addRect(QRectF()); |
| item1->setFlag(QGraphicsItem::ItemIsSelectable); |
| item2->setFlag(QGraphicsItem::ItemIsSelectable); |
| scene.addRect(QRectF())->setParentItem(item1); |
| QGraphicsItem *leaf = scene.addRect(QRectF()); |
| leaf->setFlag(QGraphicsItem::ItemIsSelectable); |
| leaf->setParentItem(item2); |
| |
| QGraphicsItemGroup *group = scene.createItemGroup(QList<QGraphicsItem *>() << item1 << item2); |
| QCOMPARE(group->scene(), &scene); |
| group->setFlag(QGraphicsItem::ItemIsSelectable); |
| foreach (QGraphicsItem *item, scene.items()) { |
| if (item == group) |
| QVERIFY(!item->group()); |
| else |
| QCOMPARE(item->group(), group); |
| } |
| |
| QVERIFY(group->handlesChildEvents()); |
| QVERIFY(!group->isSelected()); |
| group->setSelected(false); |
| QVERIFY(!group->isSelected()); |
| group->setSelected(true); |
| QVERIFY(group->isSelected()); |
| foreach (QGraphicsItem *item, scene.items()) |
| QVERIFY(item->isSelected()); |
| group->setSelected(false); |
| QVERIFY(!group->isSelected()); |
| foreach (QGraphicsItem *item, scene.items()) |
| QVERIFY(!item->isSelected()); |
| leaf->setSelected(true); |
| foreach (QGraphicsItem *item, scene.items()) |
| QVERIFY(item->isSelected()); |
| leaf->setSelected(false); |
| foreach (QGraphicsItem *item, scene.items()) |
| QVERIFY(!item->isSelected()); |
| |
| leaf->setSelected(true); |
| QGraphicsScene scene2; |
| scene2.addItem(item1); |
| QVERIFY(!item1->isSelected()); |
| QVERIFY(item2->isSelected()); |
| } |
| |
| void tst_QGraphicsItem::selected_textItem() |
| { |
| QGraphicsScene scene; |
| QGraphicsTextItem *text = scene.addText(QLatin1String("Text")); |
| text->setFlag(QGraphicsItem::ItemIsSelectable); |
| |
| QGraphicsView view(&scene); |
| view.show(); |
| QVERIFY(QTest::qWaitForWindowExposed(&view)); |
| |
| QTRY_VERIFY(!text->isSelected()); |
| QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, |
| view.mapFromScene(text->mapToScene(0, 0))); |
| QTRY_VERIFY(text->isSelected()); |
| |
| text->setSelected(false); |
| text->setTextInteractionFlags(Qt::TextEditorInteraction); |
| |
| QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, |
| view.mapFromScene(text->mapToScene(0, 0))); |
| QTRY_VERIFY(text->isSelected()); |
| } |
| |
| void tst_QGraphicsItem::selected_multi() |
| { |
| // Test multiselection behavior |
| QGraphicsScene scene; |
| |
| // Create two disjoint items |
| QGraphicsItem *item1 = scene.addRect(QRectF(-10, -10, 20, 20)); |
| QGraphicsItem *item2 = scene.addRect(QRectF(-10, -10, 20, 20)); |
| item1->setPos(-15, 0); |
| item2->setPos(15, 20); |
| |
| // Make both items selectable |
| item1->setFlag(QGraphicsItem::ItemIsSelectable); |
| item2->setFlag(QGraphicsItem::ItemIsSelectable); |
| |
| // Create and show a view |
| QGraphicsView view(&scene); |
| view.show(); |
| view.fitInView(scene.sceneRect()); |
| QVERIFY(QTest::qWaitForWindowActive(&view)); |
| |
| QVERIFY(!item1->isSelected()); |
| QVERIFY(!item2->isSelected()); |
| |
| // Click on item1 |
| QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item1->scenePos())); |
| QVERIFY(item1->isSelected()); |
| QVERIFY(!item2->isSelected()); |
| |
| // Click on item2 |
| QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item2->scenePos())); |
| QVERIFY(item2->isSelected()); |
| QVERIFY(!item1->isSelected()); |
| |
| // Ctrl-click on item1 |
| QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(item1->scenePos())); |
| QVERIFY(item2->isSelected()); |
| QVERIFY(item1->isSelected()); |
| |
| // Ctrl-click on item1 again |
| QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(item1->scenePos())); |
| QVERIFY(item2->isSelected()); |
| QVERIFY(!item1->isSelected()); |
| |
| // Ctrl-click on item2 |
| QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(item2->scenePos())); |
| QVERIFY(!item2->isSelected()); |
| QVERIFY(!item1->isSelected()); |
| |
| // Click on item1 |
| QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item1->scenePos())); |
| QVERIFY(item1->isSelected()); |
| QVERIFY(!item2->isSelected()); |
| |
| // Click on scene |
| QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(0, 0)); |
| QVERIFY(!item1->isSelected()); |
| QVERIFY(!item2->isSelected()); |
| |
| // Click on item1 |
| QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item1->scenePos())); |
| QVERIFY(item1->isSelected()); |
| QVERIFY(!item2->isSelected()); |
| |
| // Ctrl-click on scene |
| QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(0, 0)); |
| QVERIFY(item1->isSelected()); |
| QVERIFY(!item2->isSelected()); |
| |
| // Click on scene |
| QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(0, 0)); |
| QVERIFY(!item1->isSelected()); |
| QVERIFY(!item2->isSelected()); |
| |
| // Click on item1 |
| QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item1->scenePos())); |
| QVERIFY(item1->isSelected()); |
| QVERIFY(!item2->isSelected()); |
| |
| // Press on item2 |
| QTest::mousePress(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item2->scenePos())); |
| QVERIFY(!item1->isSelected()); |
| QVERIFY(item2->isSelected()); |
| |
| // Release on item2 |
| QTest::mouseRelease(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item2->scenePos())); |
| QVERIFY(!item1->isSelected()); |
| QVERIFY(item2->isSelected()); |
| |
| // Click on item1 |
| QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item1->scenePos())); |
| QVERIFY(item1->isSelected()); |
| QVERIFY(!item2->isSelected()); |
| |
| // Ctrl-click on item1 |
| QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(item1->scenePos())); |
| QVERIFY(!item1->isSelected()); |
| QVERIFY(!item2->isSelected()); |
| |
| // Ctrl-press on item1 |
| QTest::mousePress(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(item1->scenePos())); |
| QVERIFY(!item1->isSelected()); |
| QVERIFY(!item2->isSelected()); |
| |
| { |
| // Ctrl-move on item1 |
| const QPoint item1Point = view.mapFromScene(item1->scenePos()) + QPoint(1, 0); |
| QMouseEvent event(QEvent::MouseMove, item1Point, view.viewport()->mapToGlobal(item1Point), Qt::LeftButton, Qt::LeftButton, Qt::ControlModifier); |
| QApplication::sendEvent(view.viewport(), &event); |
| QVERIFY(!item1->isSelected()); |
| QVERIFY(!item2->isSelected()); |
| } |
| |
| // Release on item1 |
| QTest::mouseRelease(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(item1->scenePos())); |
| QVERIFY(item1->isSelected()); |
| QVERIFY(!item2->isSelected()); |
| |
| item1->setFlag(QGraphicsItem::ItemIsMovable); |
| item1->setSelected(false); |
| |
| // Ctrl-press on item1 |
| QTest::mousePress(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(item1->scenePos())); |
| QVERIFY(!item1->isSelected()); |
| QVERIFY(!item2->isSelected()); |
| |
| { |
| // Ctrl-move on item1 |
| const QPoint item1Point = view.mapFromScene(item1->scenePos()) + QPoint(1, 0); |
| QMouseEvent event(QEvent::MouseMove, item1Point, view.viewport()->mapToGlobal(item1Point), Qt::LeftButton, Qt::LeftButton, Qt::ControlModifier); |
| QApplication::sendEvent(view.viewport(), &event); |
| QVERIFY(item1->isSelected()); |
| QVERIFY(!item2->isSelected()); |
| } |
| |
| // Release on item1 |
| QTest::mouseRelease(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(item1->scenePos())); |
| QVERIFY(item1->isSelected()); |
| QVERIFY(!item2->isSelected()); |
| } |
| |
| void tst_QGraphicsItem::acceptedMouseButtons() |
| { |
| QGraphicsScene scene; |
| QGraphicsRectItem *item1 = scene.addRect(QRectF(-10, -10, 20, 20)); |
| QGraphicsRectItem *item2 = scene.addRect(QRectF(-10, -10, 20, 20)); |
| item2->setZValue(1); |
| |
| item1->setFlag(QGraphicsItem::ItemIsMovable); |
| item2->setFlag(QGraphicsItem::ItemIsMovable); |
| |
| QCOMPARE(item1->acceptedMouseButtons(), Qt::MouseButtons(0x1f)); |
| QCOMPARE(item2->acceptedMouseButtons(), Qt::MouseButtons(0x1f)); |
| |
| QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress); |
| event.setButton(Qt::LeftButton); |
| event.setScenePos(QPointF(0, 0)); |
| QApplication::sendEvent(&scene, &event); |
| QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)item2); |
| item2->setAcceptedMouseButtons(0); |
| QCOMPARE(scene.mouseGrabberItem(), nullptr); |
| QApplication::sendEvent(&scene, &event); |
| QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)item1); |
| } |
| |
| class HoverItem : public QGraphicsRectItem |
| { |
| public: |
| HoverItem(const QRectF &rect) |
| : QGraphicsRectItem(rect), hoverInCount(0), |
| hoverMoveCount(0), hoverOutCount(0) |
| { } |
| |
| int hoverInCount; |
| int hoverMoveCount; |
| int hoverOutCount; |
| protected: |
| void hoverEnterEvent(QGraphicsSceneHoverEvent *) |
| { ++hoverInCount; } |
| |
| void hoverMoveEvent(QGraphicsSceneHoverEvent *) |
| { ++hoverMoveCount; } |
| |
| void hoverLeaveEvent(QGraphicsSceneHoverEvent *) |
| { ++hoverOutCount; } |
| }; |
| |
| void tst_QGraphicsItem::acceptHoverEvents() |
| { |
| QGraphicsScene scene; |
| HoverItem *item1 = new HoverItem(QRectF(-10, -10, 20, 20)); |
| HoverItem *item2 = new HoverItem(QRectF(-5, -5, 10, 10)); |
| scene.addItem(item1); |
| scene.addItem(item2); |
| item2->setZValue(1); |
| |
| QVERIFY(!item1->acceptHoverEvents()); |
| QVERIFY(!item2->acceptHoverEvents()); |
| item1->setAcceptHoverEvents(true); |
| item2->setAcceptHoverEvents(true); |
| |
| QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseMove); |
| event.setScenePos(QPointF(-100, -100)); |
| QApplication::sendEvent(&scene, &event); |
| event.setScenePos(QPointF(-2.5, -2.5)); |
| QApplication::sendEvent(&scene, &event); |
| |
| QCOMPARE(item1->hoverInCount, 0); |
| QCOMPARE(item2->hoverInCount, 1); |
| |
| item1->setAcceptHoverEvents(false); |
| item2->setAcceptHoverEvents(false); |
| |
| event.setScenePos(QPointF(-100, -100)); |
| QApplication::sendEvent(&scene, &event); |
| event.setScenePos(QPointF(-2.5, -2.5)); |
| QApplication::sendEvent(&scene, &event); |
| |
| QCOMPARE(item1->hoverInCount, 0); |
| QCOMPARE(item2->hoverInCount, 1); |
| |
| item1->setAcceptHoverEvents(true); |
| item2->setAcceptHoverEvents(false); |
| |
| event.setScenePos(QPointF(-100, -100)); |
| QApplication::sendEvent(&scene, &event); |
| event.setScenePos(QPointF(-2.5, -2.5)); |
| QApplication::sendEvent(&scene, &event); |
| |
| QCOMPARE(item1->hoverInCount, 1); |
| QCOMPARE(item2->hoverInCount, 1); |
| } |
| |
| void tst_QGraphicsItem::childAcceptsHoverEvents() |
| { |
| QGraphicsScene scene; |
| HoverItem *item1 = new HoverItem(QRectF(-10, -10, 20, 20)); |
| HoverItem *item2 = new HoverItem(QRectF(-5, -5, 10, 10)); |
| |
| scene.addItem(item1); |
| scene.addItem(item2); |
| item2->setParentItem(item1); |
| item2->setAcceptHoverEvents(true); |
| |
| QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseMove); |
| event.setScenePos(QPointF(-100, -100)); |
| QApplication::sendEvent(&scene, &event); |
| QCOMPARE(item2->hoverInCount, 0); |
| QCOMPARE(item2->hoverMoveCount, 0); |
| QCOMPARE(item2->hoverOutCount, 0); |
| QCOMPARE(item1->hoverInCount, 0); |
| QCOMPARE(item1->hoverMoveCount, 0); |
| QCOMPARE(item1->hoverOutCount, 0); |
| |
| event.setScenePos(QPointF(-2.5, -2.5)); |
| QApplication::sendEvent(&scene, &event); |
| |
| QCOMPARE(item2->hoverInCount, 1); |
| QCOMPARE(item2->hoverMoveCount, 1); |
| QCOMPARE(item2->hoverOutCount, 0); |
| QCOMPARE(item1->hoverInCount, 0); |
| QCOMPARE(item1->hoverMoveCount, 0); |
| QCOMPARE(item1->hoverOutCount, 0); |
| |
| event.setScenePos(QPointF(0, 0)); |
| QApplication::sendEvent(&scene, &event); |
| |
| QCOMPARE(item2->hoverInCount, 1); |
| QCOMPARE(item2->hoverMoveCount, 2); |
| QCOMPARE(item2->hoverOutCount, 0); |
| QCOMPARE(item1->hoverInCount, 0); |
| QCOMPARE(item1->hoverMoveCount, 0); |
| QCOMPARE(item1->hoverOutCount, 0); |
| |
| event.setScenePos(QPointF(-7, -7)); |
| QApplication::sendEvent(&scene, &event); |
| |
| QCOMPARE(item2->hoverInCount, 1); |
| QCOMPARE(item2->hoverMoveCount, 2); |
| QCOMPARE(item2->hoverOutCount, 1); |
| QCOMPARE(item1->hoverInCount, 0); |
| QCOMPARE(item1->hoverMoveCount, 0); |
| QCOMPARE(item1->hoverOutCount, 0); |
| |
| event.setScenePos(QPointF(0, 0)); |
| QApplication::sendEvent(&scene, &event); |
| |
| QCOMPARE(item2->hoverInCount, 2); |
| QCOMPARE(item2->hoverMoveCount, 3); |
| QCOMPARE(item2->hoverOutCount, 1); |
| QCOMPARE(item1->hoverInCount, 0); |
| QCOMPARE(item1->hoverMoveCount, 0); |
| QCOMPARE(item1->hoverOutCount, 0); |
| |
| HoverItem *item0 = new HoverItem(QRectF(-20, -20, 20, 20)); |
| scene.addItem(item0); |
| item1->setParentItem(item0); |
| item0->setAcceptHoverEvents(true); |
| |
| event.setScenePos(QPointF(-100, -100)); |
| QApplication::sendEvent(&scene, &event); |
| |
| event.setScenePos(QPointF(-15, -15)); |
| QApplication::sendEvent(&scene, &event); |
| |
| QCOMPARE(item2->hoverInCount, 2); |
| QCOMPARE(item2->hoverMoveCount, 3); |
| QCOMPARE(item2->hoverOutCount, 2); |
| QCOMPARE(item1->hoverInCount, 0); |
| QCOMPARE(item1->hoverMoveCount, 0); |
| QCOMPARE(item1->hoverOutCount, 0); |
| QCOMPARE(item0->hoverInCount, 1); |
| QCOMPARE(item0->hoverMoveCount, 1); |
| QCOMPARE(item0->hoverOutCount, 0); |
| } |
| |
| void tst_QGraphicsItem::hasFocus() |
| { |
| QGraphicsLineItem *line = new QGraphicsLineItem; |
| QVERIFY(!line->hasFocus()); |
| line->setFocus(); |
| QVERIFY(!line->hasFocus()); |
| |
| QGraphicsScene scene; |
| QEvent activate(QEvent::WindowActivate); |
| QApplication::sendEvent(&scene, &activate); |
| |
| scene.addItem(line); |
| |
| line->setFocus(); |
| QVERIFY(!line->hasFocus()); |
| line->setFlag(QGraphicsItem::ItemIsFocusable); |
| line->setFocus(); |
| QVERIFY(line->hasFocus()); |
| |
| QGraphicsScene scene2; |
| QApplication::sendEvent(&scene2, &activate); |
| |
| scene2.addItem(line); |
| QVERIFY(!line->hasFocus()); |
| |
| QCOMPARE(scene.focusItem(), nullptr); |
| QCOMPARE(scene2.focusItem(), nullptr); |
| |
| line->setFocus(); |
| QVERIFY(line->hasFocus()); |
| line->clearFocus(); |
| QVERIFY(!line->hasFocus()); |
| |
| QGraphicsLineItem *line2 = new QGraphicsLineItem; |
| line2->setFlag(QGraphicsItem::ItemIsFocusable); |
| scene2.addItem(line2); |
| |
| line2->setFocus(); |
| QVERIFY(!line->hasFocus()); |
| QVERIFY(line2->hasFocus()); |
| line->setFocus(); |
| QVERIFY(line->hasFocus()); |
| QVERIFY(!line2->hasFocus()); |
| } |
| |
| void tst_QGraphicsItem::pos() |
| { |
| QGraphicsItem *child = new QGraphicsLineItem; |
| QGraphicsItem *parent = new QGraphicsLineItem; |
| |
| QCOMPARE(child->pos(), QPointF()); |
| QCOMPARE(parent->pos(), QPointF()); |
| |
| child->setParentItem(parent); |
| child->setPos(10, 10); |
| |
| QCOMPARE(child->pos(), QPointF(10, 10)); |
| |
| parent->setPos(10, 10); |
| |
| QCOMPARE(parent->pos(), QPointF(10, 10)); |
| QCOMPARE(child->pos(), QPointF(10, 10)); |
| |
| delete child; |
| delete parent; |
| } |
| |
| void tst_QGraphicsItem::scenePos() |
| { |
| QGraphicsItem *child = new QGraphicsLineItem; |
| QGraphicsItem *parent = new QGraphicsLineItem; |
| |
| QCOMPARE(child->scenePos(), QPointF()); |
| QCOMPARE(parent->scenePos(), QPointF()); |
| |
| child->setParentItem(parent); |
| child->setPos(10, 10); |
| |
| QCOMPARE(child->scenePos(), QPointF(10, 10)); |
| |
| parent->setPos(10, 10); |
| |
| QCOMPARE(parent->scenePos(), QPointF(10, 10)); |
| QCOMPARE(child->scenePos(), QPointF(20, 20)); |
| |
| parent->setPos(20, 20); |
| |
| QCOMPARE(parent->scenePos(), QPointF(20, 20)); |
| QCOMPARE(child->scenePos(), QPointF(30, 30)); |
| |
| delete child; |
| delete parent; |
| } |
| |
| void tst_QGraphicsItem::matrix() |
| { |
| QGraphicsLineItem line; |
| QCOMPARE(line.transform(), QTransform()); |
| line.setTransform(QTransform().rotate(90)); |
| QCOMPARE(line.transform(), QTransform().rotate(90)); |
| line.setTransform(QTransform().rotate(90)); |
| QCOMPARE(line.transform(), QTransform().rotate(90)); |
| line.setTransform(QTransform().rotate(90), true); |
| QCOMPARE(line.transform(), QTransform().rotate(180)); |
| line.setTransform(QTransform().rotate(-90), true); |
| QCOMPARE(line.transform(), QTransform().rotate(90)); |
| line.resetTransform(); |
| QCOMPARE(line.transform(), QTransform()); |
| |
| line.setTransform(QTransform().rotate(90), true); |
| QCOMPARE(line.transform(), QTransform().rotate(90)); |
| line.setTransform(QTransform().rotate(90), true); |
| QCOMPARE(line.transform(), QTransform().rotate(90).rotate(90)); |
| line.resetTransform(); |
| |
| line.setTransform(QTransform::fromScale(2, 4), true); |
| QCOMPARE(line.transform(), QTransform::fromScale(2, 4)); |
| line.setTransform(QTransform::fromScale(2, 4), true); |
| QCOMPARE(line.transform(), QTransform::fromScale(2, 4).scale(2, 4)); |
| line.resetTransform(); |
| |
| line.setTransform(QTransform().shear(2, 4), true); |
| QCOMPARE(line.transform(), QTransform().shear(2, 4)); |
| line.setTransform(QTransform().shear(2, 4), true); |
| QCOMPARE(line.transform(), QTransform().shear(2, 4).shear(2, 4)); |
| line.resetTransform(); |
| |
| line.setTransform(QTransform::fromTranslate(10, 10), true); |
| QCOMPARE(line.transform(), QTransform::fromTranslate(10, 10)); |
| line.setTransform(QTransform::fromTranslate(10, 10), true); |
| QCOMPARE(line.transform(), QTransform::fromTranslate(10, 10).translate(10, 10)); |
| line.resetTransform(); |
| } |
| |
| void tst_QGraphicsItem::sceneTransform() |
| { |
| QGraphicsLineItem *parent = new QGraphicsLineItem; |
| QGraphicsLineItem *child = new QGraphicsLineItem(QLineF(), parent); |
| |
| QCOMPARE(parent->sceneTransform(), QTransform()); |
| QCOMPARE(child->sceneTransform(), QTransform()); |
| |
| parent->setTransform(QTransform::fromTranslate(10, 10), true); |
| QCOMPARE(parent->sceneTransform(), QTransform().translate(10, 10)); |
| QCOMPARE(child->sceneTransform(), QTransform().translate(10, 10)); |
| |
| child->setTransform(QTransform::fromTranslate(10, 10), true); |
| QCOMPARE(parent->sceneTransform(), QTransform().translate(10, 10)); |
| QCOMPARE(child->sceneTransform(), QTransform().translate(20, 20)); |
| |
| parent->setTransform(QTransform().rotate(90), true); |
| QCOMPARE(parent->sceneTransform(), QTransform().translate(10, 10).rotate(90)); |
| QCOMPARE(child->sceneTransform(), QTransform().translate(10, 10).rotate(90).translate(10, 10)); |
| |
| delete child; |
| delete parent; |
| } |
| |
| void tst_QGraphicsItem::setTransform() |
| { |
| QGraphicsScene scene; |
| QSignalSpy spy(&scene, SIGNAL(changed(QList<QRectF>))); |
| QRectF unrotatedRect(-12, -34, 56, 78); |
| QGraphicsRectItem item(unrotatedRect, 0); |
| item.setPen(QPen(Qt::black, 0)); |
| scene.addItem(&item); |
| scene.update(scene.sceneRect()); |
| QApplication::instance()->processEvents(); |
| |
| QCOMPARE(spy.count(), 1); |
| |
| item.setTransform(QTransform().rotate(qreal(12.34))); |
| QRectF rotatedRect = scene.sceneRect(); |
| QVERIFY(unrotatedRect != rotatedRect); |
| scene.update(scene.sceneRect()); |
| QApplication::instance()->processEvents(); |
| |
| QCOMPARE(spy.count(), 2); |
| |
| item.setTransform(QTransform()); |
| |
| scene.update(scene.sceneRect()); |
| QApplication::instance()->processEvents(); |
| |
| QCOMPARE(spy.count(), 3); |
| QList<QRectF> rlist = qvariant_cast<QList<QRectF> >(spy.last().at(0)); |
| |
| QCOMPARE(rlist.size(), 2); |
| // From item.setMatrix() (clearing rotated rect), from scene.update() (updating scene rect), |
| // squashed into one |
| QCOMPARE(rlist.at(0), rotatedRect); |
| QCOMPARE(rlist.at(1), unrotatedRect); // From post-update (update current state) |
| } |
| |
| static QList<QGraphicsItem *> _paintedItems; |
| class PainterItem : public QGraphicsItem |
| { |
| protected: |
| QRectF boundingRect() const |
| { return QRectF(-10, -10, 20, 20); } |
| |
| void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) |
| { _paintedItems << this; painter->fillRect(boundingRect(), Qt::red); } |
| }; |
| |
| void tst_QGraphicsItem::zValue() |
| { |
| Q_CHECK_PAINTEVENTS |
| |
| QGraphicsScene scene; |
| |
| QGraphicsItem *item1 = new PainterItem; |
| QGraphicsItem *item2 = new PainterItem; |
| QGraphicsItem *item3 = new PainterItem; |
| QGraphicsItem *item4 = new PainterItem; |
| scene.addItem(item1); |
| scene.addItem(item2); |
| scene.addItem(item3); |
| scene.addItem(item4); |
| item2->setZValue(-3); |
| item4->setZValue(-2); |
| item1->setZValue(-1); |
| item3->setZValue(0); |
| |
| QGraphicsView view(&scene); |
| view.show(); |
| QVERIFY(QTest::qWaitForWindowExposed(&view)); |
| |
| QApplication::processEvents(); |
| |
| QTRY_VERIFY(!_paintedItems.isEmpty()); |
| QVERIFY((_paintedItems.size() % 4) == 0); |
| for (int i = 0; i < 3; ++i) |
| QVERIFY(_paintedItems.at(i)->zValue() < _paintedItems.at(i + 1)->zValue()); |
| } |
| |
| void tst_QGraphicsItem::shape() |
| { |
| QGraphicsLineItem line(QLineF(-10, -10, 20, 20)); |
| line.setPen(QPen(Qt::black, 0)); |
| |
| // We unfortunately need this hack as QPainterPathStroker will set a width of 1.0 |
| // if we pass a value of 0.0 to QPainterPathStroker::setWidth() |
| const qreal penWidthZero = qreal(0.00000001); |
| |
| QPainterPathStroker ps; |
| ps.setWidth(penWidthZero); |
| |
| QPainterPath path(line.line().p1()); |
| path.lineTo(line.line().p2()); |
| QPainterPath p = ps.createStroke(path); |
| p.addPath(path); |
| QCOMPARE(line.shape(), p); |
| |
| QPen linePen; |
| linePen.setWidthF(5.0); |
| linePen.setCapStyle(Qt::RoundCap); |
| line.setPen(linePen); |
| |
| ps.setCapStyle(line.pen().capStyle()); |
| ps.setWidth(line.pen().widthF()); |
| p = ps.createStroke(path); |
| p.addPath(path); |
| QCOMPARE(line.shape(), p); |
| |
| linePen.setCapStyle(Qt::FlatCap); |
| line.setPen(linePen); |
| ps.setCapStyle(line.pen().capStyle()); |
| p = ps.createStroke(path); |
| p.addPath(path); |
| QCOMPARE(line.shape(), p); |
| |
| linePen.setCapStyle(Qt::SquareCap); |
| line.setPen(linePen); |
| ps.setCapStyle(line.pen().capStyle()); |
| p = ps.createStroke(path); |
| p.addPath(path); |
| QCOMPARE(line.shape(), p); |
| |
| QGraphicsRectItem rect(QRectF(-10, -10, 20, 20)); |
| rect.setPen(QPen(Qt::black, 0)); |
| QPainterPathStroker ps1; |
| ps1.setWidth(penWidthZero); |
| path = QPainterPath(); |
| path.addRect(rect.rect()); |
| p = ps1.createStroke(path); |
| p.addPath(path); |
| QCOMPARE(rect.shape(), p); |
| |
| QGraphicsEllipseItem ellipse(QRectF(-10, -10, 20, 20)); |
| ellipse.setPen(QPen(Qt::black, 0)); |
| QPainterPathStroker ps2; |
| ps2.setWidth(ellipse.pen().widthF() <= 0.0 ? penWidthZero : ellipse.pen().widthF()); |
| path = QPainterPath(); |
| path.addEllipse(ellipse.rect()); |
| p = ps2.createStroke(path); |
| p.addPath(path); |
| QCOMPARE(ellipse.shape(), p); |
| |
| QPainterPathStroker ps3; |
| ps3.setWidth(penWidthZero); |
| p = ps3.createStroke(path); |
| p.addPath(path); |
| QGraphicsPathItem pathItem(path); |
| pathItem.setPen(QPen(Qt::black, 0)); |
| QCOMPARE(pathItem.shape(), p); |
| |
| QRegion region(QRect(0, 0, 300, 200)); |
| region = region.subtracted(QRect(50, 50, 200, 100)); |
| |
| QImage image(300, 200, QImage::Format_ARGB32_Premultiplied); |
| image.fill(0); |
| QPainter painter(&image); |
| painter.setClipRegion(region); |
| painter.fillRect(0, 0, 300, 200, Qt::green); |
| painter.end(); |
| QPixmap pixmap = QPixmap::fromImage(image); |
| |
| QGraphicsPixmapItem pixmapItem(pixmap); |
| path = QPainterPath(); |
| path.addRegion(region); |
| |
| { |
| QBitmap bitmap(300, 200); |
| bitmap.clear(); |
| QPainter painter(&bitmap); |
| painter.setClipRegion(region); |
| painter.fillRect(0, 0, 300, 200, Qt::color1); |
| painter.end(); |
| |
| QBitmap bitmap2(300, 200); |
| bitmap2.clear(); |
| painter.begin(&bitmap2); |
| painter.setClipPath(pixmapItem.shape()); |
| painter.fillRect(0, 0, 300, 200, Qt::color1); |
| painter.end(); |
| |
| QCOMPARE(bitmap.toImage(), bitmap2.toImage()); |
| } |
| |
| QPolygonF poly; |
| poly << QPointF(0, 0) << QPointF(10, 0) << QPointF(0, 10); |
| QGraphicsPolygonItem polygon(poly); |
| polygon.setPen(QPen(Qt::black, 0)); |
| path = QPainterPath(); |
| path.addPolygon(poly); |
| |
| QPainterPathStroker ps4; |
| ps4.setWidth(penWidthZero); |
| p = ps4.createStroke(path); |
| p.addPath(path); |
| QCOMPARE(polygon.shape(), p); |
| } |
| |
| void tst_QGraphicsItem::contains() |
| { |
| if (sizeof(qreal) != sizeof(double)) |
| QSKIP("Skipped due to rounding errors"); |
| |
| // Rect |
| QGraphicsRectItem rect(QRectF(-10, -10, 20, 20)); |
| QVERIFY(!rect.contains(QPointF(-11, -10))); |
| QVERIFY(rect.contains(QPointF(-10, -10))); |
| QVERIFY(!rect.contains(QPointF(-11, 0))); |
| QVERIFY(rect.contains(QPointF(-10, 0))); |
| QVERIFY(rect.contains(QPointF(0, -10))); |
| QVERIFY(rect.contains(QPointF(0, 0))); |
| QVERIFY(rect.contains(QPointF(9, 9))); |
| |
| // Ellipse |
| QGraphicsEllipseItem ellipse(QRectF(-10, -10, 20, 20)); |
| QVERIFY(!ellipse.contains(QPointF(-10, -10))); |
| QVERIFY(ellipse.contains(QPointF(-9, 0))); |
| QVERIFY(ellipse.contains(QPointF(0, -9))); |
| QVERIFY(ellipse.contains(QPointF(0, 0))); |
| QVERIFY(!ellipse.contains(QPointF(9, 9))); |
| |
| // Line |
| QGraphicsLineItem line(QLineF(-10, -10, 20, 20)); |
| QVERIFY(!line.contains(QPointF(-10, 0))); |
| QVERIFY(!line.contains(QPointF(0, -10))); |
| QVERIFY(!line.contains(QPointF(10, 0))); |
| QVERIFY(!line.contains(QPointF(0, 10))); |
| QVERIFY(line.contains(QPointF(0, 0))); |
| QVERIFY(line.contains(QPointF(-9, -9))); |
| QVERIFY(line.contains(QPointF(9, 9))); |
| |
| // Polygon |
| QGraphicsPolygonItem polygon(QPolygonF() |
| << QPointF(0, 0) |
| << QPointF(10, 0) |
| << QPointF(0, 10)); |
| QVERIFY(polygon.contains(QPointF(1, 1))); |
| QVERIFY(polygon.contains(QPointF(4, 4))); |
| QVERIFY(polygon.contains(QPointF(1, 4))); |
| QVERIFY(polygon.contains(QPointF(4, 1))); |
| QVERIFY(!polygon.contains(QPointF(8, 8))); |
| QVERIFY(polygon.contains(QPointF(1, 8))); |
| QVERIFY(polygon.contains(QPointF(8, 1))); |
| } |
| |
| void tst_QGraphicsItem::collidesWith_item() |
| { |
| // Rectangle |
| QGraphicsRectItem rect(QRectF(-10, -10, 20, 20)); |
| QGraphicsRectItem rect2(QRectF(-10, -10, 20, 20)); |
| QVERIFY(rect.collidesWithItem(&rect2)); |
| QVERIFY(rect2.collidesWithItem(&rect)); |
| rect2.setPos(21, 21); |
| QVERIFY(!rect.collidesWithItem(&rect2)); |
| QVERIFY(!rect2.collidesWithItem(&rect)); |
| rect2.setPos(-21, -21); |
| QVERIFY(!rect.collidesWithItem(&rect2)); |
| QVERIFY(!rect2.collidesWithItem(&rect)); |
| rect2.setPos(-17, -17); |
| QVERIFY(rect.collidesWithItem(&rect2)); |
| QVERIFY(rect2.collidesWithItem(&rect)); |
| |
| QGraphicsEllipseItem ellipse(QRectF(-10, -10, 20, 20)); |
| QGraphicsEllipseItem ellipse2(QRectF(-10, -10, 20, 20)); |
| QVERIFY(ellipse.collidesWithItem(&ellipse2)); |
| QVERIFY(ellipse2.collidesWithItem(&ellipse)); |
| ellipse2.setPos(21, 21); |
| QVERIFY(!ellipse.collidesWithItem(&ellipse2)); |
| QVERIFY(!ellipse2.collidesWithItem(&ellipse)); |
| ellipse2.setPos(-21, -21); |
| QVERIFY(!ellipse.collidesWithItem(&ellipse2)); |
| QVERIFY(!ellipse2.collidesWithItem(&ellipse)); |
| |
| ellipse2.setPos(-17, -17); |
| QVERIFY(!ellipse.collidesWithItem(&ellipse2)); |
| QVERIFY(!ellipse2.collidesWithItem(&ellipse)); |
| |
| { |
| QGraphicsScene scene; |
| QGraphicsRectItem rect(20, 20, 100, 100, 0); |
| scene.addItem(&rect); |
| QGraphicsRectItem rect2(40, 40, 50, 50, 0); |
| scene.addItem(&rect2); |
| rect2.setZValue(1); |
| QGraphicsLineItem line(0, 0, 200, 200, 0); |
| scene.addItem(&line); |
| line.setZValue(2); |
| |
| QCOMPARE(scene.items().size(), 3); |
| |
| QList<QGraphicsItem *> col1 = rect.collidingItems(); |
| QCOMPARE(col1.size(), 2); |
| QCOMPARE(col1.first(), static_cast<QGraphicsItem *>(&line)); |
| QCOMPARE(col1.last(), static_cast<QGraphicsItem *>(&rect2)); |
| |
| QList<QGraphicsItem *> col2 = rect2.collidingItems(); |
| QCOMPARE(col2.size(), 2); |
| QCOMPARE(col2.first(), static_cast<QGraphicsItem *>(&line)); |
| QCOMPARE(col2.last(), static_cast<QGraphicsItem *>(&rect)); |
| |
| QList<QGraphicsItem *> col3 = line.collidingItems(); |
| QCOMPARE(col3.size(), 2); |
| QCOMPARE(col3.first(), static_cast<QGraphicsItem *>(&rect2)); |
| QCOMPARE(col3.last(), static_cast<QGraphicsItem *>(&rect)); |
| } |
| } |
| |
| void tst_QGraphicsItem::collidesWith_path_data() |
| { |
| QTest::addColumn<QPointF>("pos"); |
| QTest::addColumn<QTransform>("transform"); |
| QTest::addColumn<QPainterPath>("shape"); |
| QTest::addColumn<bool>("rectCollides"); |
| QTest::addColumn<bool>("ellipseCollides"); |
| |
| QTest::newRow("nothing") << QPointF(0, 0) << QTransform() << QPainterPath() << false << false; |
| |
| QPainterPath rect; |
| rect.addRect(0, 0, 20, 20); |
| |
| QTest::newRow("rect1") << QPointF(0, 0) << QTransform() << rect << true << true; |
| QTest::newRow("rect2") << QPointF(0, 0) << QTransform::fromTranslate(21, 21) << rect << false << false; |
| QTest::newRow("rect3") << QPointF(21, 21) << QTransform() << rect << false << false; |
| } |
| |
| void tst_QGraphicsItem::collidesWith_path() |
| { |
| QFETCH(QPointF, pos); |
| QFETCH(QTransform, transform); |
| QFETCH(QPainterPath, shape); |
| QFETCH(bool, rectCollides); |
| QFETCH(bool, ellipseCollides); |
| |
| QGraphicsRectItem rect(QRectF(0, 0, 20, 20)); |
| QGraphicsEllipseItem ellipse(QRectF(0, 0, 20, 20)); |
| |
| rect.setPos(pos); |
| rect.setTransform(transform); |
| |
| ellipse.setPos(pos); |
| ellipse.setTransform(transform); |
| |
| QPainterPath mappedShape = rect.sceneTransform().inverted().map(shape); |
| |
| if (rectCollides) |
| QVERIFY(rect.collidesWithPath(mappedShape)); |
| else |
| QVERIFY(!rect.collidesWithPath(mappedShape)); |
| |
| if (ellipseCollides) |
| QVERIFY(ellipse.collidesWithPath(mappedShape)); |
| else |
| QVERIFY(!ellipse.collidesWithPath(mappedShape)); |
| } |
| |
| void tst_QGraphicsItem::collidesWithItemWithClip() |
| { |
| QGraphicsScene scene; |
| |
| QGraphicsEllipseItem *ellipse = scene.addEllipse(0, 0, 100, 100); |
| ellipse->setFlag(QGraphicsItem::ItemClipsChildrenToShape); |
| QGraphicsEllipseItem *ellipse2 = scene.addEllipse(0, 0, 10, 10); |
| ellipse2->setParentItem(ellipse); |
| QGraphicsEllipseItem *ellipse3 = scene.addEllipse(0, 0, 10, 10); |
| ellipse3->setParentItem(ellipse); |
| QGraphicsEllipseItem *ellipse5 = scene.addEllipse(50, 50, 10, 10); |
| ellipse5->setParentItem(ellipse); |
| QGraphicsEllipseItem *ellipse4 = scene.addEllipse(0, 0, 10, 10); |
| |
| QVERIFY(ellipse2->collidesWithItem(ellipse3)); |
| QVERIFY(ellipse3->collidesWithItem(ellipse2)); |
| QVERIFY(!ellipse2->collidesWithItem(ellipse)); |
| QVERIFY(!ellipse->collidesWithItem(ellipse2)); |
| QVERIFY(!ellipse4->collidesWithItem(ellipse)); |
| QVERIFY(!ellipse4->collidesWithItem(ellipse2)); |
| QVERIFY(!ellipse4->collidesWithItem(ellipse3)); |
| QVERIFY(!ellipse->collidesWithItem(ellipse4)); |
| QVERIFY(!ellipse2->collidesWithItem(ellipse4)); |
| QVERIFY(!ellipse3->collidesWithItem(ellipse4)); |
| QVERIFY(ellipse->collidesWithItem(ellipse5)); |
| QVERIFY(ellipse5->collidesWithItem(ellipse)); |
| } |
| |
| class MyItem : public QGraphicsEllipseItem |
| { |
| public: |
| bool isObscuredBy(const QGraphicsItem *item) const |
| { |
| const MyItem *myItem = qgraphicsitem_cast<const MyItem *>(item); |
| if (myItem) { |
| if (item->zValue() > zValue()) { |
| QRectF r = rect(); |
| QPointF topMid = (r.topRight()+r.topLeft())/2; |
| QPointF botMid = (r.bottomRight()+r.bottomLeft())/2; |
| QPointF leftMid = (r.topLeft()+r.bottomLeft())/2; |
| QPointF rightMid = (r.topRight()+r.bottomRight())/2; |
| |
| QPainterPath mappedShape = item->mapToItem(this, item->opaqueArea()); |
| |
| if (mappedShape.contains(topMid) && |
| mappedShape.contains(botMid) && |
| mappedShape.contains(leftMid) && |
| mappedShape.contains(rightMid)) |
| return true; |
| else |
| return false; |
| } |
| else return false; |
| } |
| else |
| return QGraphicsItem::isObscuredBy(item); |
| } |
| |
| QPainterPath opaqueArea() const |
| { |
| return shape(); |
| } |
| |
| enum { |
| Type = UserType+1 |
| }; |
| int type() const { return Type; } |
| }; |
| |
| void tst_QGraphicsItem::isObscuredBy() |
| { |
| QGraphicsScene scene; |
| |
| MyItem myitem1, myitem2; |
| |
| myitem1.setRect(QRectF(50, 50, 40, 200)); |
| myitem1.setTransform(QTransform().rotate(67), true); |
| |
| myitem2.setRect(QRectF(25, 25, 20, 20)); |
| myitem2.setZValue(-1.0); |
| scene.addItem(&myitem1); |
| scene.addItem(&myitem2); |
| |
| QVERIFY(!myitem2.isObscuredBy(&myitem1)); |
| QVERIFY(!myitem1.isObscuredBy(&myitem2)); |
| |
| myitem2.setRect(QRectF(-50, 85, 20, 20)); |
| QVERIFY(myitem2.isObscuredBy(&myitem1)); |
| QVERIFY(!myitem1.isObscuredBy(&myitem2)); |
| |
| myitem2.setRect(QRectF(-30, 70, 20, 20)); |
| QVERIFY(!myitem2.isObscuredBy(&myitem1)); |
| QVERIFY(!myitem1.isObscuredBy(&myitem2)); |
| |
| QGraphicsRectItem rect1, rect2; |
| |
| rect1.setRect(QRectF(-40, -40, 50, 50)); |
| rect1.setBrush(QBrush(Qt::red)); |
| rect2.setRect(QRectF(-30, -20, 20, 20)); |
| rect2.setZValue(-1.0); |
| rect2.setBrush(QBrush(Qt::blue)); |
| |
| QVERIFY(rect2.isObscuredBy(&rect1)); |
| QVERIFY(!rect1.isObscuredBy(&rect2)); |
| |
| rect2.setPos(QPointF(-20, -25)); |
| |
| QVERIFY(!rect2.isObscuredBy(&rect1)); |
| QVERIFY(!rect1.isObscuredBy(&rect2)); |
| |
| rect2.setPos(QPointF(-100, -100)); |
| |
| QVERIFY(!rect2.isObscuredBy(&rect1)); |
| QVERIFY(!rect1.isObscuredBy(&rect2)); |
| } |
| |
| class OpaqueItem : public QGraphicsRectItem |
| { |
| protected: |
| QPainterPath opaqueArea() const |
| { |
| return shape(); |
| } |
| }; |
| |
| void tst_QGraphicsItem::isObscured() |
| { |
| if (sizeof(qreal) != sizeof(double)) |
| QSKIP("Skipped due to rounding errors"); |
| |
| OpaqueItem *item1 = new OpaqueItem; |
| item1->setRect(0, 0, 100, 100); |
| item1->setZValue(0); |
| |
| OpaqueItem *item2 = new OpaqueItem; |
| item2->setZValue(1); |
| item2->setRect(0, 0, 100, 100); |
| |
| QGraphicsScene scene; |
| scene.addItem(item1); |
| scene.addItem(item2); |
| |
| QVERIFY(item1->isObscured()); |
| QVERIFY(item1->isObscuredBy(item2)); |
| QVERIFY(item1->isObscured(QRectF(0, 0, 50, 50))); |
| QVERIFY(item1->isObscured(QRectF(50, 0, 50, 50))); |
| QVERIFY(item1->isObscured(QRectF(50, 50, 50, 50))); |
| QVERIFY(item1->isObscured(QRectF(0, 50, 50, 50))); |
| QVERIFY(item1->isObscured(0, 0, 50, 50)); |
| QVERIFY(item1->isObscured(50, 0, 50, 50)); |
| QVERIFY(item1->isObscured(50, 50, 50, 50)); |
| QVERIFY(item1->isObscured(0, 50, 50, 50)); |
| QVERIFY(!item2->isObscured()); |
| QVERIFY(!item2->isObscuredBy(item1)); |
| QVERIFY(!item2->isObscured(QRectF(0, 0, 50, 50))); |
| QVERIFY(!item2->isObscured(QRectF(50, 0, 50, 50))); |
| QVERIFY(!item2->isObscured(QRectF(50, 50, 50, 50))); |
| QVERIFY(!item2->isObscured(QRectF(0, 50, 50, 50))); |
| QVERIFY(!item2->isObscured(0, 0, 50, 50)); |
| QVERIFY(!item2->isObscured(50, 0, 50, 50)); |
| QVERIFY(!item2->isObscured(50, 50, 50, 50)); |
| QVERIFY(!item2->isObscured(0, 50, 50, 50)); |
| |
| item2->moveBy(50, 0); |
| |
| QVERIFY(!item1->isObscured()); |
| QVERIFY(!item1->isObscuredBy(item2)); |
| QVERIFY(!item1->isObscured(QRectF(0, 0, 50, 50))); |
| QVERIFY(item1->isObscured(QRectF(50, 0, 50, 50))); |
| QVERIFY(item1->isObscured(QRectF(50, 50, 50, 50))); |
| QVERIFY(!item1->isObscured(QRectF(0, 50, 50, 50))); |
| QVERIFY(!item1->isObscured(0, 0, 50, 50)); |
| QVERIFY(item1->isObscured(50, 0, 50, 50)); |
| QVERIFY(item1->isObscured(50, 50, 50, 50)); |
| QVERIFY(!item1->isObscured(0, 50, 50, 50)); |
| QVERIFY(!item2->isObscured()); |
| QVERIFY(!item2->isObscuredBy(item1)); |
| QVERIFY(!item2->isObscured(QRectF(0, 0, 50, 50))); |
| QVERIFY(!item2->isObscured(QRectF(50, 0, 50, 50))); |
| QVERIFY(!item2->isObscured(QRectF(50, 50, 50, 50))); |
| QVERIFY(!item2->isObscured(QRectF(0, 50, 50, 50))); |
| QVERIFY(!item2->isObscured(0, 0, 50, 50)); |
| QVERIFY(!item2->isObscured(50, 0, 50, 50)); |
| QVERIFY(!item2->isObscured(50, 50, 50, 50)); |
| QVERIFY(!item2->isObscured(0, 50, 50, 50)); |
| } |
| |
| void tst_QGraphicsItem::mapFromToParent() |
| { |
| QPainterPath path1; |
| path1.addRect(0, 0, 200, 200); |
| |
| QPainterPath path2; |
| path2.addRect(0, 0, 100, 100); |
| |
| QPainterPath path3; |
| path3.addRect(0, 0, 50, 50); |
| |
| QPainterPath path4; |
| path4.addRect(0, 0, 25, 25); |
| |
| QGraphicsItem *item1 = new QGraphicsPathItem(path1); |
| QGraphicsItem *item2 = new QGraphicsPathItem(path2, item1); |
| QGraphicsItem *item3 = new QGraphicsPathItem(path3, item2); |
| QGraphicsItem *item4 = new QGraphicsPathItem(path4, item3); |
| |
| item1->setPos(10, 10); |
| item2->setPos(10, 10); |
| item3->setPos(10, 10); |
| item4->setPos(10, 10); |
| |
| for (int i = 0; i < 4; ++i) { |
| QTransform transform; |
| transform.rotate(i * 90); |
| transform.translate(i * 100, -i * 100); |
| transform.scale(2, 4); |
| item1->setTransform(transform); |
| |
| QCOMPARE(item1->mapToParent(QPointF(0, 0)), item1->pos() + transform.map(QPointF(0, 0))); |
| QCOMPARE(item2->mapToParent(QPointF(0, 0)), item2->pos()); |
| QCOMPARE(item3->mapToParent(QPointF(0, 0)), item3->pos()); |
| QCOMPARE(item4->mapToParent(QPointF(0, 0)), item4->pos()); |
| QCOMPARE(item1->mapToParent(QPointF(10, -10)), item1->pos() + transform.map(QPointF(10, -10))); |
| QCOMPARE(item2->mapToParent(QPointF(10, -10)), item2->pos() + QPointF(10, -10)); |
| QCOMPARE(item3->mapToParent(QPointF(10, -10)), item3->pos() + QPointF(10, -10)); |
| QCOMPARE(item4->mapToParent(QPointF(10, -10)), item4->pos() + QPointF(10, -10)); |
| QCOMPARE(item1->mapToParent(QPointF(-10, 10)), item1->pos() + transform.map(QPointF(-10, 10))); |
| QCOMPARE(item2->mapToParent(QPointF(-10, 10)), item2->pos() + QPointF(-10, 10)); |
| QCOMPARE(item3->mapToParent(QPointF(-10, 10)), item3->pos() + QPointF(-10, 10)); |
| QCOMPARE(item4->mapToParent(QPointF(-10, 10)), item4->pos() + QPointF(-10, 10)); |
| QCOMPARE(item1->mapFromParent(item1->pos()), transform.inverted().map(QPointF(0, 0))); |
| QCOMPARE(item2->mapFromParent(item2->pos()), QPointF(0, 0)); |
| QCOMPARE(item3->mapFromParent(item3->pos()), QPointF(0, 0)); |
| QCOMPARE(item4->mapFromParent(item4->pos()), QPointF(0, 0)); |
| QCOMPARE(item1->mapFromParent(item1->pos() + QPointF(10, -10)), |
| transform.inverted().map(QPointF(10, -10))); |
| QCOMPARE(item2->mapFromParent(item2->pos() + QPointF(10, -10)), QPointF(10, -10)); |
| QCOMPARE(item3->mapFromParent(item3->pos() + QPointF(10, -10)), QPointF(10, -10)); |
| QCOMPARE(item4->mapFromParent(item4->pos() + QPointF(10, -10)), QPointF(10, -10)); |
| QCOMPARE(item1->mapFromParent(item1->pos() + QPointF(-10, 10)), |
| transform.inverted().map(QPointF(-10, 10))); |
| QCOMPARE(item2->mapFromParent(item2->pos() + QPointF(-10, 10)), QPointF(-10, 10)); |
| QCOMPARE(item3->mapFromParent(item3->pos() + QPointF(-10, 10)), QPointF(-10, 10)); |
| QCOMPARE(item4->mapFromParent(item4->pos() + QPointF(-10, 10)), QPointF(-10, 10)); |
| } |
| |
| delete item1; |
| } |
| |
| void tst_QGraphicsItem::mapFromToScene() |
| { |
| QGraphicsItem *item1 = new QGraphicsPathItem(QPainterPath()); |
| QGraphicsItem *item2 = new QGraphicsPathItem(QPainterPath(), item1); |
| QGraphicsItem *item3 = new QGraphicsPathItem(QPainterPath(), item2); |
| QGraphicsItem *item4 = new QGraphicsPathItem(QPainterPath(), item3); |
| |
| item1->setPos(100, 100); |
| item2->setPos(100, 100); |
| item3->setPos(100, 100); |
| item4->setPos(100, 100); |
| QCOMPARE(item1->pos(), QPointF(100, 100)); |
| QCOMPARE(item2->pos(), QPointF(100, 100)); |
| QCOMPARE(item3->pos(), QPointF(100, 100)); |
| QCOMPARE(item4->pos(), QPointF(100, 100)); |
| QCOMPARE(item1->pos(), item1->mapToParent(0, 0)); |
| QCOMPARE(item2->pos(), item2->mapToParent(0, 0)); |
| QCOMPARE(item3->pos(), item3->mapToParent(0, 0)); |
| QCOMPARE(item4->pos(), item4->mapToParent(0, 0)); |
| QCOMPARE(item1->mapToParent(10, 10), QPointF(110, 110)); |
| QCOMPARE(item2->mapToParent(10, 10), QPointF(110, 110)); |
| QCOMPARE(item3->mapToParent(10, 10), QPointF(110, 110)); |
| QCOMPARE(item4->mapToParent(10, 10), QPointF(110, 110)); |
| QCOMPARE(item1->mapToScene(0, 0), QPointF(100, 100)); |
| QCOMPARE(item2->mapToScene(0, 0), QPointF(200, 200)); |
| QCOMPARE(item3->mapToScene(0, 0), QPointF(300, 300)); |
| QCOMPARE(item4->mapToScene(0, 0), QPointF(400, 400)); |
| QCOMPARE(item1->mapToScene(10, 0), QPointF(110, 100)); |
| QCOMPARE(item2->mapToScene(10, 0), QPointF(210, 200)); |
| QCOMPARE(item3->mapToScene(10, 0), QPointF(310, 300)); |
| QCOMPARE(item4->mapToScene(10, 0), QPointF(410, 400)); |
| QCOMPARE(item1->mapFromScene(100, 100), QPointF(0, 0)); |
| QCOMPARE(item2->mapFromScene(200, 200), QPointF(0, 0)); |
| QCOMPARE(item3->mapFromScene(300, 300), QPointF(0, 0)); |
| QCOMPARE(item4->mapFromScene(400, 400), QPointF(0, 0)); |
| QCOMPARE(item1->mapFromScene(110, 100), QPointF(10, 0)); |
| QCOMPARE(item2->mapFromScene(210, 200), QPointF(10, 0)); |
| QCOMPARE(item3->mapFromScene(310, 300), QPointF(10, 0)); |
| QCOMPARE(item4->mapFromScene(410, 400), QPointF(10, 0)); |
| |
| // Rotate item1 90 degrees clockwise |
| QTransform transform; transform.rotate(90); |
| item1->setTransform(transform); |
| QCOMPARE(item1->pos(), item1->mapToParent(0, 0)); |
| QCOMPARE(item2->pos(), item2->mapToParent(0, 0)); |
| QCOMPARE(item3->pos(), item3->mapToParent(0, 0)); |
| QCOMPARE(item4->pos(), item4->mapToParent(0, 0)); |
| QCOMPARE(item1->mapToParent(10, 0), QPointF(100, 110)); |
| QCOMPARE(item2->mapToParent(10, 0), QPointF(110, 100)); |
| QCOMPARE(item3->mapToParent(10, 0), QPointF(110, 100)); |
| QCOMPARE(item4->mapToParent(10, 0), QPointF(110, 100)); |
| QCOMPARE(item1->mapToScene(0, 0), QPointF(100, 100)); |
| QCOMPARE(item2->mapToScene(0, 0), QPointF(0, 200)); |
| QCOMPARE(item3->mapToScene(0, 0), QPointF(-100, 300)); |
| QCOMPARE(item4->mapToScene(0, 0), QPointF(-200, 400)); |
| QCOMPARE(item1->mapToScene(10, 0), QPointF(100, 110)); |
| QCOMPARE(item2->mapToScene(10, 0), QPointF(0, 210)); |
| QCOMPARE(item3->mapToScene(10, 0), QPointF(-100, 310)); |
| QCOMPARE(item4->mapToScene(10, 0), QPointF(-200, 410)); |
| QCOMPARE(item1->mapFromScene(100, 100), QPointF(0, 0)); |
| QCOMPARE(item2->mapFromScene(0, 200), QPointF(0, 0)); |
| QCOMPARE(item3->mapFromScene(-100, 300), QPointF(0, 0)); |
| QCOMPARE(item4->mapFromScene(-200, 400), QPointF(0, 0)); |
| QCOMPARE(item1->mapFromScene(100, 110), QPointF(10, 0)); |
| QCOMPARE(item2->mapFromScene(0, 210), QPointF(10, 0)); |
| QCOMPARE(item3->mapFromScene(-100, 310), QPointF(10, 0)); |
| QCOMPARE(item4->mapFromScene(-200, 410), QPointF(10, 0)); |
| |
| // Rotate item2 90 degrees clockwise |
| item2->setTransform(transform); |
| QCOMPARE(item1->pos(), item1->mapToParent(0, 0)); |
| QCOMPARE(item2->pos(), item2->mapToParent(0, 0)); |
| QCOMPARE(item3->pos(), item3->mapToParent(0, 0)); |
| QCOMPARE(item4->pos(), item4->mapToParent(0, 0)); |
| QCOMPARE(item1->mapToParent(10, 0), QPointF(100, 110)); |
| QCOMPARE(item2->mapToParent(10, 0), QPointF(100, 110)); |
| QCOMPARE(item3->mapToParent(10, 0), QPointF(110, 100)); |
| QCOMPARE(item4->mapToParent(10, 0), QPointF(110, 100)); |
| QCOMPARE(item1->mapToScene(0, 0), QPointF(100, 100)); |
| QCOMPARE(item2->mapToScene(0, 0), QPointF(0, 200)); |
| QCOMPARE(item3->mapToScene(0, 0), QPointF(-100, 100)); |
| QCOMPARE(item4->mapToScene(0, 0), QPointF(-200, 0)); |
| QCOMPARE(item1->mapToScene(10, 0), QPointF(100, 110)); |
| QCOMPARE(item2->mapToScene(10, 0), QPointF(-10, 200)); |
| QCOMPARE(item3->mapToScene(10, 0), QPointF(-110, 100)); |
| QCOMPARE(item4->mapToScene(10, 0), QPointF(-210, 0)); |
| QCOMPARE(item1->mapFromScene(100, 100), QPointF(0, 0)); |
| QCOMPARE(item2->mapFromScene(0, 200), QPointF(0, 0)); |
| QCOMPARE(item3->mapFromScene(-100, 100), QPointF(0, 0)); |
| QCOMPARE(item4->mapFromScene(-200, 0), QPointF(0, 0)); |
| QCOMPARE(item1->mapFromScene(100, 110), QPointF(10, 0)); |
| QCOMPARE(item2->mapFromScene(-10, 200), QPointF(10, 0)); |
| QCOMPARE(item3->mapFromScene(-110, 100), QPointF(10, 0)); |
| QCOMPARE(item4->mapFromScene(-210, 0), QPointF(10, 0)); |
| |
| // Translate item3 50 points, then rotate 90 degrees counterclockwise |
| QTransform transform2; |
| transform2.translate(50, 0); |
| transform2.rotate(-90); |
| item3->setTransform(transform2); |
| QCOMPARE(item1->pos(), item1->mapToParent(0, 0)); |
| QCOMPARE(item2->pos(), item2->mapToParent(0, 0)); |
| QCOMPARE(item3->pos(), item3->mapToParent(0, 0) - QPointF(50, 0)); |
| QCOMPARE(item4->pos(), item4->mapToParent(0, 0)); |
| QCOMPARE(item1->mapToParent(10, 0), QPointF(100, 110)); |
| QCOMPARE(item2->mapToParent(10, 0), QPointF(100, 110)); |
| QCOMPARE(item3->mapToParent(10, 0), QPointF(150, 90)); |
| QCOMPARE(item4->mapToParent(10, 0), QPointF(110, 100)); |
| QCOMPARE(item1->mapToScene(0, 0), QPointF(100, 100)); |
| QCOMPARE(item2->mapToScene(0, 0), QPointF(0, 200)); |
| QCOMPARE(item3->mapToScene(0, 0), QPointF(-150, 100)); |
| QCOMPARE(item4->mapToScene(0, 0), QPointF(-250, 200)); |
| QCOMPARE(item1->mapToScene(10, 0), QPointF(100, 110)); |
| QCOMPARE(item2->mapToScene(10, 0), QPointF(-10, 200)); |
| QCOMPARE(item3->mapToScene(10, 0), QPointF(-150, 110)); |
| QCOMPARE(item4->mapToScene(10, 0), QPointF(-250, 210)); |
| QCOMPARE(item1->mapFromScene(100, 100), QPointF(0, 0)); |
| QCOMPARE(item2->mapFromScene(0, 200), QPointF(0, 0)); |
| QCOMPARE(item3->mapFromScene(-150, 100), QPointF(0, 0)); |
| QCOMPARE(item4->mapFromScene(-250, 200), QPointF(0, 0)); |
| QCOMPARE(item1->mapFromScene(100, 110), QPointF(10, 0)); |
| QCOMPARE(item2->mapFromScene(-10, 200), QPointF(10, 0)); |
| QCOMPARE(item3->mapFromScene(-150, 110), QPointF(10, 0)); |
| QCOMPARE(item4->mapFromScene(-250, 210), QPointF(10, 0)); |
| |
| delete item1; |
| } |
| |
| void tst_QGraphicsItem::mapFromToItem() |
| { |
| QGraphicsItem *item1 = new QGraphicsPathItem; |
| QGraphicsItem *item2 = new QGraphicsPathItem; |
| QGraphicsItem *item3 = new QGraphicsPathItem; |
| QGraphicsItem *item4 = new QGraphicsPathItem; |
| |
| item1->setPos(-100, -100); |
| item2->setPos(100, -100); |
| item3->setPos(100, 100); |
| item4->setPos(-100, 100); |
| |
| QCOMPARE(item1->mapFromItem(item2, 0, 0), QPointF(200, 0)); |
| QCOMPARE(item2->mapFromItem(item3, 0, 0), QPointF(0, 200)); |
| QCOMPARE(item3->mapFromItem(item4, 0, 0), QPointF(-200, 0)); |
| QCOMPARE(item4->mapFromItem(item1, 0, 0), QPointF(0, -200)); |
| QCOMPARE(item1->mapFromItem(item4, 0, 0), QPointF(0, 200)); |
| QCOMPARE(item2->mapFromItem(item1, 0, 0), QPointF(-200, 0)); |
| QCOMPARE(item3->mapFromItem(item2, 0, 0), QPointF(0, -200)); |
| QCOMPARE(item4->mapFromItem(item3, 0, 0), QPointF(200, 0)); |
| |
| QTransform transform; |
| transform.translate(100, 100); |
| item1->setTransform(transform); |
| |
| QCOMPARE(item1->mapFromItem(item2, 0, 0), QPointF(100, -100)); |
| QCOMPARE(item2->mapFromItem(item3, 0, 0), QPointF(0, 200)); |
| QCOMPARE(item3->mapFromItem(item4, 0, 0), QPointF(-200, 0)); |
| QCOMPARE(item4->mapFromItem(item1, 0, 0), QPointF(100, -100)); |
| QCOMPARE(item1->mapFromItem(item4, 0, 0), QPointF(-100, 100)); |
| QCOMPARE(item2->mapFromItem(item1, 0, 0), QPointF(-100, 100)); |
| QCOMPARE(item3->mapFromItem(item2, 0, 0), QPointF(0, -200)); |
| QCOMPARE(item4->mapFromItem(item3, 0, 0), QPointF(200, 0)); |
| |
| transform.rotate(90); |
| item1->setTransform(transform); |
| item2->setTransform(transform); |
| item3->setTransform(transform); |
| item4->setTransform(transform); |
| |
| QCOMPARE(item1->mapFromItem(item2, 0, 0), QPointF(0, -200)); |
| QCOMPARE(item2->mapFromItem(item3, 0, 0), QPointF(200, 0)); |
| QCOMPARE(item3->mapFromItem(item4, 0, 0), QPointF(0, 200)); |
| QCOMPARE(item4->mapFromItem(item1, 0, 0), QPointF(-200, 0)); |
| QCOMPARE(item1->mapFromItem(item4, 0, 0), QPointF(200, 0)); |
| QCOMPARE(item2->mapFromItem(item1, 0, 0), QPointF(0, 200)); |
| QCOMPARE(item3->mapFromItem(item2, 0, 0), QPointF(-200, 0)); |
| QCOMPARE(item4->mapFromItem(item3, 0, 0), QPointF(0, -200)); |
| QCOMPARE(item1->mapFromItem(item2, 10, -5), QPointF(10, -205)); |
| QCOMPARE(item2->mapFromItem(item3, 10, -5), QPointF(210, -5)); |
| QCOMPARE(item3->mapFromItem(item4, 10, -5), QPointF(10, 195)); |
| QCOMPARE(item4->mapFromItem(item1, 10, -5), QPointF(-190, -5)); |
| QCOMPARE(item1->mapFromItem(item4, 10, -5), QPointF(210, -5)); |
| QCOMPARE(item2->mapFromItem(item1, 10, -5), QPointF(10, 195)); |
| QCOMPARE(item3->mapFromItem(item2, 10, -5), QPointF(-190, -5)); |
| QCOMPARE(item4->mapFromItem(item3, 10, -5), QPointF(10, -205)); |
| |
| QCOMPARE(item1->mapFromItem(0, 10, -5), item1->mapFromScene(10, -5)); |
| QCOMPARE(item2->mapFromItem(0, 10, -5), item2->mapFromScene(10, -5)); |
| QCOMPARE(item3->mapFromItem(0, 10, -5), item3->mapFromScene(10, -5)); |
| QCOMPARE(item4->mapFromItem(0, 10, -5), item4->mapFromScene(10, -5)); |
| QCOMPARE(item1->mapToItem(0, 10, -5), item1->mapToScene(10, -5)); |
| QCOMPARE(item2->mapToItem(0, 10, -5), item2->mapToScene(10, -5)); |
| QCOMPARE(item3->mapToItem(0, 10, -5), item3->mapToScene(10, -5)); |
| QCOMPARE(item4->mapToItem(0, 10, -5), item4->mapToScene(10, -5)); |
| |
| delete item1; |
| delete item2; |
| delete item3; |
| delete item4; |
| } |
| |
| void tst_QGraphicsItem::mapRectFromToParent_data() |
| { |
| QTest::addColumn<bool>("parent"); |
| QTest::addColumn<QPointF>("parentPos"); |
| QTest::addColumn<QTransform>("parentTransform"); |
| QTest::addColumn<QPointF>("pos"); |
| QTest::addColumn<QTransform>("transform"); |
| QTest::addColumn<QRectF>("inputRect"); |
| QTest::addColumn<QRectF>("outputRect"); |
| |
| QTest::newRow("nil") << false << QPointF() << QTransform() << QPointF() << QTransform() << QRectF() << QRectF(); |
| QTest::newRow("simple") << false << QPointF() << QTransform() << QPointF() << QTransform() |
| << QRectF(0, 0, 10, 10) << QRectF(0, 0, 10, 10); |
| QTest::newRow("simple w/parent") << true |
| << QPointF() << QTransform() |
| << QPointF() << QTransform() |
| << QRectF(0, 0, 10, 10) << QRectF(0, 0, 10, 10); |
| QTest::newRow("simple w/parent parentPos") << true |
| << QPointF(50, 50) << QTransform() |
| << QPointF() << QTransform() |
| << QRectF(0, 0, 10, 10) << QRectF(0, 0, 10, 10); |
| QTest::newRow("simple w/parent parentPos parentRotation") << true |
| << QPointF(50, 50) << QTransform().rotate(45) |
| << QPointF() << QTransform() |
| << QRectF(0, 0, 10, 10) << QRectF(0, 0, 10, 10); |
| QTest::newRow("pos w/parent") << true |
| << QPointF() << QTransform() |
| << QPointF(50, 50) << QTransform() |
| << QRectF(0, 0, 10, 10) << QRectF(50, 50, 10, 10); |
| QTest::newRow("rotation w/parent") << true |
| << QPointF() << QTransform() |
| << QPointF() << QTransform().rotate(90) |
| << QRectF(0, 0, 10, 10) << QRectF(-10, 0, 10, 10); |
| QTest::newRow("pos rotation w/parent") << true |
| << QPointF() << QTransform() |
| << QPointF(50, 50) << QTransform().rotate(90) |
| << QRectF(0, 0, 10, 10) << QRectF(40, 50, 10, 10); |
| QTest::newRow("pos rotation w/parent parentPos parentRotation") << true |
| << QPointF(-170, -190) << QTransform().rotate(90) |
| << QPointF(50, 50) << QTransform().rotate(90) |
| << QRectF(0, 0, 10, 10) << QRectF(40, 50, 10, 10); |
| } |
| |
| void tst_QGraphicsItem::mapRectFromToParent() |
| { |
| QFETCH(bool, parent); |
| QFETCH(QPointF, parentPos); |
| QFETCH(QTransform, parentTransform); |
| QFETCH(QPointF, pos); |
| QFETCH(QTransform, transform); |
| QFETCH(QRectF, inputRect); |
| QFETCH(QRectF, outputRect); |
| |
| QGraphicsRectItem *rect = new QGraphicsRectItem; |
| rect->setPos(pos); |
| rect->setTransform(transform); |
| |
| if (parent) { |
| QGraphicsRectItem *rectParent = new QGraphicsRectItem; |
| rect->setParentItem(rectParent); |
| rectParent->setPos(parentPos); |
| rectParent->setTransform(parentTransform); |
| } |
| |
| // Make sure we use non-destructive transform operations (e.g., 90 degree |
| // rotations). |
| QCOMPARE(rect->mapRectToParent(inputRect), outputRect); |
| QCOMPARE(rect->mapRectFromParent(outputRect), inputRect); |
| QCOMPARE(rect->itemTransform(rect->parentItem()).mapRect(inputRect), outputRect); |
| QCOMPARE(rect->mapToParent(inputRect).boundingRect(), outputRect); |
| QCOMPARE(rect->mapToParent(QPolygonF(inputRect)).boundingRect(), outputRect); |
| QCOMPARE(rect->mapFromParent(outputRect).boundingRect(), inputRect); |
| QCOMPARE(rect->mapFromParent(QPolygonF(outputRect)).boundingRect(), inputRect); |
| QPainterPath inputPath; |
| inputPath.addRect(inputRect); |
| QPainterPath outputPath; |
| outputPath.addRect(outputRect); |
| QCOMPARE(rect->mapToParent(inputPath).boundingRect(), outputPath.boundingRect()); |
| QCOMPARE(rect->mapFromParent(outputPath).boundingRect(), inputPath.boundingRect()); |
| } |
| |
| void tst_QGraphicsItem::isAncestorOf() |
| { |
| QGraphicsItem *grandPa = new QGraphicsRectItem; |
| QGraphicsItem *parent = new QGraphicsRectItem; |
| QGraphicsItem *child = new QGraphicsRectItem; |
| |
| QVERIFY(!parent->isAncestorOf(0)); |
| QVERIFY(!child->isAncestorOf(0)); |
| QVERIFY(!parent->isAncestorOf(child)); |
| QVERIFY(!child->isAncestorOf(parent)); |
| QVERIFY(!parent->isAncestorOf(parent)); |
| |
| child->setParentItem(parent); |
| parent->setParentItem(grandPa); |
| |
| QVERIFY(parent->isAncestorOf(child)); |
| QVERIFY(grandPa->isAncestorOf(parent)); |
| QVERIFY(grandPa->isAncestorOf(child)); |
| QVERIFY(!child->isAncestorOf(parent)); |
| QVERIFY(!parent->isAncestorOf(grandPa)); |
| QVERIFY(!child->isAncestorOf(grandPa)); |
| QVERIFY(!child->isAncestorOf(child)); |
| QVERIFY(!parent->isAncestorOf(parent)); |
| QVERIFY(!grandPa->isAncestorOf(grandPa)); |
| |
| parent->setParentItem(0); |
| |
| delete child; |
| delete parent; |
| delete grandPa; |
| } |
| |
| void tst_QGraphicsItem::commonAncestorItem() |
| { |
| QGraphicsRectItem ancestorItem; |
| QGraphicsItem *ancestor = &ancestorItem; |
| QGraphicsItem *grandMa = new QGraphicsRectItem; |
| QGraphicsItem *grandPa = new QGraphicsRectItem; |
| QGraphicsItem *brotherInLaw = new QGraphicsRectItem; |
| QGraphicsItem *cousin = new QGraphicsRectItem; |
| QGraphicsItem *husband = new QGraphicsRectItem; |
| QGraphicsItem *child = new QGraphicsRectItem; |
| QGraphicsItem *wife = new QGraphicsRectItem; |
| |
| child->setParentItem(husband); |
| husband->setParentItem(grandPa); |
| brotherInLaw->setParentItem(grandPa); |
| cousin->setParentItem(brotherInLaw); |
| wife->setParentItem(grandMa); |
| grandMa->setParentItem(ancestor); |
| grandPa->setParentItem(ancestor); |
| |
| QCOMPARE(grandMa->commonAncestorItem(grandMa), grandMa); |
| QCOMPARE(grandMa->commonAncestorItem(0), nullptr); |
| QCOMPARE(grandMa->commonAncestorItem(grandPa), ancestor); |
| QCOMPARE(grandPa->commonAncestorItem(grandMa), ancestor); |
| QCOMPARE(grandPa->commonAncestorItem(husband), grandPa); |
| QCOMPARE(grandPa->commonAncestorItem(wife), ancestor); |
| QCOMPARE(grandMa->commonAncestorItem(husband), ancestor); |
| QCOMPARE(grandMa->commonAncestorItem(wife), grandMa); |
| QCOMPARE(wife->commonAncestorItem(grandMa), grandMa); |
| QCOMPARE(child->commonAncestorItem(cousin), grandPa); |
| QCOMPARE(cousin->commonAncestorItem(child), grandPa); |
| QCOMPARE(wife->commonAncestorItem(child), ancestor); |
| QCOMPARE(child->commonAncestorItem(wife), ancestor); |
| } |
| |
| void tst_QGraphicsItem::data() |
| { |
| QGraphicsTextItem text; |
| |
| QCOMPARE(text.data(0), QVariant()); |
| text.setData(0, "TextItem"); |
| QCOMPARE(text.data(0), QVariant(QString("TextItem"))); |
| text.setData(0, QVariant()); |
| QCOMPARE(text.data(0), QVariant()); |
| } |
| |
| void tst_QGraphicsItem::type() |
| { |
| QCOMPARE(int(QGraphicsItem::Type), 1); |
| QCOMPARE(int(QGraphicsPathItem::Type), 2); |
| QCOMPARE(int(QGraphicsRectItem::Type), 3); |
| QCOMPARE(int(QGraphicsEllipseItem::Type), 4); |
| QCOMPARE(int(QGraphicsPolygonItem::Type), 5); |
| QCOMPARE(int(QGraphicsLineItem::Type), 6); |
| QCOMPARE(int(QGraphicsPixmapItem::Type), 7); |
| QCOMPARE(int(QGraphicsTextItem::Type), 8); |
| |
| QCOMPARE(QGraphicsPathItem().type(), 2); |
| QCOMPARE(QGraphicsRectItem().type(), 3); |
| QCOMPARE(QGraphicsEllipseItem().type(), 4); |
| QCOMPARE(QGraphicsPolygonItem().type(), 5); |
| QCOMPARE(QGraphicsLineItem().type(), 6); |
| QCOMPARE(QGraphicsPixmapItem().type(), 7); |
| QCOMPARE(QGraphicsTextItem().type(), 8); |
| } |
| |
| void tst_QGraphicsItem::graphicsitem_cast() |
| { |
| QGraphicsPathItem pathItem; |
| const QGraphicsPathItem *pPathItem = &pathItem; |
| QGraphicsRectItem rectItem; |
| const QGraphicsRectItem *pRectItem = &rectItem; |
| QGraphicsEllipseItem ellipseItem; |
| const QGraphicsEllipseItem *pEllipseItem = &ellipseItem; |
| QGraphicsPolygonItem polygonItem; |
| const QGraphicsPolygonItem *pPolygonItem = &polygonItem; |
| QGraphicsLineItem lineItem; |
| const QGraphicsLineItem *pLineItem = &lineItem; |
| QGraphicsPixmapItem pixmapItem; |
| const QGraphicsPixmapItem *pPixmapItem = &pixmapItem; |
| QGraphicsTextItem textItem; |
| const QGraphicsTextItem *pTextItem = &textItem; |
| |
| QVERIFY(qgraphicsitem_cast<QGraphicsPathItem *>(&pathItem)); |
| //QVERIFY(qgraphicsitem_cast<QAbstractGraphicsPathItem *>(&pathItem)); |
| QVERIFY(qgraphicsitem_cast<QGraphicsItem *>(&pathItem)); |
| QVERIFY(qgraphicsitem_cast<const QGraphicsItem *>(pPathItem)); |
| QVERIFY(qgraphicsitem_cast<const QGraphicsPathItem *>(pPathItem)); |
| |
| QVERIFY(qgraphicsitem_cast<QGraphicsRectItem *>(&rectItem)); |
| QVERIFY(qgraphicsitem_cast<QGraphicsItem *>(&rectItem)); |
| QVERIFY(qgraphicsitem_cast<const QGraphicsItem *>(pRectItem)); |
| QVERIFY(qgraphicsitem_cast<const QGraphicsRectItem *>(pRectItem)); |
| |
| QVERIFY(qgraphicsitem_cast<QGraphicsEllipseItem *>(&ellipseItem)); |
| QVERIFY(qgraphicsitem_cast<QGraphicsItem *>(&ellipseItem)); |
| QVERIFY(qgraphicsitem_cast<const QGraphicsItem *>(pEllipseItem)); |
| QVERIFY(qgraphicsitem_cast<const QGraphicsEllipseItem *>(pEllipseItem)); |
| |
| QVERIFY(qgraphicsitem_cast<QGraphicsPolygonItem *>(&polygonItem)); |
| //QVERIFY(qgraphicsitem_cast<QAbstractGraphicsPathItem *>(&polygonItem)); |
| QVERIFY(qgraphicsitem_cast<QGraphicsItem *>(&polygonItem)); |
| QVERIFY(qgraphicsitem_cast<const QGraphicsItem *>(pPolygonItem)); |
| QVERIFY(qgraphicsitem_cast<const QGraphicsPolygonItem *>(pPolygonItem)); |
| |
| QVERIFY(qgraphicsitem_cast<QGraphicsLineItem *>(&lineItem)); |
| QVERIFY(qgraphicsitem_cast<QGraphicsItem *>(&lineItem)); |
| QVERIFY(qgraphicsitem_cast<const QGraphicsItem *>(pLineItem)); |
| QVERIFY(qgraphicsitem_cast<const QGraphicsLineItem *>(pLineItem)); |
| |
| QVERIFY(qgraphicsitem_cast<QGraphicsPixmapItem *>(&pixmapItem)); |
| QVERIFY(qgraphicsitem_cast<QGraphicsItem *>(&pixmapItem)); |
| QVERIFY(qgraphicsitem_cast<const QGraphicsItem *>(pPixmapItem)); |
| QVERIFY(qgraphicsitem_cast<const QGraphicsPixmapItem *>(pPixmapItem)); |
| |
| QVERIFY(qgraphicsitem_cast<QGraphicsTextItem *>(&textItem)); |
| QVERIFY(qgraphicsitem_cast<QGraphicsItem *>(&textItem)); |
| QVERIFY(qgraphicsitem_cast<const QGraphicsItem *>(pTextItem)); |
| QVERIFY(qgraphicsitem_cast<const QGraphicsTextItem *>(pTextItem)); |
| |
| // and some casts that _should_ fail: |
| QVERIFY(!qgraphicsitem_cast<QGraphicsEllipseItem *>(&pathItem)); |
| QVERIFY(!qgraphicsitem_cast<const QGraphicsTextItem *>(pPolygonItem)); |
| |
| // and this shouldn't crash |
| QGraphicsItem *ptr = 0; |
| QVERIFY(!qgraphicsitem_cast<QGraphicsTextItem *>(ptr)); |
| QVERIFY(!qgraphicsitem_cast<QGraphicsItem *>(ptr)); |
| } |
| |
| void tst_QGraphicsItem::hoverEventsGenerateRepaints() |
| { |
| Q_CHECK_PAINTEVENTS |
| |
| QGraphicsScene scene; |
| QGraphicsView view(&scene); |
| view.show(); |
| QVERIFY(QTest::qWaitForWindowExposed(&view)); |
| QVERIFY(QTest::qWaitForWindowActive(&view)); |
| QCoreApplication::processEvents(); // Process all queued paint events |
| |
| EventTester *tester = new EventTester; |
| scene.addItem(tester); |
| tester->setAcceptHoverEvents(true); |
| |
| QTRY_COMPARE(tester->repaints, 1); |
| |
| // Send a hover enter event |
| QGraphicsSceneHoverEvent hoverEnterEvent(QEvent::GraphicsSceneHoverEnter); |
| hoverEnterEvent.setScenePos(QPointF(0, 0)); |
| hoverEnterEvent.setPos(QPointF(0, 0)); |
| QApplication::sendEvent(&scene, &hoverEnterEvent); |
| |
| // Check that we get a repaint |
| int npaints = tester->repaints; |
| qApp->processEvents(); |
| qApp->processEvents(); |
| QCOMPARE(tester->events.size(), 2); // enter + move |
| QCOMPARE(tester->repaints, npaints + 1); |
| QCOMPARE(tester->events.last(), QEvent::GraphicsSceneHoverMove); |
| |
| // Send a hover move event |
| QGraphicsSceneHoverEvent hoverMoveEvent(QEvent::GraphicsSceneHoverMove); |
| hoverMoveEvent.setScenePos(QPointF(0, 0)); |
| hoverMoveEvent.setPos(QPointF(0, 0)); |
| QApplication::sendEvent(&scene, &hoverMoveEvent); |
| |
| // Check that we don't get a repaint |
| qApp->processEvents(); |
| qApp->processEvents(); |
| |
| QCOMPARE(tester->events.size(), 3); |
| QCOMPARE(tester->repaints, npaints + 1); |
| QCOMPARE(tester->events.last(), QEvent::GraphicsSceneHoverMove); |
| |
| // Send a hover leave event |
| QGraphicsSceneHoverEvent hoverLeaveEvent(QEvent::GraphicsSceneHoverLeave); |
| hoverLeaveEvent.setScenePos(QPointF(-100, -100)); |
| hoverLeaveEvent.setPos(QPointF(0, 0)); |
| QApplication::sendEvent(&scene, &hoverLeaveEvent); |
| |
| // Check that we get a repaint |
| qApp->processEvents(); |
| qApp->processEvents(); |
| |
| QCOMPARE(tester->events.size(), 4); |
| QCOMPARE(tester->repaints, npaints + 2); |
| QCOMPARE(tester->events.last(), QEvent::GraphicsSceneHoverLeave); |
| } |
| |
| void tst_QGraphicsItem::boundingRects_data() |
| { |
| QTest::addColumn<QGraphicsItem *>("item"); |
| QTest::addColumn<QRectF>("boundingRect"); |
| |
| QRectF rect(0, 0, 100, 100); |
| QPainterPath path; |
| path.addRect(rect); |
| |
| QRectF adjustedRect(-0.5, -0.5, 101, 101); |
| |
| QTest::newRow("path") << (QGraphicsItem *)new QGraphicsPathItem(path) << adjustedRect; |
| QTest::newRow("rect") << (QGraphicsItem *)new QGraphicsRectItem(rect) << adjustedRect; |
| QTest::newRow("ellipse") << (QGraphicsItem *)new QGraphicsEllipseItem(rect) << adjustedRect; |
| QTest::newRow("polygon") << (QGraphicsItem *)new QGraphicsPolygonItem(rect) << adjustedRect; |
| } |
| |
| void tst_QGraphicsItem::boundingRects() |
| { |
| QFETCH(QGraphicsItem *, item); |
| QFETCH(QRectF, boundingRect); |
| |
| ((QAbstractGraphicsShapeItem *)item)->setPen(QPen(Qt::black, 1)); |
| QCOMPARE(item->boundingRect(), boundingRect); |
| } |
| |
| void tst_QGraphicsItem::boundingRects2() |
| { |
| QGraphicsPixmapItem pixmap(QPixmap::fromImage(QImage(100, 100, QImage::Format_ARGB32_Premultiplied))); |
| QCOMPARE(pixmap.boundingRect(), QRectF(0, 0, 100, 100)); |
| |
| QGraphicsLineItem line(0, 0, 100, 0); |
| line.setPen(QPen(Qt::black, 1)); |
| QCOMPARE(line.boundingRect(), QRectF(-0.5, -0.5, 101, 1)); |
| } |
| |
| void tst_QGraphicsItem::sceneBoundingRect() |
| { |
| QGraphicsScene scene; |
| QGraphicsRectItem *item = scene.addRect(QRectF(0, 0, 100, 100), QPen(Qt::black, 0)); |
| item->setPos(100, 100); |
| |
| QCOMPARE(item->boundingRect(), QRectF(0, 0, 100, 100)); |
| QCOMPARE(item->sceneBoundingRect(), QRectF(100, 100, 100, 100)); |
| |
| item->setTransform(QTransform().rotate(90), true); |
| |
| QCOMPARE(item->boundingRect(), QRectF(0, 0, 100, 100)); |
| QCOMPARE(item->sceneBoundingRect(), QRectF(0, 100, 100, 100)); |
| } |
| |
| void tst_QGraphicsItem::childrenBoundingRect() |
| { |
| QGraphicsScene scene; |
| QGraphicsRectItem *parent = scene.addRect(QRectF(0, 0, 100, 100), QPen(Qt::black, 0)); |
| QGraphicsRectItem *child = scene.addRect(QRectF(0, 0, 100, 100), QPen(Qt::black, 0)); |
| child->setParentItem(parent); |
| parent->setPos(100, 100); |
| child->setPos(100, 100); |
| |
| QCOMPARE(parent->boundingRect(), QRectF(0, 0, 100, 100)); |
| QCOMPARE(child->boundingRect(), QRectF(0, 0, 100, 100)); |
| QCOMPARE(child->childrenBoundingRect(), QRectF()); |
| QCOMPARE(parent->childrenBoundingRect(), QRectF(100, 100, 100, 100)); |
| |
| QGraphicsRectItem *child2 = scene.addRect(QRectF(0, 0, 100, 100), QPen(Qt::black, 0)); |
| child2->setParentItem(parent); |
| child2->setPos(-100, -100); |
| QCOMPARE(parent->childrenBoundingRect(), QRectF(-100, -100, 300, 300)); |
| |
| QGraphicsRectItem *childChild = scene.addRect(QRectF(0, 0, 100, 100), QPen(Qt::black, 0)); |
| childChild->setParentItem(child); |
| childChild->setPos(500, 500); |
| child->setTransform(QTransform().rotate(90), true); |
| |
| scene.addPolygon(parent->mapToScene(parent->boundingRect() | parent->childrenBoundingRect()))->setPen(QPen(Qt::red));; |
| |
| QGraphicsView view(&scene); |
| view.show(); |
| |
| QVERIFY(QTest::qWaitForWindowExposed(&view)); |
| |
| QTRY_COMPARE(parent->childrenBoundingRect(), QRectF(-500, -100, 600, 800)); |
| } |
| |
| void tst_QGraphicsItem::childrenBoundingRectTransformed() |
| { |
| QGraphicsScene scene; |
| |
| QGraphicsRectItem *rect = scene.addRect(QRectF(0, 0, 100, 100)); |
| QGraphicsRectItem *rect2 = scene.addRect(QRectF(0, 0, 100, 100)); |
| QGraphicsRectItem *rect3 = scene.addRect(QRectF(0, 0, 100, 100)); |
| QGraphicsRectItem *rect4 = scene.addRect(QRectF(0, 0, 100, 100)); |
| QGraphicsRectItem *rect5 = scene.addRect(QRectF(0, 0, 100, 100)); |
| rect2->setParentItem(rect); |
| rect3->setParentItem(rect2); |
| rect4->setParentItem(rect3); |
| rect5->setParentItem(rect4); |
| |
| rect->setPen(QPen(Qt::black, 0)); |
| rect2->setPen(QPen(Qt::black, 0)); |
| rect3->setPen(QPen(Qt::black, 0)); |
| rect4->setPen(QPen(Qt::black, 0)); |
| rect5->setPen(QPen(Qt::black, 0)); |
| |
| rect2->setTransform(QTransform().translate(50, 50).rotate(45)); |
| rect2->setPos(25, 25); |
| rect3->setTransform(QTransform().translate(50, 50).rotate(45)); |
| rect3->setPos(25, 25); |
| rect4->setTransform(QTransform().translate(50, 50).rotate(45)); |
| rect4->setPos(25, 25); |
| rect5->setTransform(QTransform().translate(50, 50).rotate(45)); |
| rect5->setPos(25, 25); |
| |
| QRectF subTreeRect = rect->childrenBoundingRect(); |
| QCOMPARE(subTreeRect.left(), qreal(-206.0660171779821)); |
| QCOMPARE(subTreeRect.top(), qreal(75.0)); |
| QCOMPARE(subTreeRect.width(), qreal(351.7766952966369)); |
| QCOMPARE(subTreeRect.height(), qreal(251.7766952966369)); |
| |
| rect->setTransform(QTransform().rotate(45), true); |
| rect2->setTransform(QTransform().rotate(-45), true); |
| rect3->setTransform(QTransform().rotate(45), true); |
| rect4->setTransform(QTransform().rotate(-45), true); |
| rect5->setTransform(QTransform().rotate(45), true); |
| |
| subTreeRect = rect->childrenBoundingRect(); |
| QCOMPARE(rect->childrenBoundingRect(), QRectF(-100, 75, 275, 250)); |
| } |
| |
| void tst_QGraphicsItem::childrenBoundingRect2() |
| { |
| QGraphicsItemGroup box; |
| QGraphicsLineItem l1(0, 0, 100, 0, &box); |
| QGraphicsLineItem l2(100, 0, 100, 100, &box); |
| QGraphicsLineItem l3(0, 0, 0, 100, &box); |
| // Make sure lines (zero with/height) are included in the childrenBoundingRect. |
| l1.setPen(QPen(Qt::black, 0)); |
| l2.setPen(QPen(Qt::black, 0)); |
| l3.setPen(QPen(Qt::black, 0)); |
| QCOMPARE(box.childrenBoundingRect(), QRectF(0, 0, 100, 100)); |
| } |
| |
| void tst_QGraphicsItem::childrenBoundingRect3() |
| { |
| QGraphicsScene scene; |
| |
| QGraphicsRectItem *rect = scene.addRect(QRectF(0, 0, 100, 100)); |
| QGraphicsRectItem *rect2 = scene.addRect(QRectF(0, 0, 100, 100)); |
| QGraphicsRectItem *rect3 = scene.addRect(QRectF(0, 0, 100, 100)); |
| QGraphicsRectItem *rect4 = scene.addRect(QRectF(0, 0, 100, 100)); |
| QGraphicsRectItem *rect5 = scene.addRect(QRectF(0, 0, 100, 100)); |
| rect2->setParentItem(rect); |
| rect3->setParentItem(rect2); |
| rect4->setParentItem(rect3); |
| rect5->setParentItem(rect4); |
| |
| rect->setPen(QPen(Qt::black, 0)); |
| rect2->setPen(QPen(Qt::black, 0)); |
| rect3->setPen(QPen(Qt::black, 0)); |
| rect4->setPen(QPen(Qt::black, 0)); |
| rect5->setPen(QPen(Qt::black, 0)); |
| |
| rect2->setTransform(QTransform().translate(50, 50).rotate(45)); |
| rect2->setPos(25, 25); |
| rect3->setTransform(QTransform().translate(50, 50).rotate(45)); |
| rect3->setPos(25, 25); |
| rect4->setTransform(QTransform().translate(50, 50).rotate(45)); |
| rect4->setPos(25, 25); |
| rect5->setTransform(QTransform().translate(50, 50).rotate(45)); |
| rect5->setPos(25, 25); |
| |
| // Try to mess up the cached bounding rect. |
| (void)rect2->childrenBoundingRect(); |
| |
| QRectF subTreeRect = rect->childrenBoundingRect(); |
| QCOMPARE(subTreeRect.left(), qreal(-206.0660171779821)); |
| QCOMPARE(subTreeRect.top(), qreal(75.0)); |
| QCOMPARE(subTreeRect.width(), qreal(351.7766952966369)); |
| QCOMPARE(subTreeRect.height(), qreal(251.7766952966369)); |
| } |
| |
| void tst_QGraphicsItem::childrenBoundingRect4() |
| { |
| QGraphicsScene scene; |
| |
| QGraphicsRectItem *rect = scene.addRect(QRectF(0, 0, 10, 10)); |
| QGraphicsRectItem *rect2 = scene.addRect(QRectF(0, 0, 20, 20)); |
| QGraphicsRectItem *rect3 = scene.addRect(QRectF(0, 0, 30, 30)); |
| rect2->setParentItem(rect); |
| rect3->setParentItem(rect); |
| |
| QGraphicsView view(&scene); |
| view.show(); |
| |
| QVERIFY(QTest::qWaitForWindowExposed(&view)); |
| |
| // Try to mess up the cached bounding rect. |
| rect->childrenBoundingRect(); |
| rect2->childrenBoundingRect(); |
| |
| rect3->setOpacity(0.0); |
| rect3->setParentItem(rect2); |
| |
| QCOMPARE(rect->childrenBoundingRect(), rect3->boundingRect()); |
| QCOMPARE(rect2->childrenBoundingRect(), rect3->boundingRect()); |
| } |
| |
| void tst_QGraphicsItem::childrenBoundingRect5() |
| { |
| QGraphicsScene scene; |
| |
| QGraphicsRectItem *parent = scene.addRect(QRectF(0, 0, 100, 100)); |
| QGraphicsRectItem *child = scene.addRect(QRectF(0, 0, 100, 100)); |
| child->setParentItem(parent); |
| |
| parent->setPen(QPen(Qt::black, 0)); |
| child->setPen(QPen(Qt::black, 0)); |
| |
| QGraphicsView view(&scene); |
| view.show(); |
| |
| QVERIFY(QTest::qWaitForWindowExposed(&view)); |
| |
| // Try to mess up the cached bounding rect. |
| QRectF expectedChildrenBoundingRect = parent->boundingRect(); |
| QCOMPARE(parent->childrenBoundingRect(), expectedChildrenBoundingRect); |
| |
| // Apply some effects. |
| QGraphicsDropShadowEffect *dropShadow = new QGraphicsDropShadowEffect; |
| dropShadow->setOffset(25, 25); |
| child->setGraphicsEffect(dropShadow); |
| parent->setGraphicsEffect(new QGraphicsOpacityEffect); |
| |
| QVERIFY(parent->childrenBoundingRect() != expectedChildrenBoundingRect); |
| expectedChildrenBoundingRect |= dropShadow->boundingRect(); |
| QCOMPARE(parent->childrenBoundingRect(), expectedChildrenBoundingRect); |
| } |
| |
| void tst_QGraphicsItem::group() |
| { |
| QGraphicsScene scene; |
| QGraphicsRectItem *parent = scene.addRect(QRectF(0, 0, 50, 50), QPen(Qt::black, 0), QBrush(Qt::green)); |
| QGraphicsRectItem *child = scene.addRect(QRectF(0, 0, 50, 50), QPen(Qt::black, 0), QBrush(Qt::blue)); |
| QGraphicsRectItem *parent2 = scene.addRect(QRectF(0, 0, 50, 50), QPen(Qt::black, 0), QBrush(Qt::red)); |
| parent2->setPos(-50, 50); |
| child->setTransform(QTransform().rotate(45), true); |
| child->setParentItem(parent); |
| parent->setPos(25, 25); |
| child->setPos(25, 25); |
| |
| QCOMPARE(parent->group(), nullptr); |
| QCOMPARE(parent2->group(), nullptr); |
| QCOMPARE(child->group(), nullptr); |
| |
| QGraphicsView view(&scene); |
| view.show(); |
| QVERIFY(QTest::qWaitForWindowExposed(&view)); |
| |
| QGraphicsItemGroup *group = new QGraphicsItemGroup; |
| group->setSelected(true); |
| scene.addItem(group); |
| |
| QRectF parentSceneBoundingRect = parent->sceneBoundingRect(); |
| group->addToGroup(parent); |
| QCOMPARE(parent->group(), group); |
| QCOMPARE(parent->sceneBoundingRect(), parentSceneBoundingRect); |
| |
| QCOMPARE(parent->parentItem(), (QGraphicsItem *)group); |
| QCOMPARE(group->childItems().size(), 1); |
| QCOMPARE(scene.items().size(), 4); |
| QCOMPARE(scene.items(group->sceneBoundingRect()).size(), 3); |
| |
| |
| QRectF parent2SceneBoundingRect = parent2->sceneBoundingRect(); |
| group->addToGroup(parent2); |
| QCOMPARE(parent2->group(), group); |
| QCOMPARE(parent2->sceneBoundingRect(), parent2SceneBoundingRect); |
| |
| QCOMPARE(parent2->parentItem(), (QGraphicsItem *)group); |
| QCOMPARE(group->childItems().size(), 2); |
| QCOMPARE(scene.items().size(), 4); |
| QCOMPARE(scene.items(group->sceneBoundingRect()).size(), 4); |
| |
| QList<QGraphicsItem *> newItems; |
| for (int i = 0; i < 100; ++i) { |
| QGraphicsItem *item = scene.addRect(QRectF(-25, -25, 50, 50), QPen(Qt::black, 0), |
| QBrush(QColor(QRandomGenerator::global()->bounded(255), QRandomGenerator::global()->bounded(255), |
| QRandomGenerator::global()->bounded(255), QRandomGenerator::global()->bounded(255)))); |
| newItems << item; |
| item->setPos(-1000 + QRandomGenerator::global()->bounded(2000), |
| -1000 + QRandomGenerator::global()->bounded(2000)); |
| item->setTransform(QTransform().rotate(QRandomGenerator::global()->bounded(90)), true); |
| } |
| |
| view.fitInView(scene.itemsBoundingRect()); |
| |
| foreach (QGraphicsItem *item, newItems) { |
| group->addToGroup(item); |
| QCOMPARE(item->group(), group); |
| } |
| } |
| |
| void tst_QGraphicsItem::setGroup() |
| { |
| QGraphicsItemGroup group1; |
| QGraphicsItemGroup group2; |
| |
| const QScopedPointer<QGraphicsRectItem> rect(new QGraphicsRectItem); |
| QCOMPARE(rect->group(), nullptr); |
| QCOMPARE(rect->parentItem(), nullptr); |
| rect->setGroup(&group1); |
| QCOMPARE(rect->group(), &group1); |
| QCOMPARE(rect->parentItem(), (QGraphicsItem *)&group1); |
| rect->setGroup(&group2); |
| QCOMPARE(rect->group(), &group2); |
| QCOMPARE(rect->parentItem(), (QGraphicsItem *)&group2); |
| rect->setGroup(0); |
| QCOMPARE(rect->group(), nullptr); |
| QCOMPARE(rect->parentItem(), nullptr); |
| } |
| |
| void tst_QGraphicsItem::setGroup2() |
| { |
| QGraphicsScene scene; |
| QGraphicsItemGroup group; |
| scene.addItem(&group); |
| |
| QGraphicsRectItem *rect = scene.addRect(50,50,50,50,Qt::NoPen,Qt::black); |
| rect->setTransformOriginPoint(50,50); |
| rect->setRotation(45); |
| rect->setScale(1.5); |
| rect->setTransform(QTransform::fromTranslate(20,20), true); |
| group.setTransform(QTransform::fromTranslate(-30, -40), true); |
| group.setRotation(180); |
| group.setScale(0.5); |
| |
| QTransform oldSceneTransform = rect->sceneTransform(); |
| rect->setGroup(&group); |
| QCOMPARE(rect->sceneTransform(), oldSceneTransform); |
| |
| group.setRotation(20); |
| group.setScale(2); |
| rect->setRotation(90); |
| rect->setScale(0.8); |
| |
| oldSceneTransform = rect->sceneTransform(); |
| rect->setGroup(0); |
| qFuzzyCompare(rect->sceneTransform(), oldSceneTransform); |
| } |
| |
| void tst_QGraphicsItem::nestedGroups() |
| { |
| QGraphicsItemGroup *group1 = new QGraphicsItemGroup; |
| QGraphicsItemGroup *group2 = new QGraphicsItemGroup; |
| |
| QGraphicsRectItem *rect = new QGraphicsRectItem; |
| QGraphicsRectItem *rect2 = new QGraphicsRectItem; |
| rect2->setParentItem(rect); |
| |
| group1->addToGroup(rect); |
| QCOMPARE(rect->group(), group1); |
| QCOMPARE(rect2->group(), group1); |
| |
| group2->addToGroup(group1); |
| QCOMPARE(rect->group(), group1); |
| QCOMPARE(rect2->group(), group1); |
| QCOMPARE(group1->group(), group2); |
| QCOMPARE(group2->group(), nullptr); |
| |
| QGraphicsScene scene; |
| scene.addItem(group1); |
| |
| QCOMPARE(rect->group(), group1); |
| QCOMPARE(rect2->group(), group1); |
| QCOMPARE(group1->group(), nullptr); |
| QVERIFY(group2->childItems().isEmpty()); |
| |
| delete group2; |
| } |
| |
| void tst_QGraphicsItem::warpChildrenIntoGroup() |
| { |
| QGraphicsScene scene; |
| QGraphicsRectItem *parentRectItem = scene.addRect(QRectF(0, 0, 100, 100)); |
| QGraphicsRectItem *childRectItem = scene.addRect(QRectF(0, 0, 100, 100)); |
| parentRectItem->setTransform(QTransform().rotate(90), true); |
| childRectItem->setPos(-50, -25); |
| childRectItem->setParentItem(parentRectItem); |
| |
| QCOMPARE(childRectItem->mapToScene(50, 0), QPointF(25, 0)); |
| QCOMPARE(childRectItem->scenePos(), QPointF(25, -50)); |
| |
| QGraphicsRectItem *parentOfGroup = scene.addRect(QRectF(0, 0, 100, 100)); |
| parentOfGroup->setPos(-200, -200); |
| parentOfGroup->setTransform(QTransform::fromScale(2, 2), true); |
| |
| QGraphicsItemGroup *group = new QGraphicsItemGroup; |
| group->setPos(50, 50); |
| group->setParentItem(parentOfGroup); |
| |
| QCOMPARE(group->scenePos(), QPointF(-100, -100)); |
| |
| group->addToGroup(childRectItem); |
| |
| QCOMPARE(childRectItem->mapToScene(50, 0), QPointF(25, 0)); |
| QCOMPARE(childRectItem->scenePos(), QPointF(25, -50)); |
| } |
| |
| void tst_QGraphicsItem::removeFromGroup() |
| { |
| QGraphicsScene scene; |
| QGraphicsRectItem *rect1 = scene.addRect(QRectF(-100, -100, 200, 200)); |
| QGraphicsRectItem *rect2 = scene.addRect(QRectF(100, 100, 200, 200)); |
| rect1->setFlag(QGraphicsItem::ItemIsSelectable); |
| rect2->setFlag(QGraphicsItem::ItemIsSelectable); |
| rect1->setSelected(true); |
| rect2->setSelected(true); |
| |
| QGraphicsView view(&scene); |
| view.show(); |
| |
| qApp->processEvents(); // index items |
| qApp->processEvents(); // emit changed |
| |
| QGraphicsItemGroup *group = scene.createItemGroup(scene.selectedItems()); |
| QVERIFY(group); |
| QCOMPARE(group->childItems().size(), 2); |
| qApp->processEvents(); // index items |
| qApp->processEvents(); // emit changed |
| |
| scene.destroyItemGroup(group); // calls removeFromGroup. |
| |
| qApp->processEvents(); // index items |
| qApp->processEvents(); // emit changed |
| |
| QCOMPARE(scene.items().size(), 2); |
| QVERIFY(!rect1->group()); |
| QVERIFY(!rect2->group()); |
| } |
| |
| class ChildEventTester : public QGraphicsRectItem |
| { |
| public: |
| ChildEventTester(const QRectF &rect, QGraphicsItem *parent = 0) |
| : QGraphicsRectItem(rect, parent), counter(0) |
| { } |
| |
| int counter; |
| |
| protected: |
| void focusInEvent(QFocusEvent *event) |
| { ++counter; QGraphicsRectItem::focusInEvent(event); } |
| void mousePressEvent(QGraphicsSceneMouseEvent *) |
| { ++counter; } |
| void mouseMoveEvent(QGraphicsSceneMouseEvent *) |
| { ++counter; } |
| void mouseReleaseEvent(QGraphicsSceneMouseEvent *) |
| { ++counter; } |
| }; |
| |
| void tst_QGraphicsItem::handlesChildEvents() |
| { |
| ChildEventTester *blue = new ChildEventTester(QRectF(0, 0, 100, 100)); |
| ChildEventTester *red = new ChildEventTester(QRectF(0, 0, 50, 50)); |
| ChildEventTester *green = new ChildEventTester(QRectF(0, 0, 25, 25)); |
| ChildEventTester *gray = new ChildEventTester(QRectF(0, 0, 25, 25)); |
| ChildEventTester *yellow = new ChildEventTester(QRectF(0, 0, 50, 50)); |
| |
| blue->setBrush(QBrush(Qt::blue)); |
| red->setBrush(QBrush(Qt::red)); |
| yellow->setBrush(QBrush(Qt::yellow)); |
| green->setBrush(QBrush(Qt::green)); |
| gray->setBrush(QBrush(Qt::gray)); |
| red->setPos(50, 0); |
| yellow->setPos(50, 50); |
| green->setPos(25, 0); |
| gray->setPos(25, 25); |
| red->setParentItem(blue); |
| yellow->setParentItem(blue); |
| green->setParentItem(red); |
| gray->setParentItem(red); |
| |
| QGraphicsScene scene; |
| scene.addItem(blue); |
| |
| QGraphicsView view(&scene); |
| view.show(); |
| QVERIFY(QTest::qWaitForWindowExposed(&view)); |
| |
| // Pull out the items, closest item first |
| QList<QGraphicsItem *> items = scene.items(scene.itemsBoundingRect()); |
| QCOMPARE(items.at(0), (QGraphicsItem *)yellow); |
| QCOMPARE(items.at(1), (QGraphicsItem *)gray); |
| QCOMPARE(items.at(2), (QGraphicsItem *)green); |
| QCOMPARE(items.at(3), (QGraphicsItem *)red); |
| QCOMPARE(items.at(4), (QGraphicsItem *)blue); |
| |
| QCOMPARE(blue->counter, 0); |
| |
| // Send events to the toplevel item |
| QGraphicsSceneMouseEvent pressEvent(QEvent::GraphicsSceneMousePress); |
| QGraphicsSceneMouseEvent releaseEvent(QEvent::GraphicsSceneMouseRelease); |
| |
| pressEvent.setButton(Qt::LeftButton); |
| pressEvent.setScenePos(blue->mapToScene(5, 5)); |
| pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos())); |
| releaseEvent.setButton(Qt::LeftButton); |
| releaseEvent.setScenePos(blue->mapToScene(5, 5)); |
| releaseEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos())); |
| QApplication::sendEvent(&scene, &pressEvent); |
| QApplication::sendEvent(&scene, &releaseEvent); |
| |
| QCOMPARE(blue->counter, 2); |
| |
| // Send events to a level1 item |
| pressEvent.setScenePos(red->mapToScene(5, 5)); |
| pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos())); |
| releaseEvent.setScenePos(red->mapToScene(5, 5)); |
| releaseEvent.setScreenPos(view.mapFromScene(releaseEvent.scenePos())); |
| QApplication::sendEvent(&scene, &pressEvent); |
| QApplication::sendEvent(&scene, &releaseEvent); |
| |
| QCOMPARE(blue->counter, 2); |
| QCOMPARE(red->counter, 2); |
| |
| // Send events to a level2 item |
| pressEvent.setScenePos(green->mapToScene(5, 5)); |
| pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos())); |
| releaseEvent.setScenePos(green->mapToScene(5, 5)); |
| releaseEvent.setScreenPos(view.mapFromScene(releaseEvent.scenePos())); |
| QApplication::sendEvent(&scene, &pressEvent); |
| QApplication::sendEvent(&scene, &releaseEvent); |
| |
| QCOMPARE(blue->counter, 2); |
| QCOMPARE(red->counter, 2); |
| QCOMPARE(green->counter, 2); |
| |
| blue->setHandlesChildEvents(true); |
| |
| // Send events to a level1 item |
| pressEvent.setScenePos(red->mapToScene(5, 5)); |
| pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos())); |
| releaseEvent.setScenePos(red->mapToScene(5, 5)); |
| releaseEvent.setScreenPos(view.mapFromScene(releaseEvent.scenePos())); |
| QApplication::sendEvent(&scene, &pressEvent); |
| QApplication::sendEvent(&scene, &releaseEvent); |
| |
| QCOMPARE(blue->counter, 4); |
| QCOMPARE(red->counter, 2); |
| |
| // Send events to a level2 item |
| pressEvent.setScenePos(green->mapToScene(5, 5)); |
| pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos())); |
| releaseEvent.setScenePos(green->mapToScene(5, 5)); |
| releaseEvent.setScreenPos(view.mapFromScene(releaseEvent.scenePos())); |
| QApplication::sendEvent(&scene, &pressEvent); |
| QApplication::sendEvent(&scene, &releaseEvent); |
| |
| QCOMPARE(blue->counter, 6); |
| QCOMPARE(red->counter, 2); |
| QCOMPARE(green->counter, 2); |
| |
| blue->setHandlesChildEvents(false); |
| |
| // Send events to a level1 item |
| pressEvent.setScenePos(red->mapToScene(5, 5)); |
| pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos())); |
| releaseEvent.setScenePos(red->mapToScene(5, 5)); |
| releaseEvent.setScreenPos(view.mapFromScene(releaseEvent.scenePos())); |
| QApplication::sendEvent(&scene, &pressEvent); |
| QApplication::sendEvent(&scene, &releaseEvent); |
| |
| QCOMPARE(blue->counter, 6); |
| QCOMPARE(red->counter, 4); |
| |
| // Send events to a level2 item |
| pressEvent.setScenePos(green->mapToScene(5, 5)); |
| pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos())); |
| releaseEvent.setScenePos(green->mapToScene(5, 5)); |
| releaseEvent.setScreenPos(view.mapFromScene(releaseEvent.scenePos())); |
| QApplication::sendEvent(&scene, &pressEvent); |
| QApplication::sendEvent(&scene, &releaseEvent); |
| |
| QCOMPARE(blue->counter, 6); |
| QCOMPARE(red->counter, 4); |
| QCOMPARE(green->counter, 4); |
| } |
| |
| void tst_QGraphicsItem::handlesChildEvents2() |
| { |
| ChildEventTester *root = new ChildEventTester(QRectF(0, 0, 10, 10)); |
| root->setHandlesChildEvents(true); |
| QVERIFY(root->handlesChildEvents()); |
| |
| ChildEventTester *child = new ChildEventTester(QRectF(0, 0, 10, 10), root); |
| QVERIFY(!child->handlesChildEvents()); |
| |
| ChildEventTester *child2 = new ChildEventTester(QRectF(0, 0, 10, 10)); |
| ChildEventTester *child3 = new ChildEventTester(QRectF(0, 0, 10, 10), child2); |
| ChildEventTester *child4 = new ChildEventTester(QRectF(0, 0, 10, 10), child3); |
| child2->setParentItem(root); |
| QVERIFY(!child2->handlesChildEvents()); |
| QVERIFY(!child3->handlesChildEvents()); |
| QVERIFY(!child4->handlesChildEvents()); |
| |
| QGraphicsScene scene; |
| scene.addItem(root); |
| |
| QGraphicsView view(&scene); |
| view.show(); |
| QVERIFY(QTest::qWaitForWindowExposed(&view)); |
| QApplication::processEvents(); |
| |
| QMouseEvent event(QEvent::MouseButtonPress, view.mapFromScene(5, 5), |
| view.viewport()->mapToGlobal(view.mapFromScene(5, 5)), Qt::LeftButton, 0, 0); |
| QApplication::sendEvent(view.viewport(), &event); |
| |
| QTRY_COMPARE(root->counter, 1); |
| } |
| |
| void tst_QGraphicsItem::handlesChildEvents3() |
| { |
| QGraphicsScene scene; |
| QEvent activate(QEvent::WindowActivate); |
| QApplication::sendEvent(&scene, &activate); |
| |
| ChildEventTester *group2 = new ChildEventTester(QRectF(), 0); |
| ChildEventTester *group1 = new ChildEventTester(QRectF(), group2); |
| ChildEventTester *leaf = new ChildEventTester(QRectF(), group1); |
| scene.addItem(group2); |
| |
| leaf->setFlag(QGraphicsItem::ItemIsFocusable); |
| group1->setFlag(QGraphicsItem::ItemIsFocusable); |
| group1->setHandlesChildEvents(true); |
| group2->setFlag(QGraphicsItem::ItemIsFocusable); |
| group2->setHandlesChildEvents(true); |
| |
| leaf->setFocus(); |
| QVERIFY(leaf->hasFocus()); // group2 stole the event, but leaf still got focus |
| QVERIFY(!group1->hasFocus()); |
| QVERIFY(!group2->hasFocus()); |
| QCOMPARE(leaf->counter, 0); |
| QCOMPARE(group1->counter, 0); |
| QCOMPARE(group2->counter, 1); |
| |
| group1->setFocus(); |
| QVERIFY(group1->hasFocus()); // group2 stole the event, but group1 still got focus |
| QVERIFY(!leaf->hasFocus()); |
| QVERIFY(!group2->hasFocus()); |
| QCOMPARE(leaf->counter, 0); |
| QCOMPARE(group1->counter, 0); |
| QCOMPARE(group2->counter, 2); |
| |
| group2->setFocus(); |
| QVERIFY(group2->hasFocus()); // group2 stole the event, and now group2 also has focus |
| QVERIFY(!leaf->hasFocus()); |
| QVERIFY(!group1->hasFocus()); |
| QCOMPARE(leaf->counter, 0); |
| QCOMPARE(group1->counter, 0); |
| QCOMPARE(group2->counter, 3); |
| } |
| |
| |
| class ChildEventFilterTester : public ChildEventTester |
| { |
| public: |
| ChildEventFilterTester(const QRectF &rect, QGraphicsItem *parent = 0) |
| : ChildEventTester(rect, parent), filter(QEvent::None) |
| { } |
| |
| QEvent::Type filter; |
| |
| protected: |
| bool sceneEventFilter(QGraphicsItem *item, QEvent *event) |
| { |
| Q_UNUSED(item); |
| if (event->type() == filter) { |
| ++counter; |
| return true; |
| } |
| return false; |
| } |
| }; |
| |
| void tst_QGraphicsItem::filtersChildEvents() |
| { |
| QGraphicsScene scene; |
| ChildEventFilterTester *root = new ChildEventFilterTester(QRectF(0, 0, 10, 10)); |
| ChildEventFilterTester *filter = new ChildEventFilterTester(QRectF(10, 10, 10, 10), root); |
| ChildEventTester *child = new ChildEventTester(QRectF(20, 20, 10, 10), filter); |
| |
| // setup filter |
| filter->setFiltersChildEvents(true); |
| filter->filter = QEvent::GraphicsSceneMousePress; |
| |
| scene.addItem(root); |
| |
| QGraphicsView view(&scene); |
| view.show(); |
| QVERIFY(QTest::qWaitForWindowExposed(&view)); |
| |
| QGraphicsSceneMouseEvent pressEvent(QEvent::GraphicsSceneMousePress); |
| QGraphicsSceneMouseEvent releaseEvent(QEvent::GraphicsSceneMouseRelease); |
| |
| // send event to child |
| pressEvent.setButton(Qt::LeftButton); |
| pressEvent.setScenePos(QPointF(25, 25));//child->mapToScene(5, 5)); |
| pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos())); |
| releaseEvent.setButton(Qt::LeftButton); |
| releaseEvent.setScenePos(QPointF(25, 25));//child->mapToScene(5, 5)); |
| releaseEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos())); |
| QApplication::sendEvent(&scene, &pressEvent); |
| QApplication::sendEvent(&scene, &releaseEvent); |
| |
| QTRY_COMPARE(child->counter, 1); // mouse release is not filtered |
| QCOMPARE(filter->counter, 1); // mouse press is filtered |
| QCOMPARE(root->counter, 0); |
| |
| // add another filter |
| root->setFiltersChildEvents(true); |
| root->filter = QEvent::GraphicsSceneMouseRelease; |
| |
| // send event to child |
| QApplication::sendEvent(&scene, &pressEvent); |
| QApplication::sendEvent(&scene, &releaseEvent); |
| |
| QCOMPARE(child->counter, 1); |
| QCOMPARE(filter->counter, 2); // mouse press is filtered |
| QCOMPARE(root->counter, 1); // mouse release is filtered |
| |
| // reparent to another sub-graph |
| ChildEventTester *parent = new ChildEventTester(QRectF(10, 10, 10, 10), root); |
| child->setParentItem(parent); |
| |
| // send event to child |
| QApplication::sendEvent(&scene, &pressEvent); |
| QApplication::sendEvent(&scene, &releaseEvent); |
| |
| QCOMPARE(child->counter, 2); // mouse press is _not_ filtered |
| QCOMPARE(parent->counter, 0); |
| QCOMPARE(filter->counter, 2); |
| QCOMPARE(root->counter, 2); // mouse release is filtered |
| } |
| |
| void tst_QGraphicsItem::filtersChildEvents2() |
| { |
| ChildEventFilterTester *root = new ChildEventFilterTester(QRectF(0, 0, 10, 10)); |
| root->setFiltersChildEvents(true); |
| root->filter = QEvent::GraphicsSceneMousePress; |
| QVERIFY(root->filtersChildEvents()); |
| |
| ChildEventTester *child = new ChildEventTester(QRectF(0, 0, 10, 10), root); |
| QVERIFY(!child->filtersChildEvents()); |
| |
| ChildEventTester *child2 = new ChildEventTester(QRectF(0, 0, 10, 10)); |
| ChildEventTester *child3 = new ChildEventTester(QRectF(0, 0, 10, 10), child2); |
| ChildEventTester *child4 = new ChildEventTester(QRectF(0, 0, 10, 10), child3); |
| |
| child2->setParentItem(root); |
| QVERIFY(!child2->filtersChildEvents()); |
| QVERIFY(!child3->filtersChildEvents()); |
| QVERIFY(!child4->filtersChildEvents()); |
| |
| QGraphicsScene scene; |
| scene.addItem(root); |
| |
| QGraphicsView view(&scene); |
| view.show(); |
| |
| QVERIFY(QTest::qWaitForWindowExposed(&view)); |
| QApplication::processEvents(); |
| |
| QMouseEvent event(QEvent::MouseButtonPress, view.mapFromScene(5, 5), |
| view.viewport()->mapToGlobal(view.mapFromScene(5, 5)), Qt::LeftButton, 0, 0); |
| QApplication::sendEvent(view.viewport(), &event); |
| |
| QTRY_COMPARE(root->counter, 1); |
| QCOMPARE(child->counter, 0); |
| QCOMPARE(child2->counter, 0); |
| QCOMPARE(child3->counter, 0); |
| QCOMPARE(child4->counter, 0); |
| } |
| |
| class CustomItem : public QGraphicsItem |
| { |
| public: |
| QRectF boundingRect() const |
| { return QRectF(-110, -110, 220, 220); } |
| |
| void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) |
| { |
| for (int x = -100; x <= 100; x += 25) |
| painter->drawLine(x, -100, x, 100); |
| for (int y = -100; y <= 100; y += 25) |
| painter->drawLine(-100, y, 100, y); |
| |
| QFont font = painter->font(); |
| font.setPointSize(4); |
| painter->setFont(font); |
| for (int x = -100; x < 100; x += 25) { |
| const QString prefix = QString::number(x) + QLatin1Char('x'); |
| for (int y = -100; y < 100; y += 25) |
| painter->drawText(QRectF(x, y, 25, 25), Qt::AlignCenter, prefix + QString::number(y)); |
| } |
| } |
| }; |
| |
| void tst_QGraphicsItem::ensureVisible() |
| { |
| QGraphicsScene scene; |
| scene.setSceneRect(-200, -200, 400, 400); |
| QGraphicsItem *item = new CustomItem; |
| scene.addItem(item); |
| |
| QGraphicsView view(&scene); |
| view.setFixedSize(300, 300); |
| view.show(); |
| QVERIFY(QTest::qWaitForWindowExposed(&view)); |
| |
| for (int i = 0; i < 25; ++i) { |
| view.scale(qreal(1.06), qreal(1.06)); |
| QApplication::processEvents(); |
| } |
| |
| item->ensureVisible(-100, -100, 25, 25); |
| |
| for (int x = -100; x < 100; x += 25) { |
| for (int y = -100; y < 100; y += 25) { |
| int xmargin = QRandomGenerator::global()->bounded(75); |
| int ymargin = QRandomGenerator::global()->bounded(75); |
| item->ensureVisible(x, y, 25, 25, xmargin, ymargin); |
| QApplication::processEvents(); |
| |
| QPolygonF viewScenePoly; |
| viewScenePoly << view.mapToScene(view.rect().topLeft()) |
| << view.mapToScene(view.rect().topRight()) |
| << view.mapToScene(view.rect().bottomRight()) |
| << view.mapToScene(view.rect().bottomLeft()); |
| |
| QVERIFY(scene.items(viewScenePoly).contains(item)); |
| |
| QPainterPath path; |
| path.addPolygon(viewScenePoly); |
| QVERIFY(path.contains(item->mapToScene(x + 12, y + 12))); |
| |
| QPolygonF viewScenePolyMinusMargins; |
| viewScenePolyMinusMargins << view.mapToScene(view.rect().topLeft() + QPoint(xmargin, ymargin)) |
| << view.mapToScene(view.rect().topRight() + QPoint(-xmargin, ymargin)) |
| << view.mapToScene(view.rect().bottomRight() + QPoint(-xmargin, -ymargin)) |
| << view.mapToScene(view.rect().bottomLeft() + QPoint(xmargin, -ymargin)); |
| |
| QPainterPath path2; |
| path2.addPolygon(viewScenePolyMinusMargins); |
| QVERIFY(path2.contains(item->mapToScene(x + 12, y + 12))); |
| } |
| } |
| |
| item->ensureVisible(100, 100, 25, 25); |
| QTest::qWait(25); |
| } |
| |
| #ifndef QT_NO_CURSOR |
| void tst_QGraphicsItem::cursor() |
| { |
| QGraphicsScene scene; |
| QGraphicsView view(&scene); |
| view.showFullScreen(); |
| QVERIFY(QTest::qWaitForWindowExposed(&view)); |
| const Qt::CursorShape viewportShape = view.viewport()->cursor().shape(); |
| |
| QGraphicsRectItem *item1 = scene.addRect(QRectF(-100, 0, 50, 50)); |
| QGraphicsRectItem *item2 = scene.addRect(QRectF(50, 0, 50, 50)); |
| |
| QVERIFY(!item1->hasCursor()); |
| QVERIFY(!item2->hasCursor()); |
| |
| item1->setCursor(Qt::IBeamCursor); |
| item2->setCursor(Qt::PointingHandCursor); |
| |
| QVERIFY(item1->hasCursor()); |
| QVERIFY(item2->hasCursor()); |
| |
| item1->setCursor(QCursor()); |
| item2->setCursor(QCursor()); |
| |
| QVERIFY(item1->hasCursor()); |
| QVERIFY(item2->hasCursor()); |
| |
| item1->unsetCursor(); |
| item2->unsetCursor(); |
| |
| QVERIFY(!item1->hasCursor()); |
| QVERIFY(!item2->hasCursor()); |
| |
| item1->setCursor(Qt::IBeamCursor); |
| item2->setCursor(Qt::PointingHandCursor); |
| |
| QPoint viewCenter = view.rect().center(); |
| QPoint item1Center = view.mapFromScene(item1->sceneBoundingRect().center()); |
| QPoint item2Center = view.mapFromScene(item2->sceneBoundingRect().center()); |
| |
| { |
| QMouseEvent event(QEvent::MouseMove, viewCenter, view.viewport()->mapToGlobal(viewCenter), Qt::NoButton, 0, 0); |
| QApplication::sendEvent(view.viewport(), &event); |
| } |
| |
| QCOMPARE(view.viewport()->cursor().shape(), viewportShape); |
| |
| { |
| QMouseEvent event(QEvent::MouseMove, item1Center, view.viewport()->mapToGlobal(item1Center), Qt::NoButton, 0, 0); |
| QApplication::sendEvent(view.viewport(), &event); |
| } |
| |
| QCOMPARE(view.viewport()->cursor().shape(), item1->cursor().shape()); |
| |
| { |
| QMouseEvent event(QEvent::MouseMove, item2Center, view.viewport()->mapToGlobal(item2Center), Qt::NoButton, 0, 0); |
| QApplication::sendEvent(view.viewport(), &event); |
| } |
| |
| QCOMPARE(view.viewport()->cursor().shape(), item2->cursor().shape()); |
| |
| { |
| QMouseEvent event(QEvent::MouseMove, viewCenter, view.viewport()->mapToGlobal(viewCenter), Qt::NoButton, 0, 0); |
| QApplication::sendEvent(view.viewport(), &event); |
| } |
| |
| QCOMPARE(view.viewport()->cursor().shape(), viewportShape); |
| |
| item1->setEnabled(false); |
| { |
| QMouseEvent event(QEvent::MouseMove, item1Center, view.viewport()->mapToGlobal(item1Center), Qt::NoButton, 0, 0); |
| QApplication::sendEvent(view.viewport(), &event); |
| } |
| |
| QCOMPARE(view.viewport()->cursor().shape(), viewportShape); |
| } |
| #endif |
| /* |
| void tst_QGraphicsItem::textControlGetterSetter() |
| { |
| QGraphicsTextItem *item = new QGraphicsTextItem; |
| QCOMPARE(item->textControl()->parent(), item); |
| QPointer<QWidgetTextControl> control = item->textControl(); |
| delete item; |
| QVERIFY(!control); |
| |
| item = new QGraphicsTextItem; |
| |
| QPointer<QWidgetTextControl> oldControl = control; |
| control = new QWidgetTextControl; |
| |
| item->setTextControl(control); |
| QCOMPARE(item->textControl(), control); |
| QVERIFY(!control->parent()); |
| QVERIFY(!oldControl); |
| |
| // set some text to give it a size, to test that |
| // setTextControl (re)connects signals |
| const QRectF oldBoundingRect = item->boundingRect(); |
| QVERIFY(oldBoundingRect.isValid()); |
| item->setPlainText("Some text"); |
| item->adjustSize(); |
| QVERIFY(item->boundingRect().isValid()); |
| QVERIFY(item->boundingRect() != oldBoundingRect); |
| |
| // test that on setting a control the item size |
| // is adjusted |
| oldControl = control; |
| control = new QWidgetTextControl; |
| control->setPlainText("foo!"); |
| item->setTextControl(control); |
| QCOMPARE(item->boundingRect().size(), control->document()->documentLayout()->documentSize()); |
| |
| QVERIFY(oldControl); |
| delete oldControl; |
| |
| delete item; |
| QVERIFY(control); |
| delete control; |
| } |
| */ |
| |
| void tst_QGraphicsItem::defaultItemTest_QGraphicsLineItem() |
| { |
| QGraphicsLineItem item; |
| QCOMPARE(item.line(), QLineF()); |
| QCOMPARE(item.pen(), QPen()); |
| QCOMPARE(item.shape(), QPainterPath()); |
| |
| item.setPen(QPen(Qt::black, 1)); |
| QCOMPARE(item.pen(), QPen(Qt::black, 1)); |
| item.setLine(QLineF(0, 0, 10, 0)); |
| QCOMPARE(item.line(), QLineF(0, 0, 10, 0)); |
| QCOMPARE(item.boundingRect(), QRectF(-0.5, -0.5, 11, 1)); |
| QCOMPARE(item.shape().elementCount(), 11); |
| |
| QPainterPath path; |
| path.moveTo(0, -0.5); |
| path.lineTo(10, -0.5); |
| path.lineTo(10.5, -0.5); |
| path.lineTo(10.5, 0.5); |
| path.lineTo(10, 0.5); |
| path.lineTo(0, 0.5); |
| path.lineTo(-0.5, 0.5); |
| path.lineTo(-0.5, -0.5); |
| path.lineTo(0, -0.5); |
| path.lineTo(0, 0); |
| path.lineTo(10, 0); |
| path.closeSubpath(); |
| |
| for (int i = 0; i < 11; ++i) |
| QCOMPARE(QPointF(item.shape().elementAt(i)), QPointF(path.elementAt(i))); |
| } |
| |
| void tst_QGraphicsItem::defaultItemTest_QGraphicsPixmapItem() |
| { |
| QGraphicsPixmapItem item; |
| QVERIFY(item.pixmap().isNull()); |
| QCOMPARE(item.offset(), QPointF()); |
| QCOMPARE(item.transformationMode(), Qt::FastTransformation); |
| |
| QPixmap pixmap(300, 200); |
| pixmap.fill(Qt::red); |
| item.setPixmap(pixmap); |
| QCOMPARE(item.pixmap(), pixmap); |
| |
| item.setTransformationMode(Qt::FastTransformation); |
| QCOMPARE(item.transformationMode(), Qt::FastTransformation); |
| item.setTransformationMode(Qt::SmoothTransformation); |
| QCOMPARE(item.transformationMode(), Qt::SmoothTransformation); |
| |
| item.setOffset(-15, -15); |
| QCOMPARE(item.offset(), QPointF(-15, -15)); |
| item.setOffset(QPointF(-10, -10)); |
| QCOMPARE(item.offset(), QPointF(-10, -10)); |
| |
| QCOMPARE(item.boundingRect(), QRectF(-10, -10, 300, 200)); |
| } |
| |
| void tst_QGraphicsItem::defaultItemTest_QGraphicsTextItem() |
| { |
| QGraphicsTextItem *text = new QGraphicsTextItem; |
| QVERIFY(!text->openExternalLinks()); |
| QVERIFY(text->textCursor().isNull()); |
| QCOMPARE(text->defaultTextColor(), QPalette().color(QPalette::Text)); |
| QVERIFY(text->document() != 0); |
| QCOMPARE(text->font(), QApplication::font()); |
| QCOMPARE(text->textInteractionFlags(), Qt::TextInteractionFlags(Qt::NoTextInteraction)); |
| QCOMPARE(text->textWidth(), -1.0); |
| QCOMPARE(text->toPlainText(), QString("")); |
| |
| QGraphicsScene scene; |
| scene.addItem(text); |
| text->setPlainText("Hello world"); |
| text->setFlag(QGraphicsItem::ItemIsMovable); |
| |
| { |
| QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress); |
| event.setScenePos(QPointF(1, 1)); |
| event.setButton(Qt::LeftButton); |
| event.setButtons(Qt::LeftButton); |
| QApplication::sendEvent(&scene, &event); |
| QGraphicsSceneMouseEvent event2(QEvent::GraphicsSceneMouseMove); |
| event2.setScenePos(QPointF(11, 11)); |
| event2.setButton(Qt::LeftButton); |
| event2.setButtons(Qt::LeftButton); |
| QApplication::sendEvent(&scene, &event2); |
| } |
| |
| QCOMPARE(text->pos(), QPointF(10, 10)); |
| |
| text->setTextInteractionFlags(Qt::NoTextInteraction); |
| QVERIFY(!(text->flags() & QGraphicsItem::ItemAcceptsInputMethod)); |
| text->setTextInteractionFlags(Qt::TextEditorInteraction); |
| QCOMPARE(text->textInteractionFlags(), Qt::TextInteractionFlags(Qt::TextEditorInteraction)); |
| QVERIFY(text->flags() & QGraphicsItem::ItemAcceptsInputMethod); |
| |
| { |
| QGraphicsSceneMouseEvent event2(QEvent::GraphicsSceneMouseMove); |
| event2.setScenePos(QPointF(21, 21)); |
| event2.setButton(Qt::LeftButton); |
| event2.setButtons(Qt::LeftButton); |
| QApplication::sendEvent(&scene, &event2); |
| } |
| |
| QCOMPARE(text->pos(), QPointF(20, 20)); // clicked on edge, item moved |
| } |
| |
| void tst_QGraphicsItem::defaultItemTest_QGraphicsEllipseItem() |
| { |
| QGraphicsEllipseItem item; |
| item.setPen(QPen(Qt::black, 0)); |
| QVERIFY(item.rect().isNull()); |
| QVERIFY(item.boundingRect().isNull()); |
| QVERIFY(item.shape().isEmpty()); |
| QCOMPARE(item.spanAngle(), 360 * 16); |
| QCOMPARE(item.startAngle(), 0); |
| |
| item.setRect(0, 0, 100, 100); |
| QCOMPARE(item.boundingRect(), QRectF(0, 0, 100, 100)); |
| |
| item.setSpanAngle(90 * 16); |
| // for some reason, the bounding rect has very few significant digits |
| // (i.e. it's likely that floats are being used inside it), so we |
| // must force the conversion from qreals to float or these tests will fail |
| QCOMPARE(float(item.boundingRect().left()), 50.0f); |
| QVERIFY(qFuzzyIsNull(float(item.boundingRect().top()))); |
| QCOMPARE(float(item.boundingRect().width()), 50.0f); |
| QCOMPARE(float(item.boundingRect().height()), 50.0f); |
| |
| item.setPen(QPen(Qt::black, 1)); |
| QCOMPARE(item.boundingRect(), QRectF(49.5, -0.5, 51, 51)); |
| |
| item.setSpanAngle(180 * 16); |
| QCOMPARE(item.boundingRect(), QRectF(-0.5, -0.5, 101, 51)); |
| |
| item.setSpanAngle(360 * 16); |
| QCOMPARE(item.boundingRect(), QRectF(-0.5, -0.5, 101, 101)); |
| } |
| |
| class ItemChangeTester : public QGraphicsRectItem |
| { |
| public: |
| ItemChangeTester() |
| { setFlag(ItemSendsGeometryChanges); clear(); } |
| ItemChangeTester(QGraphicsItem *parent) : QGraphicsRectItem(parent) |
| { setFlag(ItemSendsGeometryChanges); clear(); } |
| |
| void clear() |
| { |
| itemChangeReturnValue = QVariant(); |
| itemSceneChangeTargetScene = 0; |
| changes.clear(); |
| values.clear(); |
| oldValues.clear(); |
| } |
| |
| QVariant itemChangeReturnValue; |
| QGraphicsScene *itemSceneChangeTargetScene; |
| |
| QList<GraphicsItemChange> changes; |
| QList<QVariant> values; |
| QList<QVariant> oldValues; |
| protected: |
| QVariant itemChange(GraphicsItemChange change, const QVariant &value) |
| { |
| changes << change; |
| values << value; |
| switch (change) { |
| case QGraphicsItem::ItemPositionChange: |
| oldValues << pos(); |
| break; |
| case QGraphicsItem::ItemPositionHasChanged: |
| break; |
| #if QT_DEPRECATED_SINCE(5, 14) |
| case QGraphicsItem::ItemMatrixChange: { |
| #if QT_DEPRECATED_SINCE(5, 13) |
| QT_WARNING_PUSH |
| QT_WARNING_DISABLE_DEPRECATED |
| QVariant variant; |
| variant.setValue<QMatrix>(matrix()); |
| oldValues << variant; |
| QT_WARNING_POP |
| #endif |
| } |
| break; |
| #endif |
| case QGraphicsItem::ItemTransformChange: { |
| QVariant variant; |
| variant.setValue<QTransform>(transform()); |
| oldValues << variant; |
| } |
| break; |
| case QGraphicsItem::ItemTransformHasChanged: |
| break; |
| case QGraphicsItem::ItemVisibleChange: |
| oldValues << isVisible(); |
| break; |
| case QGraphicsItem::ItemVisibleHasChanged: |
| break; |
| case QGraphicsItem::ItemEnabledChange: |
| oldValues << isEnabled(); |
| break; |
| case QGraphicsItem::ItemEnabledHasChanged: |
| break; |
| case QGraphicsItem::ItemSelectedChange: |
| oldValues << isSelected(); |
| break; |
| case QGraphicsItem::ItemSelectedHasChanged: |
| break; |
| case QGraphicsItem::ItemParentChange: |
| oldValues << QVariant::fromValue<void *>(parentItem()); |
| break; |
| case QGraphicsItem::ItemParentHasChanged: |
| break; |
| case QGraphicsItem::ItemChildAddedChange: |
| oldValues << childItems().size(); |
| break; |
| case QGraphicsItem::ItemChildRemovedChange: |
| oldValues << childItems().size(); |
| break; |
| case QGraphicsItem::ItemSceneChange: |
| oldValues << QVariant::fromValue<QGraphicsScene *>(scene()); |
| if (itemSceneChangeTargetScene |
| && qvariant_cast<QGraphicsScene *>(value) |
| && itemSceneChangeTargetScene != qvariant_cast<QGraphicsScene *>(value)) { |
| return QVariant::fromValue<QGraphicsScene *>(itemSceneChangeTargetScene); |
| } |
| return value; |
| case QGraphicsItem::ItemSceneHasChanged: |
| break; |
| case QGraphicsItem::ItemCursorChange: |
| #ifndef QT_NO_CURSOR |
| oldValues << cursor(); |
| #endif |
| break; |
| case QGraphicsItem::ItemCursorHasChanged: |
| break; |
| case QGraphicsItem::ItemToolTipChange: |
| oldValues << toolTip(); |
| break; |
| case QGraphicsItem::ItemToolTipHasChanged: |
| break; |
| case QGraphicsItem::ItemFlagsChange: |
| oldValues << quint32(flags()); |
| break; |
| case QGraphicsItem::ItemFlagsHaveChanged: |
| break; |
| case QGraphicsItem::ItemZValueChange: |
| oldValues << zValue(); |
| break; |
| case QGraphicsItem::ItemZValueHasChanged: |
| break; |
| case QGraphicsItem::ItemOpacityChange: |
| oldValues << opacity(); |
| break; |
| case QGraphicsItem::ItemOpacityHasChanged: |
| break; |
| case QGraphicsItem::ItemScenePositionHasChanged: |
| break; |
| case QGraphicsItem::ItemRotationChange: |
| oldValues << rotation(); |
| break; |
| case QGraphicsItem::ItemRotationHasChanged: |
| break; |
| case QGraphicsItem::ItemScaleChange: |
| oldValues << scale(); |
| break; |
| case QGraphicsItem::ItemScaleHasChanged: |
| break; |
| case QGraphicsItem::ItemTransformOriginPointChange: |
| oldValues << transformOriginPoint(); |
| break; |
| case QGraphicsItem::ItemTransformOriginPointHasChanged: |
| break; |
| } |
| return itemChangeReturnValue.isValid() ? itemChangeReturnValue : value; |
| } |
| }; |
| |
| void tst_QGraphicsItem::itemChange() |
| { |
| ItemChangeTester tester; |
| tester.itemSceneChangeTargetScene = 0; |
| |
| ItemChangeTester testerHelper; |
| QVERIFY(tester.changes.isEmpty()); |
| QVERIFY(tester.values.isEmpty()); |
| |
| int changeCount = 0; |
| { |
| // ItemEnabledChange |
| tester.itemChangeReturnValue = true; |
| tester.setEnabled(false); |
| ++changeCount; |
| ++changeCount; // HasChanged |
| QCOMPARE(tester.changes.size(), changeCount); |
| QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemEnabledChange); |
| QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemEnabledHasChanged); |
| QCOMPARE(tester.values.at(tester.values.size() - 2), QVariant(false)); |
| QCOMPARE(tester.values.at(tester.values.size() - 1), QVariant(true)); |
| QCOMPARE(tester.oldValues.last(), QVariant(true)); |
| QCOMPARE(tester.isEnabled(), true); |
| } |
| #if QT_DEPRECATED_SINCE(5, 13) |
| { |
| QT_WARNING_PUSH |
| QT_WARNING_DISABLE_DEPRECATED // QDesktopWidget::screen() |
| // ItemMatrixChange / ItemTransformHasChanged |
| tester.itemChangeReturnValue.setValue<QMatrix>(QMatrix().rotate(90)); |
| tester.setMatrix(QMatrix().translate(50, 0), true); |
| ++changeCount; // notification sent too |
| QCOMPARE(tester.changes.size(), ++changeCount); |
| QCOMPARE(int(tester.changes.at(tester.changes.size() - 2)), int(QGraphicsItem::ItemMatrixChange)); |
| QCOMPARE(int(tester.changes.last()), int(QGraphicsItem::ItemTransformHasChanged)); |
| QCOMPARE(qvariant_cast<QMatrix>(tester.values.at(tester.values.size() - 2)), |
| QMatrix().translate(50, 0)); |
| QCOMPARE(tester.values.last(), QVariant(QTransform(QMatrix().rotate(90)))); |
| QVariant variant; |
| variant.setValue<QMatrix>(QMatrix()); |
| QCOMPARE(tester.oldValues.last(), variant); |
| QCOMPARE(tester.matrix(), QMatrix().rotate(90)); |
| QT_WARNING_POP |
| } |
| #endif |
| { |
| tester.resetTransform(); |
| ++changeCount; |
| ++changeCount; // notification sent too |
| |
| // ItemTransformChange / ItemTransformHasChanged |
| tester.itemChangeReturnValue.setValue<QTransform>(QTransform().rotate(90)); |
| tester.setTransform(QTransform::fromTranslate(50, 0), true); |
| ++changeCount; // notification sent too |
| ++changeCount; |
| QCOMPARE(tester.changes.size(), changeCount); |
| QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemTransformChange); |
| QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemTransformHasChanged); |
| QCOMPARE(qvariant_cast<QTransform>(tester.values.at(tester.values.size() - 2)), |
| QTransform().translate(50, 0)); |
| QCOMPARE(qvariant_cast<QTransform>(tester.values.at(tester.values.size() - 1)), |
| QTransform().rotate(90)); |
| QVariant variant; |
| variant.setValue<QTransform>(QTransform()); |
| QCOMPARE(tester.oldValues.last(), variant); |
| QCOMPARE(tester.transform(), QTransform().rotate(90)); |
| } |
| { |
| // ItemPositionChange / ItemPositionHasChanged |
| tester.itemChangeReturnValue = QPointF(42, 0); |
| tester.setPos(0, 42); |
| ++changeCount; // notification sent too |
| ++changeCount; |
| QCOMPARE(tester.changes.size(), changeCount); |
| QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemPositionChange); |
| QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemPositionHasChanged); |
| QCOMPARE(tester.values.at(tester.changes.size() - 2), QVariant(QPointF(0, 42))); |
| QCOMPARE(tester.values.at(tester.changes.size() - 1), QVariant(QPointF(42, 0))); |
| QCOMPARE(tester.oldValues.last(), QVariant(QPointF())); |
| QCOMPARE(tester.pos(), QPointF(42, 0)); |
| } |
| { |
| // ItemZValueChange / ItemZValueHasChanged |
| tester.itemChangeReturnValue = qreal(2.0); |
| tester.setZValue(1.0); |
| ++changeCount; // notification sent too |
| ++changeCount; |
| QCOMPARE(tester.changes.size(), changeCount); |
| QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemZValueChange); |
| QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemZValueHasChanged); |
| QCOMPARE(tester.values.at(tester.changes.size() - 2), QVariant(qreal(1.0))); |
| QCOMPARE(tester.values.at(tester.changes.size() - 1), QVariant(qreal(2.0))); |
| QCOMPARE(tester.oldValues.last(), QVariant(qreal(0.0))); |
| QCOMPARE(tester.zValue(), qreal(2.0)); |
| } |
| { |
| // ItemRotationChange / ItemRotationHasChanged |
| tester.itemChangeReturnValue = qreal(15.0); |
| tester.setRotation(10.0); |
| ++changeCount; // notification sent too |
| ++changeCount; |
| QCOMPARE(tester.changes.size(), changeCount); |
| QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemRotationChange); |
| QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemRotationHasChanged); |
| QCOMPARE(tester.values.at(tester.changes.size() - 2), QVariant(qreal(10.0))); |
| QCOMPARE(tester.values.at(tester.changes.size() - 1), QVariant(qreal(15.0))); |
| QCOMPARE(tester.oldValues.last(), QVariant(qreal(0.0))); |
| QCOMPARE(tester.rotation(), qreal(15.0)); |
| } |
| { |
| // ItemScaleChange / ItemScaleHasChanged |
| tester.itemChangeReturnValue = qreal(2.0); |
| tester.setScale(1.5); |
| ++changeCount; // notification sent too |
| ++changeCount; |
| QCOMPARE(tester.changes.size(), changeCount); |
| QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemScaleChange); |
| QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemScaleHasChanged); |
| QCOMPARE(tester.values.at(tester.changes.size() - 2), QVariant(qreal(1.5))); |
| QCOMPARE(tester.values.at(tester.changes.size() - 1), QVariant(qreal(2.0))); |
| QCOMPARE(tester.oldValues.last(), QVariant(qreal(1.0))); |
| QCOMPARE(tester.scale(), qreal(2.0)); |
| } |
| { |
| // ItemTransformOriginPointChange / ItemTransformOriginPointHasChanged |
| tester.itemChangeReturnValue = QPointF(2.0, 2.0); |
| tester.setTransformOriginPoint(1.0, 1.0); |
| ++changeCount; // notification sent too |
| ++changeCount; |
| QCOMPARE(tester.changes.size(), changeCount); |
| QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemTransformOriginPointChange); |
| QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemTransformOriginPointHasChanged); |
| QCOMPARE(tester.values.at(tester.changes.size() - 2), QVariant(QPointF(1.0, 1.0))); |
| QCOMPARE(tester.values.at(tester.changes.size() - 1), QVariant(QPointF(2.0, 2.0))); |
| QCOMPARE(tester.oldValues.last(), QVariant(QPointF(0.0, 0.0))); |
| QCOMPARE(tester.transformOriginPoint(), QPointF(2.0, 2.0)); |
| } |
| { |
| // ItemFlagsChange |
| tester.itemChangeReturnValue = QGraphicsItem::ItemIsSelectable; |
| tester.setFlag(QGraphicsItem::ItemIsSelectable, false); |
| QCOMPARE(tester.changes.size(), changeCount); // No change |
| tester.setFlag(QGraphicsItem::ItemIsSelectable, true); |
| ++changeCount; |
| ++changeCount; // ItemFlagsHasChanged |
| QCOMPARE(tester.changes.size(), changeCount); |
| QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemFlagsChange); |
| QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemFlagsHaveChanged); |
| QVariant expectedFlags = QVariant::fromValue<quint32>(QGraphicsItem::GraphicsItemFlags(QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemSendsGeometryChanges)); |
| QCOMPARE(tester.values.at(tester.values.size() - 2), expectedFlags); |
| QCOMPARE(tester.values.at(tester.values.size() - 1), QVariant::fromValue<quint32>((quint32)QGraphicsItem::ItemIsSelectable)); |
| } |
| { |
| // ItemSelectedChange |
| tester.setSelected(false); |
| QCOMPARE(tester.changes.size(), changeCount); // No change :-) |
| tester.itemChangeReturnValue = true; |
| tester.setSelected(true); |
| ++changeCount; |
| ++changeCount; // ItemSelectedHasChanged |
| QCOMPARE(tester.changes.size(), changeCount); |
| QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemSelectedChange); |
| QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemSelectedHasChanged); |
| QCOMPARE(tester.values.at(tester.values.size() - 2), QVariant(true)); |
| QCOMPARE(tester.values.at(tester.values.size() - 1), QVariant(true)); |
| QCOMPARE(tester.oldValues.last(), QVariant(false)); |
| QCOMPARE(tester.isSelected(), true); |
| |
| tester.itemChangeReturnValue = false; |
| tester.setSelected(true); |
| |
| // the value hasn't changed to the itemChange return value |
| // bacause itemChange is never called (true -> true is a noop). |
| QCOMPARE(tester.isSelected(), true); |
| } |
| { |
| // ItemVisibleChange |
| tester.itemChangeReturnValue = false; |
| QVERIFY(tester.isVisible()); |
| tester.setVisible(false); |
| ++changeCount; // ItemVisibleChange |
| ++changeCount; // ItemSelectedChange |
| ++changeCount; // ItemSelectedHasChanged |
| ++changeCount; // ItemVisibleHasChanged |
| QCOMPARE(tester.changes.size(), changeCount); |
| QCOMPARE(tester.changes.at(tester.changes.size() - 4), QGraphicsItem::ItemVisibleChange); |
| QCOMPARE(tester.changes.at(tester.changes.size() - 3), QGraphicsItem::ItemSelectedChange); |
| QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemSelectedHasChanged); |
| QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemVisibleHasChanged); |
| QCOMPARE(tester.values.at(tester.values.size() - 4), QVariant(false)); |
| QCOMPARE(tester.values.at(tester.values.size() - 3), QVariant(false)); |
| QCOMPARE(tester.values.at(tester.values.size() - 2), QVariant(false)); |
| QCOMPARE(tester.values.at(tester.values.size() - 1), QVariant(false)); |
| QCOMPARE(tester.isVisible(), false); |
| } |
| { |
| // ItemParentChange |
| tester.itemChangeReturnValue.setValue<QGraphicsItem *>(0); |
| tester.setParentItem(&testerHelper); |
| QCOMPARE(tester.changes.size(), ++changeCount); |
| QCOMPARE(tester.changes.last(), QGraphicsItem::ItemParentChange); |
| QCOMPARE(qvariant_cast<QGraphicsItem *>(tester.values.last()), (QGraphicsItem *)&testerHelper); |
| QCOMPARE(qvariant_cast<QGraphicsItem *>(tester.oldValues.last()), nullptr); |
| QCOMPARE(tester.parentItem(), nullptr); |
| } |
| { |
| // ItemOpacityChange |
| tester.itemChangeReturnValue = 1.0; |
| tester.setOpacity(0.7); |
| QCOMPARE(tester.changes.size(), ++changeCount); |
| QCOMPARE(tester.changes.last(), QGraphicsItem::ItemOpacityChange); |
| QVERIFY(qFuzzyCompare(qreal(tester.values.last().toDouble()), qreal(0.7))); |
| QCOMPARE(tester.oldValues.last().toDouble(), double(1.0)); |
| QCOMPARE(tester.opacity(), qreal(1.0)); |
| tester.itemChangeReturnValue = 0.7; |
| tester.setOpacity(0.7); |
| ++changeCount; // ItemOpacityChange |
| ++changeCount; // ItemOpacityHasChanged |
| QCOMPARE(tester.changes.size(), changeCount); |
| QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemOpacityChange); |
| QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemOpacityHasChanged); |
| QCOMPARE(tester.opacity(), qreal(0.7)); |
| } |
| { |
| // ItemChildAddedChange |
| tester.itemChangeReturnValue.clear(); |
| testerHelper.setParentItem(&tester); |
| QCOMPARE(tester.changes.size(), ++changeCount); |
| QCOMPARE(tester.changes.last(), QGraphicsItem::ItemChildAddedChange); |
| QCOMPARE(qvariant_cast<QGraphicsItem *>(tester.values.last()), (QGraphicsItem *)&testerHelper); |
| } |
| { |
| // ItemChildRemovedChange 1 |
| testerHelper.setParentItem(0); |
| QCOMPARE(tester.changes.size(), ++changeCount); |
| QCOMPARE(tester.changes.last(), QGraphicsItem::ItemChildRemovedChange); |
| QCOMPARE(qvariant_cast<QGraphicsItem *>(tester.values.last()), (QGraphicsItem *)&testerHelper); |
| |
| // ItemChildRemovedChange 1 |
| ItemChangeTester *test = new ItemChangeTester; |
| test->itemSceneChangeTargetScene = 0; |
| int count = 0; |
| QGraphicsScene *scene = new QGraphicsScene; |
| scene->addItem(test); |
| count = test->changes.size(); |
| //We test here the fact that when a child is deleted the parent receive only one ItemChildRemovedChange |
| QGraphicsRectItem *child = new QGraphicsRectItem(test); |
| //We received ItemChildAddedChange |
| QCOMPARE(test->changes.size(), ++count); |
| QCOMPARE(test->changes.last(), QGraphicsItem::ItemChildAddedChange); |
| delete child; |
| child = 0; |
| QCOMPARE(test->changes.size(), ++count); |
| QCOMPARE(test->changes.last(), QGraphicsItem::ItemChildRemovedChange); |
| |
| ItemChangeTester *childTester = new ItemChangeTester(test); |
| //Changes contains all sceneHasChanged and so on, we don't want to test that |
| int childCount = childTester->changes.size(); |
| //We received ItemChildAddedChange |
| QCOMPARE(test->changes.size(), ++count); |
| child = new QGraphicsRectItem(childTester); |
| //We received ItemChildAddedChange |
| QCOMPARE(childTester->changes.size(), ++childCount); |
| QCOMPARE(childTester->changes.last(), QGraphicsItem::ItemChildAddedChange); |
| //Delete the child of the top level with all its children |
| delete childTester; |
| //Only one removal |
| QCOMPARE(test->changes.size(), ++count); |
| QCOMPARE(test->changes.last(), QGraphicsItem::ItemChildRemovedChange); |
| delete scene; |
| } |
| { |
| // ItemChildRemovedChange 2 |
| ItemChangeTester parent; |
| ItemChangeTester *child = new ItemChangeTester; |
| child->setParentItem(&parent); |
| QCOMPARE(parent.changes.last(), QGraphicsItem::ItemChildAddedChange); |
| QCOMPARE(qvariant_cast<QGraphicsItem *>(parent.values.last()), (QGraphicsItem *)child); |
| delete child; |
| QCOMPARE(parent.changes.last(), QGraphicsItem::ItemChildRemovedChange); |
| QCOMPARE(qvariant_cast<QGraphicsItem *>(parent.values.last()), (QGraphicsItem *)child); |
| } |
| { |
| // !!! Note: If this test crashes because of double-deletion, there's |
| // a bug somewhere in QGraphicsScene or QGraphicsItem. |
| |
| // ItemSceneChange |
| QGraphicsScene scene; |
| QGraphicsScene scene2; |
| scene.addItem(&tester); |
| ++changeCount; // ItemSceneChange (scene) |
| ++changeCount; // ItemSceneHasChanged (scene) |
| QCOMPARE(tester.changes.size(), changeCount); |
| |
| QCOMPARE(tester.scene(), &scene); |
| QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemSceneChange); |
| QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemSceneHasChanged); |
| // Item's old value was 0 |
| // Item's current value is scene |
| QCOMPARE(qvariant_cast<QGraphicsScene *>(tester.oldValues.last()), nullptr); |
| QCOMPARE(qvariant_cast<QGraphicsScene *>(tester.values.last()), (QGraphicsScene *)&scene); |
| scene2.addItem(&tester); |
| ++changeCount; // ItemSceneChange (0) was: (scene) |
| ++changeCount; // ItemSceneHasChanged (0) |
| ++changeCount; // ItemSceneChange (scene2) was: (0) |
| ++changeCount; // ItemSceneHasChanged (scene2) |
| QCOMPARE(tester.changes.size(), changeCount); |
| |
| QCOMPARE(tester.scene(), &scene2); |
| QCOMPARE(tester.changes.at(tester.changes.size() - 4), QGraphicsItem::ItemSceneChange); |
| QCOMPARE(tester.changes.at(tester.changes.size() - 3), QGraphicsItem::ItemSceneHasChanged); |
| QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemSceneChange); |
| QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemSceneHasChanged); |
| // Item's last old value was scene |
| // Item's last current value is 0 |
| |
| QCOMPARE(qvariant_cast<QGraphicsScene *>(tester.oldValues.at(tester.oldValues.size() - 2)), (QGraphicsScene *)&scene); |
| QCOMPARE(qvariant_cast<QGraphicsScene *>(tester.oldValues.at(tester.oldValues.size() - 1)), nullptr); |
| QCOMPARE(qvariant_cast<QGraphicsScene *>(tester.values.at(tester.values.size() - 4)), nullptr); |
| QCOMPARE(qvariant_cast<QGraphicsScene *>(tester.values.at(tester.values.size() - 3)), nullptr); |
| QCOMPARE(qvariant_cast<QGraphicsScene *>(tester.values.at(tester.values.size() - 2)), (QGraphicsScene *)&scene2); |
| QCOMPARE(qvariant_cast<QGraphicsScene *>(tester.values.at(tester.values.size() - 1)), (QGraphicsScene *)&scene2); |
| // Item's last old value was 0 |
| // Item's last current value is scene2 |
| QCOMPARE(qvariant_cast<QGraphicsScene *>(tester.oldValues.last()), nullptr); |
| QCOMPARE(qvariant_cast<QGraphicsScene *>(tester.values.last()), (QGraphicsScene *)&scene2); |
| |
| scene2.removeItem(&tester); |
| ++changeCount; // ItemSceneChange (0) was: (scene2) |
| ++changeCount; // ItemSceneHasChanged (0) |
| QCOMPARE(tester.changes.size(), changeCount); |
| |
| QCOMPARE(tester.scene(), nullptr); |
| QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemSceneChange); |
| QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemSceneHasChanged); |
| // Item's last old value was scene2 |
| // Item's last current value is 0 |
| QCOMPARE(qvariant_cast<QGraphicsScene *>(tester.oldValues.last()), (QGraphicsScene *)&scene2); |
| QCOMPARE(qvariant_cast<QGraphicsScene *>(tester.values.at(tester.values.size() - 2)), nullptr); |
| QCOMPARE(qvariant_cast<QGraphicsScene *>(tester.values.at(tester.values.size() - 1)), nullptr); |
| |
| tester.itemSceneChangeTargetScene = &scene; |
| scene2.addItem(&tester); |
| ++changeCount; // ItemSceneChange (scene2) was: (0) |
| ++changeCount; // ItemSceneChange (scene) was: (0) |
| ++changeCount; // ItemSceneHasChanged (scene) |
| QCOMPARE(tester.values.size(), changeCount); |
| |
| QCOMPARE(qvariant_cast<QGraphicsScene *>(tester.values.at(tester.values.size() - 3)), (QGraphicsScene *)&scene2); |
| QCOMPARE(qvariant_cast<QGraphicsScene *>(tester.values.at(tester.values.size() - 2)), (QGraphicsScene *)&scene); |
| QCOMPARE(qvariant_cast<QGraphicsScene *>(tester.values.at(tester.values.size() - 1)), (QGraphicsScene *)&scene); |
| |
| QCOMPARE(tester.scene(), &scene); |
| tester.itemSceneChangeTargetScene = 0; |
| tester.itemChangeReturnValue = QVariant(); |
| scene.removeItem(&tester); |
| ++changeCount; // ItemSceneChange |
| ++changeCount; // ItemSceneHasChanged |
| QCOMPARE(tester.scene(), nullptr); |
| } |
| { |
| // ItemToolTipChange/ItemToolTipHasChanged |
| const QString toolTip(QLatin1String("I'm soo cool")); |
| const QString overridenToolTip(QLatin1String("No, you are not soo cool")); |
| tester.itemChangeReturnValue = overridenToolTip; |
| tester.setToolTip(toolTip); |
| ++changeCount; // ItemToolTipChange |
| ++changeCount; // ItemToolTipHasChanged |
| QCOMPARE(tester.changes.size(), changeCount); |
| QCOMPARE(tester.changes.at(changeCount - 2), QGraphicsItem::ItemToolTipChange); |
| QCOMPARE(tester.values.at(changeCount - 2).toString(), toolTip); |
| QCOMPARE(tester.changes.at(changeCount - 1), QGraphicsItem::ItemToolTipHasChanged); |
| QCOMPARE(tester.values.at(changeCount - 1).toString(), overridenToolTip); |
| QCOMPARE(tester.toolTip(), overridenToolTip); |
| tester.itemChangeReturnValue = QVariant(); |
| } |
| } |
| |
| class EventFilterTesterItem : public QGraphicsLineItem |
| { |
| public: |
| QList<QEvent::Type> filteredEvents; |
| QList<QGraphicsItem *> filteredEventReceivers; |
| bool handlesSceneEvents; |
| |
| QList<QEvent::Type> receivedEvents; |
| |
| EventFilterTesterItem() : handlesSceneEvents(false) {} |
| |
| protected: |
| bool sceneEventFilter(QGraphicsItem *watched, QEvent *event) |
| { |
| filteredEvents << event->type(); |
| filteredEventReceivers << watched; |
| return handlesSceneEvents; |
| } |
| |
| bool sceneEvent(QEvent *event) |
| { |
| return QGraphicsLineItem::sceneEvent(event); |
| } |
| }; |
| |
| void tst_QGraphicsItem::sceneEventFilter() |
| { |
| QGraphicsScene scene; |
| |
| QGraphicsView view(&scene); |
| view.show(); |
| QApplication::setActiveWindow(&view); |
| QVERIFY(QTest::qWaitForWindowExposed(&view)); |
| QVERIFY(QTest::qWaitForWindowActive(&view)); |
| |
| QGraphicsTextItem *text1 = scene.addText(QLatin1String("Text1")); |
| QGraphicsTextItem *text2 = scene.addText(QLatin1String("Text2")); |
| QGraphicsTextItem *text3 = scene.addText(QLatin1String("Text3")); |
| text1->setFlag(QGraphicsItem::ItemIsFocusable); |
| text2->setFlag(QGraphicsItem::ItemIsFocusable); |
| text3->setFlag(QGraphicsItem::ItemIsFocusable); |
| |
| EventFilterTesterItem *tester = new EventFilterTesterItem; |
| scene.addItem(tester); |
| |
| QTRY_VERIFY(!text1->hasFocus()); |
| text1->installSceneEventFilter(tester); |
| text1->setFocus(); |
| QTRY_VERIFY(text1->hasFocus()); |
| |
| QCOMPARE(tester->filteredEvents.size(), 1); |
| QCOMPARE(tester->filteredEvents.at(0), QEvent::FocusIn); |
| QCOMPARE(tester->filteredEventReceivers.at(0), static_cast<QGraphicsItem *>(text1)); |
| |
| text2->installSceneEventFilter(tester); |
| text3->installSceneEventFilter(tester); |
| |
| text2->setFocus(); |
| text3->setFocus(); |
| |
| QCOMPARE(tester->filteredEvents.size(), 5); |
| QCOMPARE(tester->filteredEvents.at(1), QEvent::FocusOut); |
| QCOMPARE(tester->filteredEventReceivers.at(1), static_cast<QGraphicsItem *>(text1)); |
| QCOMPARE(tester->filteredEvents.at(2), QEvent::FocusIn); |
| QCOMPARE(tester->filteredEventReceivers.at(2), static_cast<QGraphicsItem *>(text2)); |
| QCOMPARE(tester->filteredEvents.at(3), QEvent::FocusOut); |
| QCOMPARE(tester->filteredEventReceivers.at(3), static_cast<QGraphicsItem *>(text2)); |
| QCOMPARE(tester->filteredEvents.at(4), QEvent::FocusIn); |
| QCOMPARE(tester->filteredEventReceivers.at(4), static_cast<QGraphicsItem *>(text3)); |
| |
| text1->removeSceneEventFilter(tester); |
| text1->setFocus(); |
| |
| QCOMPARE(tester->filteredEvents.size(), 6); |
| QCOMPARE(tester->filteredEvents.at(5), QEvent::FocusOut); |
| QCOMPARE(tester->filteredEventReceivers.at(5), static_cast<QGraphicsItem *>(text3)); |
| |
| tester->handlesSceneEvents = true; |
| text2->setFocus(); |
| |
| QCOMPARE(tester->filteredEvents.size(), 7); |
| QCOMPARE(tester->filteredEvents.at(6), QEvent::FocusIn); |
| QCOMPARE(tester->filteredEventReceivers.at(6), static_cast<QGraphicsItem *>(text2)); |
| |
| QVERIFY(text2->hasFocus()); |
| |
| //Let check if the items are correctly removed from the sceneEventFilters array |
| //to avoid stale pointers. |
| QGraphicsView gv; |
| QGraphicsScene *anotherScene = new QGraphicsScene; |
| QGraphicsTextItem *ti = anotherScene->addText("This is a test #1"); |
| ti->moveBy(50, 50); |
| QGraphicsTextItem *ti2 = anotherScene->addText("This is a test #2"); |
| QGraphicsTextItem *ti3 = anotherScene->addText("This is a test #3"); |
| gv.setScene(anotherScene); |
| gv.show(); |
| QVERIFY(QTest::qWaitForWindowExposed(&gv)); |
| ti->installSceneEventFilter(ti2); |
| ti3->installSceneEventFilter(ti); |
| delete ti2; |
| //we souldn't crash |
| QTest::mouseMove(gv.viewport(), gv.mapFromScene(ti->scenePos())); |
| QTest::qWait(30); |
| delete ti; |
| } |
| |
| class GeometryChanger : public QGraphicsRectItem |
| { |
| public: |
| explicit GeometryChanger(QRectF r) : QGraphicsRectItem(r) {} |
| void changeGeometry() |
| { prepareGeometryChange(); } |
| }; |
| |
| void tst_QGraphicsItem::prepareGeometryChange() |
| { |
| { |
| QGraphicsScene scene; |
| const QRectF rect(0, 0, 100, 100); |
| GeometryChanger item(rect); |
| scene.addItem(&item); |
| QVERIFY(scene.items(rect).contains(&item)); |
| item.changeGeometry(); |
| QVERIFY(scene.items(rect).contains(&item)); |
| } |
| } |
| |
| |
| class PaintTester : public QGraphicsRectItem |
| { |
| public: |
| PaintTester() : widget(NULL), painted(0) { setRect(QRectF(10, 10, 20, 20));} |
| |
| void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *w) |
| { |
| widget = w; |
| painted++; |
| } |
| |
| QWidget* widget; |
| int painted; |
| }; |
| |
| void tst_QGraphicsItem::paint() |
| { |
| QGraphicsScene scene; |
| |
| PaintTester paintTester; |
| scene.addItem(&paintTester); |
| |
| QGraphicsView view(&scene); |
| view.show(); |
| QVERIFY(QTest::qWaitForWindowExposed(&view)); |
| QApplication::processEvents(); |
| #ifdef Q_OS_WIN32 |
| //we try to switch the desktop: if it fails, we skip the test |
| if (::SwitchDesktop( ::GetThreadDesktop( ::GetCurrentThreadId() ) ) == 0) { |
| QSKIP("The Graphics View doesn't get the paint events"); |
| } |
| #endif |
| |
| QTRY_COMPARE(paintTester.widget, view.viewport()); |
| |
| view.hide(); |
| |
| QGraphicsScene scene2; |
| QGraphicsView view2(&scene2); |
| view2.show(); |
| QVERIFY(QTest::qWaitForWindowExposed(&view2)); |
| QCoreApplication::processEvents(); // Process all queued paint events |
| |
| PaintTester tester2; |
| scene2.addItem(&tester2); |
| |
| //First show at least one paint |
| QCOMPARE(tester2.painted, 0); |
| QTRY_VERIFY(tester2.painted > 0); |
| int painted = tester2.painted; |
| |
| //nominal case, update call paint |
| tester2.update(); |
| QTRY_COMPARE(tester2.painted, painted + 1); |
| painted = tester2.painted; |
| |
| //we remove the item from the scene, number of updates is still the same |
| tester2.update(); |
| scene2.removeItem(&tester2); |
| QTRY_COMPARE(tester2.painted, painted); |
| |
| //We re-add the item, the number of paint should increase |
| scene2.addItem(&tester2); |
| tester2.update(); |
| QTRY_COMPARE(tester2.painted, painted + 1); |
| } |
| |
| class HarakiriItem : public QGraphicsRectItem |
| { |
| public: |
| HarakiriItem(int harakiriPoint) |
| : QGraphicsRectItem(QRectF(0, 0, 100, 100)), harakiri(harakiriPoint) |
| { dead = 0; } |
| |
| static int dead; |
| |
| void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) |
| { |
| QGraphicsRectItem::paint(painter, option, widget); |
| if (harakiri == 0) { |
| // delete unsupported since 4.5 |
| /* |
| dead = 1; |
| delete this; |
| */ |
| } |
| } |
| |
| void advance(int n) |
| { |
| if (harakiri == 1 && n == 0) { |
| // delete unsupported |
| /* |
| dead = 1; |
| delete this; |
| */ |
| } |
| if (harakiri == 2 && n == 1) { |
| dead = 1; |
| delete this; |
| } |
| } |
| |
| protected: |
| #ifndef QT_NO_CONTEXTMENU |
| void contextMenuEvent(QGraphicsSceneContextMenuEvent *) |
| { |
| if (harakiri == 3) { |
| dead = 1; |
| delete this; |
| } |
| } |
| #endif // QT_NO_CONTEXTMENU |
| |
| void dragEnterEvent(QGraphicsSceneDragDropEvent *event) |
| { |
| // ?? |
| QGraphicsRectItem::dragEnterEvent(event); |
| } |
| |
| void dragLeaveEvent(QGraphicsSceneDragDropEvent *event) |
| { |
| // ?? |
| QGraphicsRectItem::dragLeaveEvent(event); |
| } |
| |
| void dragMoveEvent(QGraphicsSceneDragDropEvent *event) |
| { |
| // ?? |
| QGraphicsRectItem::dragMoveEvent(event); |
| } |
| |
| void dropEvent(QGraphicsSceneDragDropEvent *event) |
| { |
| // ?? |
| QGraphicsRectItem::dropEvent(event); |
| } |
| |
| void focusInEvent(QFocusEvent *) |
| { |
| if (harakiri == 4) { |
| dead = 1; |
| delete this; |
| } |
| } |
| |
| void focusOutEvent(QFocusEvent *) |
| { |
| if (harakiri == 5) { |
| dead = 1; |
| delete this; |
| } |
| } |
| |
| void hoverEnterEvent(QGraphicsSceneHoverEvent *) |
| { |
| if (harakiri == 6) { |
| dead = 1; |
| delete this; |
| } |
| } |
| |
| void hoverLeaveEvent(QGraphicsSceneHoverEvent *) |
| { |
| if (harakiri == 7) { |
| dead = 1; |
| delete this; |
| } |
| } |
| |
| void hoverMoveEvent(QGraphicsSceneHoverEvent *) |
| { |
| if (harakiri == 8) { |
| dead = 1; |
| delete this; |
| } |
| } |
| |
| void inputMethodEvent(QInputMethodEvent *event) |
| { |
| // ?? |
| QGraphicsRectItem::inputMethodEvent(event); |
| } |
| |
| QVariant inputMethodQuery(Qt::InputMethodQuery query) const |
| { |
| // ?? |
| return QGraphicsRectItem::inputMethodQuery(query); |
| } |
| |
| QVariant itemChange(GraphicsItemChange change, const QVariant &value) |
| { |
| // deletion not supported |
| return QGraphicsRectItem::itemChange(change, value); |
| } |
| |
| void keyPressEvent(QKeyEvent *) |
| { |
| if (harakiri == 9) { |
| dead = 1; |
| delete this; |
| } |
| } |
| |
| void keyReleaseEvent(QKeyEvent *) |
| { |
| if (harakiri == 10) { |
| dead = 1; |
| delete this; |
| } |
| } |
| |
| void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *) |
| { |
| if (harakiri == 11) { |
| dead = 1; |
| delete this; |
| } |
| } |
| |
| void mouseMoveEvent(QGraphicsSceneMouseEvent *) |
| { |
| if (harakiri == 12) { |
| dead = 1; |
| delete this; |
| } |
| } |
| |
| void mousePressEvent(QGraphicsSceneMouseEvent *) |
| { |
| if (harakiri == 13) { |
| dead = 1; |
| delete this; |
| } |
| } |
| |
| void mouseReleaseEvent(QGraphicsSceneMouseEvent *) |
| { |
| if (harakiri == 14) { |
| dead = 1; |
| delete this; |
| } |
| } |
| |
| bool sceneEvent(QEvent *event) |
| { |
| // deletion not supported |
| return QGraphicsRectItem::sceneEvent(event); |
| } |
| |
| bool sceneEventFilter(QGraphicsItem *watched, QEvent *event) |
| { |
| // deletion not supported |
| return QGraphicsRectItem::sceneEventFilter(watched, event); |
| } |
| |
| void wheelEvent(QGraphicsSceneWheelEvent *) |
| { |
| if (harakiri == 16) { |
| dead = 1; |
| delete this; |
| } |
| } |
| |
| private: |
| int harakiri; |
| }; |
| |
| int HarakiriItem::dead; |
| |
| void tst_QGraphicsItem::deleteItemInEventHandlers() |
| { |
| for (int i = 0; i < 17; ++i) { |
| QGraphicsScene scene; |
| HarakiriItem *item = new HarakiriItem(i); |
| item->setAcceptHoverEvents(true); |
| item->setFlag(QGraphicsItem::ItemIsFocusable); |
| |
| scene.addItem(item); |
| |
| item->installSceneEventFilter(item); // <- ehey! |
| |
| QGraphicsView view(&scene); |
| view.show(); |
| |
| qApp->processEvents(); |
| qApp->processEvents(); |
| |
| if (!item->dead) |
| scene.advance(); |
| |
| #ifndef QT_NO_CONTEXTMENU |
| if (!item->dead) { |
| QContextMenuEvent event(QContextMenuEvent::Other, |
| view.mapFromScene(item->scenePos())); |
| QCoreApplication::sendEvent(view.viewport(), &event); |
| } |
| #endif // QT_NO_CONTEXTMENU |
| if (!item->dead) |
| QTest::mouseMove(view.viewport(), view.mapFromScene(item->scenePos())); |
| if (!item->dead) |
| QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item->scenePos())); |
| if (!item->dead) |
| QTest::mouseDClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item->scenePos())); |
| if (!item->dead) |
| QTest::mouseClick(view.viewport(), Qt::RightButton, 0, view.mapFromScene(item->scenePos())); |
| if (!item->dead) |
| QTest::mouseMove(view.viewport(), view.mapFromScene(item->scenePos() + QPointF(20, -20))); |
| if (!item->dead) |
| item->setFocus(); |
| if (!item->dead) |
| item->clearFocus(); |
| if (!item->dead) |
| item->setFocus(); |
| if (!item->dead) |
| QTest::keyPress(view.viewport(), Qt::Key_A); |
| if (!item->dead) |
| QTest::keyRelease(view.viewport(), Qt::Key_A); |
| if (!item->dead) |
| QTest::keyPress(view.viewport(), Qt::Key_A); |
| if (!item->dead) |
| QTest::keyRelease(view.viewport(), Qt::Key_A); |
| } |
| } |
| |
| class ItemPaintsOutsideShape : public QGraphicsItem |
| { |
| public: |
| QRectF boundingRect() const |
| { |
| return QRectF(0, 0, 100, 100); |
| } |
| |
| void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) |
| { |
| painter->fillRect(-50, -50, 200, 200, Qt::red); |
| painter->fillRect(0, 0, 100, 100, Qt::blue); |
| } |
| }; |
| |
| void tst_QGraphicsItem::itemClipsToShape() |
| { |
| QGraphicsItem *clippedItem = new ItemPaintsOutsideShape; |
| clippedItem->setFlag(QGraphicsItem::ItemClipsToShape); |
| |
| QGraphicsItem *unclippedItem = new ItemPaintsOutsideShape; |
| unclippedItem->setPos(200, 0); |
| |
| QGraphicsScene scene(-50, -50, 400, 200); |
| scene.addItem(clippedItem); |
| scene.addItem(unclippedItem); |
| |
| QImage image(400, 200, QImage::Format_ARGB32_Premultiplied); |
| image.fill(0); |
| QPainter painter(&image); |
| painter.setRenderHint(QPainter::Antialiasing); |
| scene.render(&painter); |
| painter.end(); |
| |
| QCOMPARE(image.pixel(45, 100), QRgb(0)); |
| QCOMPARE(image.pixel(100, 45), QRgb(0)); |
| QCOMPARE(image.pixel(155, 100), QRgb(0)); |
| QCOMPARE(image.pixel(45, 155), QRgb(0)); |
| QCOMPARE(image.pixel(55, 100), QColor(Qt::blue).rgba()); |
| QCOMPARE(image.pixel(100, 55), QColor(Qt::blue).rgba()); |
| QCOMPARE(image.pixel(145, 100), QColor(Qt::blue).rgba()); |
| QCOMPARE(image.pixel(55, 145), QColor(Qt::blue).rgba()); |
| QCOMPARE(image.pixel(245, 100), QColor(Qt::red).rgba()); |
| QCOMPARE(image.pixel(300, 45), QColor(Qt::red).rgba()); |
| QCOMPARE(image.pixel(355, 100), QColor(Qt::red).rgba()); |
| QCOMPARE(image.pixel(245, 155), QColor(Qt::red).rgba()); |
| QCOMPARE(image.pixel(255, 100), QColor(Qt::blue).rgba()); |
| QCOMPARE(image.pixel(300, 55), QColor(Qt::blue).rgba()); |
| QCOMPARE(image.pixel(345, 100), QColor(Qt::blue).rgba()); |
| QCOMPARE(image.pixel(255, 145), QColor(Qt::blue).rgba()); |
| } |
| |
| void tst_QGraphicsItem::itemClipsChildrenToShape() |
| { |
| QGraphicsScene scene; |
| QGraphicsItem *rect = scene.addRect(0, 0, 50, 50, QPen(Qt::NoPen), QBrush(Qt::yellow)); |
| |
| QGraphicsItem *ellipse = scene.addEllipse(0, 0, 100, 100, QPen(Qt::NoPen), QBrush(Qt::green)); |
| ellipse->setParentItem(rect); |
| |
| QGraphicsItem *clippedEllipse = scene.addEllipse(0, 0, 50, 50, QPen(Qt::NoPen), QBrush(Qt::blue)); |
| clippedEllipse->setParentItem(ellipse); |
| |
| QGraphicsItem *clippedEllipse2 = scene.addEllipse(0, 0, 25, 25, QPen(Qt::NoPen), QBrush(Qt::red)); |
| clippedEllipse2->setParentItem(clippedEllipse); |
| |
| QGraphicsItem *clippedEllipse3 = scene.addEllipse(50, 50, 25, 25, QPen(Qt::NoPen), QBrush(Qt::red)); |
| clippedEllipse3->setParentItem(clippedEllipse); |
| |
| QVERIFY(!(ellipse->flags() & QGraphicsItem::ItemClipsChildrenToShape)); |
| ellipse->setFlag(QGraphicsItem::ItemClipsChildrenToShape); |
| QVERIFY((ellipse->flags() & QGraphicsItem::ItemClipsChildrenToShape)); |
| |
| QImage image(100, 100, QImage::Format_ARGB32_Premultiplied); |
| image.fill(0); |
| QPainter painter(&image); |
| painter.setRenderHint(QPainter::Antialiasing); |
| scene.render(&painter); |
| painter.end(); |
| |
| QCOMPARE(image.pixel(16, 16), QColor(255, 0, 0).rgba()); |
| QCOMPARE(image.pixel(32, 32), QColor(0, 0, 255).rgba()); |
| QCOMPARE(image.pixel(50, 50), QColor(0, 255, 0).rgba()); |
| QCOMPARE(image.pixel(12, 12), QColor(255, 255, 0).rgba()); |
| QCOMPARE(image.pixel(60, 60), QColor(255, 0, 0).rgba()); |
| } |
| |
| void tst_QGraphicsItem::itemClipsChildrenToShape2() |
| { |
| QGraphicsRectItem *parent = new QGraphicsRectItem(QRectF(0, 0, 10, 10)); |
| QGraphicsEllipseItem *child1 = new QGraphicsEllipseItem(QRectF(50, 50, 100, 100)); |
| QGraphicsRectItem *child2 = new QGraphicsRectItem(QRectF(15, 15, 80, 80)); |
| |
| child1->setParentItem(parent); |
| child1->setFlag(QGraphicsItem::ItemClipsChildrenToShape); |
| child2->setParentItem(child1); |
| |
| parent->setBrush(Qt::blue); |
| child1->setBrush(Qt::green); |
| child2->setBrush(Qt::red); |
| |
| QGraphicsScene scene; |
| scene.addItem(parent); |
| |
| QCOMPARE(scene.items(QPointF(5, 5)).value(0, nullptr), (QGraphicsItem *)parent); |
| QVERIFY(scene.items(QPointF(15, 5)).isEmpty()); |
| QVERIFY(scene.items(QPointF(5, 15)).isEmpty()); |
| QVERIFY(scene.items(QPointF(60, 60)).isEmpty()); |
| QVERIFY(scene.items(QPointF(140, 60)).isEmpty()); |
| QVERIFY(scene.items(QPointF(60, 140)).isEmpty()); |
| QVERIFY(scene.items(QPointF(140, 140)).isEmpty()); |
| QCOMPARE(scene.items(QPointF(75, 75)).value(0, nullptr), (QGraphicsItem *)child2); |
| QCOMPARE(scene.items(QPointF(75, 100)).value(0, nullptr), (QGraphicsItem *)child1); |
| QCOMPARE(scene.items(QPointF(100, 75)).value(0, nullptr), (QGraphicsItem *)child1); |
| |
| QImage image(100, 100, QImage::Format_ARGB32_Premultiplied); |
| image.fill(0); |
| QPainter painter(&image); |
| scene.render(&painter); |
| painter.end(); |
| |
| QCOMPARE(image.pixel(5, 5), QColor(0, 0, 255).rgba()); |
| QCOMPARE(image.pixel(5, 10), QRgb(0)); |
| QCOMPARE(image.pixel(10, 5), QRgb(0)); |
| QCOMPARE(image.pixel(40, 40), QRgb(0)); |
| QCOMPARE(image.pixel(90, 40), QRgb(0)); |
| QCOMPARE(image.pixel(40, 90), QRgb(0)); |
| QCOMPARE(image.pixel(95, 95), QRgb(0)); |
| QCOMPARE(image.pixel(50, 70), QColor(0, 255, 0).rgba()); |
| QCOMPARE(image.pixel(70, 50), QColor(0, 255, 0).rgba()); |
| QCOMPARE(image.pixel(50, 60), QColor(255, 0, 0).rgba()); |
| QCOMPARE(image.pixel(60, 50), QColor(255, 0, 0).rgba()); |
| } |
| |
| void tst_QGraphicsItem::itemClipsChildrenToShape3() |
| { |
| // Construct a scene with nested children, each 50 pixels offset from the elder. |
| // Set a top-level clipping flag |
| QGraphicsScene scene; |
| QGraphicsRectItem *parent = scene.addRect( 0, 0, 150, 150 ); |
| QGraphicsRectItem *child = scene.addRect( 0, 0, 150, 150 ); |
| QGraphicsRectItem *grandchild = scene.addRect( 0, 0, 150, 150 ); |
| child->setParentItem(parent); |
| grandchild->setParentItem(child); |
| child->setPos( 50, 50 ); |
| grandchild->setPos( 50, 50 ); |
| parent->setFlag(QGraphicsItem::ItemClipsChildrenToShape); |
| |
| QCOMPARE(scene.items(QPointF(25, 25)).value(0, nullptr), (QGraphicsItem *)parent); |
| QCOMPARE(scene.items(QPointF(75, 75)).value(0, nullptr), (QGraphicsItem *)child); |
| QCOMPARE(scene.items(QPointF(125, 125)).value(0, nullptr), (QGraphicsItem *)grandchild); |
| QVERIFY(scene.items(QPointF(175, 175)).isEmpty()); |
| |
| // Move child to fully overlap the parent. The grandchild should |
| // now occupy two-thirds of the scene |
| child->prepareGeometryChange(); |
| child->setPos( 0, 0 ); |
| |
| QCOMPARE(scene.items(QPointF(25, 25)).value(0, nullptr), (QGraphicsItem *)child); |
| QCOMPARE(scene.items(QPointF(75, 75)).value(0, nullptr), (QGraphicsItem *)grandchild); |
| QCOMPARE(scene.items(QPointF(125, 125)).value(0, nullptr), (QGraphicsItem *)grandchild); |
| QVERIFY(scene.items(QPointF(175, 175)).isEmpty()); |
| } |
| |
| class MyProxyWidget : public QGraphicsProxyWidget |
| { |
| public: |
| MyProxyWidget(QGraphicsItem *parent) : QGraphicsProxyWidget(parent) |
| { |
| painted = false; |
| } |
| |
| void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) |
| { |
| QGraphicsProxyWidget::paint(painter, option, widget); |
| painted = true; |
| } |
| bool painted; |
| }; |
| |
| void tst_QGraphicsItem::itemClipsChildrenToShape4() |
| { |
| QGraphicsScene scene; |
| QGraphicsView view(&scene); |
| |
| QGraphicsWidget * outerWidget = new QGraphicsWidget(); |
| outerWidget->setFlag(QGraphicsItem::ItemClipsChildrenToShape, true); |
| MyProxyWidget * innerWidget = new MyProxyWidget(outerWidget); |
| QLabel * label = new QLabel(); |
| label->setText("Welcome back my friends to the show that never ends..."); |
| innerWidget->setWidget(label); |
| view.resize(300, 300); |
| scene.addItem(outerWidget); |
| outerWidget->resize( 200, 100 ); |
| scene.addEllipse( 100, 100, 100, 50 ); // <-- this is important to trigger the right codepath* |
| //now the label is shown |
| outerWidget->setFlag(QGraphicsItem::ItemClipsChildrenToShape, false ); |
| QApplication::setActiveWindow(&view); |
| view.show(); |
| QTRY_COMPARE(QApplication::activeWindow(), (QWidget *)&view); |
| QTRY_COMPARE(innerWidget->painted, true); |
| } |
| |
| //#define DEBUG_ITEM_CLIPS_CHILDREN_TO_SHAPE_5 |
| static inline void renderSceneToImage(QGraphicsScene *scene, QImage *image, const QString &filename) |
| { |
| image->fill(0); |
| QPainter painter(image); |
| scene->render(&painter); |
| painter.end(); |
| #ifdef DEBUG_ITEM_CLIPS_CHILDREN_TO_SHAPE_5 |
| image->save(filename); |
| #else |
| Q_UNUSED(filename); |
| #endif |
| } |
| |
| void tst_QGraphicsItem::itemClipsChildrenToShape5() |
| { |
| class ParentItem : public QGraphicsRectItem |
| { |
| public: |
| ParentItem(qreal x, qreal y, qreal width, qreal height) |
| : QGraphicsRectItem(x, y, width, height) {} |
| |
| QPainterPath shape() const |
| { |
| QPainterPath path; |
| path.addRect(50, 50, 200, 200); |
| return path; |
| } |
| }; |
| |
| ParentItem *parent = new ParentItem(0, 0, 300, 300); |
| parent->setBrush(Qt::blue); |
| parent->setOpacity(0.5); |
| |
| const QRegion parentRegion(0, 0, 300, 300); |
| const QRegion clippedParentRegion = parentRegion & QRect(50, 50, 200, 200); |
| QRegion childRegion; |
| QRegion grandChildRegion; |
| |
| QGraphicsRectItem *topLeftChild = new QGraphicsRectItem(0, 0, 100, 100); |
| topLeftChild->setBrush(Qt::red); |
| topLeftChild->setParentItem(parent); |
| childRegion += QRect(0, 0, 100, 100); |
| |
| QGraphicsRectItem *topRightChild = new QGraphicsRectItem(0, 0, 100, 100); |
| topRightChild->setBrush(Qt::red); |
| topRightChild->setParentItem(parent); |
| topRightChild->setFlag(QGraphicsItem::ItemClipsChildrenToShape); |
| topRightChild->setPos(200, 0); |
| childRegion += QRect(200, 0, 100, 100); |
| |
| QGraphicsRectItem *topRightGrandChild = new QGraphicsRectItem(0, 0, 100, 100); |
| topRightGrandChild->setBrush(Qt::green); |
| topRightGrandChild->setParentItem(topRightChild); |
| topRightGrandChild->setPos(-40, 40); |
| grandChildRegion += QRect(200 - 40, 0 + 40, 100, 100) & QRect(200, 0, 100, 100); |
| |
| QGraphicsRectItem *bottomLeftChild = new QGraphicsRectItem(0, 0, 100, 100); |
| bottomLeftChild->setBrush(Qt::red); |
| bottomLeftChild->setParentItem(parent); |
| bottomLeftChild->setFlag(QGraphicsItem::ItemClipsToShape); |
| bottomLeftChild->setPos(0, 200); |
| childRegion += QRect(0, 200, 100, 100); |
| |
| QGraphicsRectItem *bottomLeftGrandChild = new QGraphicsRectItem(0, 0, 160, 160); |
| bottomLeftGrandChild->setBrush(Qt::green); |
| bottomLeftGrandChild->setParentItem(bottomLeftChild); |
| bottomLeftGrandChild->setFlag(QGraphicsItem::ItemClipsToShape); |
| bottomLeftGrandChild->setPos(0, -60); |
| grandChildRegion += QRect(0, 200 - 60, 160, 160); |
| |
| QGraphicsRectItem *bottomRightChild = new QGraphicsRectItem(0, 0, 100, 100); |
| bottomRightChild->setBrush(Qt::red); |
| bottomRightChild->setParentItem(parent); |
| bottomRightChild->setPos(200, 200); |
| childRegion += QRect(200, 200, 100, 100); |
| |
| QPoint controlPoints[17] = { |
| QPoint(5, 5) , QPoint(95, 5) , QPoint(205, 5) , QPoint(295, 5) , |
| QPoint(5, 95) , QPoint(95, 95) , QPoint(205, 95) , QPoint(295, 95) , |
| QPoint(150, 150), |
| QPoint(5, 205), QPoint(95, 205), QPoint(205, 205), QPoint(295, 205), |
| QPoint(5, 295), QPoint(95, 295), QPoint(205, 295), QPoint(295, 295), |
| }; |
| |
| const QRegion clippedChildRegion = childRegion & QRect(50, 50, 200, 200); |
| const QRegion clippedGrandChildRegion = grandChildRegion & QRect(50, 50, 200, 200); |
| |
| QGraphicsScene scene; |
| scene.addItem(parent); |
| QImage sceneImage(300, 300, QImage::Format_ARGB32); |
| |
| #define VERIFY_CONTROL_POINTS(pRegion, cRegion, gRegion) \ |
| for (int i = 0; i < 17; ++i) { \ |
| QPoint controlPoint = controlPoints[i]; \ |
| QRgb pixel = sceneImage.pixel(controlPoint.x(), controlPoint.y()); \ |
| if (pRegion.contains(controlPoint)) \ |
| QVERIFY(qBlue(pixel) != 0); \ |
| else \ |
| QVERIFY(qBlue(pixel) == 0); \ |
| if (cRegion.contains(controlPoint)) \ |
| QVERIFY(qRed(pixel) != 0); \ |
| else \ |
| QVERIFY(qRed(pixel) == 0); \ |
| if (gRegion.contains(controlPoint)) \ |
| QVERIFY(qGreen(pixel) != 0); \ |
| else \ |
| QVERIFY(qGreen(pixel) == 0); \ |
| } |
| |
| const QList<QGraphicsItem *> children = parent->childItems(); |
| const int childrenCount = children.count(); |
| |
| for (int i = 0; i < 5; ++i) { |
| QString clipString; |
| QString childString; |
| switch (i) { |
| case 0: |
| // All children stacked in front. |
| childString = QLatin1String("ChildrenInFront.png"); |
| foreach (QGraphicsItem *child, children) |
| child->setFlag(QGraphicsItem::ItemStacksBehindParent, false); |
| break; |
| case 1: |
| // All children stacked behind. |
| childString = QLatin1String("ChildrenBehind.png"); |
| foreach (QGraphicsItem *child, children) |
| child->setFlag(QGraphicsItem::ItemStacksBehindParent, true); |
| break; |
| case 2: |
| // First half of the children behind, second half in front. |
| childString = QLatin1String("FirstHalfBehind_SecondHalfInFront.png"); |
| for (int j = 0; j < childrenCount; ++j) { |
| QGraphicsItem *child = children.at(j); |
| child->setFlag(QGraphicsItem::ItemStacksBehindParent, (j < childrenCount / 2)); |
| } |
| break; |
| case 3: |
| // First half of the children in front, second half behind. |
| childString = QLatin1String("FirstHalfInFront_SecondHalfBehind.png"); |
| for (int j = 0; j < childrenCount; ++j) { |
| QGraphicsItem *child = children.at(j); |
| child->setFlag(QGraphicsItem::ItemStacksBehindParent, (j >= childrenCount / 2)); |
| } |
| break; |
| case 4: |
| // Child2 and child4 behind, rest in front. |
| childString = QLatin1String("Child2And4Behind_RestInFront.png"); |
| for (int j = 0; j < childrenCount; ++j) { |
| QGraphicsItem *child = children.at(j); |
| if (j == 1 || j == 3) |
| child->setFlag(QGraphicsItem::ItemStacksBehindParent, true); |
| else |
| child->setFlag(QGraphicsItem::ItemStacksBehindParent, false); |
| } |
| break; |
| default: |
| qFatal("internal error"); |
| } |
| |
| // Nothing is clipped. |
| parent->setFlag(QGraphicsItem::ItemClipsChildrenToShape, false); |
| parent->setFlag(QGraphicsItem::ItemClipsToShape, false); |
| clipString = QLatin1String("nothingClipped_"); |
| renderSceneToImage(&scene, &sceneImage, clipString + childString); |
| VERIFY_CONTROL_POINTS(parentRegion, childRegion, grandChildRegion); |
| |
| // Parent clips children to shape. |
| parent->setFlag(QGraphicsItem::ItemClipsChildrenToShape); |
| clipString = QLatin1String("parentClipsChildrenToShape_"); |
| renderSceneToImage(&scene, &sceneImage, clipString + childString); |
| VERIFY_CONTROL_POINTS(parentRegion, clippedChildRegion, clippedGrandChildRegion); |
| |
| // Parent clips itself and children to shape. |
| parent->setFlag(QGraphicsItem::ItemClipsToShape); |
| clipString = QLatin1String("parentClipsItselfAndChildrenToShape_"); |
| renderSceneToImage(&scene, &sceneImage, clipString + childString); |
| VERIFY_CONTROL_POINTS(clippedParentRegion, clippedChildRegion, clippedGrandChildRegion); |
| |
| // Parent clips itself to shape. |
| parent->setFlag(QGraphicsItem::ItemClipsChildrenToShape, false); |
| clipString = QLatin1String("parentClipsItselfToShape_"); |
| renderSceneToImage(&scene, &sceneImage, clipString + childString); |
| VERIFY_CONTROL_POINTS(clippedParentRegion, childRegion, grandChildRegion); |
| } |
| } |
| |
| void tst_QGraphicsItem::itemClipsTextChildToShape() |
| { |
| // Construct a scene with a rect that clips its children, with one text |
| // child that has text that exceeds the size of the rect. |
| QGraphicsScene scene; |
| QGraphicsItem *rect = scene.addRect(0, 0, 50, 50, QPen(Qt::black), Qt::black); |
| rect->setFlag(QGraphicsItem::ItemClipsChildrenToShape); |
| QGraphicsTextItem *text = new QGraphicsTextItem("This is a long sentence that's wider than 50 pixels."); |
| text->setParentItem(rect); |
| |
| // Render this scene to a transparent image. |
| QRectF sr = scene.itemsBoundingRect(); |
| QImage image(sr.size().toSize(), QImage::Format_ARGB32_Premultiplied); |
| image.fill(0); |
| QPainter painter(&image); |
| scene.render(&painter); |
| |
| // Erase the area immediately underneath the rect. |
| painter.setCompositionMode(QPainter::CompositionMode_Source); |
| painter.fillRect(rect->sceneBoundingRect().translated(-sr.topLeft()).adjusted(-0.5, -0.5, 0.5, 0.5), |
| Qt::transparent); |
| painter.end(); |
| |
| // Check that you get a truly transparent image back (i.e., the text was |
| // clipped away, so there should be no trails left after erasing only the |
| // rect's area). |
| QImage emptyImage(scene.itemsBoundingRect().size().toSize(), QImage::Format_ARGB32_Premultiplied); |
| emptyImage.fill(0); |
| QCOMPARE(image, emptyImage); |
| } |
| |
| void tst_QGraphicsItem::itemClippingDiscovery() |
| { |
| // A simple scene with an ellipse parent and two rect children, one a |
| // child of the other. |
| QGraphicsScene scene; |
| QGraphicsEllipseItem *clipItem = scene.addEllipse(0, 0, 100, 100); |
| QGraphicsRectItem *leftRectItem = scene.addRect(0, 0, 50, 100); |
| QGraphicsRectItem *rightRectItem = scene.addRect(50, 0, 50, 100); |
| leftRectItem->setParentItem(clipItem); |
| rightRectItem->setParentItem(clipItem); |
| |
| // The rects item are both visible at these points. |
| QCOMPARE(scene.items(QPointF(10, 10)).value(0, nullptr), (QGraphicsItem *)leftRectItem); |
| QCOMPARE(scene.items(QPointF(90, 90)).value(0, nullptr), (QGraphicsItem *)rightRectItem); |
| |
| // The ellipse clips the rects now. |
| clipItem->setFlag(QGraphicsItem::ItemClipsChildrenToShape); |
| |
| // The rect items are no longer visible at these points. |
| QVERIFY(scene.items(QPointF(10, 10)).isEmpty()); |
| if (sizeof(qreal) != sizeof(double)) |
| QSKIP("This fails due to internal rounding errors"); |
| QVERIFY(scene.items(QPointF(90, 90)).isEmpty()); |
| } |
| |
| class ItemCountsBoundingRectCalls : public QGraphicsRectItem |
| { |
| public: |
| ItemCountsBoundingRectCalls(const QRectF & rect, QGraphicsItem *parent = 0) |
| : QGraphicsRectItem(rect, parent), boundingRectCalls(0) {} |
| QRectF boundingRect () const { |
| ++boundingRectCalls; |
| return QGraphicsRectItem::boundingRect(); |
| } |
| mutable int boundingRectCalls; |
| }; |
| |
| void tst_QGraphicsItem::itemContainsChildrenInShape() |
| { |
| ItemCountsBoundingRectCalls *parent = new ItemCountsBoundingRectCalls(QRectF(0,0, 10, 10)); |
| ItemCountsBoundingRectCalls *childOutsideShape = new ItemCountsBoundingRectCalls(QRectF(0,0, 10, 10), parent); |
| childOutsideShape->setPos(20,0); |
| |
| QGraphicsScene scene; |
| scene.setItemIndexMethod(QGraphicsScene::NoIndex); |
| scene.addItem(parent); |
| |
| QCOMPARE(parent->boundingRectCalls, childOutsideShape->boundingRectCalls); |
| |
| int oldParentBoundingRectCalls = parent->boundingRectCalls; |
| int oldChildBoundingRectCalls = childOutsideShape->boundingRectCalls; |
| |
| // First test that both items are searched if no optimization flags are set |
| QGraphicsItem* item = scene.items(QPointF(25, 5)).value(0, nullptr); |
| |
| QCOMPARE(item, childOutsideShape); |
| QVERIFY(parent->boundingRectCalls > oldParentBoundingRectCalls); |
| QVERIFY(childOutsideShape->boundingRectCalls > oldChildBoundingRectCalls); |
| QCOMPARE(parent->boundingRectCalls, childOutsideShape->boundingRectCalls); |
| |
| oldParentBoundingRectCalls = parent->boundingRectCalls; |
| oldChildBoundingRectCalls = childOutsideShape->boundingRectCalls; |
| |
| // Repeat the test to make sure that no caching/indexing is in effect |
| item = scene.items(QPointF(25, 5)).value(0, nullptr); |
| |
| QCOMPARE(item, childOutsideShape); |
| QVERIFY(parent->boundingRectCalls > oldParentBoundingRectCalls); |
| QVERIFY(childOutsideShape->boundingRectCalls > oldChildBoundingRectCalls); |
| QCOMPARE(parent->boundingRectCalls, childOutsideShape->boundingRectCalls); |
| |
| oldParentBoundingRectCalls = parent->boundingRectCalls; |
| oldChildBoundingRectCalls = childOutsideShape->boundingRectCalls; |
| |
| // Set the optimization flag and make sure that the child is not returned |
| // and that the child's boundingRect() method is never called. |
| parent->setFlag(QGraphicsItem::ItemContainsChildrenInShape); |
| item = scene.items(QPointF(25, 5)).value(0, nullptr); |
| |
| QVERIFY(!(item)); |
| QVERIFY(parent->boundingRectCalls > oldParentBoundingRectCalls); |
| QCOMPARE(childOutsideShape->boundingRectCalls, oldChildBoundingRectCalls); |
| QVERIFY(parent->boundingRectCalls > childOutsideShape->boundingRectCalls); |
| } |
| |
| void tst_QGraphicsItem::itemContainsChildrenInShape2() |
| { |
| //The tested flag behaves almost identically to ItemClipsChildrenToShape |
| //in terms of optimizations but does not enforce the clip. |
| //This test makes sure there is no clip. |
| QGraphicsScene scene; |
| QGraphicsItem *rect = scene.addRect(0, 0, 50, 50, QPen(Qt::NoPen), QBrush(Qt::yellow)); |
| |
| QGraphicsItem *ellipse = scene.addEllipse(0, 0, 100, 100, QPen(Qt::NoPen), QBrush(Qt::green)); |
| ellipse->setParentItem(rect); |
| |
| QGraphicsItem *clippedEllipse = scene.addEllipse(0, 0, 50, 50, QPen(Qt::NoPen), QBrush(Qt::blue)); |
| clippedEllipse->setParentItem(ellipse); |
| |
| QGraphicsItem *clippedEllipse2 = scene.addEllipse(0, 0, 25, 25, QPen(Qt::NoPen), QBrush(Qt::red)); |
| clippedEllipse2->setParentItem(clippedEllipse); |
| |
| QVERIFY(!(ellipse->flags() & QGraphicsItem::ItemClipsChildrenToShape)); |
| QVERIFY(!(ellipse->flags() & QGraphicsItem::ItemContainsChildrenInShape)); |
| ellipse->setFlags(QGraphicsItem::ItemContainsChildrenInShape); |
| QVERIFY(!(ellipse->flags() & QGraphicsItem::ItemClipsChildrenToShape)); |
| QVERIFY((ellipse->flags() & QGraphicsItem::ItemContainsChildrenInShape)); |
| |
| QImage image(100, 100, QImage::Format_ARGB32_Premultiplied); |
| image.fill(0); |
| QPainter painter(&image); |
| painter.setRenderHint(QPainter::Antialiasing); |
| scene.render(&painter); |
| painter.end(); |
| |
| QCOMPARE(image.pixel(2, 2), QColor(Qt::yellow).rgba()); |
| QCOMPARE(image.pixel(12, 12), QColor(Qt::red).rgba()); |
| QCOMPARE(image.pixel(2, 25), QColor(Qt::blue).rgba()); |
| QCOMPARE(image.pixel(2, 50), QColor(Qt::green).rgba()); |
| } |
| |
| void tst_QGraphicsItem::ancestorFlags() |
| { |
| QGraphicsItem *level1 = new QGraphicsRectItem; |
| QGraphicsItem *level21 = new QGraphicsRectItem; |
| level21->setParentItem(level1); |
| QGraphicsItem *level22 = new QGraphicsRectItem; |
| level22->setParentItem(level1); |
| QGraphicsItem *level31 = new QGraphicsRectItem; |
| level31->setParentItem(level21); |
| QGraphicsItem *level32 = new QGraphicsRectItem; |
| level32->setParentItem(level21); |
| |
| QCOMPARE(int(level1->d_ptr->ancestorFlags), 0); |
| QCOMPARE(int(level21->d_ptr->ancestorFlags), 0); |
| QCOMPARE(int(level22->d_ptr->ancestorFlags), 0); |
| QCOMPARE(int(level31->d_ptr->ancestorFlags), 0); |
| QCOMPARE(int(level32->d_ptr->ancestorFlags), 0); |
| |
| // HandlesChildEvents: 1) Root level sets a flag |
| level1->setHandlesChildEvents(true); |
| QCOMPARE(int(level1->d_ptr->ancestorFlags), 0); |
| QCOMPARE(int(level21->d_ptr->ancestorFlags), 1); |
| QCOMPARE(int(level22->d_ptr->ancestorFlags), 1); |
| QCOMPARE(int(level31->d_ptr->ancestorFlags), 1); |
| QCOMPARE(int(level32->d_ptr->ancestorFlags), 1); |
| |
| // HandlesChildEvents: 2) Root level set it again |
| level1->setHandlesChildEvents(true); |
| QCOMPARE(int(level1->d_ptr->ancestorFlags), 0); |
| QCOMPARE(int(level21->d_ptr->ancestorFlags), 1); |
| QCOMPARE(int(level22->d_ptr->ancestorFlags), 1); |
| QCOMPARE(int(level31->d_ptr->ancestorFlags), 1); |
| QCOMPARE(int(level32->d_ptr->ancestorFlags), 1); |
| |
| // HandlesChildEvents: 3) Root level unsets a flag |
| level1->setHandlesChildEvents(false); |
| QCOMPARE(int(level1->d_ptr->ancestorFlags), 0); |
| QCOMPARE(int(level21->d_ptr->ancestorFlags), 0); |
| QCOMPARE(int(level22->d_ptr->ancestorFlags), 0); |
| QCOMPARE(int(level31->d_ptr->ancestorFlags), 0); |
| QCOMPARE(int(level32->d_ptr->ancestorFlags), 0); |
| |
| // HandlesChildEvents: 4) Child item sets a flag |
| level21->setHandlesChildEvents(true); |
| QCOMPARE(int(level1->d_ptr->ancestorFlags), 0); |
| QCOMPARE(int(level21->d_ptr->ancestorFlags), 0); |
| QCOMPARE(int(level22->d_ptr->ancestorFlags), 0); |
| QCOMPARE(int(level31->d_ptr->ancestorFlags), 1); |
| QCOMPARE(int(level32->d_ptr->ancestorFlags), 1); |
| |
| // HandlesChildEvents: 5) Parent item sets a flag |
| level1->setHandlesChildEvents(true); |
| QCOMPARE(int(level1->d_ptr->ancestorFlags), 0); |
| QCOMPARE(int(level21->d_ptr->ancestorFlags), 1); |
| QCOMPARE(int(level22->d_ptr->ancestorFlags), 1); |
| QCOMPARE(int(level31->d_ptr->ancestorFlags), 1); |
| QCOMPARE(int(level32->d_ptr->ancestorFlags), 1); |
| |
| // HandlesChildEvents: 6) Child item unsets a flag |
| level21->setHandlesChildEvents(false); |
| QCOMPARE(int(level1->d_ptr->ancestorFlags), 0); |
| QCOMPARE(int(level21->d_ptr->ancestorFlags), 1); |
| QCOMPARE(int(level22->d_ptr->ancestorFlags), 1); |
| QCOMPARE(int(level31->d_ptr->ancestorFlags), 1); |
| QCOMPARE(int(level32->d_ptr->ancestorFlags), 1); |
| |
| // HandlesChildEvents: 7) Parent item unsets a flag |
| level21->setHandlesChildEvents(true); |
| level1->setHandlesChildEvents(false); |
| QCOMPARE(int(level1->d_ptr->ancestorFlags), 0); |
| QCOMPARE(int(level21->d_ptr->ancestorFlags), 0); |
| QCOMPARE(int(level22->d_ptr->ancestorFlags), 0); |
| QCOMPARE(int(level31->d_ptr->ancestorFlags), 1); |
| QCOMPARE(int(level32->d_ptr->ancestorFlags), 1); |
| |
| // Reparent the child to root |
| level21->setParentItem(0); |
| QCOMPARE(int(level21->d_ptr->ancestorFlags), 0); |
| QCOMPARE(int(level22->d_ptr->ancestorFlags), 0); |
| QCOMPARE(int(level31->d_ptr->ancestorFlags), 1); |
| QCOMPARE(int(level32->d_ptr->ancestorFlags), 1); |
| |
| // Reparent the child to level1 again. |
| level1->setHandlesChildEvents(true); |
| level21->setParentItem(level1); |
| QCOMPARE(int(level1->d_ptr->ancestorFlags), 0); |
| QCOMPARE(int(level21->d_ptr->ancestorFlags), 1); |
| QCOMPARE(int(level22->d_ptr->ancestorFlags), 1); |
| QCOMPARE(int(level31->d_ptr->ancestorFlags), 1); |
| QCOMPARE(int(level32->d_ptr->ancestorFlags), 1); |
| |
| // Reparenting level31 back to level1. |
| level31->setParentItem(level1); |
| QCOMPARE(int(level1->d_ptr->ancestorFlags), 0); |
| QCOMPARE(int(level21->d_ptr->ancestorFlags), 1); |
| QCOMPARE(int(level22->d_ptr->ancestorFlags), 1); |
| QCOMPARE(int(level31->d_ptr->ancestorFlags), 1); |
| QCOMPARE(int(level32->d_ptr->ancestorFlags), 1); |
| |
| // Reparenting level31 back to level21. |
| level31->setParentItem(0); |
| QCOMPARE(int(level31->d_ptr->ancestorFlags), 0); |
| level31->setParentItem(level21); |
| QCOMPARE(int(level1->d_ptr->ancestorFlags), 0); |
| QCOMPARE(int(level21->d_ptr->ancestorFlags), 1); |
| QCOMPARE(int(level22->d_ptr->ancestorFlags), 1); |
| QCOMPARE(int(level31->d_ptr->ancestorFlags), 1); |
| QCOMPARE(int(level32->d_ptr->ancestorFlags), 1); |
| |
| // Level1 doesn't handle child events |
| level1->setHandlesChildEvents(false); |
| QCOMPARE(int(level1->d_ptr->ancestorFlags), 0); |
| QCOMPARE(int(level21->d_ptr->ancestorFlags), 0); |
| QCOMPARE(int(level22->d_ptr->ancestorFlags), 0); |
| QCOMPARE(int(level31->d_ptr->ancestorFlags), 1); |
| QCOMPARE(int(level32->d_ptr->ancestorFlags), 1); |
| |
| // Nobody handles child events |
| level21->setHandlesChildEvents(false); |
| |
| for (int i = 0; i < 3; ++i) { |
| QGraphicsItem::GraphicsItemFlag flag; |
| int ancestorFlag; |
| |
| switch (i) { |
| case(0): |
| flag = QGraphicsItem::ItemClipsChildrenToShape; |
| ancestorFlag = QGraphicsItemPrivate::AncestorClipsChildren; |
| break; |
| case(1): |
| flag = QGraphicsItem::ItemIgnoresTransformations; |
| ancestorFlag = QGraphicsItemPrivate::AncestorIgnoresTransformations; |
| break; |
| case(2): |
| flag = QGraphicsItem::ItemContainsChildrenInShape; |
| ancestorFlag = QGraphicsItemPrivate::AncestorContainsChildren; |
| break; |
| default: |
| qFatal("Unknown ancestor flag, please fix!"); |
| break; |
| } |
| |
| QCOMPARE(int(level1->d_ptr->ancestorFlags), 0); |
| QCOMPARE(int(level21->d_ptr->ancestorFlags), 0); |
| QCOMPARE(int(level22->d_ptr->ancestorFlags), 0); |
| QCOMPARE(int(level31->d_ptr->ancestorFlags), 0); |
| QCOMPARE(int(level32->d_ptr->ancestorFlags), 0); |
| |
| // HandlesChildEvents: 1) Root level sets a flag |
| level1->setFlag(flag, true); |
| QCOMPARE(int(level1->d_ptr->ancestorFlags), 0); |
| QCOMPARE(int(level21->d_ptr->ancestorFlags), ancestorFlag); |
| QCOMPARE(int(level22->d_ptr->ancestorFlags), ancestorFlag); |
| QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag); |
| QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag); |
| |
| // HandlesChildEvents: 2) Root level set it again |
| level1->setFlag(flag, true); |
| QCOMPARE(int(level1->d_ptr->ancestorFlags), 0); |
| QCOMPARE(int(level21->d_ptr->ancestorFlags), ancestorFlag); |
| QCOMPARE(int(level22->d_ptr->ancestorFlags), ancestorFlag); |
| QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag); |
| QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag); |
| |
| // HandlesChildEvents: 3) Root level unsets a flag |
| level1->setFlag(flag, false); |
| QCOMPARE(int(level1->d_ptr->ancestorFlags), 0); |
| QCOMPARE(int(level21->d_ptr->ancestorFlags), 0); |
| QCOMPARE(int(level22->d_ptr->ancestorFlags), 0); |
| QCOMPARE(int(level31->d_ptr->ancestorFlags), 0); |
| QCOMPARE(int(level32->d_ptr->ancestorFlags), 0); |
| |
| // HandlesChildEvents: 4) Child item sets a flag |
| level21->setFlag(flag, true); |
| QCOMPARE(int(level1->d_ptr->ancestorFlags), 0); |
| QCOMPARE(int(level21->d_ptr->ancestorFlags), 0); |
| QCOMPARE(int(level22->d_ptr->ancestorFlags), 0); |
| QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag); |
| QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag); |
| |
| // HandlesChildEvents: 5) Parent item sets a flag |
| level1->setFlag(flag, true); |
| QCOMPARE(int(level1->d_ptr->ancestorFlags), 0); |
| QCOMPARE(int(level21->d_ptr->ancestorFlags), ancestorFlag); |
| QCOMPARE(int(level22->d_ptr->ancestorFlags), ancestorFlag); |
| QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag); |
| QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag); |
| |
| // HandlesChildEvents: 6) Child item unsets a flag |
| level21->setFlag(flag, false); |
| QCOMPARE(int(level1->d_ptr->ancestorFlags), 0); |
| QCOMPARE(int(level21->d_ptr->ancestorFlags), ancestorFlag); |
| QCOMPARE(int(level22->d_ptr->ancestorFlags), ancestorFlag); |
| QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag); |
| QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag); |
| |
| // HandlesChildEvents: 7) Parent item unsets a flag |
| level21->setFlag(flag, true); |
| level1->setFlag(flag, false); |
| QCOMPARE(int(level1->d_ptr->ancestorFlags), 0); |
| QCOMPARE(int(level21->d_ptr->ancestorFlags), 0); |
| QCOMPARE(int(level22->d_ptr->ancestorFlags), 0); |
| QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag); |
| QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag); |
| |
| // Reparent the child to root |
| level21->setParentItem(0); |
| QCOMPARE(int(level21->d_ptr->ancestorFlags), 0); |
| QCOMPARE(int(level22->d_ptr->ancestorFlags), 0); |
| QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag); |
| QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag); |
| |
| // Reparent the child to level1 again. |
| level1->setFlag(flag, true); |
| level21->setParentItem(level1); |
| QCOMPARE(int(level1->d_ptr->ancestorFlags), 0); |
| QCOMPARE(int(level21->d_ptr->ancestorFlags), ancestorFlag); |
| QCOMPARE(int(level22->d_ptr->ancestorFlags), ancestorFlag); |
| QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag); |
| QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag); |
| |
| // Reparenting level31 back to level1. |
| level31->setParentItem(level1); |
| QCOMPARE(int(level1->d_ptr->ancestorFlags), 0); |
| QCOMPARE(int(level21->d_ptr->ancestorFlags), ancestorFlag); |
| QCOMPARE(int(level22->d_ptr->ancestorFlags), ancestorFlag); |
| QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag); |
| QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag); |
| |
| // Reparenting level31 back to level21. |
| level31->setParentItem(0); |
| QCOMPARE(int(level31->d_ptr->ancestorFlags), 0); |
| level31->setParentItem(level21); |
| QCOMPARE(int(level1->d_ptr->ancestorFlags), 0); |
| QCOMPARE(int(level21->d_ptr->ancestorFlags), ancestorFlag); |
| QCOMPARE(int(level22->d_ptr->ancestorFlags), ancestorFlag); |
| QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag); |
| QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag); |
| |
| // Level1 doesn't handle child events |
| level1->setFlag(flag, false); |
| QCOMPARE(int(level1->d_ptr->ancestorFlags), 0); |
| QCOMPARE(int(level21->d_ptr->ancestorFlags), 0); |
| QCOMPARE(int(level22->d_ptr->ancestorFlags), 0); |
| QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag); |
| QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag); |
| |
| // Nobody handles child events |
| level21->setFlag(flag, false); |
| QCOMPARE(int(level1->d_ptr->ancestorFlags), 0); |
| QCOMPARE(int(level21->d_ptr->ancestorFlags), 0); |
| QCOMPARE(int(level22->d_ptr->ancestorFlags), 0); |
| QCOMPARE(int(level31->d_ptr->ancestorFlags), 0); |
| QCOMPARE(int(level32->d_ptr->ancestorFlags), 0); |
| } |
| |
| delete level1; |
| } |
| |
| void tst_QGraphicsItem::untransformable() |
| { |
| QGraphicsItem *item1 = new QGraphicsEllipseItem(QRectF(-50, -50, 100, 100)); |
| item1->setZValue(1); |
| item1->setFlag(QGraphicsItem::ItemIgnoresTransformations); |
| item1->setTransform(QTransform().rotate(45), true); |
| ((QGraphicsEllipseItem *)item1)->setBrush(Qt::red); |
| |
| QGraphicsItem *item2 = new QGraphicsEllipseItem(QRectF(-50, -50, 100, 100)); |
| item2->setParentItem(item1); |
| item2->setTransform(QTransform().rotate(45), true); |
| item2->setPos(100, 0); |
| ((QGraphicsEllipseItem *)item2)->setBrush(Qt::green); |
| |
| QGraphicsItem *item3 = new QGraphicsEllipseItem(QRectF(-50, -50, 100, 100)); |
| item3->setParentItem(item2); |
| item3->setPos(100, 0); |
| ((QGraphicsEllipseItem *)item3)->setBrush(Qt::blue); |
| |
| QGraphicsScene scene(-500, -500, 1000, 1000); |
| scene.addItem(item1); |
| |
| QWidget topLevel; |
| QGraphicsView view(&scene,&topLevel); |
| view.resize(300, 300); |
| topLevel.show(); |
| view.scale(8, 8); |
| view.centerOn(0, 0); |
| |
| // Painting with the DiagCrossPattern is really slow on Mac |
| // when zoomed out. (The test times out). Task to fix is 155567. |
| #if !defined(Q_OS_MAC) || 1 |
| view.setBackgroundBrush(QBrush(Qt::black, Qt::DiagCrossPattern)); |
| #endif |
| |
| QVERIFY(QTest::qWaitForWindowExposed(&topLevel)); |
| |
| for (int i = 0; i < 10; ++i) { |
| QPoint center = view.viewport()->rect().center(); |
| QCOMPARE(view.itemAt(center), item1); |
| QCOMPARE(view.itemAt(center - QPoint(40, 0)), item1); |
| QCOMPARE(view.itemAt(center - QPoint(-40, 0)), item1); |
| QCOMPARE(view.itemAt(center - QPoint(0, 40)), item1); |
| QCOMPARE(view.itemAt(center - QPoint(0, -40)), item1); |
| |
| center += QPoint(70, 70); |
| QCOMPARE(view.itemAt(center - QPoint(40, 0)), item2); |
| QCOMPARE(view.itemAt(center - QPoint(-40, 0)), item2); |
| QCOMPARE(view.itemAt(center - QPoint(0, 40)), item2); |
| QCOMPARE(view.itemAt(center - QPoint(0, -40)), item2); |
| |
| center += QPoint(0, 100); |
| QCOMPARE(view.itemAt(center - QPoint(40, 0)), item3); |
| QCOMPARE(view.itemAt(center - QPoint(-40, 0)), item3); |
| QCOMPARE(view.itemAt(center - QPoint(0, 40)), item3); |
| QCOMPARE(view.itemAt(center - QPoint(0, -40)), item3); |
| |
| view.scale(0.5, 0.5); |
| view.rotate(13); |
| view.shear(qreal(0.01), qreal(0.01)); |
| view.translate(10, 10); |
| } |
| } |
| |
| #ifndef QT_NO_CONTEXTMENU |
| class ContextMenuItem : public QGraphicsRectItem |
| { |
| public: |
| ContextMenuItem() |
| : ignoreEvent(true), gotEvent(false), eventWasAccepted(false) |
| { } |
| bool ignoreEvent; |
| bool gotEvent; |
| bool eventWasAccepted; |
| protected: |
| void contextMenuEvent(QGraphicsSceneContextMenuEvent *event) |
| { |
| gotEvent = true; |
| eventWasAccepted = event->isAccepted(); |
| if (ignoreEvent) |
| event->ignore(); |
| } |
| }; |
| |
| void tst_QGraphicsItem::contextMenuEventPropagation() |
| { |
| ContextMenuItem *bottomItem = new ContextMenuItem; |
| bottomItem->setRect(0, 0, 100, 100); |
| ContextMenuItem *topItem = new ContextMenuItem; |
| topItem->setParentItem(bottomItem); |
| topItem->setRect(0, 0, 100, 100); |
| |
| QGraphicsScene scene; |
| |
| QGraphicsView view(&scene); |
| view.setAlignment(Qt::AlignLeft | Qt::AlignTop); |
| view.show(); |
| view.resize(200, 200); |
| QVERIFY(QTest::qWaitForWindowExposed(&view)); |
| |
| QContextMenuEvent event(QContextMenuEvent::Mouse, QPoint(10, 10), |
| view.viewport()->mapToGlobal(QPoint(10, 10))); |
| event.ignore(); |
| QApplication::sendEvent(view.viewport(), &event); |
| QVERIFY(!event.isAccepted()); |
| |
| scene.addItem(bottomItem); |
| topItem->ignoreEvent = true; |
| bottomItem->ignoreEvent = true; |
| |
| QApplication::sendEvent(view.viewport(), &event); |
| QVERIFY(!event.isAccepted()); |
| QCOMPARE(topItem->gotEvent, true); |
| QCOMPARE(topItem->eventWasAccepted, true); |
| QCOMPARE(bottomItem->gotEvent, true); |
| QCOMPARE(bottomItem->eventWasAccepted, true); |
| |
| topItem->ignoreEvent = false; |
| topItem->gotEvent = false; |
| bottomItem->gotEvent = false; |
| |
| QApplication::sendEvent(view.viewport(), &event); |
| QVERIFY(event.isAccepted()); |
| QCOMPARE(topItem->gotEvent, true); |
| QCOMPARE(bottomItem->gotEvent, false); |
| QCOMPARE(topItem->eventWasAccepted, true); |
| } |
| #endif // QT_NO_CONTEXTMENU |
| |
| void tst_QGraphicsItem::itemIsMovable() |
| { |
| QGraphicsRectItem *rect = new QGraphicsRectItem(-50, -50, 100, 100); |
| rect->setFlag(QGraphicsItem::ItemIsMovable); |
| |
| QGraphicsScene scene; |
| scene.addItem(rect); |
| |
| { |
| QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress); |
| event.setButton(Qt::LeftButton); |
| event.setButtons(Qt::LeftButton); |
| qApp->sendEvent(&scene, &event); |
| } |
| { |
| QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseMove); |
| event.setButton(Qt::LeftButton); |
| event.setButtons(Qt::LeftButton); |
| qApp->sendEvent(&scene, &event); |
| } |
| QCOMPARE(rect->pos(), QPointF(0, 0)); |
| { |
| QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseMove); |
| event.setButtons(Qt::LeftButton); |
| event.setScenePos(QPointF(10, 10)); |
| qApp->sendEvent(&scene, &event); |
| } |
| QCOMPARE(rect->pos(), QPointF(10, 10)); |
| { |
| QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseMove); |
| event.setButtons(Qt::RightButton); |
| event.setScenePos(QPointF(20, 20)); |
| qApp->sendEvent(&scene, &event); |
| } |
| QCOMPARE(rect->pos(), QPointF(10, 10)); |
| { |
| QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseMove); |
| event.setButtons(Qt::LeftButton); |
| event.setScenePos(QPointF(30, 30)); |
| qApp->sendEvent(&scene, &event); |
| } |
| QCOMPARE(rect->pos(), QPointF(30, 30)); |
| } |
| |
| class ItemAddScene : public QGraphicsScene |
| { |
| Q_OBJECT |
| public: |
| ItemAddScene() |
| { |
| QTimer::singleShot(500, this, SLOT(newTextItem())); |
| } |
| |
| public slots: |
| void newTextItem() |
| { |
| // Add a text item |
| QGraphicsItem *item = new QGraphicsTextItem("This item will not ensure that it's visible", 0); |
| item->setPos(.0, .0); |
| item->show(); |
| } |
| }; |
| |
| void tst_QGraphicsItem::task141694_textItemEnsureVisible() |
| { |
| ItemAddScene scene; |
| scene.setSceneRect(-1000, -1000, 2000, 2000); |
| |
| QGraphicsView view(&scene); |
| view.setFixedSize(200, 200); |
| view.show(); |
| QVERIFY(QTest::qWaitForWindowExposed(&view)); |
| |
| view.ensureVisible(-1000, -1000, 5, 5); |
| int hscroll = view.horizontalScrollBar()->value(); |
| int vscroll = view.verticalScrollBar()->value(); |
| |
| QTest::qWait(10); |
| |
| // This should not cause the view to scroll |
| QTRY_COMPARE(view.horizontalScrollBar()->value(), hscroll); |
| QCOMPARE(view.verticalScrollBar()->value(), vscroll); |
| } |
| |
| void tst_QGraphicsItem::task128696_textItemEnsureMovable() |
| { |
| QGraphicsTextItem *item = new QGraphicsTextItem; |
| item->setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable); |
| item->setTextInteractionFlags(Qt::TextEditorInteraction); |
| item->setPlainText("abc de\nf ghi\n j k l"); |
| |
| QGraphicsScene scene; |
| scene.setSceneRect(-100, -100, 200, 200); |
| scene.addItem(item); |
| |
| QGraphicsView view(&scene); |
| view.setFixedSize(200, 200); |
| view.show(); |
| |
| QGraphicsSceneMouseEvent event1(QEvent::GraphicsSceneMousePress); |
| event1.setScenePos(QPointF(0, 0)); |
| event1.setButton(Qt::LeftButton); |
| event1.setButtons(Qt::LeftButton); |
| QApplication::sendEvent(&scene, &event1); |
| QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)item); |
| |
| QGraphicsSceneMouseEvent event2(QEvent::GraphicsSceneMouseMove); |
| event2.setScenePos(QPointF(10, 10)); |
| event2.setButton(Qt::LeftButton); |
| event2.setButtons(Qt::LeftButton); |
| QApplication::sendEvent(&scene, &event2); |
| QCOMPARE(item->pos(), QPointF(10, 10)); |
| } |
| |
| void tst_QGraphicsItem::task177918_lineItemUndetected() |
| { |
| QGraphicsScene scene; |
| QGraphicsLineItem *line = scene.addLine(10, 10, 10, 10); |
| QCOMPARE(line->boundingRect(), QRectF(10, 10, 0, 0)); |
| |
| const QRectF rect(9, 9, 2, 2); |
| QVERIFY(!scene.items(rect, Qt::IntersectsItemShape).isEmpty()); |
| QVERIFY(!scene.items(rect, Qt::ContainsItemShape).isEmpty()); |
| QVERIFY(!scene.items(rect, Qt::IntersectsItemBoundingRect).isEmpty()); |
| QVERIFY(!scene.items(rect, Qt::ContainsItemBoundingRect).isEmpty()); |
| } |
| |
| void tst_QGraphicsItem::task240400_clickOnTextItem_data() |
| { |
| QTest::addColumn<int>("flags"); |
| QTest::addColumn<int>("textFlags"); |
| QTest::newRow("editor, noflags") << 0 << int(Qt::TextEditorInteraction); |
| QTest::newRow("editor, movable") << int(QGraphicsItem::ItemIsMovable) << int(Qt::TextEditorInteraction); |
| QTest::newRow("editor, selectable") << int(QGraphicsItem::ItemIsSelectable) << int(Qt::TextEditorInteraction); |
| QTest::newRow("editor, movable | selectable") << int(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable) |
| << int(Qt::TextEditorInteraction); |
| QTest::newRow("noninteractive, noflags") << 0 << int(Qt::NoTextInteraction); |
| QTest::newRow("noninteractive, movable") << int(QGraphicsItem::ItemIsMovable) << int(Qt::NoTextInteraction); |
| QTest::newRow("noninteractive, selectable") << int(QGraphicsItem::ItemIsSelectable) << int(Qt::NoTextInteraction); |
| QTest::newRow("noninteractive, movable | selectable") << int(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable) |
| << int(Qt::NoTextInteraction); |
| } |
| |
| void tst_QGraphicsItem::task240400_clickOnTextItem() |
| { |
| QFETCH(int, flags); |
| QFETCH(int, textFlags); |
| |
| QGraphicsScene scene; |
| QEvent activate(QEvent::WindowActivate); |
| QApplication::sendEvent(&scene, &activate); |
| |
| QGraphicsTextItem *item = scene.addText("Hello"); |
| item->setFlags(QGraphicsItem::GraphicsItemFlags(flags)); |
| item->setTextInteractionFlags(Qt::TextInteractionFlags(textFlags)); |
| bool focusable = (item->flags() & QGraphicsItem::ItemIsFocusable); |
| QVERIFY(textFlags ? focusable : !focusable); |
| |
| int column = item->textCursor().columnNumber(); |
| QCOMPARE(column, 0); |
| |
| QVERIFY(!item->hasFocus()); |
| |
| // Click in the top-left corner of the item |
| { |
| QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress); |
| event.setScenePos(item->sceneBoundingRect().topLeft() + QPointF(0.1, 0.1)); |
| event.setButton(Qt::LeftButton); |
| event.setButtons(Qt::LeftButton); |
| QApplication::sendEvent(&scene, &event); |
| } |
| if (flags || textFlags) |
| QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)item); |
| else |
| QCOMPARE(scene.mouseGrabberItem(), nullptr); |
| { |
| QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseRelease); |
| event.setScenePos(item->sceneBoundingRect().topLeft() + QPointF(0.1, 0.1)); |
| event.setButton(Qt::LeftButton); |
| event.setButtons(0); |
| QApplication::sendEvent(&scene, &event); |
| } |
| if (textFlags) |
| QVERIFY(item->hasFocus()); |
| else |
| QVERIFY(!item->hasFocus()); |
| QVERIFY(!scene.mouseGrabberItem()); |
| bool selectable = (flags & QGraphicsItem::ItemIsSelectable); |
| QVERIFY(selectable ? item->isSelected() : !item->isSelected()); |
| |
| // Now click in the middle and check that the cursor moved. |
| { |
| QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress); |
| event.setScenePos(item->sceneBoundingRect().center()); |
| event.setButton(Qt::LeftButton); |
| event.setButtons(Qt::LeftButton); |
| QApplication::sendEvent(&scene, &event); |
| } |
| if (flags || textFlags) |
| QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)item); |
| else |
| QCOMPARE(scene.mouseGrabberItem(), nullptr); |
| { |
| QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseRelease); |
| event.setScenePos(item->sceneBoundingRect().center()); |
| event.setButton(Qt::LeftButton); |
| event.setButtons(0); |
| QApplication::sendEvent(&scene, &event); |
| } |
| if (textFlags) |
| QVERIFY(item->hasFocus()); |
| else |
| QVERIFY(!item->hasFocus()); |
| QVERIFY(!scene.mouseGrabberItem()); |
| |
| QVERIFY(selectable ? item->isSelected() : !item->isSelected()); |
| |
| // |
| if (textFlags & Qt::TextEditorInteraction) |
| QVERIFY(item->textCursor().columnNumber() > column); |
| else |
| QCOMPARE(item->textCursor().columnNumber(), 0); |
| } |
| |
| class TextItem : public QGraphicsSimpleTextItem |
| { |
| public: |
| TextItem(const QString& text) : QGraphicsSimpleTextItem(text) |
| { |
| updates = 0; |
| } |
| |
| void paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget) |
| { |
| updates++; |
| QGraphicsSimpleTextItem::paint(painter, option, widget); |
| } |
| |
| int updates; |
| }; |
| |
| void tst_QGraphicsItem::ensureUpdateOnTextItem() |
| { |
| QGraphicsScene scene; |
| QGraphicsView view(&scene); |
| view.show(); |
| QVERIFY(QTest::qWaitForWindowExposed(&view)); |
| QCoreApplication::processEvents(); // Process all queued paint events |
| TextItem *text1 = new TextItem(QLatin1String("123")); |
| scene.addItem(text1); |
| QTRY_COMPARE(text1->updates,1); |
| |
| //same bouding rect but we have to update |
| text1->setText(QLatin1String("321")); |
| QTRY_COMPARE(text1->updates,2); |
| } |
| |
| void tst_QGraphicsItem::task243707_addChildBeforeParent() |
| { |
| // Task reports that adding the child before the parent leads to an |
| // inconsistent internal state that can cause a crash. This test shows |
| // one such crash. |
| QGraphicsScene scene; |
| QGraphicsWidget *widget = new QGraphicsWidget; |
| QGraphicsWidget *widget2 = new QGraphicsWidget(widget); |
| scene.addItem(widget2); |
| QVERIFY(!widget2->parentItem()); |
| scene.addItem(widget); |
| QVERIFY(!widget->commonAncestorItem(widget2)); |
| QVERIFY(!widget2->commonAncestorItem(widget)); |
| } |
| |
| void tst_QGraphicsItem::task197802_childrenVisibility() |
| { |
| QGraphicsScene scene; |
| QGraphicsRectItem item(QRectF(0,0,20,20)); |
| |
| QGraphicsRectItem *item2 = new QGraphicsRectItem(QRectF(0,0,10,10), &item); |
| scene.addItem(&item); |
| |
| //freshly created: both visible |
| QVERIFY(item.isVisible()); |
| QVERIFY(item2->isVisible()); |
| |
| //hide child: parent visible, child not |
| item2->hide(); |
| QVERIFY(item.isVisible()); |
| QVERIFY(!item2->isVisible()); |
| |
| //hide parent: parent and child invisible |
| item.hide(); |
| QVERIFY(!item.isVisible()); |
| QVERIFY(!item2->isVisible()); |
| |
| //ask to show the child: parent and child invisible anyways |
| item2->show(); |
| QVERIFY(!item.isVisible()); |
| QVERIFY(!item2->isVisible()); |
| |
| //show the parent: both parent and child visible |
| item.show(); |
| QVERIFY(item.isVisible()); |
| QVERIFY(item2->isVisible()); |
| |
| delete item2; |
| } |
| |
| void tst_QGraphicsItem::boundingRegion_data() |
| { |
| QTest::addColumn<QLineF>("line"); |
| QTest::addColumn<qreal>("granularity"); |
| QTest::addColumn<QTransform>("transform"); |
| QTest::addColumn<QRegion>("expectedRegion"); |
| |
| QTest::newRow("(0, 0, 10, 10) | 0.0 | identity | {(0, 0, 10, 10)}") << QLineF(0, 0, 10, 10) << qreal(0.0) << QTransform() |
| << QRegion(QRect(0, 0, 10, 10)); |
| QTest::newRow("(0, 0, 10, 0) | 0.0 | identity | {(0, 0, 10, 10)}") << QLineF(0, 0, 10, 0) << qreal(0.0) << QTransform() |
| << QRegion(QRect(0, 0, 10, 1)); |
| QTest::newRow("(0, 0, 10, 0) | 0.5 | identity | {(0, 0, 10, 1)}") << QLineF(0, 0, 10, 0) << qreal(0.5) << QTransform() |
| << QRegion(QRect(0, 0, 10, 1)); |
| QTest::newRow("(0, 0, 10, 0) | 1.0 | identity | {(0, 0, 10, 1)}") << QLineF(0, 0, 10, 0) << qreal(1.0) << QTransform() |
| << QRegion(QRect(0, 0, 10, 1)); |
| QTest::newRow("(0, 0, 0, 10) | 0.0 | identity | {(0, 0, 10, 10)}") << QLineF(0, 0, 0, 10) << qreal(0.0) << QTransform() |
| << QRegion(QRect(0, 0, 1, 10)); |
| QTest::newRow("(0, 0, 0, 10) | 0.5 | identity | {(0, 0, 1, 10)}") << QLineF(0, 0, 0, 10) << qreal(0.5) << QTransform() |
| << QRegion(QRect(0, 0, 1, 10)); |
| QTest::newRow("(0, 0, 0, 10) | 1.0 | identity | {(0, 0, 1, 10)}") << QLineF(0, 0, 0, 10) << qreal(1.0) << QTransform() |
| << QRegion(QRect(0, 0, 1, 10)); |
| } |
| |
| void tst_QGraphicsItem::boundingRegion() |
| { |
| QFETCH(QLineF, line); |
| QFETCH(qreal, granularity); |
| QFETCH(QTransform, transform); |
| QFETCH(QRegion, expectedRegion); |
| |
| QGraphicsLineItem item(line); |
| item.setPen(QPen(Qt::black, 0)); |
| QCOMPARE(item.boundingRegionGranularity(), qreal(0.0)); |
| item.setBoundingRegionGranularity(granularity); |
| QCOMPARE(item.boundingRegionGranularity(), granularity); |
| QCOMPARE(item.boundingRegion(transform), expectedRegion); |
| } |
| |
| void tst_QGraphicsItem::itemTransform_parentChild() |
| { |
| QGraphicsScene scene; |
| QGraphicsItem *parent = scene.addRect(0, 0, 100, 100); |
| QGraphicsItem *child = scene.addRect(0, 0, 100, 100); |
| child->setParentItem(parent); |
| child->setPos(10, 10); |
| child->setTransform(QTransform::fromScale(2, 2), true); |
| child->setTransform(QTransform().rotate(90), true); |
| |
| QCOMPARE(child->itemTransform(parent).map(QPointF(10, 10)), QPointF(-10, 30)); |
| QCOMPARE(parent->itemTransform(child).map(QPointF(-10, 30)), QPointF(10, 10)); |
| } |
| |
| void tst_QGraphicsItem::itemTransform_siblings() |
| { |
| QGraphicsScene scene; |
| QGraphicsItem *parent = scene.addRect(0, 0, 100, 100); |
| QGraphicsItem *brother = scene.addRect(0, 0, 100, 100); |
| QGraphicsItem *sister = scene.addRect(0, 0, 100, 100); |
| parent->setTransform(QTransform::fromScale(10, 5), true); |
| parent->setTransform(QTransform().rotate(-180), true); |
| parent->setTransform(QTransform().shear(2, 3), true); |
| |
| brother->setParentItem(parent); |
| sister->setParentItem(parent); |
| |
| brother->setPos(10, 10); |
| brother->setTransform(QTransform::fromScale(2, 2), true); |
| brother->setTransform(QTransform().rotate(90), true); |
| sister->setPos(10, 10); |
| sister->setTransform(QTransform::fromScale(2, 2), true); |
| sister->setTransform(QTransform().rotate(90), true); |
| |
| QCOMPARE(brother->itemTransform(sister).map(QPointF(10, 10)), QPointF(10, 10)); |
| QCOMPARE(sister->itemTransform(brother).map(QPointF(10, 10)), QPointF(10, 10)); |
| } |
| |
| void tst_QGraphicsItem::itemTransform_unrelated() |
| { |
| QGraphicsScene scene; |
| QGraphicsItem *stranger1 = scene.addRect(0, 0, 100, 100); |
| QGraphicsItem *stranger2 = scene.addRect(0, 0, 100, 100); |
| stranger1->setPos(10, 10); |
| stranger1->setTransform(QTransform::fromScale(2, 2), true); |
| stranger1->setTransform(QTransform().rotate(90), true); |
| stranger2->setPos(10, 10); |
| stranger2->setTransform(QTransform::fromScale(2, 2), true); |
| stranger2->setTransform(QTransform().rotate(90), true); |
| |
| QCOMPARE(stranger1->itemTransform(stranger2).map(QPointF(10, 10)), QPointF(10, 10)); |
| QCOMPARE(stranger2->itemTransform(stranger1).map(QPointF(10, 10)), QPointF(10, 10)); |
| } |
| |
| void tst_QGraphicsItem::opacity_data() |
| { |
| QTest::addColumn<qreal>("p_opacity"); |
| QTest::addColumn<int>("p_opacityFlags"); |
| QTest::addColumn<qreal>("c1_opacity"); |
| QTest::addColumn<int>("c1_opacityFlags"); |
| QTest::addColumn<qreal>("c2_opacity"); |
| QTest::addColumn<int>("c2_opacityFlags"); |
| QTest::addColumn<qreal>("p_effectiveOpacity"); |
| QTest::addColumn<qreal>("c1_effectiveOpacity"); |
| QTest::addColumn<qreal>("c2_effectiveOpacity"); |
| QTest::addColumn<qreal>("c3_effectiveOpacity"); |
| |
| // Modify the opacity and see how it propagates |
| 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 |
| << qreal(1.0) << qreal(1.0) << qreal(1.0) << qreal(1.0); |
| 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 |
| << qreal(0.5) << qreal(0.5) << qreal(0.5) << qreal(0.5); |
| 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 |
| << qreal(0.5) << qreal(0.05) << qreal(0.05) << qreal(0.05); |
| 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 |
| << qreal(0.0) << qreal(0.0) << qreal(0.0) << qreal(0.0); |
| |
| // Parent doesn't propagate to children - now modify the opacity and see how it propagates |
| int flags = QGraphicsItem::ItemDoesntPropagateOpacityToChildren; |
| 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 |
| << qreal(1.0) << qreal(1.0) << qreal(1.0) << qreal(1.0); |
| 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 |
| << qreal(0.5) << qreal(1.0) << qreal(1.0) << qreal(1.0); |
| 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 |
| << qreal(0.5) << qreal(0.1) << qreal(0.1) << qreal(0.1); |
| 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 |
| << qreal(0.0) << qreal(1.0) << qreal(1.0) << qreal(1.0); |
| |
| // Child ignores parent - now modify the opacity and see how it propagates |
| flags = QGraphicsItem::ItemIgnoresParentOpacity; |
| 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 |
| << qreal(1.0) << qreal(1.0) << qreal(1.0) << qreal(1.0); |
| 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 |
| << qreal(0.5) << qreal(0.5) << qreal(0.25) << qreal(0.25); |
| 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 |
| << qreal(0.2) << qreal(0.2) << qreal(0.04) << qreal(0.04); |
| 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 |
| << qreal(0.0) << qreal(0.0) << qreal(0.0) << qreal(0.0); |
| |
| // Child ignores parent and doesn't propagate - now modify the opacity and see how it propagates |
| flags = QGraphicsItem::ItemIgnoresParentOpacity | QGraphicsItem::ItemDoesntPropagateOpacityToChildren; |
| QTest::newRow("M: 1.0 0 1.0 1 1.0 1.0 1.0 1.0 1.0") << qreal(1.0) << 0 // p |
| << qreal(1.0) << flags // c1 (no prop) |
| << qreal(1.0) << 0 // c2 |
| << qreal(1.0) << qreal(1.0) << qreal(1.0) << qreal(1.0); |
| QTest::newRow("M: 0.5 0 1.0 1 1.0 1.0 1.0 1.0 1.0") << qreal(0.5) << 0 // p |
| << qreal(1.0) << flags // c1 (no prop) |
| << qreal(1.0) << 0 // c2 |
| << qreal(0.5) << qreal(1.0) << qreal(1.0) << qreal(1.0); |
| QTest::newRow("M: 0.5 0 0.5 1 1.0 1.0 1.0 1.0 1.0") << qreal(0.5) << 0 // p |
| << qreal(0.5) << flags // c1 (no prop) |
| << qreal(1.0) << 0 // c2 |
| << qreal(0.5) << qreal(0.5) << qreal(1.0) << qreal(1.0); |
| QTest::newRow("M: 0.5 0 0.5 1 0.5 1.0 1.0 1.0 1.0") << qreal(0.5) << 0 // p |
| << qreal(0.5) << flags // c1 (no prop) |
| << qreal(0.5) << 0 // c2 |
| << qreal(0.5) << qreal(0.5) << qreal(0.5) << qreal(0.5); |
| QTest::newRow("M: 1.0 0 0.5 1 0.5 1.0 1.0 1.0 1.0") << qreal(1.0) << 0 // p |
| << qreal(0.5) << flags // c1 (no prop) |
| << qreal(0.5) << 0 // c2 |
| << qreal(1.0) << qreal(0.5) << qreal(0.5) << qreal(0.5); |
| } |
| |
| void tst_QGraphicsItem::opacity() |
| { |
| QFETCH(qreal, p_opacity); |
| QFETCH(int, p_opacityFlags); |
| QFETCH(qreal, p_effectiveOpacity); |
| QFETCH(qreal, c1_opacity); |
| QFETCH(int, c1_opacityFlags); |
| QFETCH(qreal, c1_effectiveOpacity); |
| QFETCH(qreal, c2_opacity); |
| QFETCH(int, c2_opacityFlags); |
| QFETCH(qreal, c2_effectiveOpacity); |
| QFETCH(qreal, c3_effectiveOpacity); |
| |
| const QScopedPointer<QGraphicsRectItem> p(new QGraphicsRectItem); |
| QGraphicsRectItem *c1 = new QGraphicsRectItem(p.data()); |
| QGraphicsRectItem *c2 = new QGraphicsRectItem(c1); |
| QGraphicsRectItem *c3 = new QGraphicsRectItem(c2); |
| |
| QCOMPARE(p->opacity(), qreal(1.0)); |
| QCOMPARE(p->effectiveOpacity(), qreal(1.0)); |
| int opacityMask = QGraphicsItem::ItemIgnoresParentOpacity | QGraphicsItem::ItemDoesntPropagateOpacityToChildren; |
| QVERIFY(!(p->flags() & opacityMask)); |
| |
| p->setOpacity(p_opacity); |
| c1->setOpacity(c1_opacity); |
| c2->setOpacity(c2_opacity); |
| p->setFlags(QGraphicsItem::GraphicsItemFlags(p->flags() | p_opacityFlags)); |
| c1->setFlags(QGraphicsItem::GraphicsItemFlags(c1->flags() | c1_opacityFlags)); |
| c2->setFlags(QGraphicsItem::GraphicsItemFlags(c2->flags() | c2_opacityFlags)); |
| |
| QCOMPARE(int(p->flags() & opacityMask), p_opacityFlags); |
| QCOMPARE(int(c1->flags() & opacityMask), c1_opacityFlags); |
| QCOMPARE(int(c2->flags() & opacityMask), c2_opacityFlags); |
| QCOMPARE(p->opacity(), p_opacity); |
| QCOMPARE(p->effectiveOpacity(), p_effectiveOpacity); |
| QCOMPARE(c1->effectiveOpacity(), c1_effectiveOpacity); |
| QCOMPARE(c2->effectiveOpacity(), c2_effectiveOpacity); |
| QCOMPARE(c3->effectiveOpacity(), c3_effectiveOpacity); |
| } |
| |
| void tst_QGraphicsItem::opacity2() |
| { |
| EventTester *parent = new EventTester; |
| EventTester *child = new EventTester(parent); |
| EventTester *grandChild = new EventTester(child); |
| |
| QGraphicsScene scene; |
| scene.addItem(parent); |
| |
| MyGraphicsView view(&scene); |
| view.show(); |
| QVERIFY(QTest::qWaitForWindowExposed(&view)); |
| QVERIFY(QTest::qWaitForWindowActive(&view)); |
| QCoreApplication::processEvents(); // Process all queued paint events |
| QTRY_VERIFY(view.repaints >= 1); |
| |
| #define RESET_REPAINT_COUNTERS \ |
| parent->repaints = 0; \ |
| child->repaints = 0; \ |
| grandChild->repaints = 0; \ |
| view.repaints = 0; |
| |
| RESET_REPAINT_COUNTERS |
| |
| child->setOpacity(0.0); |
| QTRY_COMPARE(view.repaints, 1); |
| QCOMPARE(parent->repaints, 1); |
| QCOMPARE(child->repaints, 0); |
| QCOMPARE(grandChild->repaints, 0); |
| |
| RESET_REPAINT_COUNTERS |
| |
| child->setOpacity(1.0); |
| QTRY_COMPARE(view.repaints, 1); |
| QCOMPARE(parent->repaints, 1); |
| QCOMPARE(child->repaints, 1); |
| QCOMPARE(grandChild->repaints, 1); |
| |
| RESET_REPAINT_COUNTERS |
| |
| parent->setOpacity(0.0); |
| QTRY_COMPARE(view.repaints, 1); |
| QCOMPARE(parent->repaints, 0); |
| QCOMPARE(child->repaints, 0); |
| QCOMPARE(grandChild->repaints, 0); |
| |
| RESET_REPAINT_COUNTERS |
| |
| parent->setOpacity(1.0); |
| QTRY_COMPARE(view.repaints, 1); |
| QCOMPARE(parent->repaints, 1); |
| QCOMPARE(child->repaints, 1); |
| QCOMPARE(grandChild->repaints, 1); |
| |
| grandChild->setFlag(QGraphicsItem::ItemIgnoresParentOpacity); |
| RESET_REPAINT_COUNTERS |
| |
| child->setOpacity(0.0); |
| QTRY_COMPARE(view.repaints, 1); |
| QCOMPARE(parent->repaints, 1); |
| QCOMPARE(child->repaints, 0); |
| QCOMPARE(grandChild->repaints, 1); |
| |
| RESET_REPAINT_COUNTERS |
| |
| child->setOpacity(0.0); // Already 0.0; no change. |
| QTest::qWait(10); |
| QCOMPARE(view.repaints, 0); |
| QCOMPARE(parent->repaints, 0); |
| QCOMPARE(child->repaints, 0); |
| QCOMPARE(grandChild->repaints, 0); |
| } |
| |
| void tst_QGraphicsItem::opacityZeroUpdates() |
| { |
| EventTester *parent = new EventTester; |
| EventTester *child = new EventTester(parent); |
| |
| child->setPos(10, 10); |
| |
| QGraphicsScene scene; |
| scene.addItem(parent); |
| |
| MyGraphicsView view(&scene); |
| view.show(); |
| QVERIFY(QTest::qWaitForWindowExposed(&view)); |
| QVERIFY(QTest::qWaitForWindowActive(&view)); |
| QCoreApplication::processEvents(); // Process all queued paint events |
| QTRY_VERIFY(view.repaints > 0); |
| |
| view.reset(); |
| parent->setOpacity(0.0); |
| |
| QTRY_COMPARE(view.repaints, 1); |
| |
| // transforming items bounding rect to view coordinates |
| const QRect childDeviceBoundingRect = child->deviceTransform(view.viewportTransform()) |
| .mapRect(child->boundingRect()).toRect(); |
| const QRect parentDeviceBoundingRect = parent->deviceTransform(view.viewportTransform()) |
| .mapRect(parent->boundingRect()).toRect(); |
| |
| QRegion expectedRegion = parentDeviceBoundingRect.adjusted(-2, -2, 2, 2); |
| expectedRegion += childDeviceBoundingRect.adjusted(-2, -2, 2, 2); |
| |
| #ifdef Q_OS_WINRT |
| QEXPECT_FAIL("", "Fails on WinRT. Figure out why - QTBUG-68297", Abort); |
| #endif |
| COMPARE_REGIONS(view.paintedRegion, expectedRegion); |
| } |
| |
| class StacksBehindParentHelper : public QGraphicsRectItem |
| { |
| public: |
| StacksBehindParentHelper(QList<QGraphicsItem *> *paintedItems, const QRectF &rect, QGraphicsItem *parent = 0) |
| : QGraphicsRectItem(rect, parent), paintedItems(paintedItems) |
| { } |
| |
| void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) |
| { |
| QGraphicsRectItem::paint(painter, option, widget); |
| paintedItems->append(this); |
| } |
| |
| private: |
| QList<QGraphicsItem *> *paintedItems; |
| }; |
| |
| void tst_QGraphicsItem::itemStacksBehindParent() |
| { |
| StacksBehindParentHelper *parent1 = new StacksBehindParentHelper(&paintedItems, QRectF(0, 0, 100, 50)); |
| StacksBehindParentHelper *child11 = new StacksBehindParentHelper(&paintedItems, QRectF(-10, 10, 50, 50), parent1); |
| StacksBehindParentHelper *grandChild111 = new StacksBehindParentHelper(&paintedItems, QRectF(-20, 20, 50, 50), child11); |
| StacksBehindParentHelper *child12 = new StacksBehindParentHelper(&paintedItems, QRectF(60, 10, 50, 50), parent1); |
| StacksBehindParentHelper *grandChild121 = new StacksBehindParentHelper(&paintedItems, QRectF(70, 20, 50, 50), child12); |
| |
| StacksBehindParentHelper *parent2 = new StacksBehindParentHelper(&paintedItems, QRectF(0, 0, 100, 50)); |
| StacksBehindParentHelper *child21 = new StacksBehindParentHelper(&paintedItems, QRectF(-10, 10, 50, 50), parent2); |
| StacksBehindParentHelper *grandChild211 = new StacksBehindParentHelper(&paintedItems, QRectF(-20, 20, 50, 50), child21); |
| StacksBehindParentHelper *child22 = new StacksBehindParentHelper(&paintedItems, QRectF(60, 10, 50, 50), parent2); |
| StacksBehindParentHelper *grandChild221 = new StacksBehindParentHelper(&paintedItems, QRectF(70, 20, 50, 50), child22); |
| |
| parent1->setData(0, "parent1"); |
| child11->setData(0, "child11"); |
| grandChild111->setData(0, "grandChild111"); |
| child12->setData(0, "child12"); |
| grandChild121->setData(0, "grandChild121"); |
| parent2->setData(0, "parent2"); |
| child21->setData(0, "child21"); |
| grandChild211->setData(0, "grandChild211"); |
| child22->setData(0, "child22"); |
| grandChild221->setData(0, "grandChild221"); |
| |
| // Disambiguate siblings |
| parent1->setZValue(1); |
| child11->setZValue(1); |
| child21->setZValue(1); |
| |
| QGraphicsScene scene; |
| scene.addItem(parent1); |
| scene.addItem(parent2); |
| |
| QGraphicsView view(&scene); |
| view.show(); |
| QVERIFY(QTest::qWaitForWindowExposed(&view)); |
| QTRY_VERIFY(!paintedItems.isEmpty()); |
| paintedItems.clear(); |
| view.viewport()->update(); |
| QApplication::processEvents(); |
| QRectF rect(0, 0, 100, 100); |
| QTRY_COMPARE(scene.items(rect), (QList<QGraphicsItem *>() |
| << grandChild111 << child11 |
| << grandChild121 << child12 << parent1 |
| << grandChild211 << child21 |
| << grandChild221 << child22 << parent2)); |
| QTRY_COMPARE(paintedItems, QList<QGraphicsItem *>() |
| << parent2 << child22 << grandChild221 |
| << child21 << grandChild211 |
| << parent1 << child12 << grandChild121 |
| << child11 << grandChild111); |
| |
| child11->setFlag(QGraphicsItem::ItemStacksBehindParent); |
| scene.update(); |
| paintedItems.clear(); |
| |
| QTRY_COMPARE(scene.items(rect), (QList<QGraphicsItem *>() |
| << grandChild121 << child12 << parent1 |
| << grandChild111 << child11 |
| << grandChild211 << child21 |
| << grandChild221 << child22 << parent2)); |
| QTRY_COMPARE(paintedItems, QList<QGraphicsItem *>() |
| << parent2 << child22 << grandChild221 |
| << child21 << grandChild211 |
| << child11 << grandChild111 |
| << parent1 << child12 << grandChild121); |
| |
| child12->setFlag(QGraphicsItem::ItemStacksBehindParent); |
| paintedItems.clear(); |
| scene.update(); |
| |
| QTRY_COMPARE(scene.items(rect), (QList<QGraphicsItem *>() |
| << parent1 << grandChild111 << child11 |
| << grandChild121 << child12 |
| << grandChild211 << child21 |
| << grandChild221 << child22 << parent2)); |
| QTRY_COMPARE(paintedItems, QList<QGraphicsItem *>() |
| << parent2 << child22 << grandChild221 |
| << child21 << grandChild211 |
| << child12 << grandChild121 |
| << child11 << grandChild111 << parent1); |
| } |
| |
| class ClippingAndTransformsScene : public QGraphicsScene |
| { |
| public: |
| QList<QGraphicsItem *> drawnItems; |
| protected: |
| void drawItems(QPainter *painter, int numItems, QGraphicsItem *items[], |
| const QStyleOptionGraphicsItem options[], QWidget *widget = 0) |
| { |
| drawnItems.clear(); |
| for (int i = 0; i < numItems; ++i) |
| drawnItems << items[i]; |
| QGraphicsScene::drawItems(painter, numItems, items, options, widget); |
| } |
| }; |
| |
| void tst_QGraphicsItem::nestedClipping() |
| { |
| ClippingAndTransformsScene scene; |
| scene.setSceneRect(-50, -50, 200, 200); |
| |
| QGraphicsRectItem *root = new QGraphicsRectItem(QRectF(0, 0, 100, 100)); |
| root->setBrush(QColor(0, 0, 255)); |
| root->setFlag(QGraphicsItem::ItemClipsChildrenToShape); |
| QGraphicsRectItem *l1 = new QGraphicsRectItem(QRectF(0, 0, 100, 100)); |
| l1->setParentItem(root); |
| l1->setPos(-50, 0); |
| l1->setBrush(QColor(255, 0, 0)); |
| l1->setFlag(QGraphicsItem::ItemClipsChildrenToShape); |
| QGraphicsEllipseItem *l2 = new QGraphicsEllipseItem(QRectF(0, 0, 100, 100)); |
| l2->setParentItem(l1); |
| l2->setPos(50, 50); |
| l2->setFlag(QGraphicsItem::ItemClipsChildrenToShape); |
| l2->setBrush(QColor(255, 255, 0)); |
| QGraphicsRectItem *l3 = new QGraphicsRectItem(QRectF(0, 0, 25, 25)); |
| l3->setParentItem(l2); |
| l3->setBrush(QColor(0, 255, 0)); |
| l3->setPos(50 - 12, -12); |
| |
| scene.addItem(root); |
| |
| root->setData(0, "root"); |
| l1->setData(0, "l1"); |
| l2->setData(0, "l2"); |
| l3->setData(0, "l3"); |
| |
| QGraphicsView view(&scene); |
| view.setOptimizationFlag(QGraphicsView::IndirectPainting); |
| view.show(); |
| QVERIFY(QTest::qWaitForWindowExposed(&view)); |
| |
| QList<QGraphicsItem *> expected; |
| expected << root << l1 << l2 << l3; |
| QTRY_COMPARE(scene.drawnItems, expected); |
| |
| QImage image(200, 200, QImage::Format_ARGB32_Premultiplied); |
| image.fill(0); |
| |
| QPainter painter(&image); |
| scene.render(&painter); |
| painter.end(); |
| |
| // Check transparent areas |
| QCOMPARE(image.pixel(100, 25), qRgba(0, 0, 0, 0)); |
| QCOMPARE(image.pixel(100, 175), qRgba(0, 0, 0, 0)); |
| QCOMPARE(image.pixel(25, 100), qRgba(0, 0, 0, 0)); |
| QCOMPARE(image.pixel(175, 100), qRgba(0, 0, 0, 0)); |
| QCOMPARE(image.pixel(70, 80), qRgba(255, 0, 0, 255)); |
| QCOMPARE(image.pixel(80, 130), qRgba(255, 255, 0, 255)); |
| QCOMPARE(image.pixel(92, 105), qRgba(0, 255, 0, 255)); |
| QCOMPARE(image.pixel(105, 105), qRgba(0, 0, 255, 255)); |
| #if 0 |
| // Enable this to compare if the test starts failing. |
| image.save("nestedClipping_reference.png"); |
| #endif |
| } |
| |
| class TransformDebugItem : public QGraphicsRectItem |
| { |
| public: |
| TransformDebugItem() |
| : QGraphicsRectItem(QRectF(-10, -10, 20, 20)) |
| { |
| setPen(QPen(Qt::black, 0)); |
| setBrush(QColor(QRandomGenerator::global()->bounded(256), QRandomGenerator::global()->bounded(256), QRandomGenerator::global()->bounded(256))); |
| } |
| |
| QTransform x; |
| |
| void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, |
| QWidget *widget = 0) |
| { |
| x = painter->worldTransform(); |
| QGraphicsRectItem::paint(painter, option, widget); |
| } |
| }; |
| |
| void tst_QGraphicsItem::nestedClippingTransforms() |
| { |
| TransformDebugItem *rootClipper = new TransformDebugItem; |
| rootClipper->setFlag(QGraphicsItem::ItemClipsChildrenToShape); |
| TransformDebugItem *child = new TransformDebugItem; |
| child->setParentItem(rootClipper); |
| child->setPos(2, 2); |
| TransformDebugItem *grandChildClipper = new TransformDebugItem; |
| grandChildClipper->setParentItem(child); |
| grandChildClipper->setFlag(QGraphicsItem::ItemClipsChildrenToShape); |
| grandChildClipper->setPos(4, 4); |
| TransformDebugItem *greatGrandChild = new TransformDebugItem; |
| greatGrandChild->setPos(2, 2); |
| greatGrandChild->setParentItem(grandChildClipper); |
| TransformDebugItem *grandChildClipper2 = new TransformDebugItem; |
| grandChildClipper2->setParentItem(child); |
| grandChildClipper2->setFlag(QGraphicsItem::ItemClipsChildrenToShape); |
| grandChildClipper2->setPos(8, 8); |
| TransformDebugItem *greatGrandChild2 = new TransformDebugItem; |
| greatGrandChild2->setPos(2, 2); |
| greatGrandChild2->setParentItem(grandChildClipper2); |
| TransformDebugItem *grandChildClipper3 = new TransformDebugItem; |
| grandChildClipper3->setParentItem(child); |
| grandChildClipper3->setFlag(QGraphicsItem::ItemClipsChildrenToShape); |
| grandChildClipper3->setPos(12, 12); |
| TransformDebugItem *greatGrandChild3 = new TransformDebugItem; |
| greatGrandChild3->setPos(2, 2); |
| greatGrandChild3->setParentItem(grandChildClipper3); |
| |
| QGraphicsScene scene; |
| scene.addItem(rootClipper); |
| |
| QImage image(scene.itemsBoundingRect().size().toSize(), QImage::Format_ARGB32_Premultiplied); |
| image.fill(0); |
| QPainter p(&image); |
| scene.render(&p); |
| p.end(); |
| |
| QCOMPARE(rootClipper->x, QTransform(1, 0, 0, 0, 1, 0, 10, 10, 1)); |
| QCOMPARE(child->x, QTransform(1, 0, 0, 0, 1, 0, 12, 12, 1)); |
| QCOMPARE(grandChildClipper->x, QTransform(1, 0, 0, 0, 1, 0, 16, 16, 1)); |
| QCOMPARE(greatGrandChild->x, QTransform(1, 0, 0, 0, 1, 0, 18, 18, 1)); |
| QCOMPARE(grandChildClipper2->x, QTransform(1, 0, 0, 0, 1, 0, 20, 20, 1)); |
| QCOMPARE(greatGrandChild2->x, QTransform(1, 0, 0, 0, 1, 0, 22, 22, 1)); |
| QCOMPARE(grandChildClipper3->x, QTransform(1, 0, 0, 0, 1, 0, 24, 24, 1)); |
| QCOMPARE(greatGrandChild3->x, QTransform(1, 0, 0, 0, 1, 0, 26, 26, 1)); |
| } |
| |
| void tst_QGraphicsItem::sceneTransformCache() |
| { |
| // Test that an item's scene transform is updated correctly when the |
| // parent is transformed. |
| QGraphicsScene scene; |
| |
| const QScopedPointer<QGraphicsRectItem> rect(scene.addRect(0, 0, 100, 100)); |
| rect->setPen(QPen(Qt::black, 0)); |
| QGraphicsRectItem *rect2 = scene.addRect(0, 0, 100, 100); |
| rect2->setPen(QPen(Qt::black, 0)); |
| rect2->setParentItem(rect.data()); |
| rect2->setTransform(QTransform().rotate(90), true); |
| rect->setTransform(QTransform::fromTranslate(0, 50), true); |
| QGraphicsView view(&scene); |
| view.show(); |
| QVERIFY(QTest::qWaitForWindowExposed(&view)); |
| rect->setTransform(QTransform::fromTranslate(0, 100), true); |
| QTransform x; |
| x.translate(0, 150); |
| x.rotate(90); |
| QCOMPARE(rect2->sceneTransform(), x); |
| |
| scene.removeItem(rect.data()); |
| |
| //Crazy use case : rect4 child of rect3 so the transformation of rect4 will be cached.Good! |
| //We remove rect4 from the scene, then the validTransform bit flag is set to 0 and the index of the cache |
| //add to the freeTransformSlots. The problem was that sceneTransformIndex was not set to -1 so if a new item arrive |
| //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 |
| //added back to the scene then it will set the transform to his old sceneTransformIndex value that will erase the new |
| //value of rect6 so rect6 transform will be wrong. |
| QGraphicsRectItem *rect3 = scene.addRect(0, 0, 100, 100); |
| QGraphicsRectItem *rect4 = scene.addRect(0, 0, 100, 100); |
| rect3->setPos(QPointF(10,10)); |
| rect3->setPen(QPen(Qt::black, 0)); |
| |
| rect4->setParentItem(rect3); |
| rect4->setPos(QPointF(10,10)); |
| rect4->setPen(QPen(Qt::black, 0)); |
| |
| QCOMPARE(rect4->mapToScene(rect4->boundingRect().topLeft()), QPointF(20,20)); |
| |
| scene.removeItem(rect4); |
| //rect4 transform is local only |
| QCOMPARE(rect4->mapToScene(rect4->boundingRect().topLeft()), QPointF(10,10)); |
| |
| QGraphicsRectItem *rect5 = scene.addRect(0, 0, 100, 100); |
| QGraphicsRectItem *rect6 = scene.addRect(0, 0, 100, 100); |
| rect5->setPos(QPointF(20,20)); |
| rect5->setPen(QPen(Qt::black, 0)); |
| |
| rect6->setParentItem(rect5); |
| rect6->setPos(QPointF(10,10)); |
| rect6->setPen(QPen(Qt::black, 0)); |
| //test if rect6 transform is ok |
| QCOMPARE(rect6->mapToScene(rect6->boundingRect().topLeft()), QPointF(30,30)); |
| |
| scene.addItem(rect4); |
| |
| QCOMPARE(rect4->mapToScene(rect4->boundingRect().topLeft()), QPointF(10,10)); |
| //test if rect6 transform is still correct |
| QCOMPARE(rect6->mapToScene(rect6->boundingRect().topLeft()), QPointF(30,30)); |
| } |
| |
| void tst_QGraphicsItem::tabChangesFocus_data() |
| { |
| QTest::addColumn<bool>("tabChangesFocus"); |
| QTest::newRow("tab changes focus") << true; |
| QTest::newRow("tab doesn't change focus") << false; |
| } |
| |
| void tst_QGraphicsItem::tabChangesFocus() |
| { |
| QFETCH(bool, tabChangesFocus); |
| |
| QGraphicsScene scene; |
| QGraphicsTextItem *item = scene.addText("Hello"); |
| item->setTabChangesFocus(tabChangesFocus); |
| item->setTextInteractionFlags(Qt::TextEditorInteraction); |
| item->setFocus(); |
| |
| QDial *dial1 = new QDial; |
| QGraphicsView *view = new QGraphicsView(&scene); |
| |
| QDial *dial2 = new QDial; |
| QVBoxLayout *layout = new QVBoxLayout; |
| layout->addWidget(dial1); |
| layout->addWidget(view); |
| layout->addWidget(dial2); |
| |
| QWidget widget; |
| widget.setLayout(layout); |
| widget.show(); |
| QVERIFY(QTest::qWaitForWindowActive(&widget)); |
| |
| QTRY_VERIFY(scene.isActive()); |
| |
| dial1->setFocus(); |
| QTRY_VERIFY(dial1->hasFocus()); |
| |
| QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab); |
| QTRY_VERIFY(view->hasFocus()); |
| QTRY_VERIFY(item->hasFocus()); |
| |
| QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab); |
| |
| if (tabChangesFocus) { |
| QTRY_VERIFY(!view->hasFocus()); |
| QTRY_VERIFY(!item->hasFocus()); |
| QTRY_VERIFY(dial2->hasFocus()); |
| } else { |
| QTRY_VERIFY(view->hasFocus()); |
| QTRY_VERIFY(item->hasFocus()); |
| QCOMPARE(item->toPlainText(), QString("\tHello")); |
| } |
| } |
| |
| void tst_QGraphicsItem::cacheMode() |
| { |
| QGraphicsScene scene(0, 0, 100, 100); |
| QGraphicsView view(&scene); |
| view.resize(150, 150); |
| view.show(); |
| QApplication::setActiveWindow(&view); |
| QVERIFY(QTest::qWaitForWindowExposed(&view)); |
| QVERIFY(QTest::qWaitForWindowActive(&view)); |
| QCoreApplication::processEvents(); // Process all queued paint events |
| |
| EventTester *tester = new EventTester; |
| EventTester *testerChild = new EventTester; |
| testerChild->setParentItem(tester); |
| EventTester *testerChild2 = new EventTester; |
| testerChild2->setParentItem(testerChild); |
| testerChild2->setFlag(QGraphicsItem::ItemIgnoresTransformations); |
| |
| scene.addItem(tester); |
| |
| for (int i = 0; i < 2; ++i) { |
| // No visual change. |
| QTRY_COMPARE(tester->repaints, 1); |
| QCOMPARE(testerChild->repaints, 1); |
| QCOMPARE(testerChild2->repaints, 1); |
| tester->setCacheMode(QGraphicsItem::NoCache); |
| testerChild->setCacheMode(QGraphicsItem::NoCache); |
| testerChild2->setCacheMode(QGraphicsItem::NoCache); |
| QTest::qWait(25); |
| QTRY_COMPARE(tester->repaints, 1); |
| QCOMPARE(testerChild->repaints, 1); |
| QCOMPARE(testerChild2->repaints, 1); |
| tester->setCacheMode(QGraphicsItem::DeviceCoordinateCache); |
| testerChild->setCacheMode(QGraphicsItem::DeviceCoordinateCache); |
| testerChild2->setCacheMode(QGraphicsItem::DeviceCoordinateCache); |
| QTest::qWait(25); |
| } |
| |
| // The first move causes a repaint as the item is painted into its pixmap. |
| // (Only occurs if the item has previously been painted without cache). |
| tester->setPos(10, 10); |
| testerChild->setPos(10, 10); |
| testerChild2->setPos(10, 10); |
| QTRY_COMPARE(tester->repaints, 2); |
| QCOMPARE(testerChild->repaints, 2); |
| QCOMPARE(testerChild2->repaints, 2); |
| |
| // Consecutive moves should not repaint. |
| tester->setPos(20, 20); |
| testerChild->setPos(20, 20); |
| testerChild2->setPos(20, 20); |
| QTest::qWait(250); |
| QCOMPARE(tester->repaints, 2); |
| QCOMPARE(testerChild->repaints, 2); |
| QCOMPARE(testerChild2->repaints, 2); |
| |
| // Translating does not result in a repaint. |
| tester->setTransform(QTransform::fromTranslate(10, 10), true); |
| QTest::qWait(25); |
| QCOMPARE(tester->repaints, 2); |
| QCOMPARE(testerChild->repaints, 2); |
| QCOMPARE(testerChild2->repaints, 2); |
| |
| // Rotating results in a repaint. |
| tester->setTransform(QTransform().rotate(45), true); |
| QTRY_COMPARE(tester->repaints, 3); |
| QCOMPARE(testerChild->repaints, 3); |
| QCOMPARE(testerChild2->repaints, 2); |
| |
| // Change to ItemCoordinateCache (triggers repaint). |
| tester->setCacheMode(QGraphicsItem::ItemCoordinateCache); // autosize |
| testerChild->setCacheMode(QGraphicsItem::ItemCoordinateCache); // autosize |
| testerChild2->setCacheMode(QGraphicsItem::ItemCoordinateCache); // autosize |
| QTRY_COMPARE(tester->repaints, 4); |
| QCOMPARE(testerChild->repaints, 4); |
| QCOMPARE(testerChild2->repaints, 3); |
| |
| // Rotating items with ItemCoordinateCache doesn't cause a repaint. |
| tester->setTransform(QTransform().rotate(22), true); |
| testerChild->setTransform(QTransform().rotate(22), true); |
| testerChild2->setTransform(QTransform().rotate(22), true); |
| QTest::qWait(25); |
| QCOMPARE(tester->repaints, 4); |
| QCOMPARE(testerChild->repaints, 4); |
| QCOMPARE(testerChild2->repaints, 3); |
| tester->resetTransform(); |
| testerChild->resetTransform(); |
| testerChild2->resetTransform(); |
| |
| // Explicit update causes a repaint. |
| tester->update(0, 0, 5, 5); |
| QTRY_COMPARE(tester->repaints, 5); |
| QCOMPARE(testerChild->repaints, 4); |
| QCOMPARE(testerChild2->repaints, 3); |
| |
| // Updating outside the item's bounds does not cause a repaint. |
| tester->update(10, 10, 5, 5); |
| QTest::qWait(25); |
| QCOMPARE(tester->repaints, 5); |
| QCOMPARE(testerChild->repaints, 4); |
| QCOMPARE(testerChild2->repaints, 3); |
| |
| // Resizing an item should cause a repaint of that item. (because of |
| // autosize). |
| tester->setGeometry(QRectF(-15, -15, 30, 30)); |
| QTRY_COMPARE(tester->repaints, 6); |
| QCOMPARE(testerChild->repaints, 4); |
| QCOMPARE(testerChild2->repaints, 3); |
| |
| // Set fixed size. |
| tester->setCacheMode(QGraphicsItem::ItemCoordinateCache, QSize(30, 30)); |
| testerChild->setCacheMode(QGraphicsItem::ItemCoordinateCache, QSize(30, 30)); |
| testerChild2->setCacheMode(QGraphicsItem::ItemCoordinateCache, QSize(30, 30)); |
| QTRY_COMPARE(tester->repaints, 7); |
| QCOMPARE(testerChild->repaints, 5); |
| QCOMPARE(testerChild2->repaints, 4); |
| |
| // Resizing the item should cause a repaint. |
| testerChild->setGeometry(QRectF(-15, -15, 30, 30)); |
| QTRY_COMPARE(testerChild->repaints, 6); |
| QCOMPARE(tester->repaints, 7); |
| QCOMPARE(testerChild2->repaints, 4); |
| |
| // Scaling the view does not cause a repaint. |
| view.scale(0.7, 0.7); |
| QTest::qWait(25); |
| QCOMPARE(tester->repaints, 7); |
| QCOMPARE(testerChild->repaints, 6); |
| QCOMPARE(testerChild2->repaints, 4); |
| |
| // Switch to device coordinate cache. |
| tester->setCacheMode(QGraphicsItem::DeviceCoordinateCache); |
| testerChild->setCacheMode(QGraphicsItem::DeviceCoordinateCache); |
| testerChild2->setCacheMode(QGraphicsItem::DeviceCoordinateCache); |
| QTRY_COMPARE(tester->repaints, 8); |
| QCOMPARE(testerChild->repaints, 7); |
| QCOMPARE(testerChild2->repaints, 5); |
| |
| // Scaling the view back should cause repaints for two of the items. |
| view.setTransform(QTransform()); |
| QTRY_COMPARE(tester->repaints, 9); |
| QCOMPARE(testerChild->repaints, 8); |
| QCOMPARE(testerChild2->repaints, 5); |
| |
| // Rotating the base item (perspective) should repaint two items. |
| tester->setTransform(QTransform().rotate(10, Qt::XAxis)); |
| QTRY_COMPARE(tester->repaints, 10); |
| QCOMPARE(testerChild->repaints, 9); |
| QCOMPARE(testerChild2->repaints, 5); |
| |
| // Moving the middle item should cause a repaint even if it's a move, |
| // because the parent is rotated with a perspective. |
| testerChild->setPos(1, 1); |
| QTRY_COMPARE(tester->repaints, 11); |
| QTRY_COMPARE(testerChild->repaints, 10); |
| QCOMPARE(testerChild2->repaints, 5); |
| tester->resetTransform(); |
| |
| // Make a huge item |
| tester->setGeometry(QRectF(-4000, -4000, 8000, 8000)); |
| QTRY_COMPARE(tester->repaints, 12); |
| QTRY_COMPARE(testerChild->repaints, 11); |
| QCOMPARE(testerChild2->repaints, 5); |
| |
| // Move the large item - will cause a repaint as the |
| // cache is clipped. |
| tester->setPos(5, 0); |
| QTRY_COMPARE(tester->repaints, 13); |
| QTRY_COMPARE(testerChild->repaints, 11); |
| QCOMPARE(testerChild2->repaints, 5); |
| |
| // Hiding and showing should invalidate the cache |
| tester->hide(); |
| QTest::qWait(25); |
| tester->show(); |
| QTRY_COMPARE(tester->repaints, 14); |
| QTRY_COMPARE(testerChild->repaints, 12); |
| QTRY_COMPARE(testerChild2->repaints, 6); |
| } |
| |
| void tst_QGraphicsItem::cacheMode2() |
| { |
| QGraphicsScene scene(0, 0, 100, 100); |
| QGraphicsView view(&scene); |
| view.resize(150, 150); |
| view.show(); |
| QApplication::setActiveWindow(&view); |
| QVERIFY(QTest::qWaitForWindowExposed(&view)); |
| QVERIFY(QTest::qWaitForWindowActive(&view)); |
| QCoreApplication::processEvents(); // Process all queued paint events |
| |
| EventTester *tester = new EventTester; |
| scene.addItem(tester); |
| QTRY_COMPARE(tester->repaints, 1); |
| |
| // Switching from NoCache to NoCache (no repaint) |
| tester->setCacheMode(QGraphicsItem::NoCache); |
| QTest::qWait(50); |
| QCOMPARE(tester->repaints, 1); |
| |
| // Switching from NoCache to DeviceCoordinateCache (no repaint) |
| tester->setCacheMode(QGraphicsItem::DeviceCoordinateCache); |
| QTest::qWait(50); |
| QCOMPARE(tester->repaints, 1); |
| |
| // Switching from DeviceCoordinateCache to DeviceCoordinateCache (no repaint) |
| tester->setCacheMode(QGraphicsItem::DeviceCoordinateCache); |
| QTest::qWait(50); |
| QCOMPARE(tester->repaints, 1); |
| |
| // Switching from DeviceCoordinateCache to NoCache (no repaint) |
| tester->setCacheMode(QGraphicsItem::NoCache); |
| QTest::qWait(50); |
| QCOMPARE(tester->repaints, 1); |
| |
| // Switching from NoCache to ItemCoordinateCache (repaint) |
| tester->setCacheMode(QGraphicsItem::ItemCoordinateCache); |
| QTRY_COMPARE(tester->repaints, 2); |
| |
| // Switching from ItemCoordinateCache to ItemCoordinateCache (no repaint) |
| tester->setCacheMode(QGraphicsItem::ItemCoordinateCache); |
| QTest::qWait(50); |
| QCOMPARE(tester->repaints, 2); |
| |
| // Switching from ItemCoordinateCache to ItemCoordinateCache with different size (repaint) |
| tester->setCacheMode(QGraphicsItem::ItemCoordinateCache, QSize(100, 100)); |
| QTRY_COMPARE(tester->repaints, 3); |
| |
| // Switching from ItemCoordinateCache to NoCache (repaint) |
| tester->setCacheMode(QGraphicsItem::NoCache); |
| QTRY_COMPARE(tester->repaints, 4); |
| |
| // Switching from DeviceCoordinateCache to ItemCoordinateCache (repaint) |
| tester->setCacheMode(QGraphicsItem::DeviceCoordinateCache); |
| QTest::qWait(50); |
| QCOMPARE(tester->repaints, 4); |
| tester->setCacheMode(QGraphicsItem::ItemCoordinateCache); |
| QTRY_COMPARE(tester->repaints, 5); |
| |
| // Switching from ItemCoordinateCache to DeviceCoordinateCache (repaint) |
| tester->setCacheMode(QGraphicsItem::DeviceCoordinateCache); |
| QTRY_COMPARE(tester->repaints, 6); |
| } |
| |
| void tst_QGraphicsItem::updateCachedItemAfterMove() |
| { |
| // A simple item that uses ItemCoordinateCache |
| EventTester *tester = new EventTester; |
| tester->setCacheMode(QGraphicsItem::ItemCoordinateCache); |
| |
| // Add to a scene, show in a view, ensure it's painted and reset its |
| // repaint counter. |
| QGraphicsScene scene; |
| scene.addItem(tester); |
| QGraphicsView view(&scene); |
| view.show(); |
| QVERIFY(QTest::qWaitForWindowExposed(&view)); |
| |
| QTRY_VERIFY(tester->repaints > 0); |
| tester->repaints = 0; |
| |
| // Move the item, should not cause repaints |
| tester->setPos(10, 0); |
| QTest::qWait(12); |
| QCOMPARE(tester->repaints, 0); |
| |
| // Move then update, should cause one repaint |
| tester->setPos(20, 0); |
| tester->update(); |
| QTRY_COMPARE(tester->repaints, 1); |
| |
| // Hiding the item doesn't cause a repaint |
| tester->hide(); |
| QTest::qWait(12); |
| QCOMPARE(tester->repaints, 1); |
| |
| // Moving a hidden item doesn't cause a repaint |
| tester->setPos(30, 0); |
| tester->update(); |
| QTest::qWait(12); |
| QCOMPARE(tester->repaints, 1); |
| } |
| |
| class Track : public QGraphicsRectItem |
| { |
| public: |
| Track(const QRectF &rect) |
| : QGraphicsRectItem(rect) |
| { |
| setAcceptHoverEvents(true); |
| } |
| |
| void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0) |
| { |
| QGraphicsRectItem::paint(painter, option, widget); |
| const QString text = QString::number(p.x()) + QLatin1Char('x') + QString::number(p.y()) |
| + QLatin1Char('\n') + QString::number(sp.x()) + QLatin1Char('x') + QString::number(sp.y()); |
| painter->drawText(boundingRect(), Qt::AlignCenter, text); |
| } |
| |
| protected: |
| void hoverMoveEvent(QGraphicsSceneHoverEvent *event) |
| { |
| p = event->pos(); |
| sp = event->widget()->mapFromGlobal(event->screenPos()); |
| update(); |
| } |
| private: |
| QPointF p; |
| QPoint sp; |
| }; |
| |
| void tst_QGraphicsItem::deviceTransform_data() |
| { |
| QTest::addColumn<bool>("untransformable1"); |
| QTest::addColumn<bool>("untransformable2"); |
| QTest::addColumn<bool>("untransformable3"); |
| QTest::addColumn<qreal>("rotation1"); |
| QTest::addColumn<qreal>("rotation2"); |
| QTest::addColumn<qreal>("rotation3"); |
| QTest::addColumn<QTransform>("deviceX"); |
| QTest::addColumn<QPointF>("mapResult1"); |
| QTest::addColumn<QPointF>("mapResult2"); |
| QTest::addColumn<QPointF>("mapResult3"); |
| |
| QTest::newRow("nil") << false << false << false |
| << qreal(0.0) << qreal(0.0) << qreal(0.0) |
| << QTransform() |
| << QPointF(150, 150) << QPointF(250, 250) << QPointF(350, 350); |
| QTest::newRow("deviceX rot 90") << false << false << false |
| << qreal(0.0) << qreal(0.0) << qreal(0.0) |
| << QTransform().rotate(90) |
| << QPointF(-150, 150) << QPointF(-250, 250) << QPointF(-350, 350); |
| QTest::newRow("deviceX rot 90 100") << true << false << false |
| << qreal(0.0) << qreal(0.0) << qreal(0.0) |
| << QTransform().rotate(90) |
| << QPointF(-50, 150) << QPointF(50, 250) << QPointF(150, 350); |
| QTest::newRow("deviceX rot 90 010") << false << true << false |
| << qreal(0.0) << qreal(0.0) << qreal(0.0) |
| << QTransform().rotate(90) |
| << QPointF(-150, 150) << QPointF(-150, 250) << QPointF(-50, 350); |
| QTest::newRow("deviceX rot 90 001") << false << false << true |
| << qreal(0.0) << qreal(0.0) << qreal(0.0) |
| << QTransform().rotate(90) |
| << QPointF(-150, 150) << QPointF(-250, 250) << QPointF(-250, 350); |
| QTest::newRow("deviceX rot 90 111") << true << true << true |
| << qreal(0.0) << qreal(0.0) << qreal(0.0) |
| << QTransform().rotate(90) |
| << QPointF(-50, 150) << QPointF(50, 250) << QPointF(150, 350); |
| QTest::newRow("deviceX rot 90 101") << true << false << true |
| << qreal(0.0) << qreal(0.0) << qreal(0.0) |
| << QTransform().rotate(90) |
| << QPointF(-50, 150) << QPointF(50, 250) << QPointF(150, 350); |
| } |
| |
| void tst_QGraphicsItem::deviceTransform() |
| { |
| QFETCH(bool, untransformable1); |
| QFETCH(bool, untransformable2); |
| QFETCH(bool, untransformable3); |
| QFETCH(qreal, rotation1); |
| QFETCH(qreal, rotation2); |
| QFETCH(qreal, rotation3); |
| QFETCH(QTransform, deviceX); |
| QFETCH(QPointF, mapResult1); |
| QFETCH(QPointF, mapResult2); |
| QFETCH(QPointF, mapResult3); |
| |
| QGraphicsScene scene; |
| Track *rect1 = new Track(QRectF(0, 0, 100, 100)); |
| Track *rect2 = new Track(QRectF(0, 0, 100, 100)); |
| Track *rect3 = new Track(QRectF(0, 0, 100, 100)); |
| rect2->setParentItem(rect1); |
| rect3->setParentItem(rect2); |
| rect1->setPos(100, 100); |
| rect2->setPos(100, 100); |
| rect3->setPos(100, 100); |
| rect1->setTransform(QTransform().rotate(rotation1), true); |
| rect2->setTransform(QTransform().rotate(rotation2), true); |
| rect3->setTransform(QTransform().rotate(rotation3), true); |
| rect1->setFlag(QGraphicsItem::ItemIgnoresTransformations, untransformable1); |
| rect2->setFlag(QGraphicsItem::ItemIgnoresTransformations, untransformable2); |
| rect3->setFlag(QGraphicsItem::ItemIgnoresTransformations, untransformable3); |
| rect1->setBrush(Qt::red); |
| rect2->setBrush(Qt::green); |
| rect3->setBrush(Qt::blue); |
| scene.addItem(rect1); |
| |
| QCOMPARE(rect1->deviceTransform(deviceX).map(QPointF(50, 50)), mapResult1); |
| QCOMPARE(rect2->deviceTransform(deviceX).map(QPointF(50, 50)), mapResult2); |
| QCOMPARE(rect3->deviceTransform(deviceX).map(QPointF(50, 50)), mapResult3); |
| } |
| |
| void tst_QGraphicsItem::update() |
| { |
| QGraphicsScene scene; |
| scene.setSceneRect(-100, -100, 200, 200); |
| QWidget topLevel; |
| MyGraphicsView view(&scene,&topLevel); |
| |
| topLevel.resize(300, 300); |
| topLevel.show(); |
| QVERIFY(QTest::qWaitForWindowExposed(&topLevel)); |
| |
| EventTester *item = new EventTester; |
| scene.addItem(item); |
| QTRY_VERIFY(item->repaints > 0); // Wait for painting |
| item->repaints = 0; |
| |
| item->update(); // Item marked as dirty |
| scene.update(); // Entire scene marked as dirty |
| QTRY_COMPARE(item->repaints, 1); |
| |
| // Make sure the dirty state from the previous update is reset so that |
| // the item don't think it is already dirty and discards this update. |
| item->update(); |
| QTRY_COMPARE(item->repaints, 2); |
| |
| // Make sure a partial update doesn't cause a full update to be discarded. |
| view.reset(); |
| item->repaints = 0; |
| item->update(QRectF(0, 0, 5, 5)); |
| item->update(); |
| QTRY_COMPARE(item->repaints, 1); |
| QTRY_COMPARE(view.repaints, 1); |
| QRect itemDeviceBoundingRect = item->deviceTransform(view.viewportTransform()) |
| .mapRect(item->boundingRect()).toAlignedRect(); |
| QRegion expectedRegion = itemDeviceBoundingRect.adjusted(-2, -2, 2, 2); |
| // The entire item's bounding rect (adjusted for antialiasing) should have been painted. |
| QCOMPARE(view.paintedRegion, expectedRegion); |
| |
| // Make sure update requests outside the bounding rect are discarded. |
| view.reset(); |
| item->repaints = 0; |
| item->update(-15, -15, 5, 5); // Item's brect: (-10, -10, 20, 20) |
| qApp->processEvents(); |
| QCOMPARE(item->repaints, 0); |
| QCOMPARE(view.repaints, 0); |
| |
| // Make sure the area occupied by an item is repainted when hiding it. |
| view.reset(); |
| item->repaints = 0; |
| item->update(); // Full update; all sub-sequent update requests are discarded. |
| item->hide(); // visible set to 0. ignoreVisible must be set to 1; the item won't be processed otherwise. |
| qApp->processEvents(); |
| QCOMPARE(item->repaints, 0); |
| QCOMPARE(view.repaints, 1); |
| // The entire item's bounding rect (adjusted for antialiasing) should have been painted. |
| QCOMPARE(view.paintedRegion, expectedRegion); |
| |
| // Make sure item is repainted when shown (after being hidden). |
| view.reset(); |
| item->repaints = 0; |
| item->show(); |
| qApp->processEvents(); |
| QCOMPARE(item->repaints, 1); |
| QCOMPARE(view.repaints, 1); |
| // The entire item's bounding rect (adjusted for antialiasing) should have been painted. |
| QCOMPARE(view.paintedRegion, expectedRegion); |
| |
| item->repaints = 0; |
| item->hide(); |
| qApp->processEvents(); |
| view.reset(); |
| const QPointF originalPos = item->pos(); |
| item->setPos(5000, 5000); |
| qApp->processEvents(); |
| QCOMPARE(item->repaints, 0); |
| QCOMPARE(view.repaints, 0); |
| qApp->processEvents(); |
| |
| item->setPos(originalPos); |
| qApp->processEvents(); |
| QCOMPARE(item->repaints, 0); |
| QCOMPARE(view.repaints, 0); |
| item->show(); |
| qApp->processEvents(); |
| QCOMPARE(item->repaints, 1); |
| QCOMPARE(view.repaints, 1); |
| // The entire item's bounding rect (adjusted for antialiasing) should have been painted. |
| QCOMPARE(view.paintedRegion, expectedRegion); |
| |
| QGraphicsViewPrivate *viewPrivate = static_cast<QGraphicsViewPrivate *>(qt_widget_private(&view)); |
| item->setPos(originalPos + QPoint(50, 50)); |
| viewPrivate->updateAll(); |
| QVERIFY(viewPrivate->fullUpdatePending); |
| QTRY_VERIFY(view.repaints > 1 && item->repaints > 1); |
| item->repaints = 0; |
| view.reset(); |
| item->setPos(originalPos); |
| QTRY_COMPARE(item->repaints, 1); |
| QCOMPARE(view.repaints, 1); |
| COMPARE_REGIONS(view.paintedRegion, expectedRegion + expectedRegion.translated(50, 50)); |
| |
| // Make sure moving a parent item triggers an update on the children |
| // (even though the parent itself is outside the viewport). |
| QGraphicsRectItem *parent = new QGraphicsRectItem(0, 0, 10, 10); |
| parent->setPos(-400, 0); |
| item->setParentItem(parent); |
| item->setPos(400, 0); |
| scene.addItem(parent); |
| itemDeviceBoundingRect = item->deviceTransform(view.viewportTransform()) |
| .mapRect(item->boundingRect()).toAlignedRect(); |
| expectedRegion = itemDeviceBoundingRect.adjusted(-2, -2, 2, 2); |
| view.reset(); |
| item->repaints = 0; |
| parent->setTransform(QTransform::fromTranslate(-400, 0), true); |
| qApp->processEvents(); |
| QCOMPARE(item->repaints, 0); |
| QCOMPARE(view.repaints, 1); |
| QCOMPARE(view.paintedRegion, expectedRegion); |
| view.reset(); |
| item->repaints = 0; |
| parent->setTransform(QTransform::fromTranslate(400, 0), true); |
| qApp->processEvents(); |
| QCOMPARE(item->repaints, 1); |
| QCOMPARE(view.repaints, 1); |
| QCOMPARE(view.paintedRegion, expectedRegion); |
| QCOMPARE(view.paintedRegion, expectedRegion); |
| } |
| |
| void tst_QGraphicsItem::setTransformProperties_data() |
| { |
| QTest::addColumn<QPointF>("origin"); |
| QTest::addColumn<qreal>("rotation"); |
| QTest::addColumn<qreal>("scale"); |
| |
| QTest::newRow("nothing") << QPointF() << qreal(0.0) << qreal(1.0); |
| |
| QTest::newRow("rotation") << QPointF() << qreal(42.2) << qreal(1.0); |
| |
| QTest::newRow("rotation dicentred") << QPointF(qreal(22.3), qreal(-56.2)) |
| << qreal(-2578.2) |
| << qreal(1.0); |
| |
| QTest::newRow("Scale") << QPointF() << qreal(0.0) |
| << qreal(6); |
| |
| QTest::newRow("Everything dicentred") << QPointF(qreal(22.3), qreal(-56.2)) << qreal(-175) << qreal(196); |
| } |
| |
| /** |
| * the normal QCOMPARE doesn't work because it doesn't use qFuzzyCompare |
| */ |
| #define QCOMPARE_TRANSFORM(X1, X2) QVERIFY(((X1)*(X2).inverted()).isIdentity()) |
| |
| void tst_QGraphicsItem::setTransformProperties() |
| { |
| QFETCH(QPointF,origin); |
| QFETCH(qreal,rotation); |
| QFETCH(qreal,scale); |
| |
| QTransform result; |
| result.translate(origin.x(), origin.y()); |
| result.rotate(rotation, Qt::ZAxis); |
| result.scale(scale, scale); |
| result.translate(-origin.x(), -origin.y()); |
| |
| QGraphicsScene scene; |
| QGraphicsRectItem *item = new QGraphicsRectItem(QRectF(0, 0, 100, 100)); |
| scene.addItem(item); |
| |
| item->setRotation(rotation); |
| item->setScale(scale); |
| item->setTransformOriginPoint(origin); |
| |
| QCOMPARE(item->rotation(), rotation); |
| QCOMPARE(item->scale(), scale); |
| QCOMPARE(item->transformOriginPoint(), origin); |
| |
| QCOMPARE(QTransform(), item->transform()); |
| QCOMPARE(result, item->sceneTransform()); |
| |
| //----------------------------------------------------------------- |
| //Change the rotation Z |
| item->setRotation(45); |
| QTransform result2; |
| result2.translate(origin.x(), origin.y()); |
| result2.rotate(45); |
| result2.scale(scale, scale); |
| result2.translate(-origin.x(), -origin.y()); |
| |
| QCOMPARE(item->rotation(), 45.); |
| QCOMPARE(item->scale(), scale); |
| QCOMPARE(item->transformOriginPoint(), origin); |
| |
| QCOMPARE(QTransform(), item->transform()); |
| QCOMPARE(result2, item->sceneTransform()); |
| |
| //----------------------------------------------------------------- |
| // calling setTransform() and setPos should change the sceneTransform |
| item->setTransform(result); |
| item->setPos(100, -150.5); |
| |
| QCOMPARE(item->rotation(), 45.); |
| QCOMPARE(item->scale(), scale); |
| QCOMPARE(item->transformOriginPoint(), origin); |
| QCOMPARE(result, item->transform()); |
| |
| QTransform result3(result); |
| |
| result3.translate(origin.x(), origin.y()); |
| result3.rotate(45); |
| result3.scale(scale, scale); |
| result3.translate(-origin.x(), -origin.y()); |
| |
| result3 *= QTransform::fromTranslate(100, -150.5); //the pos; |
| |
| QCOMPARE(result3, item->sceneTransform()); |
| |
| //----------------------------------------------------- |
| // setting the propertiees should be the same as setting a transform |
| {//with center origin on the matrix |
| QGraphicsRectItem *item1 = new QGraphicsRectItem(QRectF(50.2, -150, 230.5, 119)); |
| scene.addItem(item1); |
| QGraphicsRectItem *item2 = new QGraphicsRectItem(QRectF(50.2, -150, 230.5, 119)); |
| scene.addItem(item2); |
| |
| item1->setPos(12.3, -5); |
| item2->setPos(12.3, -5); |
| item1->setRotation(rotation); |
| item1->setScale(scale); |
| item1->setTransformOriginPoint(origin); |
| |
| item2->setTransform(result); |
| |
| QCOMPARE_TRANSFORM(item1->sceneTransform(), item2->sceneTransform()); |
| |
| QCOMPARE_TRANSFORM(item1->itemTransform(item2), QTransform()); |
| QCOMPARE_TRANSFORM(item2->itemTransform(item1), QTransform()); |
| } |
| } |
| |
| class MyStyleOptionTester : public QGraphicsRectItem |
| { |
| public: |
| MyStyleOptionTester(const QRectF &rect) |
| : QGraphicsRectItem(rect), startTrack(false) |
| {} |
| |
| void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0) |
| { |
| ++repaints; |
| if (startTrack) { |
| //Doesn't use the extended style option so the exposed rect is the boundingRect |
| if (!(flags() & QGraphicsItem::ItemUsesExtendedStyleOption)) { |
| QCOMPARE(option->exposedRect, boundingRect()); |
| QCOMPARE(option->matrix, QMatrix()); |
| } else { |
| QVERIFY(option->exposedRect != QRect()); |
| QVERIFY(option->exposedRect != boundingRect()); |
| QCOMPARE(option->matrix, sceneTransform().toAffine()); |
| } |
| } |
| QGraphicsRectItem::paint(painter, option, widget); |
| } |
| bool startTrack; |
| int repaints = 0; |
| }; |
| |
| void tst_QGraphicsItem::itemUsesExtendedStyleOption() |
| { |
| QGraphicsScene scene(0, 0, 300, 300); |
| QGraphicsPixmapItem item; |
| item.setFlag(QGraphicsItem::ItemUsesExtendedStyleOption, true); |
| QCOMPARE(item.flags(), QGraphicsItem::GraphicsItemFlags(QGraphicsItem::ItemUsesExtendedStyleOption)); |
| item.setFlag(QGraphicsItem::ItemUsesExtendedStyleOption, false); |
| QCOMPARE(item.flags(), 0); |
| |
| //We now test the content of the style option |
| MyStyleOptionTester *rect = new MyStyleOptionTester(QRect(0, 0, 100, 100)); |
| scene.addItem(rect); |
| rect->setPos(200, 200); |
| QWidget topLevel; |
| topLevel.resize(200, 200); |
| QGraphicsView view(&scene, &topLevel); |
| topLevel.setWindowFlags(Qt::X11BypassWindowManagerHint); |
| rect->startTrack = false; |
| topLevel.show(); |
| QVERIFY(QTest::qWaitForWindowExposed(&topLevel)); |
| QCoreApplication::processEvents(); // Process all queued paint events |
| QTRY_VERIFY(rect->repaints > 0); |
| rect->repaints = 0; |
| rect->startTrack = true; |
| rect->update(10, 10, 10, 10); |
| QTRY_COMPARE(rect->repaints, 1); |
| rect->repaints = 0; |
| rect->startTrack = false; |
| rect->setFlag(QGraphicsItem::ItemUsesExtendedStyleOption, true); |
| QVERIFY((rect->flags() & QGraphicsItem::ItemUsesExtendedStyleOption)); |
| QTRY_COMPARE(rect->repaints, 1); |
| rect->repaints = 0; |
| rect->startTrack = true; |
| rect->update(10, 10, 10, 10); |
| QTest::qWait(60); |
| // MyStyleOptionTester does not receive a paint event. Why not? |
| } |
| |
| void tst_QGraphicsItem::itemSendsGeometryChanges() |
| { |
| ItemChangeTester item; |
| item.setFlags(0); |
| item.clear(); |
| |
| QTransform x = QTransform().rotate(45); |
| QPointF pos(10, 10); |
| qreal o(0.5); |
| qreal r(10.0); |
| qreal s(1.5); |
| QPointF origin(1.0, 1.0); |
| item.setTransform(x); |
| item.setPos(pos); |
| item.setRotation(r); |
| item.setScale(s); |
| item.setTransformOriginPoint(origin); |
| QCOMPARE(item.transform(), x); |
| QCOMPARE(item.pos(), pos); |
| QCOMPARE(item.rotation(), r); |
| QCOMPARE(item.scale(), s); |
| QCOMPARE(item.transformOriginPoint(), origin); |
| QCOMPARE(item.changes.size(), 0); |
| |
| item.setOpacity(o); |
| QCOMPARE(item.changes.size(), 2); // opacity |
| |
| item.setFlag(QGraphicsItem::ItemSendsGeometryChanges); |
| QCOMPARE(item.changes.size(), 4); // flags |
| item.setTransform(QTransform()); |
| item.setPos(QPointF()); |
| QCOMPARE(item.changes.size(), 8); // transform + pos |
| QCOMPARE(item.transform(), QTransform()); |
| QCOMPARE(item.pos(), QPointF()); |
| QCOMPARE(item.opacity(), o); |
| item.setRotation(0.0); |
| item.setScale(1.0); |
| item.setTransformOriginPoint(0.0, 0.0); |
| QCOMPARE(item.changes.size(), 14); // rotation + scale + origin |
| QCOMPARE(item.rotation(), qreal(0.0)); |
| QCOMPARE(item.scale(), qreal(1.0)); |
| QCOMPARE(item.transformOriginPoint(), QPointF(0.0, 0.0)); |
| |
| QCOMPARE(item.changes, QList<QGraphicsItem::GraphicsItemChange>() |
| << QGraphicsItem::ItemOpacityChange |
| << QGraphicsItem::ItemOpacityHasChanged |
| << QGraphicsItem::ItemFlagsChange |
| << QGraphicsItem::ItemFlagsHaveChanged |
| << QGraphicsItem::ItemTransformChange |
| << QGraphicsItem::ItemTransformHasChanged |
| << QGraphicsItem::ItemPositionChange |
| << QGraphicsItem::ItemPositionHasChanged |
| << QGraphicsItem::ItemRotationChange |
| << QGraphicsItem::ItemRotationHasChanged |
| << QGraphicsItem::ItemScaleChange |
| << QGraphicsItem::ItemScaleHasChanged |
| << QGraphicsItem::ItemTransformOriginPointChange |
| << QGraphicsItem::ItemTransformOriginPointHasChanged); |
| } |
| |
| // Make sure we update moved items correctly. |
| void tst_QGraphicsItem::moveItem() |
| { |
| QGraphicsScene scene; |
| scene.setSceneRect(-50, -50, 200, 200); |
| |
| MyGraphicsView view(&scene); |
| view.show(); |
| QVERIFY(QTest::qWaitForWindowExposed(&view)); |
| QCoreApplication::processEvents(); // Process all queued paint events |
| |
| EventTester *parent = new EventTester; |
| EventTester *child = new EventTester(parent); |
| EventTester *grandChild = new EventTester(child); |
| |
| #define RESET_COUNTERS \ |
| parent->repaints = 0; \ |
| child->repaints = 0; \ |
| grandChild->repaints = 0; \ |
| view.reset(); |
| |
| RESET_COUNTERS |
| scene.addItem(parent); |
| QTRY_COMPARE(view.repaints, 1); |
| |
| RESET_COUNTERS |
| |
| // Item's boundingRect: (-10, -10, 20, 20). |
| QRect parentDeviceBoundingRect = parent->deviceTransform(view.viewportTransform()) |
| .mapRect(parent->boundingRect()).toAlignedRect() |
| .adjusted(-2, -2, 2, 2); // Adjusted for antialiasing. |
| |
| parent->setPos(20, 20); |
| qApp->processEvents(); |
| QCOMPARE(parent->repaints, 1); |
| QCOMPARE(view.repaints, 1); |
| QRegion expectedParentRegion = parentDeviceBoundingRect; // old position |
| parentDeviceBoundingRect.translate(20, 20); |
| expectedParentRegion += parentDeviceBoundingRect; // new position |
| COMPARE_REGIONS(view.paintedRegion, expectedParentRegion); |
| |
| RESET_COUNTERS |
| |
| child->setPos(20, 20); |
| qApp->processEvents(); |
| QCOMPARE(parent->repaints, 1); |
| QCOMPARE(child->repaints, 1); |
| QCOMPARE(view.repaints, 1); |
| const QRegion expectedChildRegion = expectedParentRegion.translated(20, 20); |
| COMPARE_REGIONS(view.paintedRegion, expectedChildRegion); |
| |
| RESET_COUNTERS |
| |
| grandChild->setPos(20, 20); |
| qApp->processEvents(); |
| QCOMPARE(parent->repaints, 1); |
| QCOMPARE(child->repaints, 1); |
| QCOMPARE(grandChild->repaints, 1); |
| QCOMPARE(view.repaints, 1); |
| const QRegion expectedGrandChildRegion = expectedParentRegion.translated(40, 40); |
| COMPARE_REGIONS(view.paintedRegion, expectedGrandChildRegion); |
| |
| RESET_COUNTERS |
| |
| parent->setTransform(QTransform::fromTranslate(20, 20), true); |
| qApp->processEvents(); |
| QCOMPARE(parent->repaints, 1); |
| QCOMPARE(child->repaints, 1); |
| QCOMPARE(grandChild->repaints, 1); |
| QCOMPARE(view.repaints, 1); |
| expectedParentRegion.translate(20, 20); |
| expectedParentRegion += expectedChildRegion.translated(20, 20); |
| expectedParentRegion += expectedGrandChildRegion.translated(20, 20); |
| COMPARE_REGIONS(view.paintedRegion, expectedParentRegion); |
| } |
| |
| void tst_QGraphicsItem::moveLineItem() |
| { |
| QGraphicsScene scene; |
| scene.setSceneRect(0, 0, 200, 200); |
| QGraphicsLineItem *item = new QGraphicsLineItem(0, 0, 100, 0); |
| item->setPos(50, 50); |
| scene.addItem(item); |
| |
| MyGraphicsView view(&scene); |
| view.show(); |
| QVERIFY(QTest::qWaitForWindowExposed(&view)); |
| QVERIFY(QTest::qWaitForWindowActive(&view)); |
| QCoreApplication::processEvents(); // Process all queued paint events |
| view.reset(); |
| |
| QRectF brect = item->boundingRect(); |
| // Do same adjustments as in qgraphicsscene.cpp |
| if (!brect.width()) |
| brect.adjust(qreal(-0.00001), 0, qreal(0.00001), 0); |
| if (!brect.height()) |
| brect.adjust(0, qreal(-0.00001), 0, qreal(0.00001)); |
| const QRect itemDeviceBoundingRect = item->deviceTransform(view.viewportTransform()) |
| .mapRect(brect).toAlignedRect(); |
| QRegion expectedRegion = itemDeviceBoundingRect.adjusted(-2, -2, 2, 2); // antialiasing |
| |
| // Make sure the calculated region is correct. |
| item->update(); |
| #ifdef Q_OS_WINRT |
| QEXPECT_FAIL("", "Fails on WinRT. Figure out why - QTBUG-68297", Abort); |
| #endif |
| QTRY_COMPARE(view.paintedRegion, expectedRegion); |
| view.reset(); |
| |
| // Old position: (50, 50) |
| item->setPos(50, 100); |
| expectedRegion += expectedRegion.translated(0, 50); |
| QTRY_COMPARE(view.paintedRegion, expectedRegion); |
| } |
| |
| void tst_QGraphicsItem::sorting_data() |
| { |
| QTest::addColumn<int>("index"); |
| |
| QTest::newRow("NoIndex") << int(QGraphicsScene::NoIndex); |
| QTest::newRow("BspTreeIndex") << int(QGraphicsScene::BspTreeIndex); |
| } |
| |
| void tst_QGraphicsItem::sorting() |
| { |
| if (qGuiApp->styleHints()->showIsFullScreen()) |
| QSKIP("Skipped because Platform is auto maximizing"); |
| |
| _paintedItems.clear(); |
| |
| QGraphicsScene scene; |
| QGraphicsItem *grid[100][100]; |
| for (int x = 0; x < 100; ++x) { |
| const QString prefix = QString::number(x) + QLatin1Char('x'); |
| for (int y = 0; y < 100; ++y) { |
| PainterItem *item = new PainterItem; |
| item->setPos(x * 25, y * 25); |
| item->setData(0, prefix + QString::number(y)); |
| grid[x][y] = item; |
| scene.addItem(item); |
| } |
| } |
| |
| PainterItem *item1 = new PainterItem; |
| PainterItem *item2 = new PainterItem; |
| item1->setData(0, "item1"); |
| item2->setData(0, "item2"); |
| scene.addItem(item1); |
| scene.addItem(item2); |
| |
| QGraphicsView view(&scene); |
| // Use Qt::Tool as fully decorated windows have a minimum width of 160 on Windows. |
| view.setWindowFlags(view.windowFlags() | Qt::Tool); |
| view.setResizeAnchor(QGraphicsView::NoAnchor); |
| view.setTransformationAnchor(QGraphicsView::NoAnchor); |
| view.resize(120, 100); |
| view.setFrameStyle(0); |
| view.show(); |
| qApp->setActiveWindow(&view); |
| QVERIFY(QTest::qWaitForWindowExposed(&view)); |
| QVERIFY(QTest::qWaitForWindowActive(&view)); |
| QTRY_VERIFY(_paintedItems.count() > 0); |
| |
| _paintedItems.clear(); |
| |
| view.viewport()->repaint(); |
| #if defined(Q_OS_MAC) |
| // There's no difference between repaint and update on the Mac, |
| // so we have to process events here to make sure we get the event. |
| QTest::qWait(100); |
| #endif |
| |
| QCOMPARE(_paintedItems, QList<QGraphicsItem *>() |
| << grid[0][0] << grid[0][1] << grid[0][2] << grid[0][3] |
| << grid[1][0] << grid[1][1] << grid[1][2] << grid[1][3] |
| << grid[2][0] << grid[2][1] << grid[2][2] << grid[2][3] |
| << grid[3][0] << grid[3][1] << grid[3][2] << grid[3][3] |
| << grid[4][0] << grid[4][1] << grid[4][2] << grid[4][3] |
| << item1 << item2); |
| } |
| |
| void tst_QGraphicsItem::itemHasNoContents() |
| { |
| PainterItem *item1 = new PainterItem; |
| PainterItem *item2 = new PainterItem; |
| item2->setParentItem(item1); |
| item2->setPos(50, 50); |
| item1->setFlag(QGraphicsItem::ItemHasNoContents); |
| item1->setFlag(QGraphicsItem::ItemClipsChildrenToShape); |
| |
| QGraphicsScene scene; |
| scene.addItem(item1); |
| |
| QGraphicsView view(&scene); |
| view.show(); |
| qApp->setActiveWindow(&view); |
| QVERIFY(QTest::qWaitForWindowExposed(&view)); |
| QVERIFY(QTest::qWaitForWindowActive(&view)); |
| QTRY_VERIFY(!_paintedItems.isEmpty()); |
| |
| _paintedItems.clear(); |
| |
| view.viewport()->repaint(); |
| #ifdef Q_OS_MAC |
| // There's no difference between update() and repaint() on the Mac, |
| // so we have to process events here to make sure we get the event. |
| QTest::qWait(10); |
| #endif |
| |
| QTRY_COMPARE(_paintedItems, QList<QGraphicsItem *>() << item2); |
| } |
| |
| void tst_QGraphicsItem::hitTestUntransformableItem() |
| { |
| QGraphicsScene scene; |
| scene.setSceneRect(-100, -100, 200, 200); |
| |
| QGraphicsView view(&scene); |
| view.show(); |
| QVERIFY(QTest::qWaitForWindowExposed(&view)); |
| |
| // Confuse the BSP with dummy items. |
| QGraphicsRectItem *dummy = new QGraphicsRectItem(0, 0, 20, 20); |
| dummy->setPos(-100, -100); |
| scene.addItem(dummy); |
| for (int i = 0; i < 100; ++i) { |
| QGraphicsItem *parent = dummy; |
| dummy = new QGraphicsRectItem(0, 0, 20, 20); |
| dummy->setPos(-100 + i, -100 + i); |
| dummy->setParentItem(parent); |
| } |
| |
| QGraphicsRectItem *item1 = new QGraphicsRectItem(0, 0, 20, 20); |
| item1->setPos(-200, -200); |
| |
| QGraphicsRectItem *item2 = new QGraphicsRectItem(0, 0, 20, 20); |
| item2->setFlag(QGraphicsItem::ItemIgnoresTransformations); |
| item2->setParentItem(item1); |
| item2->setPos(200, 200); |
| |
| QGraphicsRectItem *item3 = new QGraphicsRectItem(0, 0, 20, 20); |
| item3->setParentItem(item2); |
| item3->setPos(80, 80); |
| |
| scene.addItem(item1); |
| |
| QList<QGraphicsItem *> items = scene.items(QPointF(80, 80)); |
| QCOMPARE(items.size(), 1); |
| QCOMPARE(items.at(0), static_cast<QGraphicsItem*>(item3)); |
| |
| scene.setItemIndexMethod(QGraphicsScene::NoIndex); |
| QTest::qWait(100); |
| |
| items = scene.items(QPointF(80, 80)); |
| QCOMPARE(items.size(), 1); |
| QCOMPARE(items.at(0), static_cast<QGraphicsItem*>(item3)); |
| } |
| |
| void tst_QGraphicsItem::hitTestGraphicsEffectItem() |
| { |
| QGraphicsScene scene; |
| scene.setSceneRect(-100, -100, 200, 200); |
| |
| QWidget toplevel; |
| |
| QGraphicsView view(&scene, &toplevel); |
| toplevel.resize(300, 300); |
| toplevel.show(); |
| QVERIFY(QTest::qWaitForWindowExposed(&toplevel)); |
| QCoreApplication::processEvents(); // Process all queued paint events |
| |
| // Confuse the BSP with dummy items. |
| QGraphicsRectItem *dummy = new QGraphicsRectItem(0, 0, 20, 20); |
| dummy->setPos(-100, -100); |
| scene.addItem(dummy); |
| for (int i = 0; i < 100; ++i) { |
| QGraphicsItem *parent = dummy; |
| dummy = new QGraphicsRectItem(0, 0, 20, 20); |
| dummy->setPos(-100 + i, -100 + i); |
| dummy->setParentItem(parent); |
| } |
| |
| const QRectF itemBoundingRect(0, 0, 20, 20); |
| EventTester *item1 = new EventTester; |
| item1->br = itemBoundingRect; |
| item1->setPos(-200, -200); |
| item1->brush = Qt::red; |
| |
| EventTester *item2 = new EventTester; |
| item2->br = itemBoundingRect; |
| item2->setFlag(QGraphicsItem::ItemIgnoresTransformations); |
| item2->setParentItem(item1); |
| item2->setPos(200, 200); |
| item2->brush = Qt::green; |
| |
| EventTester *item3 = new EventTester; |
| item3->br = itemBoundingRect; |
| item3->setParentItem(item2); |
| item3->setPos(80, 80); |
| item3->brush = Qt::blue; |
| |
| scene.addItem(item1); |
| QTRY_COMPARE(item2->repaints, 1); |
| QCOMPARE(item3->repaints, 1); |
| |
| item1->repaints = 0; |
| item2->repaints = 0; |
| item3->repaints = 0; |
| |
| // Apply shadow effect to the entire sub-tree. |
| QGraphicsDropShadowEffect *shadow = new QGraphicsDropShadowEffect; |
| shadow->setOffset(-20, -20); |
| item1->setGraphicsEffect(shadow); |
| |
| // Make sure all visible items are repainted. |
| QTRY_COMPARE(item1->repaints, 1); |
| QCOMPARE(item2->repaints, 1); |
| QCOMPARE(item3->repaints, 1); |
| |
| // Make sure an item doesn't respond to a click on its shadow. |
| QList<QGraphicsItem *> items = scene.items(QPointF(75, 75)); |
| QVERIFY(items.isEmpty()); |
| items = scene.items(QPointF(80, 80)); |
| QCOMPARE(items.size(), 1); |
| QCOMPARE(items.at(0), static_cast<QGraphicsItem *>(item3)); |
| |
| scene.setItemIndexMethod(QGraphicsScene::NoIndex); |
| QTest::qWait(100); |
| |
| items = scene.items(QPointF(75, 75)); |
| QVERIFY(items.isEmpty()); |
| items = scene.items(QPointF(80, 80)); |
| QCOMPARE(items.size(), 1); |
| QCOMPARE(items.at(0), static_cast<QGraphicsItem *>(item3)); |
| } |
| |
| void tst_QGraphicsItem::focusProxy() |
| { |
| QGraphicsScene scene; |
| QEvent activate(QEvent::WindowActivate); |
| QApplication::sendEvent(&scene, &activate); |
| |
| QGraphicsItem *item = scene.addRect(0, 0, 10, 10); |
| item->setFlag(QGraphicsItem::ItemIsFocusable); |
| QVERIFY(!item->focusProxy()); |
| |
| QGraphicsItem *item2 = scene.addRect(0, 0, 10, 10); |
| item2->setFlag(QGraphicsItem::ItemIsFocusable); |
| item->setFocusProxy(item2); |
| QCOMPARE(item->focusProxy(), item2); |
| |
| item->setFocus(); |
| QVERIFY(item->hasFocus()); |
| QVERIFY(item2->hasFocus()); |
| |
| // Try to make a focus chain loop |
| QString err; |
| QTextStream stream(&err); |
| stream << "QGraphicsItem::setFocusProxy: " |
| << (void*)item << " is already in the focus proxy chain" << Qt::flush; |
| QTest::ignoreMessage(QtWarningMsg, err.toLatin1().constData()); |
| item2->setFocusProxy(item); // fails |
| QCOMPARE(item->focusProxy(), (QGraphicsItem *)item2); |
| QCOMPARE(item2->focusProxy(), nullptr); |
| |
| // Try to assign self as focus proxy |
| QTest::ignoreMessage(QtWarningMsg, "QGraphicsItem::setFocusProxy: cannot assign self as focus proxy"); |
| item->setFocusProxy(item); // fails |
| QCOMPARE(item->focusProxy(), (QGraphicsItem *)item2); |
| QCOMPARE(item2->focusProxy(), nullptr); |
| |
| // Reset the focus proxy |
| item->setFocusProxy(0); |
| QCOMPARE(item->focusProxy(), nullptr); |
| QVERIFY(!item->hasFocus()); |
| QVERIFY(item2->hasFocus()); |
| |
| // Test deletion |
| item->setFocusProxy(item2); |
| QCOMPARE(item->focusProxy(), (QGraphicsItem *)item2); |
| delete item2; |
| QCOMPARE(item->focusProxy(), nullptr); |
| |
| // Test event delivery |
| item2 = scene.addRect(0, 0, 10, 10); |
| item2->setFlag(QGraphicsItem::ItemIsFocusable); |
| item->setFocusProxy(item2); |
| item->clearFocus(); |
| |
| EventSpy focusInSpy(&scene, item, QEvent::FocusIn); |
| EventSpy focusOutSpy(&scene, item, QEvent::FocusOut); |
| EventSpy focusInSpy2(&scene, item2, QEvent::FocusIn); |
| EventSpy focusOutSpy2(&scene, item2, QEvent::FocusOut); |
| QCOMPARE(focusInSpy.count(), 0); |
| QCOMPARE(focusOutSpy.count(), 0); |
| QCOMPARE(focusInSpy2.count(), 0); |
| QCOMPARE(focusOutSpy2.count(), 0); |
| |
| item->setFocus(); |
| QCOMPARE(focusInSpy.count(), 0); |
| QCOMPARE(focusInSpy2.count(), 1); |
| item->clearFocus(); |
| QCOMPARE(focusOutSpy.count(), 0); |
| QCOMPARE(focusOutSpy2.count(), 1); |
| |
| // Test two items proxying one item. |
| QGraphicsItem *item3 = scene.addRect(0, 0, 10, 10); |
| item3->setFlag(QGraphicsItem::ItemIsFocusable); |
| item3->setFocusProxy(item2); // item and item3 use item2 as proxy |
| |
| QCOMPARE(item->focusProxy(), item2); |
| QCOMPARE(item2->focusProxy(), nullptr); |
| QCOMPARE(item3->focusProxy(), item2); |
| delete item2; |
| QCOMPARE(item->focusProxy(), nullptr); |
| QCOMPARE(item3->focusProxy(), nullptr); |
| } |
| |
| void tst_QGraphicsItem::subFocus() |
| { |
| // Construct a text item that's not part of a scene (yet) |
| // and has no parent. Setting focus on it will not make |
| // the item gain input focus; that requires a scene. But |
| // it does set subfocus, indicating that the item wishes |
| // to gain focus later. |
| QGraphicsTextItem *text = new QGraphicsTextItem("Hello"); |
| text->setTextInteractionFlags(Qt::TextEditorInteraction); |
| QVERIFY(!text->hasFocus()); |
| text->setFocus(); |
| QVERIFY(!text->hasFocus()); |
| QCOMPARE(text->focusItem(), (QGraphicsItem *)text); |
| |
| // Add a sibling. |
| QGraphicsTextItem *text2 = new QGraphicsTextItem("Hi"); |
| text2->setTextInteractionFlags(Qt::TextEditorInteraction); |
| text2->setPos(30, 30); |
| |
| // Add both items to a scene and check that it's text that |
| // got input focus. |
| QGraphicsScene scene; |
| QEvent activate(QEvent::WindowActivate); |
| QApplication::sendEvent(&scene, &activate); |
| |
| scene.addItem(text); |
| scene.addItem(text2); |
| QVERIFY(text->hasFocus()); |
| |
| text->setData(0, "text"); |
| text2->setData(0, "text2"); |
| |
| // Remove text2 and set subfocus on it. Then readd. Reparent it onto the |
| // other item and see that it gains input focus. |
| scene.removeItem(text2); |
| text2->setFocus(); |
| scene.addItem(text2); |
| QCOMPARE(text2->focusItem(), (QGraphicsItem *)text2); |
| text2->setParentItem(text); |
| QCOMPARE(text->focusItem(), (QGraphicsItem *)text2); |
| QCOMPARE(text2->focusItem(), (QGraphicsItem *)text2); |
| QVERIFY(!text->hasFocus()); |
| QVERIFY(text2->hasFocus()); |
| |
| // Remove both items from the scene, restore subfocus and |
| // readd them. Now the subfocus should kick in and give |
| // text2 focus. |
| scene.removeItem(text); |
| QCOMPARE(text->focusItem(), nullptr); |
| QCOMPARE(text2->focusItem(), nullptr); |
| text2->setFocus(); |
| QCOMPARE(text->focusItem(), (QGraphicsItem *)text2); |
| QCOMPARE(text2->focusItem(), (QGraphicsItem *)text2); |
| scene.addItem(text); |
| |
| // Hiding and showing text should pass focus to text2. |
| QCOMPARE(text->focusItem(), (QGraphicsItem *)text2); |
| QVERIFY(text2->hasFocus()); |
| |
| // Subfocus should repropagate to root when reparenting. |
| QGraphicsRectItem *rect = new QGraphicsRectItem; |
| QGraphicsRectItem *rect2 = new QGraphicsRectItem(rect); |
| QGraphicsRectItem *rect3 = new QGraphicsRectItem(rect2); |
| rect3->setFlag(QGraphicsItem::ItemIsFocusable); |
| |
| text->setData(0, "text"); |
| text2->setData(0, "text2"); |
| rect->setData(0, "rect"); |
| rect2->setData(0, "rect2"); |
| rect3->setData(0, "rect3"); |
| |
| rect3->setFocus(); |
| QVERIFY(!rect3->hasFocus()); |
| QCOMPARE(rect->focusItem(), (QGraphicsItem *)rect3); |
| QCOMPARE(rect2->focusItem(), (QGraphicsItem *)rect3); |
| QCOMPARE(rect3->focusItem(), (QGraphicsItem *)rect3); |
| rect->setParentItem(text2); |
| QCOMPARE(text->focusItem(), (QGraphicsItem *)rect3); |
| QCOMPARE(text2->focusItem(), (QGraphicsItem *)rect3); |
| QCOMPARE(rect->focusItem(), (QGraphicsItem *)rect3); |
| QCOMPARE(rect2->focusItem(), (QGraphicsItem *)rect3); |
| QCOMPARE(rect3->focusItem(), (QGraphicsItem *)rect3); |
| QVERIFY(!rect->hasFocus()); |
| QVERIFY(!rect2->hasFocus()); |
| QVERIFY(rect3->hasFocus()); |
| |
| delete rect2; |
| QCOMPARE(text->focusItem(), nullptr); |
| QCOMPARE(text2->focusItem(), nullptr); |
| QCOMPARE(rect->focusItem(), nullptr); |
| } |
| |
| void tst_QGraphicsItem::focusProxyDeletion() |
| { |
| QGraphicsRectItem *rect = new QGraphicsRectItem; |
| QGraphicsRectItem *rect2 = new QGraphicsRectItem; |
| rect->setFocusProxy(rect2); |
| QCOMPARE(rect->focusProxy(), (QGraphicsItem *)rect2); |
| |
| delete rect2; |
| QCOMPARE(rect->focusProxy(), nullptr); |
| |
| rect2 = new QGraphicsRectItem; |
| rect->setFocusProxy(rect2); |
| QGraphicsItem **danglingFocusProxyRef = &rect->d_ptr->focusProxy; |
| delete rect; // don't crash |
| QVERIFY(!rect2->d_ptr->focusProxyRefs.contains(danglingFocusProxyRef)); |
| |
| rect = new QGraphicsRectItem; |
| rect->setFocusProxy(rect2); |
| QGraphicsScene *scene = new QGraphicsScene; |
| scene->addItem(rect); |
| scene->addItem(rect2); |
| delete rect2; |
| QCOMPARE(rect->focusProxy(), nullptr); |
| |
| rect2 = new QGraphicsRectItem; |
| QTest::ignoreMessage(QtWarningMsg, "QGraphicsItem::setFocusProxy: focus proxy must be in same scene"); |
| rect->setFocusProxy(rect2); |
| QCOMPARE(rect->focusProxy(), nullptr); |
| scene->addItem(rect2); |
| rect->setFocusProxy(rect2); |
| QCOMPARE(rect->focusProxy(), (QGraphicsItem *)rect2); |
| delete rect; // don't crash |
| |
| rect = new QGraphicsRectItem; |
| rect2 = new QGraphicsRectItem; |
| rect->setFocusProxy(rect2); |
| QCOMPARE(rect->focusProxy(), (QGraphicsItem *)rect2); |
| scene->addItem(rect); |
| scene->addItem(rect2); |
| rect->setFocusProxy(rect2); |
| delete scene; // don't crash |
| } |
| |
| void tst_QGraphicsItem::negativeZStacksBehindParent() |
| { |
| QGraphicsRectItem rect; |
| QCOMPARE(rect.zValue(), qreal(0.0)); |
| QVERIFY(!(rect.flags() & QGraphicsItem::ItemNegativeZStacksBehindParent)); |
| QVERIFY(!(rect.flags() & QGraphicsItem::ItemStacksBehindParent)); |
| rect.setZValue(-1); |
| QCOMPARE(rect.zValue(), qreal(-1.0)); |
| QVERIFY(!(rect.flags() & QGraphicsItem::ItemStacksBehindParent)); |
| rect.setZValue(0); |
| rect.setFlag(QGraphicsItem::ItemNegativeZStacksBehindParent); |
| QVERIFY(rect.flags() & QGraphicsItem::ItemNegativeZStacksBehindParent); |
| QVERIFY(!(rect.flags() & QGraphicsItem::ItemStacksBehindParent)); |
| rect.setZValue(-1); |
| QVERIFY(rect.flags() & QGraphicsItem::ItemStacksBehindParent); |
| rect.setZValue(0); |
| QVERIFY(!(rect.flags() & QGraphicsItem::ItemStacksBehindParent)); |
| rect.setFlag(QGraphicsItem::ItemNegativeZStacksBehindParent, false); |
| rect.setZValue(-1); |
| rect.setFlag(QGraphicsItem::ItemNegativeZStacksBehindParent, true); |
| QVERIFY(rect.flags() & QGraphicsItem::ItemStacksBehindParent); |
| rect.setFlag(QGraphicsItem::ItemNegativeZStacksBehindParent, false); |
| QVERIFY(rect.flags() & QGraphicsItem::ItemStacksBehindParent); |
| } |
| |
| void tst_QGraphicsItem::setGraphicsEffect() |
| { |
| // Check that we don't have any effect by default. |
| QGraphicsItem *item = new QGraphicsRectItem(0, 0, 10, 10); |
| QVERIFY(!item->graphicsEffect()); |
| |
| // SetGet check. |
| QPointer<QGraphicsEffect> blurEffect = new QGraphicsBlurEffect; |
| item->setGraphicsEffect(blurEffect); |
| QCOMPARE(item->graphicsEffect(), static_cast<QGraphicsEffect *>(blurEffect)); |
| |
| // Ensure the existing effect is deleted when setting a new one. |
| QPointer<QGraphicsEffect> shadowEffect = new QGraphicsDropShadowEffect; |
| item->setGraphicsEffect(shadowEffect); |
| QVERIFY(!blurEffect); |
| QCOMPARE(item->graphicsEffect(), static_cast<QGraphicsEffect *>(shadowEffect)); |
| blurEffect = new QGraphicsBlurEffect; |
| |
| // Ensure the effect is uninstalled when setting it on a new target. |
| QGraphicsItem *anotherItem = new QGraphicsRectItem(0, 0, 10, 10); |
| anotherItem->setGraphicsEffect(blurEffect); |
| item->setGraphicsEffect(blurEffect); |
| QVERIFY(!anotherItem->graphicsEffect()); |
| QVERIFY(!shadowEffect); |
| |
| // Ensure the existing effect is deleted when deleting the item. |
| delete item; |
| QVERIFY(!blurEffect); |
| delete anotherItem; |
| |
| // Ensure the effect is uninstalled when deleting it |
| item = new QGraphicsRectItem(0, 0, 10, 10); |
| blurEffect = new QGraphicsBlurEffect; |
| item->setGraphicsEffect(blurEffect); |
| delete blurEffect; |
| QVERIFY(!item->graphicsEffect()); |
| |
| // Ensure the existing effect is uninstalled and deleted when setting a null effect |
| blurEffect = new QGraphicsBlurEffect; |
| item->setGraphicsEffect(blurEffect); |
| item->setGraphicsEffect(0); |
| QVERIFY(!item->graphicsEffect()); |
| QVERIFY(!blurEffect); |
| |
| delete item; |
| } |
| |
| void tst_QGraphicsItem::panel() |
| { |
| QGraphicsScene scene; |
| |
| QGraphicsRectItem *panel1 = new QGraphicsRectItem; |
| QGraphicsRectItem *panel2 = new QGraphicsRectItem; |
| QGraphicsRectItem *panel3 = new QGraphicsRectItem; |
| QGraphicsRectItem *panel4 = new QGraphicsRectItem; |
| QGraphicsRectItem *notPanel1 = new QGraphicsRectItem; |
| QGraphicsRectItem *notPanel2 = new QGraphicsRectItem; |
| panel1->setFlag(QGraphicsItem::ItemIsPanel); |
| panel2->setFlag(QGraphicsItem::ItemIsPanel); |
| panel3->setFlag(QGraphicsItem::ItemIsPanel); |
| panel4->setFlag(QGraphicsItem::ItemIsPanel); |
| scene.addItem(panel1); |
| scene.addItem(panel2); |
| scene.addItem(panel3); |
| scene.addItem(panel4); |
| scene.addItem(notPanel1); |
| scene.addItem(notPanel2); |
| |
| EventSpy spy_activate_panel1(&scene, panel1, QEvent::WindowActivate); |
| EventSpy spy_deactivate_panel1(&scene, panel1, QEvent::WindowDeactivate); |
| EventSpy spy_activate_panel2(&scene, panel2, QEvent::WindowActivate); |
| EventSpy spy_deactivate_panel2(&scene, panel2, QEvent::WindowDeactivate); |
| EventSpy spy_activate_panel3(&scene, panel3, QEvent::WindowActivate); |
| EventSpy spy_deactivate_panel3(&scene, panel3, QEvent::WindowDeactivate); |
| EventSpy spy_activate_panel4(&scene, panel4, QEvent::WindowActivate); |
| EventSpy spy_deactivate_panel4(&scene, panel4, QEvent::WindowDeactivate); |
| EventSpy spy_activate_notPanel1(&scene, notPanel1, QEvent::WindowActivate); |
| EventSpy spy_deactivate_notPanel1(&scene, notPanel1, QEvent::WindowDeactivate); |
| EventSpy spy_activate_notPanel2(&scene, notPanel1, QEvent::WindowActivate); |
| EventSpy spy_deactivate_notPanel2(&scene, notPanel1, QEvent::WindowDeactivate); |
| |
| QCOMPARE(spy_activate_panel1.count(), 0); |
| QCOMPARE(spy_deactivate_panel1.count(), 0); |
| QCOMPARE(spy_activate_panel2.count(), 0); |
| QCOMPARE(spy_deactivate_panel2.count(), 0); |
| QCOMPARE(spy_activate_panel3.count(), 0); |
| QCOMPARE(spy_deactivate_panel3.count(), 0); |
| QCOMPARE(spy_activate_panel4.count(), 0); |
| QCOMPARE(spy_deactivate_panel4.count(), 0); |
| QCOMPARE(spy_activate_notPanel1.count(), 0); |
| QCOMPARE(spy_deactivate_notPanel1.count(), 0); |
| QCOMPARE(spy_activate_notPanel2.count(), 0); |
| QCOMPARE(spy_deactivate_notPanel2.count(), 0); |
| |
| QVERIFY(!scene.activePanel()); |
| QVERIFY(!scene.isActive()); |
| |
| QEvent activate(QEvent::WindowActivate); |
| QEvent deactivate(QEvent::WindowDeactivate); |
| |
| QApplication::sendEvent(&scene, &activate); |
| |
| // No previous activation, so the scene is active. |
| QVERIFY(scene.isActive()); |
| QCOMPARE(scene.activePanel(), (QGraphicsItem *)panel1); |
| QVERIFY(panel1->isActive()); |
| QVERIFY(!panel2->isActive()); |
| QVERIFY(!panel3->isActive()); |
| QVERIFY(!panel4->isActive()); |
| QVERIFY(!notPanel1->isActive()); |
| QVERIFY(!notPanel2->isActive()); |
| QCOMPARE(spy_deactivate_notPanel1.count(), 0); |
| QCOMPARE(spy_deactivate_notPanel2.count(), 0); |
| QCOMPARE(spy_activate_panel1.count(), 1); |
| QCOMPARE(spy_activate_panel2.count(), 0); |
| QCOMPARE(spy_activate_panel3.count(), 0); |
| QCOMPARE(spy_activate_panel4.count(), 0); |
| |
| // Switch back to scene. |
| scene.setActivePanel(0); |
| QVERIFY(!scene.activePanel()); |
| QVERIFY(!panel1->isActive()); |
| QVERIFY(!panel2->isActive()); |
| QVERIFY(!panel3->isActive()); |
| QVERIFY(!panel4->isActive()); |
| QVERIFY(notPanel1->isActive()); |
| QVERIFY(notPanel2->isActive()); |
| QCOMPARE(spy_activate_notPanel1.count(), 1); |
| QCOMPARE(spy_activate_notPanel2.count(), 1); |
| |
| // Deactivate the scene |
| QApplication::sendEvent(&scene, &deactivate); |
| QVERIFY(!scene.activePanel()); |
| QVERIFY(!panel1->isActive()); |
| QVERIFY(!panel2->isActive()); |
| QVERIFY(!panel3->isActive()); |
| QVERIFY(!panel4->isActive()); |
| QVERIFY(!notPanel1->isActive()); |
| QVERIFY(!notPanel2->isActive()); |
| QCOMPARE(spy_deactivate_notPanel1.count(), 1); |
| QCOMPARE(spy_deactivate_notPanel2.count(), 1); |
| |
| // Reactivate the scene |
| QApplication::sendEvent(&scene, &activate); |
| QVERIFY(!scene.activePanel()); |
| QVERIFY(!panel1->isActive()); |
| QVERIFY(!panel2->isActive()); |
| QVERIFY(!panel3->isActive()); |
| QVERIFY(!panel4->isActive()); |
| QVERIFY(notPanel1->isActive()); |
| QVERIFY(notPanel2->isActive()); |
| QCOMPARE(spy_activate_notPanel1.count(), 2); |
| QCOMPARE(spy_activate_notPanel2.count(), 2); |
| |
| // Switch to panel1 |
| scene.setActivePanel(panel1); |
| QVERIFY(panel1->isActive()); |
| QCOMPARE(spy_deactivate_notPanel1.count(), 2); |
| QCOMPARE(spy_deactivate_notPanel2.count(), 2); |
| QCOMPARE(spy_activate_panel1.count(), 2); |
| |
| // Deactivate the scene |
| QApplication::sendEvent(&scene, &deactivate); |
| QVERIFY(!panel1->isActive()); |
| QCOMPARE(spy_deactivate_panel1.count(), 2); |
| |
| // Reactivate the scene |
| QApplication::sendEvent(&scene, &activate); |
| QVERIFY(panel1->isActive()); |
| QCOMPARE(spy_activate_panel1.count(), 3); |
| |
| // Deactivate the scene |
| QApplication::sendEvent(&scene, &deactivate); |
| QVERIFY(!panel1->isActive()); |
| QVERIFY(!scene.activePanel()); |
| scene.setActivePanel(0); |
| |
| // Reactivate the scene |
| QApplication::sendEvent(&scene, &activate); |
| QVERIFY(!panel1->isActive()); |
| } |
| |
| void tst_QGraphicsItem::panelWithFocusItems() |
| { |
| for (int i = 0; i < 2; ++i) |
| { |
| QGraphicsScene scene; |
| QEvent activate(QEvent::WindowActivate); |
| QApplication::sendEvent(&scene, &activate); |
| |
| bool widget = (i == 1); |
| QGraphicsItem *parentPanel = widget ? (QGraphicsItem *)new QGraphicsWidget : (QGraphicsItem *)new QGraphicsRectItem; |
| QGraphicsItem *parentPanelFocusItem = widget ? (QGraphicsItem *)new QGraphicsWidget : (QGraphicsItem *)new QGraphicsRectItem; |
| QGraphicsItem *parentPanelFocusItemSibling = widget ? (QGraphicsItem *)new QGraphicsWidget : (QGraphicsItem *)new QGraphicsRectItem; |
| parentPanel->setFlag(QGraphicsItem::ItemIsPanel); |
| parentPanelFocusItem->setFlag(QGraphicsItem::ItemIsFocusable); |
| parentPanelFocusItemSibling->setFlag(QGraphicsItem::ItemIsFocusable); |
| if (widget) { |
| static_cast<QGraphicsWidget *>(parentPanelFocusItem)->setFocusPolicy(Qt::StrongFocus); |
| static_cast<QGraphicsWidget *>(parentPanelFocusItemSibling)->setFocusPolicy(Qt::StrongFocus); |
| } |
| parentPanelFocusItem->setParentItem(parentPanel); |
| parentPanelFocusItemSibling->setParentItem(parentPanel); |
| parentPanelFocusItem->setFocus(); |
| scene.addItem(parentPanel); |
| |
| QVERIFY(parentPanel->isActive()); |
| QVERIFY(parentPanelFocusItem->hasFocus()); |
| QCOMPARE(parentPanel->focusItem(), (QGraphicsItem *)parentPanelFocusItem); |
| QCOMPARE(parentPanelFocusItem->focusItem(), (QGraphicsItem *)parentPanelFocusItem); |
| |
| QGraphicsItem *childPanel = widget ? (QGraphicsItem *)new QGraphicsWidget : (QGraphicsItem *)new QGraphicsRectItem; |
| QGraphicsItem *childPanelFocusItem = widget ? (QGraphicsItem *)new QGraphicsWidget : (QGraphicsItem *)new QGraphicsRectItem; |
| QGraphicsItem *grandChildPanelFocusItem = widget ? (QGraphicsItem *)new QGraphicsWidget : (QGraphicsItem *)new QGraphicsRectItem; |
| QGraphicsItem *grandChildPanelFocusItem2 = widget ? (QGraphicsItem *)new QGraphicsWidget : (QGraphicsItem *)new QGraphicsRectItem; |
| |
| childPanel->setFlag(QGraphicsItem::ItemIsPanel); |
| childPanelFocusItem->setFlag(QGraphicsItem::ItemIsFocusable); |
| grandChildPanelFocusItem->setFlag(QGraphicsItem::ItemIsFocusable); |
| grandChildPanelFocusItem2->setFlag(QGraphicsItem::ItemIsFocusable); |
| |
| if (widget) |
| { |
| static_cast<QGraphicsWidget *>(childPanelFocusItem)->setFocusPolicy(Qt::StrongFocus); |
| static_cast<QGraphicsWidget *>(grandChildPanelFocusItem)->setFocusPolicy(Qt::StrongFocus); |
| static_cast<QGraphicsWidget *>(grandChildPanelFocusItem2)->setFocusPolicy(Qt::StrongFocus); |
| } |
| grandChildPanelFocusItem->setParentItem(childPanelFocusItem); |
| grandChildPanelFocusItem2->setParentItem(childPanelFocusItem); |
| childPanelFocusItem->setParentItem(childPanel); |
| grandChildPanelFocusItem->setFocus(); |
| |
| QVERIFY(!grandChildPanelFocusItem->hasFocus()); |
| QCOMPARE(childPanel->focusItem(), (QGraphicsItem *)grandChildPanelFocusItem); |
| QCOMPARE(childPanelFocusItem->focusItem(), (QGraphicsItem *)grandChildPanelFocusItem); |
| QCOMPARE(grandChildPanelFocusItem->focusItem(), (QGraphicsItem *)grandChildPanelFocusItem); |
| |
| childPanel->setParentItem(parentPanel); |
| |
| QVERIFY(!parentPanel->isActive()); |
| QVERIFY(!parentPanelFocusItem->hasFocus()); |
| QCOMPARE(parentPanel->focusItem(), (QGraphicsItem *)parentPanelFocusItem); |
| QCOMPARE(parentPanelFocusItem->focusItem(), (QGraphicsItem *)parentPanelFocusItem); |
| |
| QVERIFY(childPanel->isActive()); |
| QVERIFY(!childPanelFocusItem->hasFocus()); |
| QVERIFY(grandChildPanelFocusItem->hasFocus()); |
| QCOMPARE(childPanel->focusItem(), (QGraphicsItem *)grandChildPanelFocusItem); |
| QCOMPARE(childPanelFocusItem->focusItem(), (QGraphicsItem *)grandChildPanelFocusItem); |
| |
| childPanel->hide(); |
| QCOMPARE(childPanel->focusItem(), (QGraphicsItem *)grandChildPanelFocusItem); |
| QVERIFY(!childPanel->focusItem()->hasFocus()); |
| QVERIFY(parentPanel->isActive()); |
| QVERIFY(parentPanelFocusItem->hasFocus()); |
| QCOMPARE(parentPanel->focusItem(), (QGraphicsItem *)parentPanelFocusItem); |
| QCOMPARE(parentPanelFocusItem->focusItem(), (QGraphicsItem *)parentPanelFocusItem); |
| QCOMPARE(grandChildPanelFocusItem->focusItem(), (QGraphicsItem *)grandChildPanelFocusItem); |
| |
| childPanel->show(); |
| QVERIFY(childPanel->isActive()); |
| QVERIFY(grandChildPanelFocusItem->hasFocus()); |
| QCOMPARE(childPanel->focusItem(), (QGraphicsItem *)grandChildPanelFocusItem); |
| QCOMPARE(childPanelFocusItem->focusItem(), (QGraphicsItem *)grandChildPanelFocusItem); |
| QCOMPARE(grandChildPanelFocusItem->focusItem(), (QGraphicsItem *)grandChildPanelFocusItem); |
| |
| childPanel->hide(); |
| |
| QVERIFY(parentPanel->isActive()); |
| QVERIFY(parentPanelFocusItem->hasFocus()); |
| QCOMPARE(parentPanel->focusItem(), (QGraphicsItem *)parentPanelFocusItem); |
| QCOMPARE(parentPanelFocusItem->focusItem(), (QGraphicsItem *)parentPanelFocusItem); |
| } |
| } |
| |
| void tst_QGraphicsItem::addPanelToActiveScene() |
| { |
| QGraphicsScene scene; |
| QVERIFY(!scene.isActive()); |
| |
| QGraphicsRectItem *rect = new QGraphicsRectItem; |
| scene.addItem(rect); |
| QVERIFY(!rect->isActive()); |
| scene.removeItem(rect); |
| |
| QEvent activate(QEvent::WindowActivate); |
| QEvent deactivate(QEvent::WindowDeactivate); |
| |
| QApplication::sendEvent(&scene, &activate); |
| QVERIFY(scene.isActive()); |
| scene.addItem(rect); |
| QVERIFY(rect->isActive()); |
| scene.removeItem(rect); |
| |
| rect->setFlag(QGraphicsItem::ItemIsPanel); |
| scene.addItem(rect); |
| QVERIFY(rect->isActive()); |
| QCOMPARE(scene.activePanel(), (QGraphicsItem *)rect); |
| |
| QGraphicsRectItem *rect2 = new QGraphicsRectItem; |
| scene.addItem(rect2); |
| QVERIFY(rect->isActive()); |
| QCOMPARE(scene.activePanel(), (QGraphicsItem *)rect); |
| } |
| |
| void tst_QGraphicsItem::activate() |
| { |
| QGraphicsScene scene; |
| QGraphicsRectItem *rect = scene.addRect(-10, -10, 20, 20); |
| QVERIFY(!rect->isActive()); |
| |
| QEvent activate(QEvent::WindowActivate); |
| QEvent deactivate(QEvent::WindowDeactivate); |
| |
| QApplication::sendEvent(&scene, &activate); |
| |
| // Non-panel item (active when scene is active). |
| QVERIFY(rect->isActive()); |
| |
| QGraphicsRectItem *rect2 = new QGraphicsRectItem; |
| rect2->setFlag(QGraphicsItem::ItemIsPanel); |
| QGraphicsRectItem *rect3 = new QGraphicsRectItem; |
| rect3->setFlag(QGraphicsItem::ItemIsPanel); |
| |
| // Test normal activation. |
| QVERIFY(!rect2->isActive()); |
| scene.addItem(rect2); |
| QVERIFY(rect2->isActive()); // first panel item is activated |
| scene.addItem(rect3); |
| QVERIFY(!rect3->isActive()); // second panel item is _not_ activated |
| rect3->setActive(true); |
| QVERIFY(rect3->isActive()); |
| scene.removeItem(rect3); |
| QVERIFY(!rect3->isActive()); // no panel is active anymore |
| QCOMPARE(scene.activePanel(), nullptr); |
| scene.addItem(rect3); |
| QVERIFY(rect3->isActive()); // second panel item is activated |
| |
| // Test pending activation. |
| scene.removeItem(rect3); |
| rect2->setActive(true); |
| QVERIFY(rect2->isActive()); // first panel item is activated |
| rect3->setActive(true); |
| QVERIFY(!rect3->isActive()); // not active (yet) |
| scene.addItem(rect3); |
| QVERIFY(rect3->isActive()); // now becomes active |
| |
| // Test pending deactivation. |
| scene.removeItem(rect3); |
| rect3->setActive(false); |
| scene.addItem(rect3); |
| QVERIFY(!rect3->isActive()); // doesn't become active |
| |
| // Child of panel activation. |
| rect3->setActive(true); |
| QGraphicsRectItem *rect4 = new QGraphicsRectItem; |
| rect4->setFlag(QGraphicsItem::ItemIsPanel); |
| QGraphicsRectItem *rect5 = new QGraphicsRectItem(rect4); |
| QGraphicsRectItem *rect6 = new QGraphicsRectItem(rect5); |
| scene.addItem(rect4); |
| QCOMPARE(scene.activePanel(), (QGraphicsItem *)rect3); |
| scene.removeItem(rect4); |
| rect6->setActive(true); |
| scene.addItem(rect4); |
| QVERIFY(rect4->isActive()); |
| QVERIFY(rect5->isActive()); |
| QVERIFY(rect6->isActive()); |
| QCOMPARE(scene.activePanel(), (QGraphicsItem *)rect4); |
| scene.removeItem(rect4); // no active panel |
| rect6->setActive(false); |
| scene.addItem(rect4); |
| QVERIFY(!rect4->isActive()); |
| QVERIFY(!rect5->isActive()); |
| QVERIFY(!rect6->isActive()); |
| QCOMPARE(scene.activePanel(), nullptr); |
| |
| // Controlling auto-activation when the scene changes activation. |
| rect4->setActive(true); |
| QApplication::sendEvent(&scene, &deactivate); |
| QVERIFY(!scene.isActive()); |
| QVERIFY(!rect4->isActive()); |
| rect4->setActive(false); |
| QApplication::sendEvent(&scene, &activate); |
| QVERIFY(scene.isActive()); |
| QVERIFY(!scene.activePanel()); |
| QVERIFY(!rect4->isActive()); |
| } |
| |
| void tst_QGraphicsItem::setActivePanelOnInactiveScene() |
| { |
| QGraphicsScene scene; |
| QGraphicsRectItem *item = scene.addRect(QRectF()); |
| QGraphicsRectItem *panel = scene.addRect(QRectF()); |
| panel->setFlag(QGraphicsItem::ItemIsPanel); |
| |
| EventSpy itemActivateSpy(&scene, item, QEvent::WindowActivate); |
| EventSpy itemDeactivateSpy(&scene, item, QEvent::WindowDeactivate); |
| EventSpy panelActivateSpy(&scene, panel, QEvent::WindowActivate); |
| EventSpy panelDeactivateSpy(&scene, panel, QEvent::WindowDeactivate); |
| EventSpy sceneActivationChangeSpy(&scene, QEvent::ActivationChange); |
| |
| scene.setActivePanel(panel); |
| QCOMPARE(scene.activePanel(), nullptr); |
| QCOMPARE(itemActivateSpy.count(), 0); |
| QCOMPARE(itemDeactivateSpy.count(), 0); |
| QCOMPARE(panelActivateSpy.count(), 0); |
| QCOMPARE(panelDeactivateSpy.count(), 0); |
| QCOMPARE(sceneActivationChangeSpy.count(), 0); |
| } |
| |
| void tst_QGraphicsItem::activationOnShowHide() |
| { |
| QGraphicsScene scene; |
| QEvent activate(QEvent::WindowActivate); |
| QApplication::sendEvent(&scene, &activate); |
| |
| QGraphicsRectItem *rootPanel = scene.addRect(QRectF()); |
| rootPanel->setFlag(QGraphicsItem::ItemIsPanel); |
| rootPanel->setActive(true); |
| |
| QGraphicsRectItem *subPanel = new QGraphicsRectItem; |
| subPanel->setFlag(QGraphicsItem::ItemIsPanel); |
| |
| // Reparenting onto an active panel auto-activates the child panel. |
| subPanel->setParentItem(rootPanel); |
| QVERIFY(subPanel->isActive()); |
| QVERIFY(!rootPanel->isActive()); |
| |
| // Hiding an active child panel will reactivate the parent panel. |
| subPanel->hide(); |
| QVERIFY(rootPanel->isActive()); |
| |
| // Showing a child panel will auto-activate it. |
| subPanel->show(); |
| QVERIFY(subPanel->isActive()); |
| QVERIFY(!rootPanel->isActive()); |
| |
| // Adding an unrelated panel doesn't affect activation. |
| QGraphicsRectItem *otherPanel = new QGraphicsRectItem; |
| otherPanel->setFlag(QGraphicsItem::ItemIsPanel); |
| scene.addItem(otherPanel); |
| QVERIFY(subPanel->isActive()); |
| |
| // Showing an unrelated panel doesn't affect activation. |
| otherPanel->hide(); |
| otherPanel->show(); |
| QVERIFY(subPanel->isActive()); |
| |
| // Add a non-panel item. |
| QGraphicsRectItem *otherItem = new QGraphicsRectItem; |
| scene.addItem(otherItem); |
| otherItem->setActive(true); |
| QVERIFY(otherItem->isActive()); |
| |
| // Reparent a panel onto an active non-panel item. |
| subPanel->setParentItem(otherItem); |
| QVERIFY(subPanel->isActive()); |
| |
| // Showing a child panel of a non-panel item will activate it. |
| subPanel->hide(); |
| QVERIFY(!subPanel->isActive()); |
| QVERIFY(otherItem->isActive()); |
| subPanel->show(); |
| QVERIFY(subPanel->isActive()); |
| |
| // Hiding a toplevel active panel will pass activation back |
| // to the non-panel items. |
| rootPanel->setActive(true); |
| rootPanel->hide(); |
| QVERIFY(!rootPanel->isActive()); |
| QVERIFY(otherItem->isActive()); |
| } |
| |
| class MoveWhileDying : public QGraphicsRectItem |
| { |
| public: |
| MoveWhileDying(QGraphicsItem *parent = 0) |
| : QGraphicsRectItem(parent) |
| { } |
| ~MoveWhileDying() |
| { |
| foreach (QGraphicsItem *c, childItems()) { |
| foreach (QGraphicsItem *cc, c->childItems()) { |
| cc->moveBy(10, 10); |
| } |
| c->moveBy(10, 10); |
| } |
| if (QGraphicsItem *p = parentItem()) { p->moveBy(10, 10); } |
| } |
| }; |
| |
| void tst_QGraphicsItem::deactivateInactivePanel() |
| { |
| QGraphicsScene scene; |
| QGraphicsItem *panel1 = scene.addRect(QRectF(0, 0, 10, 10)); |
| panel1->setFlag(QGraphicsItem::ItemIsPanel); |
| |
| QGraphicsItem *panel2 = scene.addRect(QRectF(0, 0, 10, 10)); |
| panel2->setFlag(QGraphicsItem::ItemIsPanel); |
| |
| QEvent event(QEvent::WindowActivate); |
| qApp->sendEvent(&scene, &event); |
| |
| panel1->setActive(true); |
| QVERIFY(scene.isActive()); |
| QVERIFY(panel1->isActive()); |
| QVERIFY(!panel2->isActive()); |
| QCOMPARE(scene.activePanel(), panel1); |
| |
| panel2->setActive(true); |
| QVERIFY(panel2->isActive()); |
| QVERIFY(!panel1->isActive()); |
| QCOMPARE(scene.activePanel(), panel2); |
| |
| panel2->setActive(false); |
| QVERIFY(panel1->isActive()); |
| QVERIFY(!panel2->isActive()); |
| QCOMPARE(scene.activePanel(), panel1); |
| |
| panel2->setActive(false); |
| QVERIFY(panel1->isActive()); |
| QVERIFY(!panel2->isActive()); |
| QCOMPARE(scene.activePanel(), panel1); |
| } |
| |
| void tst_QGraphicsItem::moveWhileDeleting() |
| { |
| QGraphicsScene scene; |
| QGraphicsRectItem *rect = new QGraphicsRectItem; |
| MoveWhileDying *silly = new MoveWhileDying(rect); |
| QGraphicsRectItem *child = new QGraphicsRectItem(silly); |
| scene.addItem(rect); |
| delete rect; // don't crash! |
| |
| rect = new QGraphicsRectItem; |
| silly = new MoveWhileDying(rect); |
| child = new QGraphicsRectItem(silly); |
| |
| QGraphicsView view(&scene); |
| view.show(); |
| QVERIFY(QTest::qWaitForWindowExposed(&view)); |
| |
| delete rect; |
| |
| rect = new QGraphicsRectItem; |
| rect->setFlag(QGraphicsItem::ItemClipsChildrenToShape); |
| silly = new MoveWhileDying(rect); |
| child = new QGraphicsRectItem(silly); |
| |
| QTest::qWait(125); |
| |
| delete rect; |
| |
| rect = new MoveWhileDying; |
| rect->setFlag(QGraphicsItem::ItemClipsChildrenToShape); |
| child = new QGraphicsRectItem(rect); |
| silly = new MoveWhileDying(child); |
| |
| QTest::qWait(125); |
| |
| delete rect; |
| } |
| |
| class MyRectItem : public QGraphicsWidget |
| { |
| Q_OBJECT |
| public: |
| MyRectItem(QGraphicsItem *parent = 0) : QGraphicsWidget(parent) |
| { |
| |
| } |
| |
| void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) |
| { |
| painter->setBrush(brush); |
| painter->drawRect(boundingRect()); |
| } |
| void move() |
| { |
| setPos(-100,-100); |
| topLevel->collidingItems(Qt::IntersectsItemBoundingRect); |
| } |
| public: |
| QGraphicsItem *topLevel; |
| QBrush brush; |
| }; |
| |
| |
| void tst_QGraphicsItem::ensureDirtySceneTransform() |
| { |
| QGraphicsScene scene; |
| |
| MyRectItem *topLevel = new MyRectItem; |
| topLevel->setGeometry(0, 0, 100, 100); |
| topLevel->setPos(-50, -50); |
| topLevel->brush = QBrush(QColor(Qt::black)); |
| scene.addItem(topLevel); |
| |
| MyRectItem *parent = new MyRectItem; |
| parent->topLevel = topLevel; |
| parent->setGeometry(0, 0, 100, 100); |
| parent->setPos(0, 0); |
| parent->brush = QBrush(QColor(Qt::magenta)); |
| parent->setObjectName("parent"); |
| scene.addItem(parent); |
| |
| MyRectItem *child = new MyRectItem(parent); |
| child->setGeometry(0, 0, 80, 80); |
| child->setPos(10, 10); |
| child->setObjectName("child"); |
| child->brush = QBrush(QColor(Qt::blue)); |
| |
| MyRectItem *child2 = new MyRectItem(parent); |
| child2->setGeometry(0, 0, 80, 80); |
| child2->setPos(15, 15); |
| child2->setObjectName("child2"); |
| child2->brush = QBrush(QColor(Qt::green)); |
| |
| MyRectItem *child3 = new MyRectItem(parent); |
| child3->setGeometry(0, 0, 80, 80); |
| child3->setPos(20, 20); |
| child3->setObjectName("child3"); |
| child3->brush = QBrush(QColor(Qt::gray)); |
| |
| QGraphicsView view(&scene); |
| view.show(); |
| QApplication::setActiveWindow(&view); |
| QVERIFY(QTest::qWaitForWindowExposed(&view)); |
| QVERIFY(QTest::qWaitForWindowActive(&view)); |
| QCOMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view)); |
| |
| //We move the parent |
| parent->move(); |
| QApplication::processEvents(); |
| |
| //We check if all items moved |
| QCOMPARE(child->pos(), QPointF(10, 10)); |
| QCOMPARE(child2->pos(), QPointF(15, 15)); |
| QCOMPARE(child3->pos(), QPointF(20, 20)); |
| |
| QCOMPARE(child->sceneBoundingRect(), QRectF(-90, -90, 80, 80)); |
| QCOMPARE(child2->sceneBoundingRect(), QRectF(-85, -85, 80, 80)); |
| QCOMPARE(child3->sceneBoundingRect(), QRectF(-80, -80, 80, 80)); |
| |
| QCOMPARE(child->sceneTransform(), QTransform::fromTranslate(-90, -90)); |
| QCOMPARE(child2->sceneTransform(), QTransform::fromTranslate(-85, -85)); |
| QCOMPARE(child3->sceneTransform(), QTransform::fromTranslate(-80, -80)); |
| } |
| |
| void tst_QGraphicsItem::focusScope() |
| { |
| // ItemIsFocusScope is an internal feature (for now). |
| QGraphicsScene scene; |
| |
| QGraphicsRectItem *scope3 = new QGraphicsRectItem; |
| scope3->setData(0, "scope3"); |
| scope3->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsFocusScope); |
| scope3->setFocus(); |
| QVERIFY(!scope3->focusScopeItem()); |
| QCOMPARE(scope3->focusItem(), (QGraphicsItem *)scope3); |
| |
| QGraphicsRectItem *scope2 = new QGraphicsRectItem; |
| scope2->setData(0, "scope2"); |
| scope2->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsFocusScope); |
| scope2->setFocus(); |
| QVERIFY(!scope2->focusScopeItem()); |
| scope3->setParentItem(scope2); |
| QCOMPARE(scope2->focusScopeItem(), (QGraphicsItem *)scope3); |
| QCOMPARE(scope2->focusItem(), (QGraphicsItem *)scope3); |
| |
| QGraphicsRectItem *scope1 = new QGraphicsRectItem; |
| scope1->setData(0, "scope1"); |
| scope1->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsFocusScope); |
| scope1->setFocus(); |
| QVERIFY(!scope1->focusScopeItem()); |
| scope2->setParentItem(scope1); |
| |
| QCOMPARE(scope1->focusItem(), (QGraphicsItem *)scope3); |
| QCOMPARE(scope2->focusItem(), (QGraphicsItem *)scope3); |
| QCOMPARE(scope3->focusItem(), (QGraphicsItem *)scope3); |
| QCOMPARE(scope1->focusScopeItem(), (QGraphicsItem *)scope2); |
| QCOMPARE(scope2->focusScopeItem(), (QGraphicsItem *)scope3); |
| QCOMPARE(scope3->focusScopeItem(), nullptr); |
| |
| scene.addItem(scope1); |
| |
| QEvent windowActivate(QEvent::WindowActivate); |
| qApp->sendEvent(&scene, &windowActivate); |
| scene.setFocus(); |
| |
| QCOMPARE(scope1->focusItem(), (QGraphicsItem *)scope3); |
| QCOMPARE(scope2->focusItem(), (QGraphicsItem *)scope3); |
| QCOMPARE(scope3->focusItem(), (QGraphicsItem *)scope3); |
| QCOMPARE(scope1->focusScopeItem(), (QGraphicsItem *)scope2); |
| QCOMPARE(scope2->focusScopeItem(), (QGraphicsItem *)scope3); |
| QCOMPARE(scope3->focusScopeItem(), nullptr); |
| |
| QVERIFY(scope3->hasFocus()); |
| |
| scope3->hide(); |
| QVERIFY(scope2->hasFocus()); |
| scope2->hide(); |
| QVERIFY(scope1->hasFocus()); |
| scope2->show(); |
| QVERIFY(scope2->hasFocus()); |
| scope3->show(); |
| QVERIFY(scope3->hasFocus()); |
| scope1->hide(); |
| QVERIFY(!scope3->hasFocus()); |
| scope1->show(); |
| QVERIFY(scope3->hasFocus()); |
| scope3->clearFocus(); |
| QVERIFY(scope2->hasFocus()); |
| scope2->clearFocus(); |
| QVERIFY(scope1->hasFocus()); |
| scope2->hide(); |
| scope2->show(); |
| QVERIFY(!scope2->hasFocus()); |
| QVERIFY(scope1->hasFocus()); |
| scope2->setFocus(); |
| QVERIFY(scope2->hasFocus()); |
| scope3->setFocus(); |
| QVERIFY(scope3->hasFocus()); |
| |
| // clearFocus() on a focus scope will remove focus from its children. |
| scope1->clearFocus(); |
| QVERIFY(!scope1->hasFocus()); |
| QVERIFY(!scope2->hasFocus()); |
| QVERIFY(!scope3->hasFocus()); |
| |
| scope1->setFocus(); |
| QVERIFY(!scope1->hasFocus()); |
| QVERIFY(!scope2->hasFocus()); |
| QVERIFY(scope3->hasFocus()); |
| |
| scope2->clearFocus(); |
| QVERIFY(scope1->hasFocus()); |
| QVERIFY(!scope2->hasFocus()); |
| QVERIFY(!scope3->hasFocus()); |
| |
| scope2->setFocus(); |
| QVERIFY(!scope1->hasFocus()); |
| QVERIFY(!scope2->hasFocus()); |
| QVERIFY(scope3->hasFocus()); |
| |
| // Focus cleared while a parent doesn't have focus remains cleared |
| // when the parent regains focus. |
| scope1->clearFocus(); |
| scope3->clearFocus(); |
| QVERIFY(!scope1->hasFocus()); |
| QVERIFY(!scope2->hasFocus()); |
| QVERIFY(!scope3->hasFocus()); |
| |
| scope1->setFocus(); |
| QVERIFY(!scope1->hasFocus()); |
| QVERIFY(scope2->hasFocus()); |
| QVERIFY(!scope3->hasFocus()); |
| |
| scope3->setFocus(); |
| QVERIFY(!scope1->hasFocus()); |
| QVERIFY(!scope2->hasFocus()); |
| QVERIFY(scope3->hasFocus()); |
| |
| QGraphicsRectItem *rect4 = new QGraphicsRectItem; |
| rect4->setData(0, "rect4"); |
| rect4->setParentItem(scope3); |
| |
| QGraphicsRectItem *rect5 = new QGraphicsRectItem; |
| rect5->setData(0, "rect5"); |
| rect5->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsFocusScope); |
| rect5->setFocus(); |
| rect5->setParentItem(rect4); |
| QCOMPARE(scope3->focusScopeItem(), (QGraphicsItem *)rect5); |
| QVERIFY(rect5->hasFocus()); |
| |
| rect4->setParentItem(0); |
| QVERIFY(rect5->hasFocus()); |
| QCOMPARE(scope3->focusScopeItem(), nullptr); |
| QCOMPARE(scope3->focusItem(), nullptr); |
| QVERIFY(!scope3->hasFocus()); |
| |
| QGraphicsRectItem *rectA = new QGraphicsRectItem; |
| QGraphicsRectItem *scopeA = new QGraphicsRectItem(rectA); |
| scopeA->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsFocusScope); |
| scopeA->setFocus(); |
| QGraphicsRectItem *scopeB = new QGraphicsRectItem(scopeA); |
| scopeB->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsFocusScope); |
| scopeB->setFocus(); |
| |
| scene.addItem(rectA); |
| QVERIFY(rect5->hasFocus()); |
| QVERIFY(!scopeB->hasFocus()); |
| |
| scopeA->setFocus(); |
| QVERIFY(scopeB->hasFocus()); |
| QCOMPARE(scopeB->focusItem(), (QGraphicsItem *)scopeB); |
| } |
| |
| void tst_QGraphicsItem::focusScope2() |
| { |
| QGraphicsRectItem *child1 = new QGraphicsRectItem; |
| child1->setFlags(QGraphicsItem::ItemIsFocusable); |
| child1->setFocus(); |
| QCOMPARE(child1->focusItem(), (QGraphicsItem *)child1); |
| |
| QGraphicsRectItem *child2 = new QGraphicsRectItem; |
| child2->setFlags(QGraphicsItem::ItemIsFocusable); |
| |
| QGraphicsRectItem *rootFocusScope = new QGraphicsRectItem; |
| rootFocusScope->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsFocusScope); |
| rootFocusScope->setFocus(); |
| QCOMPARE(rootFocusScope->focusItem(), (QGraphicsItem *)rootFocusScope); |
| |
| child1->setParentItem(rootFocusScope); |
| child2->setParentItem(rootFocusScope); |
| |
| QCOMPARE(rootFocusScope->focusScopeItem(), (QGraphicsItem *)child1); |
| QCOMPARE(rootFocusScope->focusItem(), (QGraphicsItem *)child1); |
| |
| QGraphicsRectItem *siblingChild1 = new QGraphicsRectItem; |
| siblingChild1->setFlags(QGraphicsItem::ItemIsFocusable); |
| siblingChild1->setFocus(); |
| |
| QGraphicsRectItem *siblingChild2 = new QGraphicsRectItem; |
| siblingChild2->setFlags(QGraphicsItem::ItemIsFocusable); |
| |
| QGraphicsRectItem *siblingFocusScope = new QGraphicsRectItem; |
| siblingFocusScope->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsFocusScope); |
| |
| siblingChild1->setParentItem(siblingFocusScope); |
| siblingChild2->setParentItem(siblingFocusScope); |
| |
| QCOMPARE(siblingFocusScope->focusScopeItem(), (QGraphicsItem *)siblingChild1); |
| QCOMPARE(siblingFocusScope->focusItem(), nullptr); |
| |
| QGraphicsItem *root = new QGraphicsRectItem; |
| rootFocusScope->setParentItem(root); |
| siblingFocusScope->setParentItem(root); |
| |
| QCOMPARE(root->focusItem(), (QGraphicsItem *)child1); |
| |
| QGraphicsScene scene; |
| scene.addItem(root); |
| |
| QEvent activate(QEvent::WindowActivate); |
| qApp->sendEvent(&scene, &activate); |
| scene.setFocus(); |
| |
| QCOMPARE(scene.focusItem(), (QGraphicsItem *)child1); |
| |
| // You cannot set focus on a descendant of a focus scope directly; |
| // this will only change the scope's focus scope item pointer. If |
| // you want to give true input focus, you must set it directly on |
| // the scope itself |
| siblingChild2->setFocus(); |
| QVERIFY(!siblingChild2->hasFocus()); |
| QVERIFY(!siblingChild2->focusItem()); |
| QCOMPARE(siblingFocusScope->focusScopeItem(), (QGraphicsItem *)siblingChild2); |
| QCOMPARE(siblingFocusScope->focusItem(), nullptr); |
| |
| // Set focus on the scope; focus is forwarded to the focus scope item. |
| siblingFocusScope->setFocus(); |
| QVERIFY(siblingChild2->hasFocus()); |
| QVERIFY(siblingChild2->focusItem()); |
| QCOMPARE(siblingFocusScope->focusScopeItem(), (QGraphicsItem *)siblingChild2); |
| QCOMPARE(siblingFocusScope->focusItem(), (QGraphicsItem *)siblingChild2); |
| } |
| |
| class FocusScopeItemPrivate; |
| class FocusScopeItem : public QGraphicsItem |
| { |
| Q_DECLARE_PRIVATE(FocusScopeItem) |
| public: |
| FocusScopeItem(QGraphicsItem *parent = 0); |
| QRectF boundingRect() const { return QRectF(); } |
| void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *) { } |
| |
| int focusScopeChanged; |
| FocusScopeItemPrivate *d_ptr; |
| }; |
| |
| class FocusScopeItemPrivate : QGraphicsItemPrivate |
| { |
| Q_DECLARE_PUBLIC(FocusScopeItem) |
| public: |
| void focusScopeItemChange(bool) |
| { ++q_func()->focusScopeChanged; } |
| }; |
| |
| FocusScopeItem::FocusScopeItem(QGraphicsItem *parent) |
| : QGraphicsItem(*new FocusScopeItemPrivate, parent), focusScopeChanged(0) |
| { |
| setFlag(ItemIsFocusable); |
| } |
| |
| void tst_QGraphicsItem::focusScopeItemChangedWhileScopeDoesntHaveFocus() |
| { |
| QGraphicsRectItem rect; |
| rect.setFlags(QGraphicsItem::ItemIsFocusScope | QGraphicsItem::ItemIsFocusable); |
| |
| FocusScopeItem *child1 = new FocusScopeItem(&rect); |
| FocusScopeItem *child2 = new FocusScopeItem(&rect); |
| |
| QCOMPARE(rect.focusScopeItem(), nullptr); |
| QCOMPARE(child1->focusScopeChanged, 0); |
| QCOMPARE(child2->focusScopeChanged, 0); |
| child1->setFocus(); |
| QCOMPARE(rect.focusScopeItem(), (QGraphicsItem *)child1); |
| QCOMPARE(child1->focusScopeChanged, 1); |
| QCOMPARE(child2->focusScopeChanged, 0); |
| child2->setFocus(); |
| QCOMPARE(rect.focusScopeItem(), (QGraphicsItem *)child2); |
| QCOMPARE(child1->focusScopeChanged, 2); |
| QCOMPARE(child2->focusScopeChanged, 1); |
| child1->setFocus(); |
| QCOMPARE(rect.focusScopeItem(), (QGraphicsItem *)child1); |
| QCOMPARE(child1->focusScopeChanged, 3); |
| QCOMPARE(child2->focusScopeChanged, 2); |
| child1->clearFocus(); |
| QCOMPARE(rect.focusScopeItem(), nullptr); |
| QCOMPARE(child1->focusScopeChanged, 4); |
| QCOMPARE(child2->focusScopeChanged, 2); |
| } |
| |
| void tst_QGraphicsItem::stackBefore() |
| { |
| QGraphicsRectItem parent; |
| QGraphicsRectItem *child1 = new QGraphicsRectItem(QRectF(0, 0, 5, 5), &parent); |
| QGraphicsRectItem *child2 = new QGraphicsRectItem(QRectF(0, 0, 5, 5), &parent); |
| QGraphicsRectItem *child3 = new QGraphicsRectItem(QRectF(0, 0, 5, 5), &parent); |
| QGraphicsRectItem *child4 = new QGraphicsRectItem(QRectF(0, 0, 5, 5), &parent); |
| QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child1 << child2 << child3 << child4)); |
| child1->setData(0, "child1"); |
| child2->setData(0, "child2"); |
| child3->setData(0, "child3"); |
| child4->setData(0, "child4"); |
| |
| // Remove and append |
| child2->setParentItem(0); |
| child2->setParentItem(&parent); |
| QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child1 << child3 << child4 << child2)); |
| |
| // Move child2 before child1 |
| child2->stackBefore(child1); // 2134 |
| QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child2 << child1 << child3 << child4)); |
| child2->stackBefore(child2); // 2134 |
| QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child2 << child1 << child3 << child4)); |
| child1->setZValue(1); // 2341 |
| QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child2 << child3 << child4 << child1)); |
| child1->stackBefore(child2); // 2341 |
| QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child2 << child3 << child4 << child1)); |
| child1->setZValue(0); // 1234 |
| QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child1 << child2 << child3 << child4)); |
| child4->stackBefore(child1); // 4123 |
| QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child4 << child1 << child2 << child3)); |
| child4->setZValue(1); // 1234 (4123) |
| QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child1 << child2 << child3 << child4)); |
| child3->stackBefore(child1); // 3124 (4312) |
| QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child3 << child1 << child2 << child4)); |
| child4->setZValue(0); // 4312 |
| QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child4 << child3 << child1 << child2)); |
| |
| // Make them all toplevels |
| child1->setParentItem(0); |
| child2->setParentItem(0); |
| child3->setParentItem(0); |
| child4->setParentItem(0); |
| |
| QGraphicsScene scene; |
| scene.addItem(child1); |
| scene.addItem(child2); |
| scene.addItem(child3); |
| scene.addItem(child4); |
| QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), |
| (QList<QGraphicsItem *>() << child1 << child2 << child3 << child4)); |
| |
| // Remove and append |
| scene.removeItem(child2); |
| scene.addItem(child2); |
| QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child1 << child3 << child4 << child2)); |
| |
| // Move child2 before child1 |
| child2->stackBefore(child1); // 2134 |
| QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child2 << child1 << child3 << child4)); |
| child2->stackBefore(child2); // 2134 |
| QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child2 << child1 << child3 << child4)); |
| child1->setZValue(1); // 2341 |
| QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child2 << child3 << child4 << child1)); |
| child1->stackBefore(child2); // 2341 |
| QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child2 << child3 << child4 << child1)); |
| child1->setZValue(0); // 1234 |
| QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child1 << child2 << child3 << child4)); |
| child4->stackBefore(child1); // 4123 |
| QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child4 << child1 << child2 << child3)); |
| child4->setZValue(1); // 1234 (4123) |
| QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child1 << child2 << child3 << child4)); |
| child3->stackBefore(child1); // 3124 (4312) |
| QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child3 << child1 << child2 << child4)); |
| child4->setZValue(0); // 4312 |
| QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child4 << child3 << child1 << child2)); |
| } |
| |
| void tst_QGraphicsItem::QTBUG_4233_updateCachedWithSceneRect() |
| { |
| EventTester *tester = new EventTester; |
| tester->setCacheMode(QGraphicsItem::ItemCoordinateCache); |
| |
| QGraphicsScene scene; |
| scene.addItem(tester); |
| scene.setSceneRect(-100, -100, 200, 200); // contains the tester item |
| |
| QGraphicsView view(&scene); |
| view.show(); |
| QApplication::setActiveWindow(&view); |
| QVERIFY(QTest::qWaitForWindowExposed(&view)); |
| QVERIFY(QTest::qWaitForWindowActive(&view)); |
| QCOMPARE(QApplication::activeWindow(), (QWidget *)&view); |
| |
| QTRY_COMPARE(tester->repaints, 1); |
| |
| scene.update(); // triggers "updateAll" optimization |
| qApp->processEvents(); |
| qApp->processEvents(); // in 4.6 only one processEvents is necessary |
| |
| QCOMPARE(tester->repaints, 1); |
| |
| scene.update(); // triggers "updateAll" optimization |
| tester->update(); |
| qApp->processEvents(); |
| qApp->processEvents(); // in 4.6 only one processEvents is necessary |
| |
| QCOMPARE(tester->repaints, 2); |
| } |
| |
| void tst_QGraphicsItem::sceneModality() |
| { |
| // 1) Test mouse events (delivery/propagation/redirection) |
| // 2) Test hover events (incl. leave on block, enter on unblock) |
| // 3) Test cursor stuff (incl. unset on block, set on unblock) |
| // 4) Test clickfocus |
| // 5) Test grab/ungrab events (possibly ungrab on block, regrab on unblock) |
| // 6) ### modality for non-panels is unsupported for now |
| QGraphicsScene scene; |
| |
| QGraphicsRectItem *bottomItem = scene.addRect(-150, -100, 300, 200); |
| bottomItem->setFlag(QGraphicsItem::ItemIsFocusable); |
| bottomItem->setBrush(Qt::yellow); |
| |
| QGraphicsRectItem *leftParent = scene.addRect(-50, -50, 100, 100); |
| leftParent->setFlag(QGraphicsItem::ItemIsPanel); |
| leftParent->setBrush(Qt::blue); |
| |
| QGraphicsRectItem *leftChild = scene.addRect(-25, -25, 50, 50); |
| leftChild->setFlag(QGraphicsItem::ItemIsPanel); |
| leftChild->setBrush(Qt::green); |
| leftChild->setParentItem(leftParent); |
| |
| QGraphicsRectItem *rightParent = scene.addRect(-50, -50, 100, 100); |
| rightParent->setFlag(QGraphicsItem::ItemIsPanel); |
| rightParent->setBrush(Qt::red); |
| QGraphicsRectItem *rightChild = scene.addRect(-25, -25, 50, 50); |
| rightChild->setFlag(QGraphicsItem::ItemIsPanel); |
| rightChild->setBrush(Qt::gray); |
| rightChild->setParentItem(rightParent); |
| |
| leftParent->setPos(-75, 0); |
| rightParent->setPos(75, 0); |
| |
| bottomItem->setData(0, "bottomItem"); |
| leftParent->setData(0, "leftParent"); |
| leftChild->setData(0, "leftChild"); |
| rightParent->setData(0, "rightParent"); |
| rightChild->setData(0, "rightChild"); |
| |
| scene.setSceneRect(scene.itemsBoundingRect().adjusted(-50, -50, 50, 50)); |
| |
| EventSpy2 leftParentSpy(&scene, leftParent); |
| EventSpy2 leftChildSpy(&scene, leftChild); |
| EventSpy2 rightParentSpy(&scene, rightParent); |
| EventSpy2 rightChildSpy(&scene, rightChild); |
| EventSpy2 bottomItemSpy(&scene, bottomItem); |
| |
| // Scene modality, also test multiple scene modal items |
| leftChild->setPanelModality(QGraphicsItem::SceneModal); |
| QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0); |
| QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1); |
| QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 1); |
| QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 1); |
| QCOMPARE(bottomItemSpy.counts[QEvent::WindowBlocked], 0); // not a panel |
| |
| // Click inside left child |
| sendMouseClick(&scene, leftChild->scenePos(), Qt::LeftButton); |
| QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 1); |
| QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMouseRelease], 0); // no grab |
| QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked |
| QCOMPARE(rightParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked |
| QCOMPARE(rightChildSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked |
| QCOMPARE(bottomItemSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked |
| |
| // Click on left parent, event goes to modal child |
| sendMouseClick(&scene, leftParent->sceneBoundingRect().topLeft() + QPointF(5, 5), Qt::LeftButton); |
| QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 2); |
| QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMouseRelease], 0); // no grab |
| QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked |
| QCOMPARE(rightParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked |
| QCOMPARE(rightChildSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked |
| QCOMPARE(bottomItemSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked |
| |
| // Click on all other items and outside the items |
| sendMouseClick(&scene, rightParent->sceneBoundingRect().topLeft() + QPointF(5, 5), Qt::LeftButton); |
| QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 3); |
| sendMouseClick(&scene, rightChild->scenePos(), Qt::LeftButton); |
| QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 4); |
| sendMouseClick(&scene, bottomItem->scenePos(), Qt::LeftButton); |
| QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 5); |
| sendMouseClick(&scene, QPointF(10000, 10000), Qt::LeftButton); |
| QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 6); |
| QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMouseRelease], 0); // no grab |
| QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked |
| QCOMPARE(rightParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked |
| QCOMPARE(rightChildSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked |
| QCOMPARE(bottomItemSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked |
| |
| leftChildSpy.counts.clear(); |
| rightChildSpy.counts.clear(); |
| leftParentSpy.counts.clear(); |
| rightParentSpy.counts.clear(); |
| bottomItemSpy.counts.clear(); |
| |
| leftChild->setPanelModality(QGraphicsItem::NonModal); |
| QCOMPARE(leftChildSpy.counts[QEvent::WindowUnblocked], 0); |
| QCOMPARE(rightChildSpy.counts[QEvent::WindowUnblocked], 1); |
| QCOMPARE(leftParentSpy.counts[QEvent::WindowUnblocked], 1); |
| QCOMPARE(rightParentSpy.counts[QEvent::WindowUnblocked], 1); |
| QCOMPARE(bottomItemSpy.counts[QEvent::WindowUnblocked], 0); |
| |
| // Left parent enters scene modality. |
| leftParent->setPanelModality(QGraphicsItem::SceneModal); |
| QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0); |
| QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 1); |
| QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 0); |
| QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 1); |
| QCOMPARE(bottomItemSpy.counts[QEvent::WindowBlocked], 0); |
| |
| // Click inside left child. |
| sendMouseClick(&scene, leftChild->scenePos(), Qt::LeftButton); |
| QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 1); |
| QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMouseRelease], 0); |
| QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // panel stops propagation |
| QCOMPARE(rightParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); |
| QCOMPARE(rightChildSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked |
| QCOMPARE(bottomItemSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked |
| |
| // Click on left parent. |
| sendMouseClick(&scene, leftParent->sceneBoundingRect().topLeft() + QPointF(5, 5), Qt::LeftButton); |
| QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 1); |
| QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMouseRelease], 0); |
| QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 1); |
| QCOMPARE(rightParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); |
| QCOMPARE(rightChildSpy.counts[QEvent::GraphicsSceneMousePress], 0); |
| QCOMPARE(bottomItemSpy.counts[QEvent::GraphicsSceneMousePress], 0); |
| |
| // Click on all other items and outside the items |
| sendMouseClick(&scene, rightParent->sceneBoundingRect().topLeft() + QPointF(5, 5), Qt::LeftButton); |
| QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 2); |
| sendMouseClick(&scene, rightChild->scenePos(), Qt::LeftButton); |
| QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 3); |
| sendMouseClick(&scene, bottomItem->scenePos(), Qt::LeftButton); |
| QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 4); |
| sendMouseClick(&scene, QPointF(10000, 10000), Qt::LeftButton); |
| QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 5); |
| QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMouseRelease], 0); |
| QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 1); |
| QCOMPARE(rightParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); |
| QCOMPARE(rightChildSpy.counts[QEvent::GraphicsSceneMousePress], 0); |
| QCOMPARE(bottomItemSpy.counts[QEvent::GraphicsSceneMousePress], 0); |
| |
| leftChildSpy.counts.clear(); |
| rightChildSpy.counts.clear(); |
| leftParentSpy.counts.clear(); |
| rightParentSpy.counts.clear(); |
| bottomItemSpy.counts.clear(); |
| |
| // Now both left parent and child are scene modal. Left parent is blocked. |
| leftChild->setPanelModality(QGraphicsItem::SceneModal); |
| QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0); |
| QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 0); |
| QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1); |
| QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 0); |
| QCOMPARE(bottomItemSpy.counts[QEvent::WindowBlocked], 0); |
| |
| // Click inside left child |
| sendMouseClick(&scene, leftChild->scenePos(), Qt::LeftButton); |
| QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 1); |
| QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMouseRelease], 0); // no grab |
| QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked |
| QCOMPARE(rightParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked |
| QCOMPARE(rightChildSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked |
| QCOMPARE(bottomItemSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked |
| |
| // Click on left parent, event goes to modal child |
| sendMouseClick(&scene, leftParent->sceneBoundingRect().topLeft() + QPointF(5, 5), Qt::LeftButton); |
| QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 2); |
| QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMouseRelease], 0); // no grab |
| QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked |
| QCOMPARE(rightParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked |
| QCOMPARE(rightChildSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked |
| QCOMPARE(bottomItemSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked |
| |
| // Click on all other items and outside the items |
| sendMouseClick(&scene, rightParent->sceneBoundingRect().topLeft() + QPointF(5, 5), Qt::LeftButton); |
| QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 3); |
| sendMouseClick(&scene, rightChild->scenePos(), Qt::LeftButton); |
| QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 4); |
| sendMouseClick(&scene, bottomItem->scenePos(), Qt::LeftButton); |
| QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 5); |
| sendMouseClick(&scene, QPointF(10000, 10000), Qt::LeftButton); |
| QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 6); |
| QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMouseRelease], 0); // no grab |
| QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked |
| QCOMPARE(rightParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked |
| QCOMPARE(rightChildSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked |
| QCOMPARE(bottomItemSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked |
| |
| leftChildSpy.counts.clear(); |
| rightChildSpy.counts.clear(); |
| leftParentSpy.counts.clear(); |
| rightParentSpy.counts.clear(); |
| bottomItemSpy.counts.clear(); |
| |
| // Right child enters scene modality, only left child is blocked. |
| rightChild->setPanelModality(QGraphicsItem::SceneModal); |
| QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 1); |
| QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 0); |
| QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 0); |
| QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 0); |
| QCOMPARE(bottomItemSpy.counts[QEvent::WindowBlocked], 0); |
| } |
| |
| void tst_QGraphicsItem::panelModality() |
| { |
| // 1) Test mouse events (delivery/propagation/redirection) |
| // 2) Test hover events (incl. leave on block, enter on unblock) |
| // 3) Test cursor stuff (incl. unset on block, set on unblock) |
| // 4) Test clickfocus |
| // 5) Test grab/ungrab events (possibly ungrab on block, regrab on unblock) |
| // 6) ### modality for non-panels is unsupported for now |
| QGraphicsScene scene; |
| |
| QGraphicsRectItem *bottomItem = scene.addRect(-150, -100, 300, 200); |
| bottomItem->setFlag(QGraphicsItem::ItemIsFocusable); |
| bottomItem->setBrush(Qt::yellow); |
| |
| QGraphicsRectItem *leftParent = scene.addRect(-50, -50, 100, 100); |
| leftParent->setFlag(QGraphicsItem::ItemIsPanel); |
| leftParent->setBrush(Qt::blue); |
| |
| QGraphicsRectItem *leftChild = scene.addRect(-25, -25, 50, 50); |
| leftChild->setFlag(QGraphicsItem::ItemIsPanel); |
| leftChild->setBrush(Qt::green); |
| leftChild->setParentItem(leftParent); |
| |
| QGraphicsRectItem *rightParent = scene.addRect(-50, -50, 100, 100); |
| rightParent->setFlag(QGraphicsItem::ItemIsPanel); |
| rightParent->setBrush(Qt::red); |
| QGraphicsRectItem *rightChild = scene.addRect(-25, -25, 50, 50); |
| rightChild->setFlag(QGraphicsItem::ItemIsPanel); |
| rightChild->setBrush(Qt::gray); |
| rightChild->setParentItem(rightParent); |
| |
| leftParent->setPos(-75, 0); |
| rightParent->setPos(75, 0); |
| |
| bottomItem->setData(0, "bottomItem"); |
| leftParent->setData(0, "leftParent"); |
| leftChild->setData(0, "leftChild"); |
| rightParent->setData(0, "rightParent"); |
| rightChild->setData(0, "rightChild"); |
| |
| scene.setSceneRect(scene.itemsBoundingRect().adjusted(-50, -50, 50, 50)); |
| |
| EventSpy2 leftParentSpy(&scene, leftParent); |
| EventSpy2 leftChildSpy(&scene, leftChild); |
| EventSpy2 rightParentSpy(&scene, rightParent); |
| EventSpy2 rightChildSpy(&scene, rightChild); |
| EventSpy2 bottomItemSpy(&scene, bottomItem); |
| |
| // Left Child enters panel modality, only left parent is blocked. |
| leftChild->setPanelModality(QGraphicsItem::PanelModal); |
| QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0); |
| QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 0); |
| QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1); |
| QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 0); |
| QCOMPARE(bottomItemSpy.counts[QEvent::WindowBlocked], 0); |
| |
| leftChild->setPanelModality(QGraphicsItem::NonModal); |
| leftChildSpy.counts.clear(); |
| rightChildSpy.counts.clear(); |
| leftParentSpy.counts.clear(); |
| rightParentSpy.counts.clear(); |
| bottomItemSpy.counts.clear(); |
| |
| // Left parent enter panel modality, nothing is blocked. |
| leftParent->setPanelModality(QGraphicsItem::PanelModal); |
| QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0); |
| QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 0); |
| QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 0); |
| QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 0); |
| QCOMPARE(bottomItemSpy.counts[QEvent::WindowBlocked], 0); |
| |
| // Left child enters panel modality, left parent is blocked again. |
| leftChild->setPanelModality(QGraphicsItem::PanelModal); |
| QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0); |
| QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 0); |
| QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1); |
| QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 0); |
| QCOMPARE(bottomItemSpy.counts[QEvent::WindowBlocked], 0); |
| |
| leftChildSpy.counts.clear(); |
| rightChildSpy.counts.clear(); |
| leftParentSpy.counts.clear(); |
| rightParentSpy.counts.clear(); |
| bottomItemSpy.counts.clear(); |
| |
| leftChild->setPanelModality(QGraphicsItem::NonModal); |
| QCOMPARE(leftParentSpy.counts[QEvent::WindowUnblocked], 1); |
| leftParent->setPanelModality(QGraphicsItem::NonModal); |
| QCOMPARE(leftChildSpy.counts[QEvent::WindowUnblocked], 0); |
| QCOMPARE(rightChildSpy.counts[QEvent::WindowUnblocked], 0); |
| QCOMPARE(leftParentSpy.counts[QEvent::WindowUnblocked], 1); |
| QCOMPARE(rightParentSpy.counts[QEvent::WindowUnblocked], 0); |
| QCOMPARE(bottomItemSpy.counts[QEvent::WindowUnblocked], 0); |
| |
| leftChildSpy.counts.clear(); |
| rightChildSpy.counts.clear(); |
| leftParentSpy.counts.clear(); |
| rightParentSpy.counts.clear(); |
| bottomItemSpy.counts.clear(); |
| |
| // Left and right child enter panel modality, both parents are blocked. |
| rightChild->setPanelModality(QGraphicsItem::PanelModal); |
| QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 0); |
| QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 1); |
| leftChild->setPanelModality(QGraphicsItem::PanelModal); |
| QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1); |
| QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 1); |
| } |
| |
| void tst_QGraphicsItem::mixedModality() |
| { |
| // 1) Test mouse events (delivery/propagation/redirection) |
| // 2) Test hover events (incl. leave on block, enter on unblock) |
| // 3) Test cursor stuff (incl. unset on block, set on unblock) |
| // 4) Test clickfocus |
| // 5) Test grab/ungrab events (possibly ungrab on block, regrab on unblock) |
| // 6) ### modality for non-panels is unsupported for now |
| QGraphicsScene scene; |
| |
| QGraphicsRectItem *bottomItem = scene.addRect(-150, -100, 300, 200); |
| bottomItem->setFlag(QGraphicsItem::ItemIsFocusable); |
| bottomItem->setBrush(Qt::yellow); |
| |
| QGraphicsRectItem *leftParent = scene.addRect(-50, -50, 100, 100); |
| leftParent->setFlag(QGraphicsItem::ItemIsPanel); |
| leftParent->setBrush(Qt::blue); |
| |
| QGraphicsRectItem *leftChild = scene.addRect(-25, -25, 50, 50); |
| leftChild->setFlag(QGraphicsItem::ItemIsPanel); |
| leftChild->setBrush(Qt::green); |
| leftChild->setParentItem(leftParent); |
| |
| QGraphicsRectItem *rightParent = scene.addRect(-50, -50, 100, 100); |
| rightParent->setFlag(QGraphicsItem::ItemIsPanel); |
| rightParent->setBrush(Qt::red); |
| QGraphicsRectItem *rightChild = scene.addRect(-25, -25, 50, 50); |
| rightChild->setFlag(QGraphicsItem::ItemIsPanel); |
| rightChild->setBrush(Qt::gray); |
| rightChild->setParentItem(rightParent); |
| |
| leftParent->setPos(-75, 0); |
| rightParent->setPos(75, 0); |
| |
| bottomItem->setData(0, "bottomItem"); |
| leftParent->setData(0, "leftParent"); |
| leftChild->setData(0, "leftChild"); |
| rightParent->setData(0, "rightParent"); |
| rightChild->setData(0, "rightChild"); |
| |
| scene.setSceneRect(scene.itemsBoundingRect().adjusted(-50, -50, 50, 50)); |
| |
| EventSpy2 leftParentSpy(&scene, leftParent); |
| EventSpy2 leftChildSpy(&scene, leftChild); |
| EventSpy2 rightParentSpy(&scene, rightParent); |
| EventSpy2 rightChildSpy(&scene, rightChild); |
| EventSpy2 bottomItemSpy(&scene, bottomItem); |
| |
| // Left Child enters panel modality, only left parent is blocked. |
| leftChild->setPanelModality(QGraphicsItem::PanelModal); |
| QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0); |
| QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 0); |
| QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1); |
| QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 0); |
| |
| // Left parent enters scene modality, which blocks everything except the child. |
| leftParent->setPanelModality(QGraphicsItem::SceneModal); |
| QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0); |
| QCOMPARE(leftChildSpy.counts[QEvent::WindowUnblocked], 0); |
| QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 1); |
| QCOMPARE(rightChildSpy.counts[QEvent::WindowUnblocked], 0); |
| QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1); |
| QCOMPARE(leftParentSpy.counts[QEvent::WindowUnblocked], 0); |
| QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 1); |
| QCOMPARE(rightParentSpy.counts[QEvent::WindowUnblocked], 0); |
| |
| // Right child enters panel modality (changes nothing). |
| rightChild->setPanelModality(QGraphicsItem::PanelModal); |
| QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0); |
| QCOMPARE(leftChildSpy.counts[QEvent::WindowUnblocked], 0); |
| QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 1); |
| QCOMPARE(rightChildSpy.counts[QEvent::WindowUnblocked], 0); |
| QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1); |
| QCOMPARE(leftParentSpy.counts[QEvent::WindowUnblocked], 0); |
| QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 1); |
| QCOMPARE(rightParentSpy.counts[QEvent::WindowUnblocked], 0); |
| |
| // Left parent leaves modality. Right child is unblocked. |
| leftParent->setPanelModality(QGraphicsItem::NonModal); |
| QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0); |
| QCOMPARE(leftChildSpy.counts[QEvent::WindowUnblocked], 0); |
| QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 1); |
| QCOMPARE(rightChildSpy.counts[QEvent::WindowUnblocked], 1); |
| QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1); |
| QCOMPARE(leftParentSpy.counts[QEvent::WindowUnblocked], 0); |
| QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 1); |
| QCOMPARE(rightParentSpy.counts[QEvent::WindowUnblocked], 0); |
| |
| // Right child "upgrades" its modality to scene modal. Left child is blocked. |
| // Right parent is unaffected. |
| rightChild->setPanelModality(QGraphicsItem::SceneModal); |
| QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 1); |
| QCOMPARE(leftChildSpy.counts[QEvent::WindowUnblocked], 0); |
| QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 1); |
| QCOMPARE(rightChildSpy.counts[QEvent::WindowUnblocked], 1); |
| QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1); |
| QCOMPARE(leftParentSpy.counts[QEvent::WindowUnblocked], 0); |
| QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 1); |
| QCOMPARE(rightParentSpy.counts[QEvent::WindowUnblocked], 0); |
| |
| // "downgrade" right child back to panel modal, left child is unblocked |
| rightChild->setPanelModality(QGraphicsItem::PanelModal); |
| QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 1); |
| QCOMPARE(leftChildSpy.counts[QEvent::WindowUnblocked], 1); |
| QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 1); |
| QCOMPARE(rightChildSpy.counts[QEvent::WindowUnblocked], 1); |
| QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1); |
| QCOMPARE(leftParentSpy.counts[QEvent::WindowUnblocked], 0); |
| QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 1); |
| QCOMPARE(rightParentSpy.counts[QEvent::WindowUnblocked], 0); |
| } |
| |
| void tst_QGraphicsItem::modality_hover() |
| { |
| QGraphicsScene scene; |
| QGraphicsRectItem *rect1 = scene.addRect(-50, -50, 100, 100); |
| rect1->setFlag(QGraphicsItem::ItemIsPanel); |
| rect1->setAcceptHoverEvents(true); |
| rect1->setData(0, "rect1"); |
| |
| QGraphicsRectItem *rect2 = scene.addRect(-50, -50, 100, 100); |
| rect2->setParentItem(rect1); |
| rect2->setFlag(QGraphicsItem::ItemIsPanel); |
| rect2->setAcceptHoverEvents(true); |
| rect2->setPos(50, 50); |
| rect2->setPanelModality(QGraphicsItem::SceneModal); |
| rect2->setData(0, "rect2"); |
| |
| EventSpy2 rect1Spy(&scene, rect1); |
| EventSpy2 rect2Spy(&scene, rect2); |
| |
| sendMouseMove(&scene, QPointF(-25, -25)); |
| |
| QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverEnter], 0); |
| QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverMove], 0); |
| QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverLeave], 0); |
| |
| sendMouseMove(&scene, QPointF(75, 75)); |
| |
| QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverEnter], 0); |
| QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverMove], 0); |
| QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverLeave], 0); |
| QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverEnter], 1); |
| QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverMove], 1); |
| QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverLeave], 0); |
| |
| sendMouseMove(&scene, QPointF(-25, -25)); |
| |
| QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverLeave], 1); |
| QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverEnter], 0); |
| QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverMove], 0); |
| QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverLeave], 0); |
| |
| rect2->setPanelModality(QGraphicsItem::NonModal); |
| |
| QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverEnter], 1); |
| QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverMove], 1); |
| |
| sendMouseMove(&scene, QPointF(75, 75)); |
| |
| QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverEnter], 2); |
| QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverMove], 2); |
| |
| rect2->setPanelModality(QGraphicsItem::SceneModal); |
| |
| QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverLeave], 1); |
| QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverEnter], 2); |
| // changing modality causes a spurious GraphicsSceneHoveMove, even though the mouse didn't |
| // actually move |
| QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverMove], 3); |
| |
| sendMouseMove(&scene, QPointF(-25, -25)); |
| |
| QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverLeave], 2); |
| QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverEnter], 1); |
| QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverMove], 1); |
| QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverLeave], 1); |
| |
| rect2->setPanelModality(QGraphicsItem::PanelModal); |
| |
| QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverEnter], 1); |
| QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverMove], 1); |
| QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverLeave], 1); |
| QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverEnter], 2); |
| QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverMove], 3); |
| QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverLeave], 2); |
| |
| rect2->setPanelModality(QGraphicsItem::NonModal); |
| |
| QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverEnter], 2); |
| QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverMove], 2); |
| QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverEnter], 2); |
| QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverMove], 3); |
| QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverLeave], 2); |
| } |
| |
| void tst_QGraphicsItem::modality_mouseGrabber() |
| { |
| QGraphicsScene scene; |
| QGraphicsRectItem *rect1 = scene.addRect(-50, -50, 100, 100); |
| rect1->setFlag(QGraphicsItem::ItemIsPanel); |
| rect1->setFlag(QGraphicsItem::ItemIsMovable); |
| rect1->setData(0, "rect1"); |
| |
| QGraphicsRectItem *rect2 = scene.addRect(-50, -50, 100, 100); |
| rect2->setParentItem(rect1); |
| rect2->setFlag(QGraphicsItem::ItemIsPanel); |
| rect2->setFlag(QGraphicsItem::ItemIsMovable); |
| rect2->setPos(50, 50); |
| rect2->setData(0, "rect2"); |
| |
| EventSpy2 rect1Spy(&scene, rect1); |
| EventSpy2 rect2Spy(&scene, rect2); |
| |
| { |
| // pressing mouse on rect1 starts implicit grab |
| sendMousePress(&scene, QPoint(-25, -25)); |
| QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 1); |
| QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMousePress], 1); |
| QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 0); |
| QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0); |
| QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0); |
| QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) rect1); |
| |
| // grab lost when rect1 is modally shadowed |
| rect2->setPanelModality(QGraphicsItem::SceneModal); |
| QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 1); |
| QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 1); |
| QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0); |
| QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0); |
| QCOMPARE(scene.mouseGrabberItem(), nullptr); |
| |
| // releasing goes nowhere |
| sendMouseRelease(&scene, QPoint(-25, -25)); |
| QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 1); |
| QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMouseRelease], 0); |
| QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 1); |
| QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0); |
| QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneMouseRelease], 0); |
| QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0); |
| QCOMPARE(scene.mouseGrabberItem(), nullptr); |
| |
| // pressing mouse on rect1 starts implicit grab on rect2 (since it is modal) |
| sendMouseClick(&scene, QPoint(-25, -25)); |
| QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 1); |
| QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMousePress], 1); |
| QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMouseRelease], 0); |
| QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 1); |
| QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1); |
| QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneMousePress], 1); |
| QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneMouseRelease], 1); |
| QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1); |
| |
| rect2->setPanelModality(QGraphicsItem::NonModal); |
| |
| // pressing mouse on rect1 starts implicit grab |
| sendMousePress(&scene, QPoint(-25, -25)); |
| QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 2); |
| QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMousePress], 2); |
| QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 1); |
| QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1); |
| QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1); |
| QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) rect1); |
| |
| // grab lost to rect2 when rect1 is modally shadowed |
| rect2->setPanelModality(QGraphicsItem::SceneModal); |
| QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 2); |
| QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 2); |
| QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1); |
| QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1); |
| QCOMPARE(scene.mouseGrabberItem(), nullptr); |
| |
| // rect1 does *not* re-grab when rect2 is no longer modal |
| rect2->setPanelModality(QGraphicsItem::NonModal); |
| QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 2); |
| QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 2); |
| QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1); |
| QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1); |
| QCOMPARE(scene.mouseGrabberItem(), nullptr); |
| |
| // release goes nowhere |
| sendMouseRelease(&scene, QPoint(-25, -25)); |
| QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 2); |
| QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMouseRelease], 0); |
| QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 2); |
| QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1); |
| QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1); |
| QCOMPARE(scene.mouseGrabberItem(), nullptr); |
| } |
| { |
| // repeat the test using PanelModal |
| rect2->setPanelModality(QGraphicsItem::NonModal); |
| rect1Spy.counts.clear(); |
| rect2Spy.counts.clear(); |
| |
| // pressing mouse on rect1 starts implicit grab |
| sendMousePress(&scene, QPoint(-25, -25)); |
| QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 1); |
| QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMousePress], 1); |
| QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 0); |
| QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0); |
| QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0); |
| QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) rect1); |
| |
| // grab lost when rect1 is modally shadowed |
| rect2->setPanelModality(QGraphicsItem::PanelModal); |
| QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 1); |
| QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 1); |
| QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0); |
| QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0); |
| QCOMPARE(scene.mouseGrabberItem(), nullptr); |
| |
| // releasing goes nowhere |
| sendMouseRelease(&scene, QPoint(-25, -25)); |
| QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 1); |
| QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMouseRelease], 0); |
| QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 1); |
| QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0); |
| QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneMouseRelease], 0); |
| QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0); |
| QCOMPARE(scene.mouseGrabberItem(), nullptr); |
| |
| // pressing mouse on rect1 starts implicit grab on rect2 (since it is modal) |
| sendMouseClick(&scene, QPoint(-25, -25)); |
| QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 1); |
| QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMousePress], 1); |
| QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMouseRelease], 0); |
| QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 1); |
| QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1); |
| QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneMousePress], 1); |
| QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneMouseRelease], 1); |
| QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1); |
| |
| rect2->setPanelModality(QGraphicsItem::NonModal); |
| |
| // pressing mouse on rect1 starts implicit grab |
| sendMousePress(&scene, QPoint(-25, -25)); |
| QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 2); |
| QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMousePress], 2); |
| QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 1); |
| QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1); |
| QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1); |
| QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) rect1); |
| |
| // grab lost to rect2 when rect1 is modally shadowed |
| rect2->setPanelModality(QGraphicsItem::PanelModal); |
| QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 2); |
| QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 2); |
| QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1); |
| QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1); |
| QCOMPARE(scene.mouseGrabberItem(), nullptr); |
| |
| // rect1 does *not* re-grab when rect2 is no longer modal |
| rect2->setPanelModality(QGraphicsItem::NonModal); |
| QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 2); |
| QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 2); |
| QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1); |
| QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1); |
| QCOMPARE(scene.mouseGrabberItem(), nullptr); |
| |
| // release goes nowhere |
| sendMouseRelease(&scene, QPoint(-25, -25)); |
| QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 2); |
| QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMouseRelease], 0); |
| QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 2); |
| QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1); |
| QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1); |
| QCOMPARE(scene.mouseGrabberItem(), nullptr); |
| } |
| |
| { |
| // repeat the PanelModal tests, but this time the mouse events will be on a non-modal item, |
| // meaning normal grabbing should work |
| rect2->setPanelModality(QGraphicsItem::NonModal); |
| rect1Spy.counts.clear(); |
| rect2Spy.counts.clear(); |
| |
| QGraphicsRectItem *rect3 = scene.addRect(-50, -50, 100, 100); |
| rect3->setFlag(QGraphicsItem::ItemIsPanel); |
| rect3->setFlag(QGraphicsItem::ItemIsMovable); |
| rect3->setPos(150, 50); |
| rect3->setData(0, "rect3"); |
| |
| EventSpy2 rect3Spy(&scene, rect3); |
| |
| // pressing mouse on rect3 starts implicit grab |
| sendMousePress(&scene, QPoint(150, 50)); |
| QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 0); |
| QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 0); |
| QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0); |
| QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0); |
| QCOMPARE(rect3Spy.counts[QEvent::GrabMouse], 1); |
| QCOMPARE(rect3Spy.counts[QEvent::GraphicsSceneMousePress], 1); |
| QCOMPARE(rect3Spy.counts[QEvent::UngrabMouse], 0); |
| QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) rect3); |
| |
| // grab is *not* lost when rect1 is modally shadowed by rect2 |
| rect2->setPanelModality(QGraphicsItem::PanelModal); |
| QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 0); |
| QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 0); |
| QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0); |
| QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0); |
| QCOMPARE(rect3Spy.counts[QEvent::GrabMouse], 1); |
| QCOMPARE(rect3Spy.counts[QEvent::UngrabMouse], 0); |
| QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) rect3); |
| |
| // releasing goes to rect3 |
| sendMouseRelease(&scene, QPoint(150, 50)); |
| QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 0); |
| QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 0); |
| QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0); |
| QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0); |
| QCOMPARE(rect3Spy.counts[QEvent::GrabMouse], 1); |
| QCOMPARE(rect3Spy.counts[QEvent::GraphicsSceneMouseRelease], 1); |
| QCOMPARE(rect3Spy.counts[QEvent::UngrabMouse], 1); |
| QCOMPARE(scene.mouseGrabberItem(), nullptr); |
| |
| rect2->setPanelModality(QGraphicsItem::NonModal); |
| |
| // pressing mouse on rect3 starts implicit grab |
| sendMousePress(&scene, QPoint(150, 50)); |
| QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 0); |
| QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 0); |
| QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0); |
| QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0); |
| QCOMPARE(rect3Spy.counts[QEvent::GrabMouse], 2); |
| QCOMPARE(rect3Spy.counts[QEvent::UngrabMouse], 1); |
| QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) rect3); |
| |
| // grab is not lost |
| rect2->setPanelModality(QGraphicsItem::PanelModal); |
| QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 0); |
| QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 0); |
| QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0); |
| QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0); |
| QCOMPARE(rect3Spy.counts[QEvent::GrabMouse], 2); |
| QCOMPARE(rect3Spy.counts[QEvent::UngrabMouse], 1); |
| QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) rect3); |
| |
| // grab stays on rect3 |
| rect2->setPanelModality(QGraphicsItem::NonModal); |
| QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 0); |
| QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 0); |
| QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0); |
| QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0); |
| QCOMPARE(rect3Spy.counts[QEvent::GrabMouse], 2); |
| QCOMPARE(rect3Spy.counts[QEvent::UngrabMouse], 1); |
| QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) rect3); |
| |
| // release goes to rect3 |
| sendMouseRelease(&scene, QPoint(150, 50)); |
| QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 0); |
| QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 0); |
| QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0); |
| QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0); |
| QCOMPARE(rect3Spy.counts[QEvent::GrabMouse], 2); |
| QCOMPARE(rect3Spy.counts[QEvent::UngrabMouse], 2); |
| QCOMPARE(scene.mouseGrabberItem(), nullptr); |
| } |
| } |
| |
| void tst_QGraphicsItem::modality_clickFocus() |
| { |
| QGraphicsScene scene; |
| QGraphicsRectItem *rect1 = scene.addRect(-50, -50, 100, 100); |
| rect1->setFlag(QGraphicsItem::ItemIsPanel); |
| rect1->setFlag(QGraphicsItem::ItemIsFocusable); |
| rect1->setData(0, "rect1"); |
| |
| QGraphicsRectItem *rect2 = scene.addRect(-50, -50, 100, 100); |
| rect2->setParentItem(rect1); |
| rect2->setFlag(QGraphicsItem::ItemIsPanel); |
| rect2->setFlag(QGraphicsItem::ItemIsFocusable); |
| rect2->setPos(50, 50); |
| rect2->setData(0, "rect2"); |
| |
| QEvent windowActivateEvent(QEvent::WindowActivate); |
| QApplication::sendEvent(&scene, &windowActivateEvent); |
| |
| EventSpy2 rect1Spy(&scene, rect1); |
| EventSpy2 rect2Spy(&scene, rect2); |
| |
| // activate rect1, it should get focus |
| rect1->setActive(true); |
| QCOMPARE(scene.focusItem(), (QGraphicsItem *) rect1); |
| |
| // focus stays when rect2 becomes modal |
| rect2->setPanelModality(QGraphicsItem::SceneModal); |
| QCOMPARE(scene.focusItem(), (QGraphicsItem *) rect1); |
| QCOMPARE(rect1Spy.counts[QEvent::FocusIn], 1); |
| QCOMPARE(rect1Spy.counts[QEvent::FocusOut], 0); |
| QCOMPARE(rect2Spy.counts[QEvent::FocusIn], 0); |
| QCOMPARE(rect2Spy.counts[QEvent::FocusOut], 0); |
| |
| // clicking on rect1 should not set it's focus item |
| rect1->clearFocus(); |
| sendMouseClick(&scene, QPointF(-25, -25)); |
| QCOMPARE(rect1->focusItem(), nullptr); |
| QCOMPARE(rect1Spy.counts[QEvent::FocusIn], 1); |
| QCOMPARE(rect1Spy.counts[QEvent::FocusOut], 1); |
| QCOMPARE(rect2Spy.counts[QEvent::FocusIn], 0); |
| QCOMPARE(rect2Spy.counts[QEvent::FocusOut], 0); |
| |
| // clicking on rect2 gives it focus |
| rect2->setActive(true); |
| sendMouseClick(&scene, QPointF(75, 75)); |
| QCOMPARE(scene.focusItem(), (QGraphicsItem *) rect2); |
| QCOMPARE(rect1Spy.counts[QEvent::FocusIn], 1); |
| QCOMPARE(rect1Spy.counts[QEvent::FocusOut], 1); |
| QCOMPARE(rect2Spy.counts[QEvent::FocusIn], 1); |
| QCOMPARE(rect2Spy.counts[QEvent::FocusOut], 0); |
| |
| // clicking on rect1 does *not* give it focus |
| rect1->setActive(true); |
| rect1->clearFocus(); |
| sendMouseClick(&scene, QPointF(-25, -25)); |
| QCOMPARE(scene.focusItem(), nullptr); |
| QCOMPARE(rect1Spy.counts[QEvent::FocusIn], 2); |
| QCOMPARE(rect1Spy.counts[QEvent::FocusOut], 2); |
| QCOMPARE(rect2Spy.counts[QEvent::FocusIn], 1); |
| QCOMPARE(rect2Spy.counts[QEvent::FocusOut], 1); |
| |
| // focus doesn't change when leaving modality either |
| rect2->setPanelModality(QGraphicsItem::NonModal); |
| QCOMPARE(scene.focusItem(), nullptr); |
| QCOMPARE(rect1Spy.counts[QEvent::FocusIn], 2); |
| QCOMPARE(rect1Spy.counts[QEvent::FocusOut], 2); |
| QCOMPARE(rect2Spy.counts[QEvent::FocusIn], 1); |
| QCOMPARE(rect2Spy.counts[QEvent::FocusOut], 1); |
| |
| // click on rect1, it should get focus now |
| sendMouseClick(&scene, QPointF(-25, -25)); |
| QCOMPARE(scene.focusItem(), (QGraphicsItem *) rect1); |
| QCOMPARE(rect1Spy.counts[QEvent::FocusIn], 3); |
| QCOMPARE(rect1Spy.counts[QEvent::FocusOut], 2); |
| QCOMPARE(rect2Spy.counts[QEvent::FocusIn], 1); |
| QCOMPARE(rect2Spy.counts[QEvent::FocusOut], 1); |
| } |
| |
| void tst_QGraphicsItem::modality_keyEvents() |
| { |
| QGraphicsScene scene; |
| QGraphicsRectItem *rect1 = scene.addRect(-50, -50, 100, 100); |
| rect1->setFlag(QGraphicsItem::ItemIsPanel); |
| rect1->setFlag(QGraphicsItem::ItemIsFocusable); |
| rect1->setData(0, "rect1"); |
| |
| QGraphicsRectItem *rect1child = scene.addRect(-10, -10, 20, 20); |
| rect1child->setParentItem(rect1); |
| rect1child->setFlag(QGraphicsItem::ItemIsFocusable); |
| rect1child->setData(0, "rect1child1"); |
| |
| QGraphicsRectItem *rect2 = scene.addRect(-50, -50, 100, 100); |
| rect2->setParentItem(rect1); |
| rect2->setFlag(QGraphicsItem::ItemIsPanel); |
| rect2->setFlag(QGraphicsItem::ItemIsFocusable); |
| rect2->setPos(50, 50); |
| rect2->setData(0, "rect2"); |
| |
| QGraphicsRectItem *rect2child = scene.addRect(-10, -10, 20, 20); |
| rect2child->setParentItem(rect2); |
| rect2child->setFlag(QGraphicsItem::ItemIsFocusable); |
| rect2child->setData(0, "rect2child1"); |
| |
| QEvent windowActivateEvent(QEvent::WindowActivate); |
| QApplication::sendEvent(&scene, &windowActivateEvent); |
| |
| EventSpy2 rect1Spy(&scene, rect1); |
| EventSpy2 rect1childSpy(&scene, rect1child); |
| EventSpy2 rect2Spy(&scene, rect2); |
| EventSpy2 rect2childSpy(&scene, rect2child); |
| |
| // activate rect1 and give it rect1child focus |
| rect1->setActive(true); |
| rect1child->setFocus(); |
| QCOMPARE(scene.focusItem(), (QGraphicsItem *) rect1child); |
| |
| // focus stays on rect1child when rect2 becomes modal |
| rect2->setPanelModality(QGraphicsItem::SceneModal); |
| QCOMPARE(scene.focusItem(), (QGraphicsItem *) rect1child); |
| |
| // but key events to rect1child should be neither delivered nor propagated |
| sendKeyClick(&scene, Qt::Key_A); |
| sendKeyClick(&scene, Qt::Key_S); |
| sendKeyClick(&scene, Qt::Key_D); |
| sendKeyClick(&scene, Qt::Key_F); |
| QCOMPARE(rect1childSpy.counts[QEvent::KeyPress], 0); |
| QCOMPARE(rect1childSpy.counts[QEvent::KeyRelease], 0); |
| QCOMPARE(rect1Spy.counts[QEvent::KeyPress], 0); |
| QCOMPARE(rect1Spy.counts[QEvent::KeyRelease], 0); |
| |
| // change to panel modality, rect1child1 keeps focus |
| rect2->setPanelModality(QGraphicsItem::PanelModal); |
| QCOMPARE(scene.focusItem(), (QGraphicsItem *) rect1child); |
| |
| // still no key events |
| sendKeyClick(&scene, Qt::Key_J); |
| sendKeyClick(&scene, Qt::Key_K); |
| sendKeyClick(&scene, Qt::Key_L); |
| sendKeyClick(&scene, Qt::Key_Semicolon); |
| QCOMPARE(rect1childSpy.counts[QEvent::KeyPress], 0); |
| QCOMPARE(rect1childSpy.counts[QEvent::KeyRelease], 0); |
| QCOMPARE(rect1Spy.counts[QEvent::KeyPress], 0); |
| QCOMPARE(rect1Spy.counts[QEvent::KeyRelease], 0); |
| } |
| |
| void tst_QGraphicsItem::itemIsInFront() |
| { |
| QGraphicsScene scene; |
| QGraphicsRectItem *rect1 = new QGraphicsRectItem; |
| rect1->setData(0, "rect1"); |
| scene.addItem(rect1); |
| |
| QGraphicsRectItem *rect1child1 = new QGraphicsRectItem(rect1); |
| rect1child1->setZValue(1); |
| rect1child1->setData(0, "rect1child1"); |
| |
| QGraphicsRectItem *rect1child2 = new QGraphicsRectItem(rect1); |
| rect1child2->setParentItem(rect1); |
| rect1child2->setData(0, "rect1child2"); |
| |
| QGraphicsRectItem *rect1child1_1 = new QGraphicsRectItem(rect1child1); |
| rect1child1_1->setData(0, "rect1child1_1"); |
| |
| QGraphicsRectItem *rect1child1_2 = new QGraphicsRectItem(rect1child1); |
| rect1child1_2->setFlag(QGraphicsItem::ItemStacksBehindParent); |
| rect1child1_2->setData(0, "rect1child1_2"); |
| |
| QGraphicsRectItem *rect2 = new QGraphicsRectItem; |
| rect2->setData(0, "rect2"); |
| scene.addItem(rect2); |
| |
| QGraphicsRectItem *rect2child1 = new QGraphicsRectItem(rect2); |
| rect2child1->setData(0, "rect2child1"); |
| |
| QCOMPARE(qt_closestItemFirst(rect1, rect1), false); |
| QCOMPARE(qt_closestItemFirst(rect1, rect2), false); |
| QCOMPARE(qt_closestItemFirst(rect1child1, rect2child1), false); |
| QCOMPARE(qt_closestItemFirst(rect1child1, rect1child2), true); |
| QCOMPARE(qt_closestItemFirst(rect1child1_1, rect1child2), true); |
| QCOMPARE(qt_closestItemFirst(rect1child1_1, rect1child1), true); |
| QCOMPARE(qt_closestItemFirst(rect1child1_2, rect1child2), true); |
| QCOMPARE(qt_closestItemFirst(rect1child1_2, rect1child1), false); |
| QCOMPARE(qt_closestItemFirst(rect1child1_2, rect1), true); |
| QCOMPARE(qt_closestItemFirst(rect1child1_2, rect2), false); |
| QCOMPARE(qt_closestItemFirst(rect1child1_2, rect2child1), false); |
| } |
| |
| class ScenePosChangeTester : public ItemChangeTester |
| { |
| public: |
| ScenePosChangeTester() |
| { } |
| ScenePosChangeTester(QGraphicsItem *parent) : ItemChangeTester(parent) |
| { } |
| }; |
| |
| void tst_QGraphicsItem::scenePosChange() |
| { |
| ScenePosChangeTester* root = new ScenePosChangeTester; |
| ScenePosChangeTester* child1 = new ScenePosChangeTester(root); |
| const QScopedPointer<ScenePosChangeTester> grandChild1(new ScenePosChangeTester(child1)); |
| ScenePosChangeTester* child2 = new ScenePosChangeTester(root); |
| ScenePosChangeTester* grandChild2 = new ScenePosChangeTester(child2); |
| |
| child1->setFlag(QGraphicsItem::ItemSendsScenePositionChanges, true); |
| grandChild2->setFlag(QGraphicsItem::ItemSendsScenePositionChanges, true); |
| |
| QVERIFY(child1->flags() & QGraphicsItem::ItemSendsScenePositionChanges); |
| QVERIFY(grandChild2->flags() & QGraphicsItem::ItemSendsScenePositionChanges); |
| |
| QGraphicsScene scene; |
| scene.addItem(root); |
| |
| // ignore uninteresting changes |
| child1->clear(); |
| child2->clear(); |
| grandChild1->clear(); |
| grandChild2->clear(); |
| |
| // move whole tree |
| root->moveBy(1.0, 1.0); |
| QCOMPARE(child1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 1); |
| QCOMPARE(grandChild1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 0); |
| QCOMPARE(child2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 0); |
| QCOMPARE(grandChild2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 1); |
| |
| // move subtree |
| child2->moveBy(1.0, 1.0); |
| QCOMPARE(child1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 1); |
| QCOMPARE(grandChild1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 0); |
| QCOMPARE(child2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 0); |
| QCOMPARE(grandChild2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 2); |
| |
| // reparent |
| grandChild2->setParentItem(child1); |
| child1->moveBy(1.0, 1.0); |
| QCOMPARE(child1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 2); |
| QCOMPARE(grandChild1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 0); |
| QCOMPARE(child2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 0); |
| QCOMPARE(grandChild2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 3); |
| |
| // change flags |
| grandChild1->setFlag(QGraphicsItem::ItemSendsScenePositionChanges, true); |
| grandChild2->setFlag(QGraphicsItem::ItemSendsScenePositionChanges, false); |
| QCoreApplication::processEvents(); // QGraphicsScenePrivate::_q_updateScenePosDescendants() |
| child1->moveBy(1.0, 1.0); |
| QCOMPARE(child1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 3); |
| QCOMPARE(grandChild1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 1); |
| QCOMPARE(child2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 0); |
| QCOMPARE(grandChild2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 3); |
| |
| // remove |
| scene.removeItem(grandChild1.data()); |
| delete grandChild2; grandChild2 = 0; |
| QCoreApplication::processEvents(); // QGraphicsScenePrivate::_q_updateScenePosDescendants() |
| root->moveBy(1.0, 1.0); |
| QCOMPARE(child1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 4); |
| QCOMPARE(grandChild1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 1); |
| QCOMPARE(child2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 0); |
| |
| root->setX(1); |
| QCOMPARE(child1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 5); |
| QCOMPARE(grandChild1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 1); |
| QCOMPARE(child2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 0); |
| |
| root->setY(1); |
| QCOMPARE(child1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 6); |
| QCOMPARE(grandChild1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 1); |
| QCOMPARE(child2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 0); |
| } |
| |
| void tst_QGraphicsItem::textItem_shortcuts() |
| { |
| QWidget w; |
| QVBoxLayout l; |
| w.setLayout(&l); |
| QGraphicsScene scene; |
| QGraphicsView view(&scene); |
| l.addWidget(&view); |
| QPushButton b("Push Me"); |
| l.addWidget(&b); |
| |
| QGraphicsTextItem *item = scene.addText("Troll Text"); |
| item->setFlag(QGraphicsItem::ItemIsFocusable); |
| item->setTextInteractionFlags(Qt::TextEditorInteraction); |
| w.show(); |
| QVERIFY(QTest::qWaitForWindowExposed(&w)); |
| |
| item->setFocus(); |
| QTRY_VERIFY(item->hasFocus()); |
| QVERIFY(item->textCursor().selectedText().isEmpty()); |
| |
| // Shortcut should work (select all) |
| QTest::keyClick(&view, Qt::Key_A, Qt::ControlModifier); |
| QTRY_COMPARE(item->textCursor().selectedText(), item->toPlainText()); |
| QTextCursor tc = item->textCursor(); |
| tc.clearSelection(); |
| item->setTextCursor(tc); |
| QVERIFY(item->textCursor().selectedText().isEmpty()); |
| |
| // Shortcut should also work if the text item has the focus and another widget |
| // has the same shortcut. |
| b.setShortcut(QKeySequence("CTRL+A")); |
| QTest::keyClick(&view, Qt::Key_A, Qt::ControlModifier); |
| QTRY_COMPARE(item->textCursor().selectedText(), item->toPlainText()); |
| } |
| |
| void tst_QGraphicsItem::scroll() |
| { |
| // Create two overlapping rectangles in the scene: |
| // +-------+ |
| // | | <- item1 |
| // | +-------+ |
| // | | | |
| // +---| | <- item2 |
| // | | |
| // +-------+ |
| |
| EventTester *item1 = new EventTester; |
| item1->br = QRectF(0, 0, 200, 200); |
| item1->brush = Qt::red; |
| item1->setFlag(QGraphicsItem::ItemUsesExtendedStyleOption); |
| |
| EventTester *item2 = new EventTester; |
| item2->br = QRectF(0, 0, 200, 200); |
| item2->brush = Qt::blue; |
| item2->setFlag(QGraphicsItem::ItemUsesExtendedStyleOption); |
| item2->setPos(100, 100); |
| |
| QGraphicsScene scene(0, 0, 300, 300); |
| scene.addItem(item1); |
| scene.addItem(item2); |
| |
| MyGraphicsView view(&scene); |
| view.setFrameStyle(0); |
| view.show(); |
| QVERIFY(QTest::qWaitForWindowExposed(&view)); |
| QVERIFY(QTest::qWaitForWindowActive(&view)); |
| QTRY_VERIFY(view.repaints > 0); |
| |
| view.reset(); |
| item1->reset(); |
| item2->reset(); |
| |
| const QRectF item1BoundingRect = item1->boundingRect(); |
| const QRectF item2BoundingRect = item2->boundingRect(); |
| |
| // Scroll item1: |
| // Item1 should get full exposure |
| // Item2 should get exposure for the part that overlaps item1. |
| item1->scroll(0, -10); |
| QTRY_VERIFY(view.repaints > 0); |
| QCOMPARE(item1->lastExposedRect, item1BoundingRect); |
| |
| QRectF expectedItem2Expose = item2BoundingRect; |
| // NB! Adjusted by 2 pixels for antialiasing |
| expectedItem2Expose &= item1->mapRectToItem(item2, item1BoundingRect.adjusted(-2, -2, 2, 2)); |
| QCOMPARE(item2->lastExposedRect, expectedItem2Expose); |
| |
| // Enable ItemCoordinateCache on item1. |
| view.reset(); |
| item1->setCacheMode(QGraphicsItem::ItemCoordinateCache); |
| QTRY_VERIFY(view.repaints > 0); |
| view.reset(); |
| item1->reset(); |
| item2->reset(); |
| |
| // Scroll item1: |
| // Item1 should only get expose for the newly exposed area (accelerated scroll). |
| // Item2 should get exposure for the part that overlaps item1. |
| item1->scroll(0, -10, QRectF(50, 50, 100, 100)); |
| QTRY_VERIFY(view.repaints > 0); |
| QCOMPARE(item1->lastExposedRect, QRectF(50, 140, 100, 10)); |
| |
| expectedItem2Expose = item2BoundingRect; |
| // NB! Adjusted by 2 pixels for antialiasing |
| expectedItem2Expose &= item1->mapRectToItem(item2, QRectF(50, 50, 100, 100).adjusted(-2, -2, 2, 2)); |
| QCOMPARE(item2->lastExposedRect, expectedItem2Expose); |
| } |
| |
| Q_DECLARE_METATYPE(QGraphicsItem::GraphicsItemFlag); |
| |
| void tst_QGraphicsItem::focusHandling_data() |
| { |
| QTest::addColumn<QGraphicsItem::GraphicsItemFlag>("focusFlag"); |
| QTest::addColumn<bool>("useStickyFocus"); |
| QTest::addColumn<int>("expectedFocusItem"); // 0: none, 1: focusableUnder, 2: itemWithFocus |
| |
| QTest::newRow("Focus goes through.") |
| << static_cast<QGraphicsItem::GraphicsItemFlag>(0x0) << false << 1; |
| |
| QTest::newRow("Focus goes through, even with sticky scene.") |
| << static_cast<QGraphicsItem::GraphicsItemFlag>(0x0) << true << 1; |
| |
| QTest::newRow("With ItemStopsClickFocusPropagation, we cannot focus the item beneath the flagged one (but can still focus-out).") |
| << QGraphicsItem::ItemStopsClickFocusPropagation << false << 0; |
| |
| QTest::newRow("With ItemStopsClickFocusPropagation, we cannot focus the item beneath the flagged one (and cannot focus-out if scene is sticky).") |
| << QGraphicsItem::ItemStopsClickFocusPropagation << true << 2; |
| |
| QTest::newRow("With ItemStopsFocusHandling, focus cannot be changed by presses.") |
| << QGraphicsItem::ItemStopsFocusHandling << false << 2; |
| |
| QTest::newRow("With ItemStopsFocusHandling, focus cannot be changed by presses (even if scene is sticky).") |
| << QGraphicsItem::ItemStopsFocusHandling << true << 2; |
| } |
| |
| void tst_QGraphicsItem::focusHandling() |
| { |
| QFETCH(QGraphicsItem::GraphicsItemFlag, focusFlag); |
| QFETCH(bool, useStickyFocus); |
| QFETCH(int, expectedFocusItem); |
| |
| class MyItem : public QGraphicsRectItem |
| { |
| public: |
| MyItem() : QGraphicsRectItem(0, 0, 100, 100) {} |
| void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) |
| { |
| painter->fillRect(boundingRect(), hasFocus() ? QBrush(Qt::red) : brush()); |
| } |
| }; |
| |
| QGraphicsRectItem *noFocusOnTop = new MyItem; |
| noFocusOnTop->setFlag(QGraphicsItem::ItemIsFocusable, false); |
| noFocusOnTop->setBrush(Qt::yellow); |
| |
| QGraphicsRectItem *focusableUnder = new MyItem; |
| focusableUnder->setBrush(Qt::blue); |
| focusableUnder->setFlag(QGraphicsItem::ItemIsFocusable); |
| focusableUnder->setPos(50, 50); |
| |
| QGraphicsRectItem *itemWithFocus = new MyItem; |
| itemWithFocus->setBrush(Qt::black); |
| itemWithFocus->setFlag(QGraphicsItem::ItemIsFocusable); |
| itemWithFocus->setPos(250, 10); |
| |
| QGraphicsScene scene(-50, -50, 400, 400); |
| scene.addItem(noFocusOnTop); |
| scene.addItem(focusableUnder); |
| scene.addItem(itemWithFocus); |
| scene.setStickyFocus(useStickyFocus); |
| |
| noFocusOnTop->setFlag(focusFlag); |
| focusableUnder->stackBefore(noFocusOnTop); |
| itemWithFocus->setFocus(); |
| |
| QGraphicsView view(&scene); |
| view.show(); |
| QVERIFY(QTest::qWaitForWindowExposed(&view)); |
| |
| QApplication::setActiveWindow(&view); |
| QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view)); |
| QVERIFY(itemWithFocus->hasFocus()); |
| |
| const QPointF mousePressPoint = noFocusOnTop->mapToScene(noFocusOnTop->boundingRect().center()); |
| const QList<QGraphicsItem *> itemsAtMousePressPosition = scene.items(mousePressPoint); |
| QVERIFY(itemsAtMousePressPosition.contains(noFocusOnTop)); |
| |
| sendMousePress(&scene, mousePressPoint); |
| |
| switch (expectedFocusItem) { |
| case 0: |
| QCOMPARE(scene.focusItem(), nullptr); |
| break; |
| case 1: |
| QCOMPARE(scene.focusItem(), focusableUnder); |
| break; |
| case 2: |
| QCOMPARE(scene.focusItem(), itemWithFocus); |
| break; |
| } |
| |
| // Sanity check - manually setting the focus must work regardless of our |
| // focus handling flags: |
| focusableUnder->setFocus(); |
| QCOMPARE(scene.focusItem(), focusableUnder); |
| } |
| |
| class TouchEventTestee : public QGraphicsRectItem |
| { |
| public: |
| TouchEventTestee(const QSizeF &size = QSizeF(100, 100)) : |
| QGraphicsRectItem(QRectF(QPointF(), size)) |
| { |
| setAcceptTouchEvents(true); |
| setFlag(QGraphicsItem::ItemIsFocusable, false); |
| } |
| |
| QList<QTouchEvent::TouchPoint> touchBeginPoints() const { return m_touchBeginPoints; } |
| int touchBeginEventCount() const { return m_touchBeginPoints.size(); } |
| |
| QList<QTouchEvent::TouchPoint> touchUpdatePoints() const { return m_touchUpdatePoints; } |
| int touchUpdateEventCount() const { return m_touchUpdatePoints.size(); } |
| |
| protected: |
| bool sceneEvent(QEvent *ev) override |
| { |
| switch (ev->type()) { |
| case QEvent::TouchBegin: |
| m_touchBeginPoints.append(static_cast<const QTouchEvent *>(ev)->touchPoints().constFirst()); |
| ev->accept(); |
| return true; |
| case QEvent::TouchUpdate: |
| m_touchUpdatePoints.append(static_cast<const QTouchEvent *>(ev)->touchPoints().constFirst()); |
| ev->accept(); |
| return true; |
| default: |
| break; |
| } |
| |
| return QGraphicsRectItem::sceneEvent(ev); |
| } |
| |
| private: |
| QList<QTouchEvent::TouchPoint> m_touchBeginPoints; |
| QList<QTouchEvent::TouchPoint> m_touchUpdatePoints; |
| }; |
| |
| static QList<QTouchEvent::TouchPoint> |
| createTouchPoints(const QGraphicsView &view, |
| const QPointF &scenePos, |
| const QSizeF &ellipseDiameters, |
| Qt::TouchPointState state = Qt::TouchPointPressed) |
| { |
| QTouchEvent::TouchPoint tp(0); |
| tp.setState(state); |
| tp.setScenePos(scenePos); |
| tp.setStartScenePos(scenePos); |
| tp.setLastScenePos(scenePos); |
| const QPointF screenPos = view.viewport()->mapToGlobal(view.mapFromScene(scenePos)); |
| tp.setScreenPos(screenPos); |
| tp.setStartScreenPos(screenPos); |
| tp.setLastScreenPos(screenPos); |
| tp.setEllipseDiameters(ellipseDiameters); |
| const QSizeF screenSize = view.screen()->geometry().size(); |
| tp.setNormalizedPos(QPointF(screenPos.x() / screenSize.width(), screenPos.y() / screenSize.height())); |
| return QList<QTouchEvent::TouchPoint>() << tp; |
| } |
| |
| static bool comparePointF(const QPointF &p1, const QPointF &p2) |
| { |
| return qFuzzyCompare(p1.x(), p2.x()) && qFuzzyCompare(p1.y(), p2.y()); |
| } |
| |
| static bool compareSizeF(const QSizeF &s1, const QSizeF &s2) |
| { |
| return qFuzzyCompare(s1.width(), s2.width()) && qFuzzyCompare(s1.height(), s2.height()); |
| } |
| |
| static QByteArray msgPointFComparisonFailed(const QPointF &p1, const QPointF &p2) |
| { |
| return QByteArray::number(p1.x()) + ", " + QByteArray::number(p1.y()) |
| + " != " + QByteArray::number(p2.x()) + ", " + QByteArray::number(p2.y()); |
| } |
| |
| static QByteArray msgSizeFComparisonFailed(const QSizeF &s1, const QSizeF &s2) |
| { |
| return QByteArray::number(s1.width()) + 'x' + QByteArray::number(s1.height()) |
| + " != " + QByteArray::number(s2.width()) + 'x' + QByteArray::number(s2.height()); |
| } |
| |
| #define COMPARE_POINTF(ACTUAL, EXPECTED) \ |
| QVERIFY2(comparePointF(ACTUAL, EXPECTED), msgPointFComparisonFailed(ACTUAL, EXPECTED).constData()) |
| |
| #define COMPARE_SIZEF(ACTUAL, EXPECTED) \ |
| QVERIFY2(compareSizeF(ACTUAL, EXPECTED), msgSizeFComparisonFailed(ACTUAL, EXPECTED).constData()) |
| |
| void tst_QGraphicsItem::touchEventPropagation_data() |
| { |
| QTest::addColumn<QGraphicsItem::GraphicsItemFlag>("flag"); |
| QTest::addColumn<int>("expectedCount"); |
| |
| QTest::newRow("ItemIsPanel") |
| << QGraphicsItem::ItemIsPanel << 0; |
| QTest::newRow("ItemStopsClickFocusPropagation") |
| << QGraphicsItem::ItemStopsClickFocusPropagation << 1; |
| QTest::newRow("ItemStopsFocusHandling") |
| << QGraphicsItem::ItemStopsFocusHandling << 1; |
| } |
| |
| void tst_QGraphicsItem::touchEventPropagation() |
| { |
| QFETCH(QGraphicsItem::GraphicsItemFlag, flag); |
| QFETCH(int, expectedCount); |
| |
| TouchEventTestee *touchEventReceiver = new TouchEventTestee; |
| QGraphicsItem *topMost = new QGraphicsRectItem(touchEventReceiver->boundingRect()); |
| |
| QGraphicsScene scene; |
| scene.addItem(topMost); |
| scene.addItem(touchEventReceiver); |
| |
| topMost->setAcceptTouchEvents(true); |
| topMost->setZValue(FLT_MAX); |
| topMost->setFlag(QGraphicsItem::ItemIsFocusable, false); |
| topMost->setFlag(flag, true); |
| |
| QGraphicsView view(&scene); |
| view.setWindowTitle(QLatin1String(QTest::currentTestFunction()) + QLatin1String("::") |
| + QLatin1String(QTest::currentDataTag())); |
| view.setSceneRect(touchEventReceiver->boundingRect()); |
| view.show(); |
| QVERIFY(QTest::qWaitForWindowExposed(&view)); |
| |
| QCOMPARE(touchEventReceiver->touchBeginEventCount(), 0); |
| |
| const QPointF scenePos = view.sceneRect().center(); |
| sendMousePress(&scene, scenePos); |
| if (m_touchDevice == nullptr) |
| m_touchDevice = QTest::createTouchDevice(); |
| QTouchEvent touchBegin(QEvent::TouchBegin, m_touchDevice, Qt::NoModifier, Qt::TouchPointPressed, |
| createTouchPoints(view, scenePos, QSizeF(10, 10))); |
| touchBegin.setTarget(view.viewport()); |
| |
| qApp->sendEvent(&scene, &touchBegin); |
| QCOMPARE(touchEventReceiver->touchBeginEventCount(), expectedCount); |
| } |
| |
| void tst_QGraphicsItem::touchEventTransformation_data() |
| { |
| QTest::addColumn<QGraphicsItem::GraphicsItemFlag>("flag"); |
| QTest::addColumn<QTransform>("viewTransform"); |
| QTest::addColumn<QPointF>("touchScenePos"); |
| QTest::addColumn<QSizeF>("ellipseDiameters"); |
| QTest::addColumn<QPointF>("expectedItemPos"); |
| |
| QTest::newRow("notransform") |
| << QGraphicsItem::ItemIsSelectable << QTransform() |
| << QPointF(150, 150) << QSizeF(7, 8) << QPointF(50, 50); |
| QTest::newRow("scaled") |
| << QGraphicsItem::ItemIsSelectable << QTransform::fromScale(0.5, 0.5) |
| << QPointF(150, 150) << QSizeF(7, 8) << QPointF(50, 50); |
| // QTBUG-66192: When the item ignores the downscaling transformation, |
| // it will receive the touch point at 25,25 instead of 50,50. |
| QTest::newRow("scaled/ItemIgnoresTransformations") |
| << QGraphicsItem::ItemIgnoresTransformations << QTransform::fromScale(0.5, 0.5) |
| << QPointF(150, 150) << QSizeF(7, 8) << QPointF(25, 25); |
| } |
| |
| void tst_QGraphicsItem::touchEventTransformation() |
| { |
| QFETCH(QGraphicsItem::GraphicsItemFlag, flag); |
| QFETCH(QTransform, viewTransform); |
| QFETCH(QPointF, touchScenePos); |
| QFETCH(QSizeF, ellipseDiameters); |
| QFETCH(QPointF, expectedItemPos); |
| |
| TouchEventTestee *touchEventReceiver = new TouchEventTestee; |
| |
| QGraphicsScene scene; |
| scene.addItem(touchEventReceiver); |
| const QPointF itemPos(100, 100); |
| |
| touchEventReceiver->setPos(itemPos); |
| |
| touchEventReceiver->setFlag(flag, true); |
| |
| QGraphicsView view(&scene); |
| view.setWindowTitle(QLatin1String(QTest::currentTestFunction()) + QLatin1String("::") |
| + QLatin1String(QTest::currentDataTag())); |
| view.setSceneRect(QRectF(QPointF(0, 0), QSizeF(300, 300))); |
| view.setTransform(viewTransform); |
| view.show(); |
| QVERIFY(QTest::qWaitForWindowExposed(&view)); |
| |
| QCOMPARE(touchEventReceiver->touchBeginEventCount(), 0); |
| |
| if (m_touchDevice == nullptr) |
| m_touchDevice = QTest::createTouchDevice(); |
| QTouchEvent touchBegin(QEvent::TouchBegin, m_touchDevice, Qt::NoModifier, Qt::TouchPointPressed, |
| createTouchPoints(view, touchScenePos, ellipseDiameters)); |
| touchBegin.setTarget(view.viewport()); |
| |
| QCoreApplication::sendEvent(&scene, &touchBegin); |
| QCOMPARE(touchEventReceiver->touchBeginEventCount(), 1); |
| |
| const QTouchEvent::TouchPoint touchBeginPoint = touchEventReceiver->touchBeginPoints().constFirst(); |
| |
| COMPARE_POINTF(touchBeginPoint.scenePos(), touchScenePos); |
| COMPARE_POINTF(touchBeginPoint.startScenePos(), touchScenePos); |
| COMPARE_POINTF(touchBeginPoint.lastScenePos(), touchScenePos); |
| COMPARE_POINTF(touchBeginPoint.pos(), expectedItemPos); |
| COMPARE_SIZEF(touchBeginPoint.ellipseDiameters(), ellipseDiameters); // Must remain untransformed |
| |
| QTouchEvent touchUpdate(QEvent::TouchUpdate, m_touchDevice, Qt::NoModifier, Qt::TouchPointMoved, |
| createTouchPoints(view, touchScenePos, ellipseDiameters, Qt::TouchPointMoved)); |
| touchUpdate.setTarget(view.viewport()); |
| |
| QCoreApplication::sendEvent(&scene, &touchUpdate); |
| QCOMPARE(touchEventReceiver->touchUpdateEventCount(), 1); |
| |
| const QTouchEvent::TouchPoint touchUpdatePoint = touchEventReceiver->touchUpdatePoints().constFirst(); |
| |
| COMPARE_POINTF(touchUpdatePoint.scenePos(), touchScenePos); |
| COMPARE_POINTF(touchBeginPoint.startScenePos(), touchScenePos); |
| COMPARE_POINTF(touchUpdatePoint.lastScenePos(), touchScenePos); |
| COMPARE_POINTF(touchUpdatePoint.pos(), expectedItemPos); |
| COMPARE_SIZEF(touchUpdatePoint.ellipseDiameters(), ellipseDiameters); // Must remain untransformed |
| |
| } |
| |
| void tst_QGraphicsItem::deviceCoordinateCache_simpleRotations() |
| { |
| // Make sure we don't invalidate the cache when applying simple |
| // (90, 180, 270, 360) rotation transforms to the item. |
| QGraphicsRectItem *item = new QGraphicsRectItem(0, 0, 300, 200); |
| item->setBrush(Qt::red); |
| item->setCacheMode(QGraphicsItem::DeviceCoordinateCache); |
| |
| QGraphicsScene scene; |
| scene.setSceneRect(0, 0, 300, 200); |
| scene.addItem(item); |
| |
| MyGraphicsView view(&scene); |
| view.show(); |
| QVERIFY(QTest::qWaitForWindowExposed(&view)); |
| QTRY_VERIFY(view.repaints > 0); |
| |
| QGraphicsItemCache *itemCache = QGraphicsItemPrivate::get(item)->extraItemCache(); |
| QVERIFY(itemCache); |
| QPixmapCache::Key currentKey = itemCache->deviceData.value(view.viewport()).key; |
| |
| // Trigger an update and verify that the cache is unchanged. |
| QPixmapCache::Key oldKey = currentKey; |
| view.reset(); |
| view.viewport()->update(); |
| QTRY_VERIFY(view.repaints > 0); |
| currentKey = itemCache->deviceData.value(view.viewport()).key; |
| QCOMPARE(currentKey, oldKey); |
| |
| // Check 90, 180, 270 and 360 degree rotations. |
| for (int angle = 90; angle <= 360; angle += 90) { |
| // Rotate item and verify that the cache was invalidated. |
| oldKey = currentKey; |
| view.reset(); |
| QTransform transform; |
| transform.translate(150, 100); |
| transform.rotate(angle); |
| transform.translate(-150, -100); |
| item->setTransform(transform); |
| QTRY_VERIFY(view.repaints > 0); |
| currentKey = itemCache->deviceData.value(view.viewport()).key; |
| QVERIFY(currentKey != oldKey); |
| |
| // IMPORTANT PART: |
| // Trigger an update and verify that the cache is unchanged. |
| oldKey = currentKey; |
| view.reset(); |
| view.viewport()->update(); |
| QTRY_VERIFY(view.repaints > 0); |
| currentKey = itemCache->deviceData.value(view.viewport()).key; |
| QCOMPARE(currentKey, oldKey); |
| } |
| |
| // 45 degree rotation. |
| oldKey = currentKey; |
| view.reset(); |
| QTransform transform; |
| transform.translate(150, 100); |
| transform.rotate(45); |
| transform.translate(-150, -100); |
| item->setTransform(transform); |
| QTRY_VERIFY(view.repaints > 0); |
| currentKey = itemCache->deviceData.value(view.viewport()).key; |
| QVERIFY(currentKey != oldKey); |
| |
| // Trigger an update and verify that the cache was invalidated. |
| // We should always invalidate the cache for non-trivial transforms. |
| oldKey = currentKey; |
| view.reset(); |
| view.viewport()->update(); |
| QTRY_VERIFY(view.repaints > 0); |
| currentKey = itemCache->deviceData.value(view.viewport()).key; |
| QVERIFY(currentKey != oldKey); |
| } |
| |
| void tst_QGraphicsItem::QTBUG_5418_textItemSetDefaultColor() |
| { |
| struct Item : public QGraphicsTextItem |
| { |
| int painted; |
| void paint(QPainter *painter, const QStyleOptionGraphicsItem *opt, QWidget *wid) |
| { |
| painted++; |
| QGraphicsTextItem::paint(painter, opt, wid); |
| } |
| }; |
| |
| Item *i = new Item; |
| i->painted = 0; |
| i->setPlainText("I AM A TROLL"); |
| |
| QGraphicsScene scene; |
| QGraphicsView view(&scene); |
| view.show(); |
| QVERIFY(QTest::qWaitForWindowExposed(&view)); |
| scene.addItem(i); |
| QApplication::processEvents(); |
| QTRY_VERIFY(i->painted); |
| QApplication::processEvents(); |
| |
| i->painted = 0; |
| QColor col(Qt::red); |
| i->setDefaultTextColor(col); |
| QApplication::processEvents(); |
| QTRY_COMPARE(i->painted, 1); //check that changing the color force an update |
| |
| i->painted = false; |
| QImage image(400, 200, QImage::Format_RGB32); |
| image.fill(0); |
| QPainter painter(&image); |
| scene.render(&painter); |
| painter.end(); |
| QCOMPARE(i->painted, 1); |
| |
| int numRedPixel = 0; |
| QRgb rgb = col.rgb(); |
| for (int y = 0; y < image.height(); ++y) { |
| for (int x = 0; x < image.width(); ++x) { |
| // Because of antialiasing we allow a certain range of errors here. |
| QRgb pixel = image.pixel(x, y); |
| if (qAbs((int)(pixel & 0xff) - (int)(rgb & 0xff)) + |
| qAbs((int)((pixel & 0xff00) >> 8) - (int)((rgb & 0xff00) >> 8)) + |
| qAbs((int)((pixel & 0xff0000) >> 16) - (int)((rgb & 0xff0000) >> 16)) <= 50) { |
| if (++numRedPixel >= 10) { |
| return; |
| } |
| } |
| } |
| } |
| QCOMPARE(numRedPixel, -1); //color not found, FAIL! |
| |
| i->painted = 0; |
| i->setDefaultTextColor(col); |
| QApplication::processEvents(); |
| QCOMPARE(i->painted, 0); //same color as before should not trigger an update (QTBUG-6242) |
| } |
| |
| void tst_QGraphicsItem::QTBUG_6738_missingUpdateWithSetParent() |
| { |
| // In all 3 test cases below the reparented item should disappear |
| EventTester *parent = new EventTester; |
| EventTester *child = new EventTester(parent); |
| EventTester *child2 = new EventTester(parent); |
| EventTester *child3 = new EventTester(parent); |
| EventTester *child4 = new EventTester(parent); |
| |
| child->setPos(10, 10); |
| child2->setPos(20, 20); |
| child3->setPos(30, 30); |
| child4->setPos(40, 40); |
| |
| QGraphicsScene scene; |
| scene.addItem(parent); |
| |
| MyGraphicsView view(&scene); |
| view.show(); |
| qApp->setActiveWindow(&view); |
| QVERIFY(QTest::qWaitForWindowExposed(&view)); |
| QVERIFY(QTest::qWaitForWindowActive(&view)); |
| QCoreApplication::processEvents(); // Process all queued paint events |
| QTRY_VERIFY(view.repaints > 0); |
| |
| // test case #1 |
| view.reset(); |
| child2->setVisible(false); |
| child2->setParentItem(child); |
| |
| QTRY_COMPARE(view.repaints, 1); |
| |
| // test case #2 |
| view.reset(); |
| child3->setOpacity(0.0); |
| child3->setParentItem(child); |
| |
| QTRY_COMPARE(view.repaints, 1); |
| |
| // test case #3 |
| view.reset(); |
| child4->setParentItem(child); |
| child4->setVisible(false); |
| |
| QTRY_COMPARE(view.repaints, 1); |
| } |
| |
| void tst_QGraphicsItem::QT_2653_fullUpdateDiscardingOpacityUpdate() |
| { |
| QGraphicsScene scene(0, 0, 200, 200); |
| MyGraphicsView view(&scene); |
| |
| EventTester *parentGreen = new EventTester(); |
| parentGreen->setGeometry(QRectF(20, 20, 100, 100)); |
| parentGreen->brush = Qt::green; |
| |
| EventTester *childYellow = new EventTester(parentGreen); |
| childYellow->setGeometry(QRectF(10, 10, 50, 50)); |
| childYellow->brush = Qt::yellow; |
| |
| scene.addItem(parentGreen); |
| |
| childYellow->setOpacity(0.0); |
| parentGreen->setOpacity(0.0); |
| |
| // set any of the flags below to trigger a fullUpdate to reproduce the bug: |
| // ItemIgnoresTransformations, ItemClipsChildrenToShape, ItemIsSelectable |
| parentGreen->setFlag(QGraphicsItem::ItemIgnoresTransformations); |
| |
| view.show(); |
| QVERIFY(QTest::qWaitForWindowExposed(&view)); |
| QVERIFY(QTest::qWaitForWindowActive(&view)); |
| QCoreApplication::processEvents(); // Process all queued paint events |
| view.reset(); |
| |
| parentGreen->setOpacity(1.0); |
| |
| QTRY_COMPARE(view.repaints, 1); |
| |
| view.reset(); |
| childYellow->repaints = 0; |
| |
| childYellow->setOpacity(1.0); |
| |
| QTRY_COMPARE(view.repaints, 1); |
| QTRY_COMPARE(childYellow->repaints, 1); |
| } |
| |
| void tst_QGraphicsItem::QTBUG_7714_fullUpdateDiscardingOpacityUpdate2() |
| { |
| QGraphicsScene scene(0, 0, 200, 200); |
| MyGraphicsView view(&scene); |
| MyGraphicsView origView(&scene); |
| |
| EventTester *parentGreen = new EventTester(); |
| parentGreen->setGeometry(QRectF(20, 20, 100, 100)); |
| parentGreen->brush = Qt::green; |
| |
| EventTester *childYellow = new EventTester(parentGreen); |
| childYellow->setGeometry(QRectF(10, 10, 50, 50)); |
| childYellow->brush = Qt::yellow; |
| |
| scene.addItem(parentGreen); |
| |
| origView.show(); |
| QVERIFY(QTest::qWaitForWindowActive(&origView)); |
| QCoreApplication::processEvents(); // Process all queued paint events |
| |
| origView.setGeometry(origView.x() + origView.width() + 20, origView.y() + 20, |
| origView.width(), origView.height()); |
| |
| parentGreen->setFlag(QGraphicsItem::ItemIgnoresTransformations); |
| |
| origView.reset(); |
| childYellow->setOpacity(0.0); |
| |
| QTRY_VERIFY(origView.repaints > 0); |
| |
| view.show(); |
| qApp->setActiveWindow(&view); |
| QVERIFY(QTest::qWaitForWindowExposed(&view)); |
| QVERIFY(QTest::qWaitForWindowActive(&view)); |
| view.reset(); |
| origView.reset(); |
| |
| childYellow->setOpacity(1.0); |
| |
| #ifdef Q_OS_WINRT |
| QEXPECT_FAIL("", "Fails on WinRT. Figure out why - QTBUG-68297", Abort); |
| #endif |
| |
| QTRY_VERIFY(origView.repaints > 0); |
| QTRY_VERIFY(view.repaints > 0); |
| } |
| |
| void tst_QGraphicsItem::QT_2649_focusScope() |
| { |
| QGraphicsScene *scene = new QGraphicsScene; |
| |
| QGraphicsRectItem *subFocusItem = new QGraphicsRectItem; |
| subFocusItem->setFlags(QGraphicsItem::ItemIsFocusable); |
| subFocusItem->setFocus(); |
| QCOMPARE(subFocusItem->focusItem(), (QGraphicsItem *)subFocusItem); |
| |
| QGraphicsRectItem *scope = new QGraphicsRectItem; |
| scope->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsFocusScope); |
| scope->setFocus(); |
| subFocusItem->setParentItem(scope); |
| QCOMPARE(subFocusItem->focusItem(), (QGraphicsItem *)subFocusItem); |
| QCOMPARE(subFocusItem->focusScopeItem(), nullptr); |
| QCOMPARE(scope->focusItem(), (QGraphicsItem *)subFocusItem); |
| QCOMPARE(scope->focusScopeItem(), (QGraphicsItem *)subFocusItem); |
| |
| QGraphicsRectItem *rootItem = new QGraphicsRectItem; |
| rootItem->setFlags(QGraphicsItem::ItemIsFocusable); |
| scope->setParentItem(rootItem); |
| QCOMPARE(rootItem->focusItem(), (QGraphicsItem *)subFocusItem); |
| QCOMPARE(rootItem->focusScopeItem(), nullptr); |
| QCOMPARE(subFocusItem->focusItem(), (QGraphicsItem *)subFocusItem); |
| QCOMPARE(subFocusItem->focusScopeItem(), nullptr); |
| QCOMPARE(scope->focusItem(), (QGraphicsItem *)subFocusItem); |
| QCOMPARE(scope->focusScopeItem(), (QGraphicsItem *)subFocusItem); |
| |
| scene->addItem(rootItem); |
| |
| QEvent windowActivate(QEvent::WindowActivate); |
| qApp->sendEvent(scene, &windowActivate); |
| scene->setFocus(); |
| |
| QCOMPARE(rootItem->focusItem(), (QGraphicsItem *)subFocusItem); |
| QCOMPARE(scope->focusItem(), (QGraphicsItem *)subFocusItem); |
| QCOMPARE(subFocusItem->focusItem(), (QGraphicsItem *)subFocusItem); |
| QCOMPARE(rootItem->focusScopeItem(), nullptr); |
| QCOMPARE(scope->focusScopeItem(), (QGraphicsItem *)subFocusItem); |
| QCOMPARE(subFocusItem->focusScopeItem(), nullptr); |
| QVERIFY(subFocusItem->hasFocus()); |
| |
| scope->hide(); |
| |
| QCOMPARE(rootItem->focusItem(), nullptr); |
| QCOMPARE(scope->focusItem(), nullptr); |
| QCOMPARE(subFocusItem->focusItem(), nullptr); |
| QCOMPARE(rootItem->focusScopeItem(), nullptr); |
| QCOMPARE(scope->focusScopeItem(), (QGraphicsItem *)subFocusItem); |
| QCOMPARE(subFocusItem->focusScopeItem(), nullptr); |
| QVERIFY(!subFocusItem->hasFocus()); |
| |
| scope->show(); |
| |
| QCOMPARE(rootItem->focusItem(), (QGraphicsItem *)subFocusItem); |
| QCOMPARE(scope->focusItem(), (QGraphicsItem *)subFocusItem); |
| QCOMPARE(subFocusItem->focusItem(), (QGraphicsItem *)subFocusItem); |
| QCOMPARE(rootItem->focusScopeItem(), nullptr); |
| QCOMPARE(scope->focusScopeItem(), (QGraphicsItem *)subFocusItem); |
| QCOMPARE(subFocusItem->focusScopeItem(), nullptr); |
| QVERIFY(subFocusItem->hasFocus()); |
| |
| // This should not crash |
| scope->hide(); |
| delete scene; |
| } |
| |
| class MyGraphicsItemWithItemChange : public QGraphicsWidget |
| { |
| public: |
| MyGraphicsItemWithItemChange(QGraphicsItem *parent = 0) : QGraphicsWidget(parent) |
| {} |
| |
| QVariant itemChange(GraphicsItemChange change, const QVariant &value) |
| { |
| if (change == QGraphicsItem::ItemSceneHasChanged) { |
| foreach (QGraphicsView *view, scene()->views()) { |
| //We trigger a sort of unindexed items in the BSP |
| view->sceneRect(); |
| } |
| } |
| return QGraphicsWidget::itemChange(change, value); |
| } |
| }; |
| |
| void tst_QGraphicsItem::sortItemsWhileAdding() |
| { |
| QGraphicsScene scene; |
| QGraphicsView view(&scene); |
| QGraphicsWidget grandGrandParent; |
| grandGrandParent.resize(200, 200); |
| scene.addItem(&grandGrandParent); |
| QGraphicsWidget grandParent; |
| grandParent.resize(200, 200); |
| QGraphicsWidget parent(&grandParent); |
| parent.resize(200, 200); |
| MyGraphicsItemWithItemChange item(&parent); |
| grandParent.setParentItem(&grandGrandParent); |
| } |
| |
| void tst_QGraphicsItem::doNotMarkFullUpdateIfNotInScene() |
| { |
| struct Item : public QGraphicsTextItem |
| { |
| int painted; |
| void paint(QPainter *painter, const QStyleOptionGraphicsItem *opt, QWidget *wid) |
| { |
| painted++; |
| QGraphicsTextItem::paint(painter, opt, wid); |
| } |
| }; |
| QGraphicsScene scene; |
| MyGraphicsView view(&scene); |
| Item *item = new Item; |
| item->painted = 0; |
| item->setPlainText("Grandparent"); |
| Item *item2 = new Item; |
| item2->setPlainText("parent"); |
| item2->painted = 0; |
| Item *item3 = new Item; |
| item3->setPlainText("child"); |
| item3->painted = 0; |
| QGraphicsOpacityEffect *effect = new QGraphicsOpacityEffect; |
| effect->setOpacity(0.5); |
| item2->setGraphicsEffect(effect); |
| item3->setParentItem(item2); |
| item2->setParentItem(item); |
| scene.addItem(item); |
| view.show(); |
| QVERIFY(QTest::qWaitForWindowExposed(view.windowHandle())); |
| QVERIFY(QTest::qWaitForWindowActive(view.windowHandle())); |
| QCoreApplication::processEvents(); // Process all queued paint events |
| view.activateWindow(); |
| QTRY_VERIFY(view.isActiveWindow()); |
| QTRY_VERIFY(view.repaints >= 1); |
| int count = view.repaints; |
| QTRY_COMPARE(item->painted, count); |
| // cached as graphics effects, not painted multiple times |
| QTRY_COMPARE(item2->painted, 1); |
| QTRY_COMPARE(item3->painted, 1); |
| item2->update(); |
| QApplication::processEvents(); |
| QTRY_COMPARE(item->painted, count + 1); |
| QTRY_COMPARE(item2->painted, 2); |
| QTRY_COMPARE(item3->painted, 2); |
| item2->update(); |
| QApplication::processEvents(); |
| QTRY_COMPARE(item->painted, count + 2); |
| QTRY_COMPARE(item2->painted, 3); |
| QTRY_COMPARE(item3->painted, 3); |
| } |
| |
| void tst_QGraphicsItem::itemDiesDuringDraggingOperation() |
| { |
| QGraphicsScene scene; |
| QGraphicsView view(&scene); |
| QGraphicsRectItem *item = new QGraphicsRectItem(QRectF(0, 0, 100, 100)); |
| item->setFlag(QGraphicsItem::ItemIsMovable); |
| item->setAcceptDrops(true); |
| scene.addItem(item); |
| view.show(); |
| QApplication::setActiveWindow(&view); |
| QVERIFY(QTest::qWaitForWindowExposed(&view)); |
| QVERIFY(QTest::qWaitForWindowActive(&view)); |
| QCOMPARE(QApplication::activeWindow(), (QWidget *)&view); |
| QGraphicsSceneDragDropEvent dragEnter(QEvent::GraphicsSceneDragEnter); |
| dragEnter.setScenePos(item->boundingRect().center()); |
| QApplication::sendEvent(&scene, &dragEnter); |
| QGraphicsSceneDragDropEvent event(QEvent::GraphicsSceneDragMove); |
| event.setScenePos(item->boundingRect().center()); |
| QApplication::sendEvent(&scene, &event); |
| QCOMPARE(QGraphicsScenePrivate::get(&scene)->dragDropItem, item); |
| delete item; |
| QVERIFY(!QGraphicsScenePrivate::get(&scene)->dragDropItem); |
| } |
| |
| void tst_QGraphicsItem::QTBUG_12112_focusItem() |
| { |
| QGraphicsScene scene; |
| QGraphicsView view(&scene); |
| QGraphicsRectItem *item1 = new QGraphicsRectItem(0, 0, 20, 20); |
| item1->setFlag(QGraphicsItem::ItemIsFocusable); |
| QGraphicsRectItem *item2 = new QGraphicsRectItem(20, 20, 20, 20); |
| item2->setFlag(QGraphicsItem::ItemIsFocusable); |
| item1->setFocus(); |
| scene.addItem(item2); |
| scene.addItem(item1); |
| |
| view.show(); |
| QApplication::setActiveWindow(&view); |
| QVERIFY(QTest::qWaitForWindowExposed(&view)); |
| QVERIFY(QTest::qWaitForWindowActive(&view)); |
| QCOMPARE(QApplication::activeWindow(), (QWidget *)&view); |
| |
| QVERIFY(item1->focusItem()); |
| QVERIFY(!item2->focusItem()); |
| |
| item2->setFocus(); |
| QVERIFY(!item1->focusItem()); |
| QVERIFY(item2->focusItem()); |
| } |
| |
| void tst_QGraphicsItem::QTBUG_13473_sceneposchange() |
| { |
| ScenePosChangeTester* parent = new ScenePosChangeTester; |
| ScenePosChangeTester* child = new ScenePosChangeTester(parent); |
| |
| // parent's disabled ItemSendsGeometryChanges flag must not affect |
| // child's scene pos change notifications |
| parent->setFlag(QGraphicsItem::ItemSendsGeometryChanges, false); |
| child->setFlag(QGraphicsItem::ItemSendsScenePositionChanges, true); |
| |
| QGraphicsScene scene; |
| scene.addItem(parent); |
| |
| // ignore uninteresting changes |
| parent->clear(); |
| child->clear(); |
| |
| // move |
| parent->moveBy(1.0, 1.0); |
| QCOMPARE(child->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 1); |
| |
| // transform |
| parent->setTransform(QTransform::fromScale(0.5, 0.5)); |
| QCOMPARE(child->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 2); |
| } |
| |
| class MyGraphicsWidget : public QGraphicsWidget { |
| Q_OBJECT |
| public: |
| MyGraphicsWidget() |
| : QGraphicsWidget(0) |
| { |
| QGraphicsLinearLayout *lay = new QGraphicsLinearLayout(Qt::Vertical); |
| QLatin1String wiseWords("AZ BUKI VEDI"); |
| QString sentence(wiseWords); |
| QStringList words = sentence.split(QLatin1Char(' '), QString::SkipEmptyParts); |
| for (int i = 0; i < words.count(); ++i) { |
| QGraphicsProxyWidget *proxy = new QGraphicsProxyWidget(this); |
| QLabel *label = new QLabel(words.at(i)); |
| proxy->setWidget(label); |
| proxy->setFocusPolicy(Qt::StrongFocus); |
| proxy->setFlag(QGraphicsItem::ItemAcceptsInputMethod, true); |
| if (i%2 == 0) |
| proxy->setVisible(false); |
| proxy->setFocus(); |
| lay->addItem(proxy); |
| } |
| setLayout(lay); |
| } |
| |
| }; |
| |
| class MyWidgetWindow : public QGraphicsWidget |
| { |
| public: |
| MyWidgetWindow() |
| : QGraphicsWidget(0, Qt::Window) |
| { |
| QGraphicsLinearLayout *lay = new QGraphicsLinearLayout(Qt::Vertical); |
| MyGraphicsWidget *widget = new MyGraphicsWidget(); |
| lay->addItem(widget); |
| setLayout(lay); |
| } |
| }; |
| |
| void tst_QGraphicsItem::QTBUG_16374_crashInDestructor() |
| { |
| QGraphicsScene scene; |
| QGraphicsView view(&scene); |
| |
| MyWidgetWindow win; |
| scene.addItem(&win); |
| |
| view.show(); |
| QVERIFY(QTest::qWaitForWindowExposed(&view)); |
| } |
| |
| void tst_QGraphicsItem::QTBUG_20699_focusScopeCrash() |
| { |
| QGraphicsScene scene; |
| QGraphicsView view(&scene); |
| QGraphicsPixmapItem fs; |
| fs.setFlags(QGraphicsItem::ItemIsFocusScope | QGraphicsItem::ItemIsFocusable); |
| scene.addItem(&fs); |
| QGraphicsPixmapItem* fs2 = new QGraphicsPixmapItem(&fs); |
| fs2->setFlags(QGraphicsItem::ItemIsFocusScope | QGraphicsItem::ItemIsFocusable); |
| QGraphicsPixmapItem* fi2 = new QGraphicsPixmapItem(&fs); |
| fi2->setFlags(QGraphicsItem::ItemIsFocusable); |
| QGraphicsPixmapItem* fi = new QGraphicsPixmapItem(fs2); |
| fi->setFlags(QGraphicsItem::ItemIsFocusable); |
| fs.setFocus(); |
| fi->setFocus(); |
| |
| view.show(); |
| QVERIFY(QTest::qWaitForWindowExposed(&view)); |
| |
| fi->setParentItem(fi2); |
| fi->setFocus(); |
| fs.setFocus(); |
| fi->setParentItem(fs2); |
| fi->setFocus(); |
| fs2->setFocus(); |
| fs.setFocus(); |
| fi->setParentItem(fi2); |
| fi->setFocus(); |
| fs.setFocus(); |
| } |
| |
| void tst_QGraphicsItem::QTBUG_30990_rightClickSelection() |
| { |
| QGraphicsScene scene; |
| QGraphicsItem *item1 = scene.addRect(10, 10, 10, 10); |
| item1->setFlags(QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemIsMovable); |
| QGraphicsItem *item2 = scene.addRect(100, 100, 10, 10); |
| item2->setFlags(QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemIsMovable); |
| |
| // right mouse press & release over an item should not make it selected |
| sendMousePress(&scene, item1->boundingRect().center(), Qt::RightButton); |
| QVERIFY(!item1->isSelected()); |
| sendMouseRelease(&scene, item1->boundingRect().center(), Qt::RightButton); |
| QVERIFY(!item1->isSelected()); |
| |
| // right mouse press over one item, moving over another item, |
| // and then releasing should make neither of the items selected |
| sendMousePress(&scene, item1->boundingRect().center(), Qt::RightButton); |
| QVERIFY(!item1->isSelected()); |
| QVERIFY(!item2->isSelected()); |
| sendMouseMove(&scene, item2->boundingRect().center(), Qt::RightButton); |
| QVERIFY(!item1->isSelected()); |
| QVERIFY(!item2->isSelected()); |
| sendMouseRelease(&scene, item2->boundingRect().center(), Qt::RightButton); |
| QVERIFY(!item1->isSelected()); |
| QVERIFY(!item2->isSelected()); |
| } |
| |
| void tst_QGraphicsItem::QTBUG_21618_untransformable_sceneTransform() |
| { |
| QGraphicsScene scene(0, 0, 150, 150); |
| scene.addRect(-2, -2, 4, 4); |
| |
| QGraphicsItem *item1 = scene.addRect(0, 0, 100, 100, QPen(), Qt::red); |
| item1->setPos(50, 50); |
| item1->setTransform(QTransform::fromTranslate(50, 50), true); |
| item1->setTransform(QTransform().rotate(90), true); |
| QGraphicsItem *item2 = scene.addRect(0, 0, 100, 100, QPen(), Qt::green); |
| item2->setPos(50, 50); |
| item2->setTransform(QTransform::fromTranslate(50, 50), true); |
| item2->setTransform(QTransform().rotate(90), true); |
| item2->setFlags(QGraphicsItem::ItemIgnoresTransformations); |
| |
| QGraphicsRectItem *item1_topleft = new QGraphicsRectItem(QRectF(-2, -2, 4, 4)); |
| item1_topleft->setParentItem(item1); |
| item1_topleft->setBrush(Qt::black); |
| QGraphicsRectItem *item1_bottomright = new QGraphicsRectItem(QRectF(-2, -2, 4, 4)); |
| item1_bottomright->setParentItem(item1); |
| item1_bottomright->setPos(100, 100); |
| item1_bottomright->setBrush(Qt::yellow); |
| |
| QGraphicsRectItem *item2_topleft = new QGraphicsRectItem(QRectF(-2, -2, 4, 4)); |
| item2_topleft->setParentItem(item2); |
| item2_topleft->setBrush(Qt::black); |
| QGraphicsRectItem *item2_bottomright = new QGraphicsRectItem(QRectF(-2, -2, 4, 4)); |
| item2_bottomright->setParentItem(item2); |
| item2_bottomright->setPos(100, 100); |
| item2_bottomright->setBrush(Qt::yellow); |
| |
| QCOMPARE(item1->sceneTransform(), item2->sceneTransform()); |
| QCOMPARE(item1_topleft->sceneTransform(), item2_topleft->sceneTransform()); |
| QCOMPARE(item1_bottomright->sceneTransform(), item2_bottomright->sceneTransform()); |
| QCOMPARE(item1->deviceTransform(QTransform()), item2->deviceTransform(QTransform())); |
| QCOMPARE(item1->deviceTransform(QTransform()).map(QPointF()), QPointF(100, 100)); |
| QCOMPARE(item2->deviceTransform(QTransform()).map(QPointF()), QPointF(100, 100)); |
| QCOMPARE(item1->deviceTransform(QTransform()).map(QPointF(100, 100)), QPointF(0, 200)); |
| QCOMPARE(item2->deviceTransform(QTransform()).map(QPointF(100, 100)), QPointF(0, 200)); |
| QCOMPARE(item1_topleft->deviceTransform(QTransform()).map(QPointF()), QPointF(100, 100)); |
| QCOMPARE(item2_topleft->deviceTransform(QTransform()).map(QPointF()), QPointF(100, 100)); |
| QCOMPARE(item1_bottomright->deviceTransform(QTransform()).map(QPointF()), QPointF(0, 200)); |
| QCOMPARE(item2_bottomright->deviceTransform(QTransform()).map(QPointF()), QPointF(0, 200)); |
| |
| item2->setParentItem(item1); |
| |
| QCOMPARE(item2->deviceTransform(QTransform()).map(QPointF()), QPointF(100, 200)); |
| QCOMPARE(item2->deviceTransform(QTransform()).map(QPointF(100, 100)), QPointF(0, 300)); |
| QCOMPARE(item2_topleft->deviceTransform(QTransform()).map(QPointF()), QPointF(100, 200)); |
| QCOMPARE(item2_bottomright->deviceTransform(QTransform()).map(QPointF()), QPointF(0, 300)); |
| |
| QTransform tx = QTransform::fromTranslate(100, 0); |
| QCOMPARE(item1->deviceTransform(tx).map(QPointF()), QPointF(200, 100)); |
| QCOMPARE(item1->deviceTransform(tx).map(QPointF(100, 100)), QPointF(100, 200)); |
| QCOMPARE(item2->deviceTransform(tx).map(QPointF()), QPointF(200, 200)); |
| QCOMPARE(item2->deviceTransform(tx).map(QPointF(100, 100)), QPointF(100, 300)); |
| QCOMPARE(item2_topleft->deviceTransform(tx).map(QPointF()), QPointF(200, 200)); |
| QCOMPARE(item2_bottomright->deviceTransform(tx).map(QPointF()), QPointF(100, 300)); |
| } |
| |
| void tst_QGraphicsItem::resolvePaletteForItemChildren() |
| { |
| QGraphicsScene scene; |
| QGraphicsRectItem item(0, 0, 50, -150); |
| scene.addItem(&item); |
| QGraphicsWidget widget; |
| widget.setParentItem(&item); |
| |
| QColor green(Qt::green); |
| QPalette paletteForScene = scene.palette(); |
| paletteForScene.setColor(QPalette::Active, QPalette::Window, green); |
| scene.setPalette(paletteForScene); |
| |
| QCOMPARE(widget.palette().color(QPalette::Active, QPalette::Window), green); |
| } |
| |
| QTEST_MAIN(tst_QGraphicsItem) |
| #include "tst_qgraphicsitem.moc" |