Fix tabFocusFirst when that item is removed from QGraphicsScene

If tabFocusFirst is not cleared or set to another valid item,
there will be crash later if the removed item is deleted after
removal.

Task-number: QTBUG-30923
Change-Id: Iba9a6ce9334c52f8e552b0accda95ebb5fcfcdb1
Reviewed-by: Jan Arve Sæther <jan-arve.saether@digia.com>
bb10
Miikka Heikkinen 2013-04-30 10:35:06 +03:00 committed by The Qt Project
parent bf2a0c795e
commit 01bc34088e
2 changed files with 27 additions and 0 deletions

View File

@ -637,6 +637,15 @@ void QGraphicsScenePrivate::removeItemHelper(QGraphicsItem *item)
if (item == lastActivePanel)
lastActivePanel = 0;
// Change tabFocusFirst to the next widget in focus chain if removing the current one.
if (item == tabFocusFirst) {
QGraphicsWidgetPrivate *wd = tabFocusFirst->d_func();
if (wd->focusNext && wd->focusNext != tabFocusFirst && wd->focusNext->scene() == q)
tabFocusFirst = wd->focusNext;
else
tabFocusFirst = 0;
}
// Cancel active touches
{
QMap<int, QGraphicsItem *>::iterator it = itemForTouchPointId.begin();

View File

@ -1695,6 +1695,24 @@ void tst_QGraphicsWidget::verifyFocusChain()
QVERIFY(w1_1->hasFocus());
delete w;
}
{
// QTBUG-30923:
// Child QGraphicsWidget with tabFocusFirst gets removed & deleted should not crash.
// This case simulates what QtQuick1 does when you have QGraphicsObject based
// item in different qml views that are loaded one after another.
QGraphicsItem *parent1 = new QGraphicsRectItem(0); // root item
scene.addItem(parent1);
for (int i = 0; i < 2; i++) {
SubQGraphicsWidget *w1 = new SubQGraphicsWidget(parent1);
w1->setFocusPolicy(Qt::StrongFocus);
w1->setFocus();
QVERIFY(w1->hasFocus());
scene.removeItem(w1);
delete w1;
QApplication::processEvents();
}
delete parent1;
}
{
// remove the tabFocusFirst widget from the scene.
QWidget *window = new QWidget;