QComboBox: fix item activation via completer

Task-number: QTBUG-31146
Change-Id: I64291f397d80bf934152f63e629810540abf466e
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@digia.com>
Reviewed-by: Stephen Kelly <stephen.kelly@kdab.com>
Reviewed-by: Thorbjørn Lund Martsum <tmartsum@gmail.com>
This commit is contained in:
J-P Nurmi 2013-07-02 15:49:50 +02:00 committed by The Qt Project
parent d0c8fc3b28
commit 737abb8a5e
4 changed files with 65 additions and 9 deletions

View File

@ -59,6 +59,7 @@
#include <qheaderview.h> #include <qheaderview.h>
#include <qmath.h> #include <qmath.h>
#include <qmetaobject.h> #include <qmetaobject.h>
#include <qabstractproxymodel.h>
#include <private/qguiapplication_p.h> #include <private/qguiapplication_p.h>
#include <private/qapplication_p.h> #include <private/qapplication_p.h>
#include <private/qcombobox_p.h> #include <private/qcombobox_p.h>
@ -173,18 +174,28 @@ QStyleOptionMenuItem QComboMenuDelegate::getStyleOption(const QStyleOptionViewIt
return menuOption; return menuOption;
} }
#ifdef QT_KEYPAD_NAVIGATION #ifndef QT_NO_COMPLETER
void QComboBoxPrivate::_q_completerActivated() void QComboBoxPrivate::_q_completerActivated(const QModelIndex &index)
{ {
Q_Q(QComboBox); Q_Q(QComboBox);
if (index.isValid() && q->completer()) {
QAbstractProxyModel *proxy = qobject_cast<QAbstractProxyModel *>(q->completer()->completionModel());
if (proxy) {
q->setCurrentIndex(proxy->mapToSource(index).row());
emitActivated(currentIndex);
}
}
# ifdef QT_KEYPAD_NAVIGATION
if ( QApplication::keypadNavigationEnabled() if ( QApplication::keypadNavigationEnabled()
&& q->isEditable() && q->isEditable()
&& q->completer() && q->completer()
&& q->completer()->completionMode() == QCompleter::UnfilteredPopupCompletion ) { && q->completer()->completionMode() == QCompleter::UnfilteredPopupCompletion ) {
q->setEditFocus(false); q->setEditFocus(false);
} }
# endif // QT_KEYPAD_NAVIGATION
} }
#endif #endif // !QT_NO_COMPLETER
void QComboBoxPrivate::updateArrow(QStyle::StateFlag state) void QComboBoxPrivate::updateArrow(QStyle::StateFlag state)
{ {
@ -1149,6 +1160,14 @@ void QComboBoxPrivate::_q_editingFinished()
void QComboBoxPrivate::_q_returnPressed() void QComboBoxPrivate::_q_returnPressed()
{ {
Q_Q(QComboBox); Q_Q(QComboBox);
// The insertion code below does not apply when the policy is QComboBox::NoInsert.
// In case a completer is installed, item activation via the completer is handled
// in _q_completerActivated(). Otherwise _q_editingFinished() updates the current
// index as appropriate.
if (insertPolicy == QComboBox::NoInsert)
return;
if (lineEdit && !lineEdit->text().isEmpty()) { if (lineEdit && !lineEdit->text().isEmpty()) {
if (q->count() >= maxCount && !(this->insertPolicy == QComboBox::InsertAtCurrent)) if (q->count() >= maxCount && !(this->insertPolicy == QComboBox::InsertAtCurrent))
return; return;
@ -1191,7 +1210,6 @@ void QComboBoxPrivate::_q_returnPressed()
break; break;
} }
break; break;
case QComboBox::NoInsert:
default: default:
break; break;
} }
@ -1393,6 +1411,7 @@ void QComboBox::setAutoCompletion(bool enable)
if (d->lineEdit->completer()) if (d->lineEdit->completer())
return; return;
d->completer = new QCompleter(d->model, d->lineEdit); d->completer = new QCompleter(d->model, d->lineEdit);
connect(d->completer, SIGNAL(activated(QModelIndex)), this, SLOT(_q_completerActivated(QModelIndex)));
d->completer->setCaseSensitivity(d->autoCompletionCaseSensitivity); d->completer->setCaseSensitivity(d->autoCompletionCaseSensitivity);
d->completer->setCompletionMode(QCompleter::InlineCompletion); d->completer->setCompletionMode(QCompleter::InlineCompletion);
d->completer->setCompletionColumn(d->modelColumn); d->completer->setCompletionColumn(d->modelColumn);
@ -1805,8 +1824,10 @@ void QComboBox::setCompleter(QCompleter *c)
if (!d->lineEdit) if (!d->lineEdit)
return; return;
d->lineEdit->setCompleter(c); d->lineEdit->setCompleter(c);
if (c) if (c) {
connect(c, SIGNAL(activated(QModelIndex)), this, SLOT(_q_completerActivated(QModelIndex)));
c->setWidget(this); c->setWidget(this);
}
} }
/*! /*!

View File

@ -259,8 +259,8 @@ private:
Q_PRIVATE_SLOT(d_func(), void _q_rowsRemoved(const QModelIndex & parent, int start, int end)) Q_PRIVATE_SLOT(d_func(), void _q_rowsRemoved(const QModelIndex & parent, int start, int end))
Q_PRIVATE_SLOT(d_func(), void _q_modelDestroyed()) Q_PRIVATE_SLOT(d_func(), void _q_modelDestroyed())
Q_PRIVATE_SLOT(d_func(), void _q_modelReset()) Q_PRIVATE_SLOT(d_func(), void _q_modelReset())
#ifdef QT_KEYPAD_NAVIGATION #ifndef QT_NO_COMPLETER
Q_PRIVATE_SLOT(d_func(), void _q_completerActivated()) Q_PRIVATE_SLOT(d_func(), void _q_completerActivated(const QModelIndex &index))
#endif #endif
}; };

View File

@ -348,8 +348,8 @@ public:
void _q_emitCurrentIndexChanged(const QModelIndex &index); void _q_emitCurrentIndexChanged(const QModelIndex &index);
void _q_modelDestroyed(); void _q_modelDestroyed();
void _q_modelReset(); void _q_modelReset();
#ifdef QT_KEYPAD_NAVIGATION #ifndef QT_NO_COMPLETER
void _q_completerActivated(); void _q_completerActivated(const QModelIndex &index);
#endif #endif
void _q_resetButton(); void _q_resetButton();
void _q_dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight); void _q_dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight);

View File

@ -160,6 +160,7 @@ private slots:
void maxVisibleItems(); void maxVisibleItems();
void task_QTBUG_10491_currentIndexAndModelColumn(); void task_QTBUG_10491_currentIndexAndModelColumn();
void highlightedSignal(); void highlightedSignal();
void task_QTBUG_31146_popupCompletion();
}; };
class MyAbstractItemDelegate : public QAbstractItemDelegate class MyAbstractItemDelegate : public QAbstractItemDelegate
@ -2755,5 +2756,39 @@ void tst_QComboBox::highlightedSignal()
QCOMPARE(spy.size(), 1); QCOMPARE(spy.size(), 1);
} }
void tst_QComboBox::task_QTBUG_31146_popupCompletion()
{
QComboBox comboBox;
comboBox.setEditable(true);
comboBox.setAutoCompletion(true);
comboBox.setInsertPolicy(QComboBox::NoInsert);
comboBox.completer()->setCaseSensitivity(Qt::CaseInsensitive);
comboBox.completer()->setCompletionMode(QCompleter::PopupCompletion);
comboBox.addItems(QStringList() << QStringLiteral("item") << QStringLiteral("item"));
comboBox.show();
comboBox.activateWindow();
QVERIFY(QTest::qWaitForWindowActive(&comboBox));
QCOMPARE(comboBox.currentIndex(), 0);
comboBox.lineEdit()->selectAll();
QTest::keyClicks(comboBox.lineEdit(), "item");
QTest::keyClick(comboBox.completer()->popup(), Qt::Key_Down);
QTest::keyClick(comboBox.completer()->popup(), Qt::Key_Down);
QTest::keyClick(comboBox.completer()->popup(), Qt::Key_Enter);
QCOMPARE(comboBox.currentIndex(), 1);
comboBox.lineEdit()->selectAll();
QTest::keyClicks(comboBox.lineEdit(), "item");
QTest::keyClick(comboBox.completer()->popup(), Qt::Key_Up);
QTest::keyClick(comboBox.completer()->popup(), Qt::Key_Up);
QTest::keyClick(comboBox.completer()->popup(), Qt::Key_Enter);
QCOMPARE(comboBox.currentIndex(), 0);
}
QTEST_MAIN(tst_QComboBox) QTEST_MAIN(tst_QComboBox)
#include "tst_qcombobox.moc" #include "tst_qcombobox.moc"