From 7d09f690d5b4c56699092444665d1879deb86a6e Mon Sep 17 00:00:00 2001
From: Yoann Lopes <yoann.lopes@nokia.com>
Date: Fri, 9 Jul 2010 16:28:18 +0200
Subject: Fixes crash in QGraphicsScene::addItem().
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Crashed because tabFocusFirst could end up being a dangling pointer when
removing an item from the scene before deleting it.
When setting tabFocusFirst in fixFocusChainBeforeReparenting, we now
check that the item is in the scene. If it is not, tabFocusFirst is set
to 0.

Autotest included.

Task-number: QTBUG-12056
Reviewed-by: Alexis Ménard <alexis.menard@nokia.com>
---
 src/gui/graphicsview/qgraphicswidget_p.cpp         |  4 ++--
 tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp | 20 ++++++++++++++++++++
 2 files changed, 22 insertions(+), 2 deletions(-)

diff --git a/src/gui/graphicsview/qgraphicswidget_p.cpp b/src/gui/graphicsview/qgraphicswidget_p.cpp
index 28070da..f7850ca 100644
--- a/src/gui/graphicsview/qgraphicswidget_p.cpp
+++ b/src/gui/graphicsview/qgraphicswidget_p.cpp
@@ -761,7 +761,7 @@ void QGraphicsWidgetPrivate::fixFocusChainBeforeReparenting(QGraphicsWidget *new
 
     QGraphicsWidget *firstOld = 0;
     bool wasPreviousNew = true;
-    
+
     while (w != q) {
         bool isCurrentNew = q->isAncestorOf(w);
         if (isCurrentNew) {
@@ -796,7 +796,7 @@ void QGraphicsWidgetPrivate::fixFocusChainBeforeReparenting(QGraphicsWidget *new
         newScene = newParent->scene();
 
     if (oldScene && newScene != oldScene)
-        oldScene->d_func()->tabFocusFirst = firstOld;
+        oldScene->d_func()->tabFocusFirst = (firstOld && firstOld->scene() == oldScene) ? firstOld : 0;
 
     QGraphicsItem *topLevelItem = newParent ? newParent->topLevelItem() : 0;
     QGraphicsWidget *topLevel = 0;
diff --git a/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp b/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp
index ed8ff04..a771332 100644
--- a/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp
+++ b/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp
@@ -176,6 +176,7 @@ private slots:
     void task243004_setStyleCrash();
     void task250119_shortcutContext();
     void QT_BUG_6544_tabFocusFirstUnsetWhenRemovingItems();
+    void QT_BUG_12056_tabFocusFirstUnsetWhenRemovingItems();
 };
 
 
@@ -3089,6 +3090,25 @@ void tst_QGraphicsWidget::QT_BUG_6544_tabFocusFirstUnsetWhenRemovingItems()
 
     //This should not crash
 }
+void tst_QGraphicsWidget::QT_BUG_12056_tabFocusFirstUnsetWhenRemovingItems()
+{
+    QGraphicsScene scene;
+    QGraphicsWidget* item1 = new QGraphicsWidget;
+    QGraphicsWidget* item2 = new QGraphicsWidget;
+    QGraphicsWidget* item3 = new QGraphicsWidget;
+
+    scene.addItem(item1);
+    scene.addItem(item2);
+
+    scene.removeItem(item2);
+    scene.removeItem(item1);
+    delete item2;
+    delete item1;
+
+    scene.addItem(item3);
+
+    //This should not crash
+}
 
 QTEST_MAIN(tst_QGraphicsWidget)
 #include "tst_qgraphicswidget.moc"
-- 
cgit v0.12


From b5b011a181bd187dcef5ee8f46a3ac2c5dc2e09c Mon Sep 17 00:00:00 2001
From: Yoann Lopes <yoann.lopes@nokia.com>
Date: Tue, 13 Jul 2010 14:21:44 +0200
Subject: Fixes QGraphicsItem::focusItem() returning incorrect value.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

When setting focus on an item, subfocus chain was previously updated
only for items with a common ancestor. We now make sure that this chain
is updated also for the previously focused item (possibly not sharing
any common ancestor with the newly focused item).

Autotest included.

Task-number: QTBUG-12112
Reviewed-by: Alexis Ménard <alexis.menard@nokia.com>
---
 src/gui/graphicsview/qgraphicsitem.cpp         |  6 ++++--
 tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp | 27 ++++++++++++++++++++++++++
 2 files changed, 31 insertions(+), 2 deletions(-)

diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp
index 848de2c..fe2a84e 100644
--- a/src/gui/graphicsview/qgraphicsitem.cpp
+++ b/src/gui/graphicsview/qgraphicsitem.cpp
@@ -3257,6 +3257,8 @@ void QGraphicsItemPrivate::setFocusHelper(Qt::FocusReason focusReason, bool clim
     }
 
     // Update the child focus chain.
+    if (scene && scene->focusItem())
+        scene->focusItem()->d_ptr->clearSubFocus();
     f->d_ptr->setSubFocus();
 
     // Update the scene's focus item.
@@ -7637,9 +7639,9 @@ int QGraphicsItemPrivate::children_count(QDeclarativeListProperty<QGraphicsObjec
 QGraphicsObject *QGraphicsItemPrivate::children_at(QDeclarativeListProperty<QGraphicsObject> *list, int index)
 {
     QGraphicsItemPrivate *d = QGraphicsItemPrivate::get(static_cast<QGraphicsObject *>(list->object));
-    if (index >= 0 && index < d->children.count()) 
+    if (index >= 0 && index < d->children.count())
         return d->children.at(index)->toGraphicsObject();
-    else 
+    else
         return 0;
 }
 
diff --git a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp
index 1ae3ecf..3634ce9 100644
--- a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp
+++ b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp
@@ -463,6 +463,7 @@ private slots:
     void sortItemsWhileAdding();
     void doNotMarkFullUpdateIfNotInScene();
     void itemDiesDuringDraggingOperation();
+    void QTBUG_12112_focusItem();
 
 private:
     QList<QGraphicsItem *> paintedItems;
@@ -10724,5 +10725,31 @@ void tst_QGraphicsItem::itemDiesDuringDraggingOperation()
     delete item;
     QVERIFY(QGraphicsScenePrivate::get(&scene)->dragDropItem == 0);
 }
+
+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);
+    QTest::qWaitForWindowShown(&view);
+    QTRY_COMPARE(QApplication::activeWindow(), (QWidget *)&view);
+
+    QVERIFY(item1->focusItem());
+    QVERIFY(!item2->focusItem());
+
+    item2->setFocus();
+    QVERIFY(!item1->focusItem());
+    QVERIFY(item2->focusItem());
+}
+
 QTEST_MAIN(tst_QGraphicsItem)
 #include "tst_qgraphicsitem.moc"
-- 
cgit v0.12