Do its best in QComboBox to map completer's index

Add additional code paths to map the index passed by QCompleter in its
activated() signal in case when QCompleter's model isn't the same as
QComboBox's one.

Task-number: QTBUG-52027
Change-Id: I1d74037fccbe19962bb7f242aa7b1c2441aa5d54
Reviewed-by: Gabriel de Dietrich <gabriel.dedietrich@qt.io>
This commit is contained in:
Alexey Chernov 2016-03-22 01:01:13 +03:00 committed by Gabriel de Dietrich
parent 46b8997b52
commit 8b6d6d4832
2 changed files with 73 additions and 1 deletions

View File

@ -192,7 +192,21 @@ void QComboBoxPrivate::_q_completerActivated(const QModelIndex &index)
if (index.isValid() && q->completer()) {
QAbstractProxyModel *proxy = qobject_cast<QAbstractProxyModel *>(q->completer()->completionModel());
if (proxy) {
q->setCurrentIndex(proxy->mapToSource(index).row());
const QModelIndex &completerIndex = proxy->mapToSource(index);
int row = -1;
if (completerIndex.model() == model) {
row = completerIndex.row();
} else {
// if QCompleter uses a proxy model to host widget's one - map again
QAbstractProxyModel *completerProxy = qobject_cast<QAbstractProxyModel *>(q->completer()->model());
if (completerProxy && completerProxy->sourceModel() == model) {
row = completerProxy->mapToSource(completerIndex).row();
} else {
QString match = q->completer()->model()->data(completerIndex).toString();
row = q->findText(match, matchFlags());
}
}
q->setCurrentIndex(row);
emitActivated(currentIndex);
}
}

View File

@ -168,6 +168,7 @@ private slots:
void task_QTBUG_49831_scrollerNotActivated();
void task_QTBUG_56693_itemFontFromModel();
void inputMethodUpdate();
void task_QTBUG_52027_mapCompleterIndex();
private:
PlatformInputContext m_platformInputContext;
@ -3399,5 +3400,62 @@ void tst_QComboBox::inputMethodUpdate()
QVERIFY(m_platformInputContext.m_updateCallCount >= 1);
}
void tst_QComboBox::task_QTBUG_52027_mapCompleterIndex()
{
QStringList words;
words << "" << "foobar1" << "foobar2";
QStringList altWords;
altWords << "foobar2" << "hello" << "," << "world" << "" << "foobar0" << "foobar1";
QComboBox cbox;
setFrameless(&cbox);
cbox.setEditable(true);
cbox.setInsertPolicy(QComboBox::NoInsert);
cbox.addItems(words);
QCompleter *completer = new QCompleter(altWords);
completer->setCaseSensitivity(Qt::CaseInsensitive);
cbox.setCompleter(completer);
QSignalSpy spy(&cbox, SIGNAL(activated(int)));
QCOMPARE(spy.count(), 0);
cbox.move(200, 200);
cbox.show();
QApplication::setActiveWindow(&cbox);
QVERIFY(QTest::qWaitForWindowActive(&cbox));
QTest::keyClicks(&cbox, "foobar2");
QApplication::processEvents();
QTRY_VERIFY(completer->popup());
QTest::keyClick(completer->popup(), Qt::Key_Down);
QApplication::processEvents();
QTest::keyClick(completer->popup(), Qt::Key_Return);
QApplication::processEvents();
QList<QVariant> arguments = spy.takeLast();
QCOMPARE(arguments.at(0).toInt(), 2);
cbox.lineEdit()->selectAll();
cbox.lineEdit()->del();
QSortFilterProxyModel* model = new QSortFilterProxyModel();
model->setSourceModel(cbox.model());
model->setFilterFixedString("foobar1");
completer->setModel(model);
QApplication::setActiveWindow(&cbox);
QVERIFY(QTest::qWaitForWindowActive(&cbox));
QTest::keyClicks(&cbox, "foobar1");
QApplication::processEvents();
QTRY_VERIFY(completer->popup());
QTest::keyClick(completer->popup(), Qt::Key_Down);
QApplication::processEvents();
QTest::keyClick(completer->popup(), Qt::Key_Return);
QApplication::processEvents();
arguments = spy.takeLast();
QCOMPARE(arguments.at(0).toInt(), 1);
}
QTEST_MAIN(tst_QComboBox)
#include "tst_qcombobox.moc"