From c416ec00e7c859a844a5bcb24c7a31147aed974c Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Wed, 13 Oct 2010 11:00:29 +0200 Subject: QCompleter: do not auto complete when directory is changed. Fixed regression for QCompleter associated with a QFileSystemModel. It would popup a popup each time the directory is changed. This was a regression in Qt 4.7.0, introduced with 319b0262418d74cc416a7d Task-number: QTBUG-14292 Reviewed-by: Thierry --- src/gui/util/qcompleter.cpp | 18 +++++--- src/gui/util/qcompleter_p.h | 1 + tests/auto/qcompleter/tst_qcompleter.cpp | 74 ++++++++++++++++++++++++++++++++ 3 files changed, 87 insertions(+), 6 deletions(-) diff --git a/src/gui/util/qcompleter.cpp b/src/gui/util/qcompleter.cpp index e718212..bcd601b 100644 --- a/src/gui/util/qcompleter.cpp +++ b/src/gui/util/qcompleter.cpp @@ -782,7 +782,8 @@ QMatchData QUnsortedModelEngine::filter(const QString& part, const QModelIndex& /////////////////////////////////////////////////////////////////////////////// QCompleterPrivate::QCompleterPrivate() : widget(0), proxy(0), popup(0), cs(Qt::CaseSensitive), role(Qt::EditRole), column(0), - maxVisibleItems(7), sorting(QCompleter::UnsortedModel), wrap(true), eatFocusOut(true) + maxVisibleItems(7), sorting(QCompleter::UnsortedModel), wrap(true), eatFocusOut(true), + hiddenBecauseNoMatch(false) { } @@ -921,12 +922,14 @@ void QCompleterPrivate::showPopup(const QRect& rect) void QCompleterPrivate::_q_fileSystemModelDirectoryLoaded(const QString &path) { Q_Q(QCompleter); -#ifndef QT_NO_LINEEDIT - QLineEdit *lineEdit = qobject_cast(widget); - //the path given by QFileSystemModel does not end with / - if (lineEdit && !lineEdit->text().isEmpty() && !q->completionPrefix().isEmpty() && q->completionPrefix() != path + QLatin1Char('/')) + // Slot called when QFileSystemModel has finished loading. + // If we hide the popup because there was no match because the model was not loaded yet, + // we re-start the completion when we get the results + if (hiddenBecauseNoMatch + && prefix.startsWith(path) && prefix != (path + '/') + && widget) { q->complete(); -#endif + } } /*! @@ -1200,6 +1203,7 @@ bool QCompleter::eventFilter(QObject *o, QEvent *e) Q_D(QCompleter); if (d->eatFocusOut && o == d->widget && e->type() == QEvent::FocusOut) { + d->hiddenBecauseNoMatch = false; if (d->popup && d->popup->isVisible()) return true; } @@ -1378,6 +1382,7 @@ void QCompleter::complete(const QRect& rect) { Q_D(QCompleter); QModelIndex idx = d->proxy->currentIndex(false); + d->hiddenBecauseNoMatch = false; if (d->mode == QCompleter::InlineCompletion) { if (idx.isValid()) d->_q_complete(idx, true); @@ -1389,6 +1394,7 @@ void QCompleter::complete(const QRect& rect) || (d->mode == QCompleter::UnfilteredPopupCompletion && d->proxy->rowCount() == 0)) { if (d->popup) d->popup->hide(); // no suggestion, hide + d->hiddenBecauseNoMatch = true; return; } diff --git a/src/gui/util/qcompleter_p.h b/src/gui/util/qcompleter_p.h index 8f00793..19b76e5 100644 --- a/src/gui/util/qcompleter_p.h +++ b/src/gui/util/qcompleter_p.h @@ -93,6 +93,7 @@ public: bool eatFocusOut; QRect popupRect; + bool hiddenBecauseNoMatch; void showPopup(const QRect&); void _q_complete(QModelIndex, bool = false); diff --git a/tests/auto/qcompleter/tst_qcompleter.cpp b/tests/auto/qcompleter/tst_qcompleter.cpp index 3e05fbc..6d28f9f 100644 --- a/tests/auto/qcompleter/tst_qcompleter.cpp +++ b/tests/auto/qcompleter/tst_qcompleter.cpp @@ -151,6 +151,7 @@ private slots: void task253125_lineEditCompletion_data(); void task253125_lineEditCompletion(); void task247560_keyboardNavigation(); + void QTBUG_14292_filesystem(); private: void filter(bool assync = false); @@ -571,6 +572,7 @@ void tst_QCompleter::csMatchingOnCiSortedModel() void tst_QCompleter::directoryModel_data() { delete completer; + completer = new CsvCompleter; completer->setModelSorting(QCompleter::CaseSensitivelySortedModel); setSourceModel(DIRECTORY_MODEL); @@ -1451,5 +1453,77 @@ void tst_QCompleter::task247560_keyboardNavigation() QCOMPARE(edit.text(), QString("row 3 column 1")); } +void tst_QCompleter::QTBUG_14292_filesystem() +{ + QDir tmpDir = QDir::temp(); + qsrand(QTime::currentTime().msec()); + QString d = "tst_QCompleter_" + QString::number(qrand()); + QVERIFY(tmpDir.mkdir(d)); + +#if 0 + struct Cleanup { + QString dir; + ~Cleanup() { + qDebug() << dir << + QFile::remove(dir); } + } cleanup; + cleanup.dir = tmpDir.absolutePath()+"/" +d; +#endif + + QVERIFY(tmpDir.cd(d)); + QVERIFY(tmpDir.mkdir("hello")); + QVERIFY(tmpDir.mkdir("holla")); + + QLineEdit edit; + QCompleter comp; + QFileSystemModel model; + model.setRootPath(tmpDir.path()); + comp.setModel(&model); + edit.setCompleter(&comp); + + edit.show(); + QApplication::setActiveWindow(&edit); + QTest::qWaitForWindowShown(&edit); + QTRY_VERIFY(QApplication::activeWindow() == &edit); + + QVERIFY(!comp.popup()->isVisible()); + edit.setText(tmpDir.path()); + QTest::keyClick(&edit, '/'); + QTRY_VERIFY(comp.popup()->isVisible()); + QCOMPARE(comp.popup()->model()->rowCount(), 2); + QTest::keyClick(&edit, 'h'); + QCOMPARE(comp.popup()->model()->rowCount(), 2); + QTest::keyClick(&edit, 'e'); + QCOMPARE(comp.popup()->model()->rowCount(), 1); + QTest::keyClick(&edit, 'r'); + QTRY_VERIFY(!comp.popup()->isVisible()); + QVERIFY(tmpDir.mkdir("hero")); + QTRY_VERIFY(comp.popup()->isVisible()); + QCOMPARE(comp.popup()->model()->rowCount(), 1); + QTest::keyClick(comp.popup(), Qt::Key_Escape); + QTRY_VERIFY(!comp.popup()->isVisible()); + QVERIFY(tmpDir.mkdir("nothingThere")); + //there is no reason creating a file should open a popup, it did in Qt 4.7.0 + QTest::qWait(60); + QVERIFY(!comp.popup()->isVisible()); + + QTest::keyClick(&edit, Qt::Key_Backspace); + QTRY_VERIFY(comp.popup()->isVisible()); + QCOMPARE(comp.popup()->model()->rowCount(), 2); + QTest::keyClick(&edit, 'm'); + QTRY_VERIFY(!comp.popup()->isVisible()); + + QWidget w; + w.show(); + QApplication::setActiveWindow(&w); + QTest::qWaitForWindowShown(&w); + QTRY_VERIFY(!edit.hasFocus() && !comp.popup()->hasFocus()); + + QVERIFY(tmpDir.mkdir("hemo")); + //there is no reason creating a file should open a popup, it did in Qt 4.7.0 + QTest::qWait(60); + QVERIFY(!comp.popup()->isVisible()); +} + QTEST_MAIN(tst_QCompleter) #include "tst_qcompleter.moc" -- cgit v0.12