From d29f0bc65c1817bb73153cd546d7ab76e0768be0 Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Fri, 25 Aug 2017 16:24:44 +0700 Subject: Avoid calling QCompleter::popup() internally QCompleter::popup() is used to lazily create the popup itself. However, we oftentimes call this function only to check if the popup is visible. Change-Id: I55531e1e6810c02a44f5f65124cf641b1a89de69 Reviewed-by: Gabriel de Dietrich Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/widgets/widgets/qcombobox.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'src/widgets/widgets/qcombobox.cpp') diff --git a/src/widgets/widgets/qcombobox.cpp b/src/widgets/widgets/qcombobox.cpp index b6bb31c391..54d33a7eea 100644 --- a/src/widgets/widgets/qcombobox.cpp +++ b/src/widgets/widgets/qcombobox.cpp @@ -71,6 +71,7 @@ #include #include #include +#include #include #if 0 /* Used to be included in Qt4 for Q_WS_MAC */ && QT_CONFIG(effetcts) && QT_CONFIG(style_mac) #include @@ -3140,13 +3141,13 @@ void QComboBox::keyPressEvent(QKeyEvent *e) Q_D(QComboBox); #if QT_CONFIG(completer) - if (d->lineEdit - && d->lineEdit->completer() - && d->lineEdit->completer()->popup() - && d->lineEdit->completer()->popup()->isVisible()) { - // provide same autocompletion support as line edit - d->lineEdit->event(e); - return; + if (const auto *cmpltr = completer()) { + const auto *popup = QCompleterPrivate::get(cmpltr)->popup; + if (popup && popup->isVisible()) { + // provide same autocompletion support as line edit + d->lineEdit->event(e); + return; + } } #endif -- cgit v1.2.3 From 4c025ca9c73bda320f0e7577a4fbd141c31d7c8c Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Mon, 28 Aug 2017 10:04:35 +0700 Subject: QCompleter: Send activated() signal only once on return key Due to the complex event forwarding logic between QCompleter, QComboBox, QLineEdit and QWidgetLineControl, in some cases the same single user return key press could result in duplicated activated() signals being emitted by QComboBox. The first one would be emitted because QLineEdit emitted editingFinished() as a result of QCompleter::eventFilter() having forwarded the return key press event to QComboBox. The second one, would happen right after, as QCompleter::eventFilter() would process the same event on behalf of its popup. (We recall that QCompleter is installed as its own popup event filter. That's also the case for the completer's widget, although the purpose there is limited to focus-out events). The current fix consists on skipping the emit as a result of QLineEdit::editingFinished() if the completer's popup is still active. For this to be accurate, it helps to test whether the completer's popup is visible, so we will not be hiding it in QWidgetLineControl::processKeyEvent() anymore. Indeed, we know that if the popup is visible, that means that processKeyEvent() was called after being forwarded by the completer's popup event filter. Furthermore, the popup will be hidden by its event filter shortly after it returns from said event forwarding call. Based on a patch by Alexey Chernov <4ernov@gmail.com>. Task-number: QTBUG-51858 Task-number: QTBUG-51889 Change-Id: I013f6c3000ae37b5b0ec20eaf5cf7746c9c903e3 Reviewed-by: Richard Moe Gustavsen --- src/widgets/widgets/qcombobox.cpp | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) (limited to 'src/widgets/widgets/qcombobox.cpp') diff --git a/src/widgets/widgets/qcombobox.cpp b/src/widgets/widgets/qcombobox.cpp index 54d33a7eea..e0bc198d2e 100644 --- a/src/widgets/widgets/qcombobox.cpp +++ b/src/widgets/widgets/qcombobox.cpp @@ -1210,8 +1210,27 @@ Qt::MatchFlags QComboBoxPrivate::matchFlags() const void QComboBoxPrivate::_q_editingFinished() { Q_Q(QComboBox); - if (lineEdit && !lineEdit->text().isEmpty() && itemText(currentIndex) != lineEdit->text()) { - const int index = q_func()->findText(lineEdit->text(), matchFlags()); + if (!lineEdit) + return; + const auto leText = lineEdit->text(); + if (!leText.isEmpty() && itemText(currentIndex) != leText) { +#if QT_CONFIG(completer) + const auto *leCompleter = lineEdit->completer(); + const auto *popup = leCompleter ? QCompleterPrivate::get(leCompleter)->popup : nullptr; + if (popup && popup->isVisible()) { + // QLineEdit::editingFinished() will be emitted before the code flow returns + // to QCompleter::eventFilter(), where QCompleter::activated() may be emitted. + // We know that the completer popup will still be visible at this point, and + // that any selection should be valid. + const QItemSelectionModel *selModel = popup->selectionModel(); + const QModelIndex curIndex = popup->currentIndex(); + const bool completerIsActive = selModel && selModel->selectedIndexes().contains(curIndex); + + if (completerIsActive) + return; + } +#endif + const int index = q_func()->findText(leText, matchFlags()); if (index != -1) { q->setCurrentIndex(index); emitActivated(currentIndex); -- cgit v1.2.3