From 60a67dc41eb79ed488e8509769a2e2b96bed93bb Mon Sep 17 00:00:00 2001 From: Yin Jie Date: Thu, 16 Dec 2021 13:37:53 +0800 Subject: [PATCH] Position QCompleter popup based on the widget's screen geometry If adding a QLineEdit to a QGraphicsScene as a QGraphicsProxyWidget, the popup completion of that QLineEdit is drawn in the wrong location. When the completer getting the rect of screen, it gets the rect of the QGraphicsScene where QLineEdit is located rather than the rect of the screen, resulting in an error in the following calculation. Note that as long as the completer popup is a toplevel widget not parented to the target widget, it will not be automatically embedded into the graphics view via QGraphicsProxyWidget. So with multiple views for a scene, or in views that use transformations, the geometry will still be off. Pick-to: 6.3 Task-number: QTBUG-20531 Change-Id: If5d8a707ca35a9e4709117b077978145c6143e46 Reviewed-by: Volker Hilsheimer --- src/widgets/util/qcompleter.cpp | 2 +- .../util/qcompleter/tst_qcompleter.cpp | 32 +++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/widgets/util/qcompleter.cpp b/src/widgets/util/qcompleter.cpp index ab3703abe4d..115af89de2c 100644 --- a/src/widgets/util/qcompleter.cpp +++ b/src/widgets/util/qcompleter.cpp @@ -921,7 +921,7 @@ void QCompleterPrivate::_q_autoResizePopup() void QCompleterPrivate::showPopup(const QRect& rect) { - const QRect screen = QWidgetPrivate::availableScreenGeometry(widget); + const QRect screen = widget->screen()->availableGeometry(); Qt::LayoutDirection dir = widget->layoutDirection(); QPoint pos; int rh, w; diff --git a/tests/auto/widgets/util/qcompleter/tst_qcompleter.cpp b/tests/auto/widgets/util/qcompleter/tst_qcompleter.cpp index 51a75573a45..6e04568e2c4 100644 --- a/tests/auto/widgets/util/qcompleter/tst_qcompleter.cpp +++ b/tests/auto/widgets/util/qcompleter/tst_qcompleter.cpp @@ -145,6 +145,7 @@ private slots: void QTBUG_14292_filesystem(); void QTBUG_52028_tabAutoCompletes(); void QTBUG_51889_activatedSentTwice(); + void showPopupInGraphicsView(); private: void filter(bool assync = false); @@ -1828,5 +1829,36 @@ void tst_QCompleter::QTBUG_51889_activatedSentTwice() QTRY_COMPARE(activatedSpy.count(), 1); } +void tst_QCompleter::showPopupInGraphicsView() +{ + QGraphicsView view; + QGraphicsScene scene; + view.setScene(&scene); + + QLineEdit lineEdit; + lineEdit.setCompleter(new QCompleter({"alpha", "omega", "omicron", "zeta"})); + scene.addWidget(&lineEdit); + + view.move(view.screen()->availableGeometry().topLeft() + QPoint(10, 10)); + view.show(); + QVERIFY(QTest::qWaitForWindowExposed(&view)); + + // show popup under line edit + QTest::keyClick(&lineEdit, Qt::Key_A); + QVERIFY(lineEdit.completer()->popup()); + QVERIFY(lineEdit.completer()->popup()->isVisible()); + QCOMPARE(lineEdit.completer()->popup()->geometry().x(), lineEdit.mapToGlobal(QPoint(0, 0)).x()); + QVERIFY(lineEdit.completer()->popup()->geometry().top() >= (lineEdit.mapToGlobal(QPoint(0, lineEdit.height() - 1)).y() - 1)); + + // move widget to the bottom of screen + lineEdit.clear(); + int y = view.screen()->availableGeometry().height() - lineEdit.geometry().y(); + view.move(view.geometry().x(), y); + + // show popup above line edit + QTest::keyClick(&lineEdit, Qt::Key_A); + QVERIFY(lineEdit.completer()->popup()->geometry().bottom() < lineEdit.mapToGlobal(QPoint(0, 0)).y()); +} + QTEST_MAIN(tst_QCompleter) #include "tst_qcompleter.moc"