diff --git a/src/widgets/itemviews/qabstractitemdelegate.cpp b/src/widgets/itemviews/qabstractitemdelegate.cpp index 3268fda2fca..117de8edf97 100644 --- a/src/widgets/itemviews/qabstractitemdelegate.cpp +++ b/src/widgets/itemviews/qabstractitemdelegate.cpp @@ -526,7 +526,15 @@ bool QAbstractItemDelegatePrivate::editorEventFilter(QObject *object, QEvent *ev if (tryFixup(editor)) emit q->commitData(editor); + // If the application loses focus while editing, then the focus needs to go back + // to the itemview when the editor closes. This ensures that when the application + // is active again it will have the focus on the itemview as expected. + const bool manuallyFixFocus = (event->type() == QEvent::FocusOut) && !editor->hasFocus() && + editor->parentWidget() && + (static_cast(event)->reason() == Qt::ActiveWindowFocusReason); emit q->closeEditor(editor, QAbstractItemDelegate::NoHint); + if (manuallyFixFocus) + editor->parentWidget()->setFocus(); } #ifndef QT_NO_SHORTCUT } else if (event->type() == QEvent::ShortcutOverride) { diff --git a/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp b/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp index e99ed8f2f42..47232212930 100644 --- a/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp +++ b/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp @@ -149,6 +149,8 @@ private slots: void inputMethodEnabled(); void currentFollowsIndexWidget_data(); void currentFollowsIndexWidget(); + void checkFocusAfterActivationChanges_data(); + void checkFocusAfterActivationChanges(); }; class MyAbstractItemDelegate : public QAbstractItemDelegate @@ -2443,5 +2445,82 @@ void tst_QAbstractItemView::currentFollowsIndexWidget() QCOMPARE(view->currentIndex(), item1->index()); } +class EditorItemDelegate : public QItemDelegate +{ +public: + EditorItemDelegate() : QItemDelegate(), openedEditor(nullptr) { } + QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &, + const QModelIndex &) const override + { + openedEditor = new QLineEdit(parent); + return openedEditor; + } + mutable QPointer openedEditor; +}; + +// Testing the case reported in QTBUG-62253. +// When an itemview with an editor that has focus loses focus +// due to a change in the active window then we need to check +// that the itemview gets focus once the activation is back +// on the original window. +void tst_QAbstractItemView::checkFocusAfterActivationChanges_data() +{ + QTest::addColumn("viewType"); + + QTest::newRow("QListView") << "QListView"; + QTest::newRow("QTableView") << "QTableView"; + QTest::newRow("QTreeView") << "QTreeView"; +} + +void tst_QAbstractItemView::checkFocusAfterActivationChanges() +{ + QFETCH(QString, viewType); + + const QRect availableGeo = qApp->primaryScreen()->availableGeometry(); + const int halfWidth = availableGeo.width() / 2; + QWidget otherTopLevel; + otherTopLevel.setGeometry(availableGeo.x(), availableGeo.y(), + halfWidth, availableGeo.height()); + otherTopLevel.show(); + + QWidget w; + w.setGeometry(availableGeo.x() + halfWidth, availableGeo.y(), + halfWidth, availableGeo.height()); + QLineEdit *le = new QLineEdit(&w); + QAbstractItemView *view = 0; + if (viewType == "QListView") + view = new QListView(&w); + else if (viewType == "QTableView") + view = new QTableView(&w); + else if (viewType == "QTreeView") + view = new QTreeView(&w); + + QStandardItemModel model(5, 5); + view->setModel(&model); + view->move(0, 50); + EditorItemDelegate delegate; + view->setItemDelegate(&delegate); + w.show(); + + QTest::qWaitForWindowActive(&w); + QVERIFY(le->hasFocus()); + + view->setFocus(); + QVERIFY(view->hasFocus()); + + view->edit(model.index(0,0)); + QVERIFY(QTest::qWaitForWindowExposed(delegate.openedEditor)); + QVERIFY(delegate.openedEditor->hasFocus()); + + QApplication::setActiveWindow(&otherTopLevel); + QTest::qWaitForWindowActive(&otherTopLevel); + otherTopLevel.setFocus(); + QVERIFY(!delegate.openedEditor); + + QApplication::setActiveWindow(&w); + QTest::qWaitForWindowActive(&w); + QVERIFY(view->hasFocus()); +} + QTEST_MAIN(tst_QAbstractItemView) #include "tst_qabstractitemview.moc"