summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Aardal Hanssen <andreas.hanssen@tandberg.com>2010-07-08 08:43:50 (GMT)
committerYoann Lopes <yoann.lopes@nokia.com>2010-07-08 11:22:21 (GMT)
commit2ab84f72671013380d397afe2bb407823446516c (patch)
tree5ea25f0728eabf239dd69a7dfd9bdf4ba08c2691
parent6d5655089fa4e2231a1a8edc98ecbb6b29e344e1 (diff)
downloadQt-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.cpp3
-rw-r--r--tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp49
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;