Itemviews: Set the WA_InputMethodEnabled attribute correctly

When focus is put back onto an itemview and the current item is editable
then the WA_InputMethodEnabled attribute should be set. Likewise this
should be set/unset when the current index changes too, depending on
whether the index is editable or not.

Change-Id: Iaea075e669efd21bdaa89a49c500c449272d098b
Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
This commit is contained in:
Andy Shaw 2017-08-09 11:32:07 +02:00
parent 269c9fce3c
commit 35bb55cd12
2 changed files with 114 additions and 10 deletions

View File

@ -2230,7 +2230,7 @@ void QAbstractItemView::focusInEvent(QFocusEvent *event)
QAbstractScrollArea::focusInEvent(event);
const QItemSelectionModel* model = selectionModel();
const bool currentIndexValid = currentIndex().isValid();
bool currentIndexValid = currentIndex().isValid();
if (model
&& !d->currentIndexSet
@ -2238,19 +2238,16 @@ void QAbstractItemView::focusInEvent(QFocusEvent *event)
bool autoScroll = d->autoScroll;
d->autoScroll = false;
QModelIndex index = moveCursor(MoveNext, Qt::NoModifier); // first visible index
if (index.isValid() && d->isIndexEnabled(index) && event->reason() != Qt::MouseFocusReason)
if (index.isValid() && d->isIndexEnabled(index) && event->reason() != Qt::MouseFocusReason) {
selectionModel()->setCurrentIndex(index, QItemSelectionModel::NoUpdate);
currentIndexValid = true;
}
d->autoScroll = autoScroll;
}
if (model && currentIndexValid) {
if (currentIndex().flags() != Qt::ItemIsEditable)
setAttribute(Qt::WA_InputMethodEnabled, false);
else
setAttribute(Qt::WA_InputMethodEnabled);
}
if (!currentIndexValid)
if (model && currentIndexValid)
setAttribute(Qt::WA_InputMethodEnabled, (currentIndex().flags() & Qt::ItemIsEditable));
else if (!currentIndexValid)
setAttribute(Qt::WA_InputMethodEnabled, false);
d->viewport->update();
@ -3652,6 +3649,7 @@ void QAbstractItemView::currentChanged(const QModelIndex &current, const QModelI
d->shouldScrollToCurrentOnShow = d->autoScroll;
}
}
setAttribute(Qt::WA_InputMethodEnabled, (current.isValid() && (current.flags() & Qt::ItemIsEditable)));
}
#ifndef QT_NO_DRAGANDDROP

View File

@ -55,6 +55,8 @@
#include <qproxystyle.h>
#include <qdialog.h>
Q_DECLARE_METATYPE(Qt::ItemFlags);
static inline void setFrameless(QWidget *w)
{
Qt::WindowFlags flags = w->windowFlags();
@ -154,6 +156,8 @@ private slots:
void testDialogAsEditor();
void QTBUG46785_mouseout_hover_state();
void testClearModelInClickedSignal();
void inputMethodEnabled_data();
void inputMethodEnabled();
};
class MyAbstractItemDelegate : public QAbstractItemDelegate
@ -2291,5 +2295,107 @@ void tst_QAbstractItemView::testClearModelInClickedSignal()
QCOMPARE(view.model(), nullptr);
}
void tst_QAbstractItemView::inputMethodEnabled_data()
{
QTest::addColumn<QByteArray>("viewType");
QTest::addColumn<Qt::ItemFlags>("itemFlags");
QTest::addColumn<bool>("result");
QList<QByteArray> widgets;
widgets << "QListView" << "QTreeView" << "QTableView";
for (const QByteArray &widget : qAsConst(widgets)) {
QTest::newRow(widget + ": no flags") << widget << Qt::ItemFlags(Qt::NoItemFlags) << false;
QTest::newRow(widget + ": checkable") << widget << Qt::ItemFlags(Qt::ItemIsUserCheckable) << false;
QTest::newRow(widget + ": selectable") << widget << Qt::ItemFlags(Qt::ItemIsSelectable) << false;
QTest::newRow(widget + ": enabled") << widget << Qt::ItemFlags(Qt::ItemIsEnabled) << false;
QTest::newRow(widget + ": selectable|enabled")
<< widget << Qt::ItemFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled) << false;
QTest::newRow(widget + ": editable|enabled")
<< widget << Qt::ItemFlags(Qt::ItemIsEditable | Qt::ItemIsEnabled) << true;
QTest::newRow(widget + ": editable|enabled|selectable")
<< widget << Qt::ItemFlags(Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable) << true;
}
}
void tst_QAbstractItemView::inputMethodEnabled()
{
QFETCH(QByteArray, viewType);
QFETCH(Qt::ItemFlags, itemFlags);
QFETCH(bool, result);
QScopedPointer<QAbstractItemView> 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 *item = new QStandardItem("first item");
item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
model->appendRow(item);
QStandardItem *secondItem = new QStandardItem("test item");
secondItem->setFlags(Qt::ItemFlags(itemFlags));
model->appendRow(secondItem);
view->setModel(model);
// Check current changed
view->setCurrentIndex(model->index(0, 0));
QVERIFY(!view->testAttribute(Qt::WA_InputMethodEnabled));
view->setCurrentIndex(model->index(1, 0));
QCOMPARE(view->testAttribute(Qt::WA_InputMethodEnabled), result);
view->setCurrentIndex(model->index(0, 0));
QVERIFY(!view->testAttribute(Qt::WA_InputMethodEnabled));
// Check focus by switching the activation of the window to force a focus in
view->setCurrentIndex(model->index(1, 0));
QApplication::setActiveWindow(0);
QApplication::setActiveWindow(view.data());
QVERIFY(QTest::qWaitForWindowActive(view.data()));
QCOMPARE(view->testAttribute(Qt::WA_InputMethodEnabled), result);
view->setCurrentIndex(QModelIndex());
QVERIFY(!view->testAttribute(Qt::WA_InputMethodEnabled));
QApplication::setActiveWindow(0);
QApplication::setActiveWindow(view.data());
QVERIFY(QTest::qWaitForWindowActive(view.data()));
QModelIndex index = model->index(1, 0);
QPoint p = view->visualRect(index).center();
QTest::mouseClick(view->viewport(), Qt::LeftButton, Qt::NoModifier, p);
if (itemFlags & Qt::ItemIsEnabled)
QCOMPARE(view->currentIndex(), index);
QCOMPARE(view->testAttribute(Qt::WA_InputMethodEnabled), result);
index = model->index(0, 0);
QApplication::setActiveWindow(0);
QApplication::setActiveWindow(view.data());
QVERIFY(QTest::qWaitForWindowActive(view.data()));
p = view->visualRect(index).center();
QTest::mouseClick(view->viewport(), Qt::LeftButton, Qt::NoModifier, p);
QCOMPARE(view->currentIndex(), index);
QVERIFY(!view->testAttribute(Qt::WA_InputMethodEnabled));
// There is a case when it goes to the first visible item so we
// make the flags of the first item match the ones we are testing
// to check the attribute correctly
QApplication::setActiveWindow(0);
view->setCurrentIndex(QModelIndex());
view->reset();
item->setFlags(Qt::ItemFlags(itemFlags));
QApplication::setActiveWindow(view.data());
QVERIFY(QTest::qWaitForWindowActive(view.data()));
QCOMPARE(view->testAttribute(Qt::WA_InputMethodEnabled), result);
}
QTEST_MAIN(tst_QAbstractItemView)
#include "tst_qabstractitemview.moc"