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 <volker.hilsheimer@qt.io>
This commit is contained in:
Yin Jie 2021-12-16 13:37:53 +08:00 committed by Volker Hilsheimer
parent 936771d901
commit 60a67dc41e
2 changed files with 33 additions and 1 deletions

View File

@ -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;

View File

@ -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"