diff options
author | Andreas Aardal Hanssen <andreas.hanssen@tandberg.com> | 2010-07-08 08:43:50 (GMT) |
---|---|---|
committer | Yoann Lopes <yoann.lopes@nokia.com> | 2010-07-08 11:22:21 (GMT) |
commit | 2ab84f72671013380d397afe2bb407823446516c (patch) | |
tree | 5ea25f0728eabf239dd69a7dfd9bdf4ba08c2691 | |
parent | 6d5655089fa4e2231a1a8edc98ecbb6b29e344e1 (diff) | |
download | Qt-2ab84f72671013380d397afe2bb407823446516c.zip Qt-2ab84f72671013380d397afe2bb407823446516c.tar.gz Qt-2ab84f72671013380d397afe2bb407823446516c.tar.bz2 |
Fix subfocus when reparenting panels.
When reparenting an item into another, QGraphicsItem will fix the
subfocus chain by first removing subfocus from the previous ancestors,
and then optionally restoring the subfocus chain to the new ancestors
of the reparented item. This allows item trees to be created and
assigned a specific focus item before even added to a scene.
The QGraphicsItemPrivate::setSubFocus function did not take into
account that the root item might be in a different panel than the
reparented item, which is the case when reparenting one panel into
another. If so, setSubFocus must not mess up the new ancestor panel's
sub focus chain. Otherwise (former behavior), the new ancestor
panel's focusItem will point to the reparented panel's focus item. This
in turn breaks an invariant; one panel's focusItem can never point to
an item in another panel.
The bundled test case shows this point: Create two panels that each have
one child that sets focus. The first panel is added to the scene just
to prepare, and verify that it's activated as expected, and its focus
child immediately gains input focus. Then we create a second panel,
which also has a focus child (but it doesn't have focus as its panel is
not active). When we reparent the new panel onto the old one, we expect
the new panel to be activated, and the child focus item to gain input
focus. However, we also expect the parent panel's focus item to remain
intact, so that when we hide the child panel, and the parent panel is
reactivated, its original focus item regains focus.
Former behavior was that the parent's focus item still pointed to the
child panel focus item.
This change only has effect when reparenting to or from a panel.
Merge-request: 735
Reviewed-by: Yoann Lopes <yoann.lopes@nokia.com>
-rw-r--r-- | src/gui/graphicsview/qgraphicsitem.cpp | 3 | ||||
-rw-r--r-- | tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp | 49 |
2 files changed, 52 insertions, 0 deletions
diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 51dc543..848de2c 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -5510,6 +5510,9 @@ void QGraphicsItemPrivate::setSubFocus(QGraphicsItem *rootItem) // Update focus child chain. Stop at panels, or if this item // is hidden, stop at the first item with a visible parent. QGraphicsItem *parent = rootItem ? rootItem : q_ptr; + if (parent->panel() != q_ptr->panel()) + return; + do { // Clear any existing ancestor's subFocusItem. if (parent != q_ptr && parent->d_ptr->subFocusItem) { diff --git a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp index 31a6845..1ae3ecf 100644 --- a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp +++ b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp @@ -422,6 +422,7 @@ private slots: void setGraphicsEffect(); void panel(); void addPanelToActiveScene(); + void panelWithFocusItem(); void activate(); void setActivePanelOnInactiveScene(); void activationOnShowHide(); @@ -8416,6 +8417,54 @@ void tst_QGraphicsItem::panel() QVERIFY(!panel1->isActive()); } +void tst_QGraphicsItem::panelWithFocusItem() +{ + QGraphicsScene scene; + QEvent activate(QEvent::WindowActivate); + QApplication::sendEvent(&scene, &activate); + + QGraphicsRectItem *parentPanel = new QGraphicsRectItem; + QGraphicsRectItem *parentPanelFocusItem = new QGraphicsRectItem(parentPanel); + parentPanel->setFlag(QGraphicsItem::ItemIsPanel); + parentPanelFocusItem->setFlag(QGraphicsItem::ItemIsFocusable); + parentPanelFocusItem->setFocus(); + scene.addItem(parentPanel); + + QVERIFY(parentPanel->isActive()); + QVERIFY(parentPanelFocusItem->hasFocus()); + QCOMPARE(parentPanel->focusItem(), (QGraphicsItem *)parentPanelFocusItem); + QCOMPARE(parentPanelFocusItem->focusItem(), (QGraphicsItem *)parentPanelFocusItem); + + QGraphicsRectItem *childPanel = new QGraphicsRectItem; + QGraphicsRectItem *childPanelFocusItem = new QGraphicsRectItem(childPanel); + childPanel->setFlag(QGraphicsItem::ItemIsPanel); + childPanelFocusItem->setFlag(QGraphicsItem::ItemIsFocusable); + childPanelFocusItem->setFocus(); + + QVERIFY(!childPanelFocusItem->hasFocus()); + QCOMPARE(childPanel->focusItem(), (QGraphicsItem *)childPanelFocusItem); + QCOMPARE(childPanelFocusItem->focusItem(), (QGraphicsItem *)childPanelFocusItem); + + 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()); + QCOMPARE(childPanel->focusItem(), (QGraphicsItem *)childPanelFocusItem); + QCOMPARE(childPanelFocusItem->focusItem(), (QGraphicsItem *)childPanelFocusItem); + + childPanel->hide(); + + QVERIFY(parentPanel->isActive()); + QVERIFY(parentPanelFocusItem->hasFocus()); + QCOMPARE(parentPanel->focusItem(), (QGraphicsItem *)parentPanelFocusItem); + QCOMPARE(parentPanelFocusItem->focusItem(), (QGraphicsItem *)parentPanelFocusItem); +} + void tst_QGraphicsItem::addPanelToActiveScene() { QGraphicsScene scene; |