summaryrefslogtreecommitdiffstats
path: root/tests/auto/widgets
diff options
context:
space:
mode:
authorAxel Spoerl <axel.spoerl@qt.io>2023-03-10 17:04:16 +0100
committerAxel Spoerl <axel.spoerl@qt.io>2023-03-14 21:15:31 +0100
commit425e635ecd8d588a87da66a1ef89fbf9ef469f1e (patch)
treeac0fd88eb66d4b9d6e63bf85c50c7a1120c35db5 /tests/auto/widgets
parentc99614711ed9df0d7b942585a258537c9d12d298 (diff)
QCompleter::setPopup() - refactor and cleanup
QCompleter::setPopup() sets window flags, focus policy, parent, focus proxy, item delate and installs an event filter, before the popup argument is assigned to d->popup. In the QCompleter::eventFilter override, QObject::eventFilter is called (under more) if d->popup is nullptr. If a custom class is inherited from QCompleter and it overrides QObject::eventFilter(), this causes an infinite loop. This patch re-factors the method. - early return is added if the new popup != d->popup - remembering the existing widget's focus policy is constified and moved ahead of the delete secion. - assignment of d->popup to popup argument is moved after the delete section. - after assignment, the argument variable is no longer used. The refactoring eliminates two issues: - potential risk of double-installing event filter due to missing early return. - inifite loop if inherited class installs another event filter. The patch adds a test function to tst_QCompleter, which implements an inherited class, installs an event filter on a popup and checks if a ChildAdded event hass been recorded. Fixes: QTBUG-111869 Pick-to: 6.5 6.2 Change-Id: I3f7a2434a11476077a5260e7686a912da9f6c60d Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
Diffstat (limited to 'tests/auto/widgets')
-rw-r--r--tests/auto/widgets/util/qcompleter/tst_qcompleter.cpp38
1 files changed, 38 insertions, 0 deletions
diff --git a/tests/auto/widgets/util/qcompleter/tst_qcompleter.cpp b/tests/auto/widgets/util/qcompleter/tst_qcompleter.cpp
index e8ebaf1491..030bb1cf5b 100644
--- a/tests/auto/widgets/util/qcompleter/tst_qcompleter.cpp
+++ b/tests/auto/widgets/util/qcompleter/tst_qcompleter.cpp
@@ -123,6 +123,7 @@ private slots:
void QTBUG_52028_tabAutoCompletes();
void QTBUG_51889_activatedSentTwice();
void showPopupInGraphicsView();
+ void inheritedEventFilter();
private:
void filter(bool assync = false);
@@ -1863,5 +1864,42 @@ void tst_QCompleter::showPopupInGraphicsView()
QVERIFY(lineEdit.completer()->popup()->geometry().bottom() < lineEdit.mapToGlobal(QPoint(0, 0)).y());
}
+void tst_QCompleter::inheritedEventFilter()
+{
+ class Completer : public QCompleter
+ {
+ public:
+ explicit Completer(QWidget *parent) : QCompleter(parent)
+ {
+ Q_ASSERT(parent);
+ setPopup(new QListView());
+ popup()->installEventFilter(this);
+ }
+
+ bool m_popupChildAdded = false;
+
+ protected:
+ bool eventFilter(QObject *watched, QEvent *event) override
+ {
+ if (watched == popup() && event->type() == QEvent::ChildAdded)
+ m_popupChildAdded = true;
+
+ return QCompleter::eventFilter(watched, event);
+ }
+ };
+
+ QComboBox comboBox;
+ comboBox.setEditable(true);
+ Completer *completer = new Completer(&comboBox);
+ comboBox.setCompleter(completer);
+
+ // comboBox.show() must not crash with an infinite loop in the event filter
+ comboBox.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&comboBox));
+
+ // Since event orders are platform dependent, only the the ChildAdded event is checked.
+ QVERIFY(QTest::qWaitFor([completer](){return completer->m_popupChildAdded; }));
+}
+
QTEST_MAIN(tst_QCompleter)
#include "tst_qcompleter.moc"