diff --git a/src/widgets/itemviews/qabstractitemview.cpp b/src/widgets/itemviews/qabstractitemview.cpp index 5bf4fec92c..a07297863d 100644 --- a/src/widgets/itemviews/qabstractitemview.cpp +++ b/src/widgets/itemviews/qabstractitemview.cpp @@ -3217,12 +3217,14 @@ void QAbstractItemView::setIndexWidget(const QModelIndex &index, QWidget *widget if (QWidget *oldWidget = indexWidget(index)) { d->persistent.remove(oldWidget); d->removeEditor(oldWidget); + oldWidget->removeEventFilter(this); oldWidget->deleteLater(); } if (widget) { widget->setParent(viewport()); d->persistent.insert(widget); d->addEditor(index, widget, true); + widget->installEventFilter(this); widget->show(); dataChanged(index, index); // update the geometry if (!d->delayedPendingLayout) @@ -4499,6 +4501,24 @@ QModelIndexList QAbstractItemViewPrivate::selectedDraggableIndexes() const return indexes; } +/*! + \reimp +*/ + +bool QAbstractItemView::eventFilter(QObject *object, QEvent *event) +{ + Q_D(QAbstractItemView); + if (object == this || object == viewport() || event->type() != QEvent::FocusIn) + return QAbstractScrollArea::eventFilter(object, event); + QWidget *widget = qobject_cast(object); + // If it is not a persistent widget then we did not install + // the event filter on it, so assume a base implementation is + // filtering + if (!widget || !d->persistent.contains(widget)) + return QAbstractScrollArea::eventFilter(object, event); + setCurrentIndex(d->indexForEditor(widget)); + return false; +} QT_END_NAMESPACE diff --git a/src/widgets/itemviews/qabstractitemview.h b/src/widgets/itemviews/qabstractitemview.h index 96745a84ea..8a138bdb67 100644 --- a/src/widgets/itemviews/qabstractitemview.h +++ b/src/widgets/itemviews/qabstractitemview.h @@ -346,6 +346,7 @@ protected: void resizeEvent(QResizeEvent *event) override; void timerEvent(QTimerEvent *event) override; void inputMethodEvent(QInputMethodEvent *event) override; + bool eventFilter(QObject *object, QEvent *event) override; #ifndef QT_NO_DRAGANDDROP enum DropIndicatorPosition { OnItem, AboveItem, BelowItem, OnViewport }; diff --git a/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp b/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp index f6723ceba4..e99ed8f2f4 100644 --- a/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp +++ b/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp @@ -147,6 +147,8 @@ private slots: void testClearModelInClickedSignal(); void inputMethodEnabled_data(); void inputMethodEnabled(); + void currentFollowsIndexWidget_data(); + void currentFollowsIndexWidget(); }; class MyAbstractItemDelegate : public QAbstractItemDelegate @@ -2390,5 +2392,56 @@ void tst_QAbstractItemView::inputMethodEnabled() QCOMPARE(view->testAttribute(Qt::WA_InputMethodEnabled), result); } +void tst_QAbstractItemView::currentFollowsIndexWidget_data() +{ + QTest::addColumn("viewType"); + + QList widgets; + widgets << "QListView" << "QTreeView" << "QTableView"; + for (const QByteArray &widget : qAsConst(widgets)) + QTest::newRow(widget) << widget; +} + +void tst_QAbstractItemView::currentFollowsIndexWidget() +{ + QFETCH(QByteArray, viewType); + + QScopedPointer view; + if (viewType == "QListView") + view.reset(new QListView()); + else if (viewType == "QTableView") + view.reset(new QTableView()); + else if (viewType == "QTreeView") + view.reset(new QTreeView()); + else + QVERIFY(0); + + centerOnScreen(view.data()); + view->show(); + QVERIFY(QTest::qWaitForWindowExposed(view.data())); + + QStandardItemModel *model = new QStandardItemModel(view.data()); + QStandardItem *item1 = new QStandardItem("first item"); + item1->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); + model->appendRow(item1); + + QStandardItem *item2 = new QStandardItem("test item"); + item2->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); + model->appendRow(item2); + + view->setModel(model); + QLineEdit *lineEdit1 = new QLineEdit; + QLineEdit *lineEdit2 = new QLineEdit; + view->setIndexWidget(item1->index(), lineEdit1); + view->setIndexWidget(item2->index(), lineEdit2); + + lineEdit2->setFocus(); + QTRY_VERIFY(lineEdit2->hasFocus()); + QCOMPARE(view->currentIndex(), item2->index()); + lineEdit1->setFocus(); + QTRY_VERIFY(lineEdit1->hasFocus()); + QCOMPARE(view->currentIndex(), item1->index()); +} + QTEST_MAIN(tst_QAbstractItemView) #include "tst_qabstractitemview.moc"