diff --git a/documentation/documentationfindwidget.h b/documentation/documentationfindwidget.h --- a/documentation/documentationfindwidget.h +++ b/documentation/documentationfindwidget.h @@ -50,9 +50,22 @@ private Q_SLOTS: void searchNext(); void searchPrevious(); - + void emitDataChanged(); + Q_SIGNALS: - void newSearch(const QString& text, KDevelop::DocumentationFindWidget::FindOptions); + /** + * Emitted when the user requests a search. + * @param text text to search in documentation + * @param options MatchCase being set or empty flags (Next/Previous unused here) + */ + void searchRequested(const QString& text, KDevelop::DocumentationFindWidget::FindOptions options); + /** + * Emitted when the user edits the search field or changes the case-sensitivity checkbox. + * Allows documentation views capable of live searches to show live results while the user types. + * @param text current text in search text field + * @param options MatchCase being set or empty flags (Next/Previous unused here) + */ + void searchDataChanged(const QString& text, KDevelop::DocumentationFindWidget::FindOptions options); /** * Emitted when the search tool view is closed, so no more search hits should be displayed. */ diff --git a/documentation/documentationfindwidget.cpp b/documentation/documentationfindwidget.cpp --- a/documentation/documentationfindwidget.cpp +++ b/documentation/documentationfindwidget.cpp @@ -29,12 +29,17 @@ m_ui = new Ui::FindWidget; m_ui->setupUi(this); + connect(m_ui->findText, &QLineEdit::textEdited, + this, &DocumentationFindWidget::emitDataChanged); + connect(m_ui->matchCase, &QAbstractButton::toggled, + this, &DocumentationFindWidget::emitDataChanged); connect(m_ui->findText, &QLineEdit::returnPressed, this, &DocumentationFindWidget::searchNext); connect(m_ui->nextButton, &QToolButton::clicked, this, &DocumentationFindWidget::searchNext); connect(m_ui->previousButton, &QToolButton::clicked, this, &DocumentationFindWidget::searchPrevious); + // TODO: disable next/previous buttons if no (more) search hits, color coding in text field } DocumentationFindWidget::~DocumentationFindWidget() @@ -48,16 +53,16 @@ if (m_ui->matchCase->isChecked()) opts |= MatchCase; - emit newSearch(m_ui->findText->text(), opts); + emit searchRequested(m_ui->findText->text(), opts); } void KDevelop::DocumentationFindWidget::searchPrevious() { FindOptions opts=Previous; if (m_ui->matchCase->isChecked()) opts |= MatchCase; - emit newSearch(m_ui->findText->text(), opts); + emit searchRequested(m_ui->findText->text(), opts); } void KDevelop::DocumentationFindWidget::startSearch() @@ -67,6 +72,15 @@ m_ui->findText->setFocus(); } +void DocumentationFindWidget::emitDataChanged() +{ + FindOptions opts; + if (m_ui->matchCase->isChecked()) + opts |= MatchCase; + + emit searchDataChanged(m_ui->findText->text(), opts); +} + void KDevelop::DocumentationFindWidget::hideEvent(QHideEvent* event) { emit searchFinished(); diff --git a/documentation/standarddocumentationview.h b/documentation/standarddocumentationview.h --- a/documentation/standarddocumentationview.h +++ b/documentation/standarddocumentationview.h @@ -76,6 +76,7 @@ * Search for @p text in the documentation view. */ void search(const QString& text, KDevelop::DocumentationFindWidget::FindOptions options); + void searchIncremental(const QString& text, KDevelop::DocumentationFindWidget::FindOptions options); void finishSearch(); /** diff --git a/documentation/standarddocumentationview.cpp b/documentation/standarddocumentationview.cpp --- a/documentation/standarddocumentationview.cpp +++ b/documentation/standarddocumentationview.cpp @@ -119,7 +119,8 @@ layout()->addWidget(d->m_view); findWidget->setEnabled(true); - connect(findWidget, &DocumentationFindWidget::newSearch, this, &StandardDocumentationView::search); + connect(findWidget, &DocumentationFindWidget::searchRequested, this, &StandardDocumentationView::search); + connect(findWidget, &DocumentationFindWidget::searchDataChanged, this, &StandardDocumentationView::searchIncremental); connect(findWidget, &DocumentationFindWidget::searchFinished, this, &StandardDocumentationView::finishSearch); #ifdef USE_QTWEBKIT @@ -183,6 +184,30 @@ d->m_view->page()->findText(text, ff); } +void StandardDocumentationView::searchIncremental(const QString& text, DocumentationFindWidget::FindOptions options) +{ +#ifdef USE_QTWEBKIT + typedef QWebPage WebkitThing; +#else + typedef QWebEnginePage WebkitThing; +#endif + WebkitThing::FindFlags findFlags; + + if (options & DocumentationFindWidget::MatchCase) + findFlags |= WebkitThing::FindCaseSensitively; + + // calling with changed text with added or removed chars at end will result in current + // selection kept, if also matching new text + // behaviour on changed case sensitivity though is advancing to next match even if current + // would be still matching. as there is no control about currently shown match, nothing + // we can do about it. thankfully case sensitivity does not happen too often, so should + // not be too grave UX + // at least with webengine 5.9.1 there is a bug when switching from no-casesensitivy to + // casesensitivity, that global matches are not updated and the ones with non-matching casing + // still active. no workaround so far. + d->m_view->page()->findText(text, findFlags); +} + void StandardDocumentationView::finishSearch() { // passing emptry string to reset search, as told in API docs