summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--examples/webengine/quicknanobrowser/BrowserWindow.qml59
-rw-r--r--examples/webengine/quicknanobrowser/FindBar.qml146
-rw-r--r--examples/webengine/quicknanobrowser/quicknanobrowser.pro1
-rw-r--r--examples/webengine/quicknanobrowser/resources.qrc1
-rw-r--r--examples/webenginewidgets/simplebrowser/browserwindow.cpp18
-rw-r--r--examples/webenginewidgets/simplebrowser/browserwindow.h1
-rw-r--r--examples/webenginewidgets/simplebrowser/tabwidget.cpp4
-rw-r--r--examples/webenginewidgets/simplebrowser/tabwidget.h1
-rw-r--r--src/core/api/core_api.pro2
-rw-r--r--src/core/api/qwebenginefindtextresult.cpp116
-rw-r--r--src/core/api/qwebenginefindtextresult.h81
-rw-r--r--src/core/find_text_helper.cpp10
-rw-r--r--src/core/find_text_helper.h5
-rw-r--r--src/core/web_contents_adapter_client.h2
-rw-r--r--src/core/web_contents_delegate_qt.cpp2
-rw-r--r--src/webengine/api/qquickwebengineview.cpp7
-rw-r--r--src/webengine/api/qquickwebengineview_p.h2
-rw-r--r--src/webengine/api/qquickwebengineview_p_p.h2
-rw-r--r--src/webengine/doc/src/webengineview_lgpl.qdoc43
-rw-r--r--src/webengine/plugin/plugin.cpp3
-rw-r--r--src/webenginewidgets/api/qwebenginepage.cpp18
-rw-r--r--src/webenginewidgets/api/qwebenginepage.h3
-rw-r--r--src/webenginewidgets/api/qwebenginepage_p.h2
-rw-r--r--src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc3
-rw-r--r--tests/auto/quick/publicapi/tst_publicapi.cpp5
-rw-r--r--tests/auto/quick/qmltests/data/tst_findText.qml84
-rw-r--r--tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp113
27 files changed, 713 insertions, 21 deletions
diff --git a/examples/webengine/quicknanobrowser/BrowserWindow.qml b/examples/webengine/quicknanobrowser/BrowserWindow.qml
index 088b23e59..39a13df59 100644
--- a/examples/webengine/quicknanobrowser/BrowserWindow.qml
+++ b/examples/webengine/quicknanobrowser/BrowserWindow.qml
@@ -57,7 +57,7 @@ import QtQuick.Controls.Styles 1.0
import QtQuick.Dialogs 1.2
import QtQuick.Layouts 1.0
import QtQuick.Window 2.1
-import QtWebEngine 1.10
+import QtWebEngine 1.11
ApplicationWindow {
id: browserWindow
@@ -73,6 +73,10 @@ ApplicationWindow {
// Make sure the Qt.WindowFullscreenButtonHint is set on OS X.
Component.onCompleted: flags = flags | Qt.WindowFullscreenButtonHint
+ onCurrentWebViewChanged: {
+ findBar.reset();
+ }
+
// Create a styleItem to determine the platform.
// When using style "mac", ToolButtons are not supposed to accept focus.
QQCPrivate.StyleItem { id: styleItem }
@@ -136,6 +140,9 @@ ApplicationWindow {
fullScreenNotification.hide();
currentWebView.triggerWebAction(WebEngineView.ExitFullScreen);
}
+
+ if (findBar.visible)
+ findBar.visible = false;
}
}
Action {
@@ -187,6 +194,21 @@ ApplicationWindow {
shortcut: StandardKey.Forward
onTriggered: currentWebView.triggerWebAction(WebEngineView.Forward)
}
+ Action {
+ shortcut: StandardKey.Find
+ onTriggered: {
+ if (!findBar.visible)
+ findBar.visible = true;
+ }
+ }
+ Action {
+ shortcut: StandardKey.FindNext
+ onTriggered: findBar.findNext()
+ }
+ Action {
+ shortcut: StandardKey.FindPrevious
+ onTriggered: findBar.findPrevious()
+ }
toolBar: ToolBar {
id: navigationBar
@@ -553,6 +575,19 @@ ApplicationWindow {
selection.certificates[0].select();
}
+ onFindTextFinished: function(result) {
+ if (!findBar.visible)
+ findBar.visible = true;
+
+ findBar.numberOfMatches = result.numberOfMatches;
+ findBar.activeMatchOrdinal = result.activeMatchOrdinal;
+ }
+
+ onLoadingChanged: function(loadRequest) {
+ if (loadRequest.status == WebEngineView.LoadStartedStatus)
+ findBar.reset();
+ }
+
Timer {
id: reloadTimer
interval: 0
@@ -625,6 +660,28 @@ ApplicationWindow {
download.accept();
}
+ FindBar {
+ id: findBar
+ visible: false
+ anchors.right: parent.right
+ anchors.rightMargin: 10
+ anchors.top: parent.top
+
+ onFindNext: {
+ if (text)
+ currentWebView && currentWebView.findText(text);
+ else if (!visible)
+ visible = true;
+ }
+ onFindPrevious: {
+ if (text)
+ currentWebView && currentWebView.findText(text, WebEngineView.FindBackward);
+ else if (!visible)
+ visible = true;
+ }
+ }
+
+
Rectangle {
id: statusBubble
color: "oldlace"
diff --git a/examples/webengine/quicknanobrowser/FindBar.qml b/examples/webengine/quicknanobrowser/FindBar.qml
new file mode 100644
index 000000000..2d673592a
--- /dev/null
+++ b/examples/webengine/quicknanobrowser/FindBar.qml
@@ -0,0 +1,146 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.5
+import QtQuick.Controls 1.4
+import QtQuick.Controls.Styles 1.4
+import QtQuick.Layouts 1.0
+
+Rectangle {
+ id: root
+
+ property int numberOfMatches: 0
+ property int activeMatchOrdinal: 0
+ property alias text: findTextField.text
+
+ function reset() {
+ numberOfMatches = 0;
+ activeMatchOrdinal = 0;
+ visible = false;
+ }
+
+ signal findNext()
+ signal findPrevious()
+
+ width: 250
+ height: 35
+ radius: 2
+
+ border.width: 1
+ border.color: "black"
+ color: "white"
+
+ onVisibleChanged: {
+ if (visible)
+ findTextField.forceActiveFocus();
+ }
+
+
+ RowLayout {
+ anchors.fill: parent
+ anchors.topMargin: 5
+ anchors.bottomMargin: 5
+ anchors.leftMargin: 10
+ anchors.rightMargin: 10
+
+ spacing: 5
+
+ Rectangle {
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+
+ TextField {
+ id: findTextField
+ anchors.fill: parent
+
+ style: TextFieldStyle {
+ background: Rectangle {
+ color: "transparent"
+ }
+ }
+
+ onAccepted: root.findNext()
+ onTextChanged: root.findNext()
+ onActiveFocusChanged: activeFocus ? selectAll() : deselect()
+ }
+ }
+
+ Label {
+ text: activeMatchOrdinal + "/" + numberOfMatches
+ visible: findTextField.text != ""
+ }
+
+ Rectangle {
+ border.width: 1
+ border.color: "#ddd"
+ width: 2
+ height: parent.height
+ anchors.topMargin: 5
+ anchors.bottomMargin: 5
+ }
+
+ ToolButton {
+ text: "<"
+ enabled: numberOfMatches > 0
+ onClicked: root.findPrevious()
+ }
+
+ ToolButton {
+ text: ">"
+ enabled: numberOfMatches > 0
+ onClicked: root.findNext()
+ }
+
+ ToolButton {
+ text: "x"
+ onClicked: root.visible = false
+ }
+ }
+}
diff --git a/examples/webengine/quicknanobrowser/quicknanobrowser.pro b/examples/webengine/quicknanobrowser/quicknanobrowser.pro
index 5a27f5fd4..922cf79e2 100644
--- a/examples/webengine/quicknanobrowser/quicknanobrowser.pro
+++ b/examples/webengine/quicknanobrowser/quicknanobrowser.pro
@@ -10,6 +10,7 @@ OTHER_FILES += ApplicationRoot.qml \
BrowserDialog.qml \
BrowserWindow.qml \
DownloadView.qml \
+ FindBar.qml \
FullScreenNotification.qml
RESOURCES += resources.qrc
diff --git a/examples/webengine/quicknanobrowser/resources.qrc b/examples/webengine/quicknanobrowser/resources.qrc
index c6270897d..50ea05f5e 100644
--- a/examples/webengine/quicknanobrowser/resources.qrc
+++ b/examples/webengine/quicknanobrowser/resources.qrc
@@ -4,6 +4,7 @@
<file>BrowserDialog.qml</file>
<file>BrowserWindow.qml</file>
<file>DownloadView.qml</file>
+ <file>FindBar.qml</file>
<file>FullScreenNotification.qml</file>
</qresource>
<qresource prefix="icons">
diff --git a/examples/webenginewidgets/simplebrowser/browserwindow.cpp b/examples/webenginewidgets/simplebrowser/browserwindow.cpp
index 5d00cd19a..2bb9045b0 100644
--- a/examples/webenginewidgets/simplebrowser/browserwindow.cpp
+++ b/examples/webenginewidgets/simplebrowser/browserwindow.cpp
@@ -66,6 +66,7 @@
#include <QStatusBar>
#include <QToolBar>
#include <QVBoxLayout>
+#include <QWebEngineFindTextResult>
#include <QWebEngineProfile>
BrowserWindow::BrowserWindow(Browser *browser, QWebEngineProfile *profile, bool forDevTools)
@@ -129,6 +130,7 @@ BrowserWindow::BrowserWindow(Browser *browser, QWebEngineProfile *profile, bool
connect(m_urlLineEdit, &QLineEdit::returnPressed, [this]() {
m_tabWidget->setUrl(QUrl::fromUserInput(m_urlLineEdit->text()));
});
+ connect(m_tabWidget, &TabWidget::findTextFinished, this, &BrowserWindow::handleFindTextFinished);
QAction *focusUrlLineEditAction = new QAction(this);
addAction(focusUrlLineEditAction);
@@ -460,10 +462,7 @@ void BrowserWindow::handleFindActionTriggered()
m_lastSearch, &ok);
if (ok && !search.isEmpty()) {
m_lastSearch = search;
- currentTab()->findText(m_lastSearch, 0, [this](bool found) {
- if (!found)
- statusBar()->showMessage(tr("\"%1\" not found.").arg(m_lastSearch));
- });
+ currentTab()->findText(m_lastSearch);
}
}
@@ -526,3 +525,14 @@ void BrowserWindow::handleDevToolsRequested(QWebEnginePage *source)
source->setDevToolsPage(m_browser->createDevToolsWindow()->currentTab()->page());
source->triggerAction(QWebEnginePage::InspectElement);
}
+
+void BrowserWindow::handleFindTextFinished(const QWebEngineFindTextResult &result)
+{
+ if (result.numberOfMatches() == 0) {
+ statusBar()->showMessage(tr("\"%1\" not found.").arg(m_lastSearch));
+ } else {
+ statusBar()->showMessage(tr("\"%1\" found: %2/%3").arg(m_lastSearch,
+ QString::number(result.activeMatchOrdinal()),
+ QString::number(result.numberOfMatches())));
+ }
+}
diff --git a/examples/webenginewidgets/simplebrowser/browserwindow.h b/examples/webenginewidgets/simplebrowser/browserwindow.h
index 8f328b751..11a655469 100644
--- a/examples/webenginewidgets/simplebrowser/browserwindow.h
+++ b/examples/webenginewidgets/simplebrowser/browserwindow.h
@@ -88,6 +88,7 @@ private slots:
void handleWebViewTitleChanged(const QString &title);
void handleWebActionEnabledChanged(QWebEnginePage::WebAction action, bool enabled);
void handleDevToolsRequested(QWebEnginePage *source);
+ void handleFindTextFinished(const QWebEngineFindTextResult &result);
private:
QMenu *createFileMenu(TabWidget *tabWidget);
diff --git a/examples/webenginewidgets/simplebrowser/tabwidget.cpp b/examples/webenginewidgets/simplebrowser/tabwidget.cpp
index 369bebfd9..3b6d84ebe 100644
--- a/examples/webenginewidgets/simplebrowser/tabwidget.cpp
+++ b/examples/webenginewidgets/simplebrowser/tabwidget.cpp
@@ -200,6 +200,10 @@ void TabWidget::setupView(WebView *webView)
closeTab(index);
});
connect(webView, &WebView::devToolsRequested, this, &TabWidget::devToolsRequested);
+ connect(webPage, &QWebEnginePage::findTextFinished, [this, webView](const QWebEngineFindTextResult &result) {
+ if (currentIndex() == indexOf(webView))
+ emit findTextFinished(result);
+ });
}
WebView *TabWidget::createTab()
diff --git a/examples/webenginewidgets/simplebrowser/tabwidget.h b/examples/webenginewidgets/simplebrowser/tabwidget.h
index bf83781df..fba61d44f 100644
--- a/examples/webenginewidgets/simplebrowser/tabwidget.h
+++ b/examples/webenginewidgets/simplebrowser/tabwidget.h
@@ -78,6 +78,7 @@ signals:
void favIconChanged(const QIcon &icon);
void webActionEnabledChanged(QWebEnginePage::WebAction action, bool enabled);
void devToolsRequested(QWebEnginePage *source);
+ void findTextFinished(const QWebEngineFindTextResult &result);
public slots:
// current tab/page slots
diff --git a/src/core/api/core_api.pro b/src/core/api/core_api.pro
index 326d4481f..5e8b8387e 100644
--- a/src/core/api/core_api.pro
+++ b/src/core/api/core_api.pro
@@ -37,6 +37,7 @@ HEADERS = \
qtwebenginecoreglobal_p.h \
qwebenginecookiestore.h \
qwebenginecookiestore_p.h \
+ qwebenginefindtextresult.h \
qwebenginehttprequest.h \
qwebenginemessagepumpscheduler_p.h \
qwebenginenotification.h \
@@ -53,6 +54,7 @@ SOURCES = \
qtwebenginecoreglobal.cpp \
qwebengineclientcertificatestore.cpp \
qwebenginecookiestore.cpp \
+ qwebenginefindtextresult.cpp \
qwebenginehttprequest.cpp \
qwebenginemessagepumpscheduler.cpp \
qwebenginenotification.cpp \
diff --git a/src/core/api/qwebenginefindtextresult.cpp b/src/core/api/qwebenginefindtextresult.cpp
new file mode 100644
index 000000000..ce1be359e
--- /dev/null
+++ b/src/core/api/qwebenginefindtextresult.cpp
@@ -0,0 +1,116 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwebenginefindtextresult.h"
+
+QT_BEGIN_NAMESPACE
+
+class QWebEngineFindTextResultPrivate : public QSharedData {
+public:
+ int numberOfMatches = 0;
+ int activeMatchOrdinal = 0;
+};
+
+/*!
+ \class QWebEngineFindTextResult
+ \brief The QWebEngineFindTextResult class encapsulates the result of a string search on a page.
+ \since 5.14
+
+ \inmodule QtWebEngineCore
+
+ Results are passed to the user in the
+ \l QWebEnginePage::findTextFinished() and
+ \l{WebEngineView::findTextFinished()}{WebEngineView.findTextFinished()} signals.
+*/
+
+/*! \internal
+*/
+QWebEngineFindTextResult::QWebEngineFindTextResult()
+ : d(new QWebEngineFindTextResultPrivate)
+{}
+
+/*! \internal
+*/
+QWebEngineFindTextResult::QWebEngineFindTextResult(int numberOfMatches, int activeMatchOrdinal)
+ : d(new QWebEngineFindTextResultPrivate)
+{
+ d->numberOfMatches = numberOfMatches;
+ d->activeMatchOrdinal = activeMatchOrdinal;
+}
+
+/*! \internal
+*/
+QWebEngineFindTextResult::QWebEngineFindTextResult(const QWebEngineFindTextResult &other)
+ : d(other.d)
+{}
+
+/*! \internal
+*/
+QWebEngineFindTextResult &QWebEngineFindTextResult::operator=(const QWebEngineFindTextResult &other)
+{
+ d = other.d;
+ return *this;
+}
+
+/*! \internal
+*/
+QWebEngineFindTextResult::~QWebEngineFindTextResult()
+{}
+
+/*!
+ \property QWebEngineFindTextResult::numberOfMatches
+ \brief The number of matches found.
+*/
+int QWebEngineFindTextResult::numberOfMatches() const
+{
+ return d->numberOfMatches;
+}
+
+/*!
+ \property QWebEngineFindTextResult::activeMatchOrdinal
+ \brief The index of the currently highlighted match.
+*/
+int QWebEngineFindTextResult::activeMatchOrdinal() const
+{
+ return d->activeMatchOrdinal;
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qwebenginefindtextresult.cpp"
diff --git a/src/core/api/qwebenginefindtextresult.h b/src/core/api/qwebenginefindtextresult.h
new file mode 100644
index 000000000..073a8135f
--- /dev/null
+++ b/src/core/api/qwebenginefindtextresult.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWEBENGINEFINDTEXTRESULT_H
+#define QWEBENGINEFINDTEXTRESULT_H
+
+#include <QtWebEngineCore/qtwebenginecoreglobal.h>
+#include <QtCore/QObject>
+#include <QtCore/QSharedData>
+
+namespace QtWebEngineCore {
+class FindTextHelper;
+}
+
+QT_BEGIN_NAMESPACE
+
+class QWebEngineFindTextResultPrivate;
+
+class Q_WEBENGINECORE_EXPORT QWebEngineFindTextResult {
+ Q_GADGET
+ Q_PROPERTY(int numberOfMatches READ numberOfMatches CONSTANT FINAL)
+ Q_PROPERTY(int activeMatchOrdinal READ activeMatchOrdinal CONSTANT FINAL)
+
+public:
+ int numberOfMatches() const;
+ int activeMatchOrdinal() const;
+
+ QWebEngineFindTextResult();
+ QWebEngineFindTextResult(const QWebEngineFindTextResult &other);
+ QWebEngineFindTextResult &operator=(const QWebEngineFindTextResult &other);
+ ~QWebEngineFindTextResult();
+
+private:
+ QWebEngineFindTextResult(int numberOfMatches, int activeMatchOrdinal);
+
+ QSharedDataPointer<QWebEngineFindTextResultPrivate> d;
+
+ friend class QtWebEngineCore::FindTextHelper;
+};
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QWebEngineFindTextResult)
+
+#endif // QWEBENGINEFINDTEXTRESULT_H
diff --git a/src/core/find_text_helper.cpp b/src/core/find_text_helper.cpp
index 5fb56dacc..effda529f 100644
--- a/src/core/find_text_helper.cpp
+++ b/src/core/find_text_helper.cpp
@@ -38,7 +38,9 @@
****************************************************************************/
#include "find_text_helper.h"
+#include "qwebenginefindtextresult.h"
#include "type_conversion.h"
+#include "web_contents_adapter_client.h"
#include "content/public/browser/web_contents.h"
#include "third_party/blink/public/mojom/frame/find_in_page.mojom.h"
@@ -48,8 +50,9 @@ namespace QtWebEngineCore {
// static
int FindTextHelper::m_findRequestIdCounter = -1;
-FindTextHelper::FindTextHelper(content::WebContents *webContents)
+FindTextHelper::FindTextHelper(content::WebContents *webContents, WebContentsAdapterClient *viewClient)
: m_webContents(webContents)
+ , m_viewClient(viewClient)
, m_currentFindRequestId(m_findRequestIdCounter++)
, m_lastCompletedFindRequestId(m_currentFindRequestId)
{
@@ -65,6 +68,7 @@ void FindTextHelper::startFinding(const QString &findText, bool caseSensitively,
{
if (findText.isEmpty()) {
stopFinding();
+ m_viewClient->findTextFinished(QWebEngineFindTextResult());
m_widgetCallbacks.invokeEmpty(resultCallback);
return;
}
@@ -77,6 +81,7 @@ void FindTextHelper::startFinding(const QString &findText, bool caseSensitively,
{
if (findText.isEmpty()) {
stopFinding();
+ m_viewClient->findTextFinished(QWebEngineFindTextResult());
if (!resultCallback.isUndefined()) {
QJSValueList args;
args.append(QJSValue(0));
@@ -103,6 +108,7 @@ void FindTextHelper::startFinding(const QString &findText, bool caseSensitively,
// waiting for it forever.
// Assume that any unfinished find has been unsuccessful when a new one is started
// to cover that case.
+ m_viewClient->findTextFinished(QWebEngineFindTextResult());
invokeResultCallback(m_currentFindRequestId, 0);
}
@@ -132,7 +138,6 @@ void FindTextHelper::handleFindReply(content::WebContents *source, int requestId
const gfx::Rect &selectionRect, int activeMatchOrdinal, bool finalUpdate)
{
Q_UNUSED(selectionRect);
- Q_UNUSED(activeMatchOrdinal);
Q_ASSERT(source == m_webContents);
@@ -141,6 +146,7 @@ void FindTextHelper::handleFindReply(content::WebContents *source, int requestId
Q_ASSERT(m_currentFindRequestId == requestId);
m_lastCompletedFindRequestId = requestId;
+ m_viewClient->findTextFinished(QWebEngineFindTextResult(numberOfMatches, activeMatchOrdinal));
invokeResultCallback(requestId, numberOfMatches);
}
diff --git a/src/core/find_text_helper.h b/src/core/find_text_helper.h
index 17e76ecc7..e8f186272 100644
--- a/src/core/find_text_helper.h
+++ b/src/core/find_text_helper.h
@@ -66,9 +66,11 @@ class Rect;
namespace QtWebEngineCore {
+class WebContentsAdapterClient;
+
class Q_WEBENGINECORE_PRIVATE_EXPORT FindTextHelper {
public:
- FindTextHelper(content::WebContents *webContents);
+ FindTextHelper(content::WebContents *webContents, WebContentsAdapterClient *viewClient);
~FindTextHelper();
void startFinding(const QString &findText, bool caseSensitively, bool findBackward, const QWebEngineCallback<bool> resultCallback);
@@ -83,6 +85,7 @@ private:
void invokeResultCallback(int requestId, int numberOfMatches);
content::WebContents *m_webContents;
+ WebContentsAdapterClient *m_viewClient;
static int m_findRequestIdCounter;
int m_currentFindRequestId;
diff --git a/src/core/web_contents_adapter_client.h b/src/core/web_contents_adapter_client.h
index 4743c1ed7..4bdb55b4c 100644
--- a/src/core/web_contents_adapter_client.h
+++ b/src/core/web_contents_adapter_client.h
@@ -64,6 +64,7 @@ QT_FORWARD_DECLARE_CLASS(CertificateErrorController)
QT_FORWARD_DECLARE_CLASS(ClientCertSelectController)
QT_FORWARD_DECLARE_CLASS(QKeyEvent)
QT_FORWARD_DECLARE_CLASS(QVariant)
+QT_FORWARD_DECLARE_CLASS(QWebEngineFindTextResult)
QT_FORWARD_DECLARE_CLASS(QWebEngineQuotaRequest)
QT_FORWARD_DECLARE_CLASS(QWebEngineRegisterProtocolHandlerRequest)
QT_FORWARD_DECLARE_CLASS(QWebEngineUrlRequestInfo)
@@ -498,6 +499,7 @@ public:
virtual TouchHandleDrawableClient *createTouchHandle(const QMap<int, QImage> &images) = 0;
virtual void showTouchSelectionMenu(TouchSelectionMenuController *menuController, const QRect &bounds, const QSize &handleSize) = 0;
virtual void hideTouchSelectionMenu() = 0;
+ virtual void findTextFinished(const QWebEngineFindTextResult &result) = 0;
virtual ProfileAdapter *profileAdapter() = 0;
virtual WebContentsAdapter* webContentsAdapter() = 0;
diff --git a/src/core/web_contents_delegate_qt.cpp b/src/core/web_contents_delegate_qt.cpp
index e3015d5f6..9855e3859 100644
--- a/src/core/web_contents_delegate_qt.cpp
+++ b/src/core/web_contents_delegate_qt.cpp
@@ -103,7 +103,7 @@ static WebContentsAdapterClient::JavaScriptConsoleMessageLevel mapToJavascriptCo
WebContentsDelegateQt::WebContentsDelegateQt(content::WebContents *webContents, WebContentsAdapterClient *adapterClient)
: m_viewClient(adapterClient)
, m_faviconManager(new FaviconManager(webContents, adapterClient))
- , m_findTextHelper(new FindTextHelper(webContents))
+ , m_findTextHelper(new FindTextHelper(webContents, adapterClient))
, m_lastLoadProgress(-1)
, m_loadingState(determineLoadingState(webContents))
, m_didStartLoadingSeen(m_loadingState == LoadingState::Loading)
diff --git a/src/webengine/api/qquickwebengineview.cpp b/src/webengine/api/qquickwebengineview.cpp
index f340ebd33..58d950cd9 100644
--- a/src/webengine/api/qquickwebengineview.cpp
+++ b/src/webengine/api/qquickwebengineview.cpp
@@ -62,6 +62,7 @@
#include "qquickwebenginesettings_p.h"
#include "qquickwebenginescript_p.h"
#include "qquickwebenginetouchhandleprovider_p_p.h"
+#include "qwebenginefindtextresult.h"
#include "qwebenginequotarequest.h"
#include "qwebengineregisterprotocolhandlerrequest.h"
@@ -699,6 +700,12 @@ void QQuickWebEngineViewPrivate::widgetChanged(RenderWidgetHostViewQtDelegate *n
bindViewAndWidget(q, static_cast<RenderWidgetHostViewQtDelegateQuick *>(newWidgetBase));
}
+void QQuickWebEngineViewPrivate::findTextFinished(const QWebEngineFindTextResult &result)
+{
+ Q_Q(QQuickWebEngineView);
+ Q_EMIT q->findTextFinished(result);
+}
+
WebEngineSettings *QQuickWebEngineViewPrivate::webEngineSettings() const
{
return m_settings->d_ptr.data();
diff --git a/src/webengine/api/qquickwebengineview_p.h b/src/webengine/api/qquickwebengineview_p.h
index 3c8e1d9ec..4a88e3c28 100644
--- a/src/webengine/api/qquickwebengineview_p.h
+++ b/src/webengine/api/qquickwebengineview_p.h
@@ -79,6 +79,7 @@ class QQuickWebEngineSettings;
class QQuickWebEngineTooltipRequest;
class QQuickWebEngineFormValidationMessageRequest;
class QQuickWebEngineViewPrivate;
+class QWebEngineFindTextResult;
class QWebEngineQuotaRequest;
class QWebEngineRegisterProtocolHandlerRequest;
@@ -574,6 +575,7 @@ Q_SIGNALS:
Q_REVISION(10) void tooltipRequested(QQuickWebEngineTooltipRequest *request);
Q_REVISION(11) void lifecycleStateChanged(LifecycleState state);
Q_REVISION(11) void recommendedStateChanged(LifecycleState state);
+ Q_REVISION(11) void findTextFinished(const QWebEngineFindTextResult &result);
#if QT_CONFIG(webengine_testsupport)
void testSupportChanged();
diff --git a/src/webengine/api/qquickwebengineview_p_p.h b/src/webengine/api/qquickwebengineview_p_p.h
index 7a1916d82..df6843ac3 100644
--- a/src/webengine/api/qquickwebengineview_p_p.h
+++ b/src/webengine/api/qquickwebengineview_p_p.h
@@ -80,6 +80,7 @@ class QQuickWebEngineSettings;
class QQuickWebEngineFaviconProvider;
class QQuickWebEngineProfilePrivate;
class QQuickWebEngineTouchHandleProvider;
+class QWebEngineFindTextResult;
QQuickWebEngineView::WebAction editorActionForKeyEvent(QKeyEvent* event);
@@ -169,6 +170,7 @@ public:
QtWebEngineCore::WebContentsAdapter *webContentsAdapter() override;
void printRequested() override;
void widgetChanged(QtWebEngineCore::RenderWidgetHostViewQtDelegate *newWidgetBase) override;
+ void findTextFinished(const QWebEngineFindTextResult &result) override;
void updateAction(QQuickWebEngineView::WebAction) const;
void adoptWebContents(QtWebEngineCore::WebContentsAdapter *webContents);
diff --git a/src/webengine/doc/src/webengineview_lgpl.qdoc b/src/webengine/doc/src/webengineview_lgpl.qdoc
index 1c4328d01..8f03774c8 100644
--- a/src/webengine/doc/src/webengineview_lgpl.qdoc
+++ b/src/webengine/doc/src/webengineview_lgpl.qdoc
@@ -414,26 +414,33 @@
\qmlmethod void WebEngineView::findText(string subString)
\since QtWebEngine 1.1
Finds the specified string, \a subString, in the page.
+ The findTextFinished() signal is emitted when a string search is completed.
To clear the search highlight, just pass an empty string.
+
+ \sa findTextFinished()
*/
/*!
\qmlmethod void WebEngineView::findText(string subString, FindFlags options)
\since QtWebEngine 1.1
Finds the specified string, \a subString, in the page, using the given \a options.
+ The findTextFinished() signal is emitted when a string search is completed.
To clear the search highlight, just pass an empty string.
\code
findText("Qt", WebEngineView.FindBackward | WebEngineView.FindCaseSensitively);
\endcode
+
+ \sa findTextFinished()
*/
/*!
\qmlmethod void WebEngineView::findText(string subString, FindFlags options, variant resultCallback)
\since QtWebEngine 1.1
Finds the specified string, \a subString, in the page, using the given \a options.
+ The findTextFinished() signal is emitted when a string search is completed.
To clear the search highlight, just pass an empty string.
@@ -447,6 +454,8 @@
console.log("Qt was found!");
});
\endcode
+
+ \sa findTextFinished()
*/
/*!
@@ -1569,5 +1578,39 @@
resource state is however completely safe.
\sa lifecycleState, {WebEngine Lifecycle Example}
+*/
+
+/*!
+ \qmltype FindTextResult
+ \instantiates QWebEngineFindTextResult
+ \inqmlmodule QtWebEngine
+ \since QtWebEngine 1.11
+
+ \brief A utility type for encapsulating the result of a string search on a page.
+
+ \sa WebEngineView::findTextFinished()
+*/
+
+/*!
+ \qmlproperty int FindTextResult::numberOfMatches
+ \readonly
+
+ \brief The number of matches found.
+*/
+
+/*!
+ \qmlproperty int FindTextResult::activeMatchOrdinal
+ \readonly
+
+ \brief The index of the currently highlighted match.
+*/
+
+/*!
+ \qmlsignal WebEngineView::findTextFinished(FindTextResult result)
+ \since QtWebEngine 1.11
+
+ This signal is emitted when a string search on a page is completed. \a result is
+ the result of the string search.
+ \sa findText(), FindTextResult
*/
diff --git a/src/webengine/plugin/plugin.cpp b/src/webengine/plugin/plugin.cpp
index ad49d6543..e47a46a95 100644
--- a/src/webengine/plugin/plugin.cpp
+++ b/src/webengine/plugin/plugin.cpp
@@ -55,6 +55,7 @@
#include <QtWebEngine/private/qquickwebenginetouchhandleprovider_p_p.h>
#include <QtWebEngine/private/qquickwebengineview_p.h>
#include <QtWebEngine/private/qquickwebengineaction_p.h>
+#include <QtWebEngineCore/qwebenginefindtextresult.h>
#include <QtWebEngineCore/qwebenginenotification.h>
#include <QtWebEngineCore/qwebenginequotarequest.h>
#include <QtWebEngineCore/qwebengineregisterprotocolhandlerrequest.h>
@@ -170,6 +171,8 @@ public:
qmlRegisterUncreatableType<QWebEngineNotification>(uri, 1, 9, "WebEngineNotification", msgUncreatableType("WebEngineNotification"));
qmlRegisterUncreatableType<QQuickWebEngineTooltipRequest>(uri, 1, 10, "TooltipRequest",
msgUncreatableType("TooltipRequest"));
+ qRegisterMetaType<QWebEngineFindTextResult>();
+ qmlRegisterUncreatableType<QWebEngineFindTextResult>(uri, 1, 11, "FindTextResult", msgUncreatableType("FindTextResult"));
}
private:
diff --git a/src/webenginewidgets/api/qwebenginepage.cpp b/src/webenginewidgets/api/qwebenginepage.cpp
index 29566f021..c9e9177b7 100644
--- a/src/webenginewidgets/api/qwebenginepage.cpp
+++ b/src/webenginewidgets/api/qwebenginepage.cpp
@@ -52,6 +52,7 @@
#include "printer_worker.h"
#endif
#include "qwebenginecertificateerror.h"
+#include "qwebenginefindtextresult.h"
#include "qwebenginefullscreenrequest.h"
#include "qwebenginehistory.h"
#include "qwebenginehistory_p.h"
@@ -171,6 +172,7 @@ QWebEnginePagePrivate::QWebEnginePagePrivate(QWebEngineProfile *_profile)
qRegisterMetaType<QWebEngineQuotaRequest>();
qRegisterMetaType<QWebEngineRegisterProtocolHandlerRequest>();
+ qRegisterMetaType<QWebEngineFindTextResult>();
// See setVisible().
wasShownTimer.setSingleShot(true);
@@ -698,6 +700,12 @@ void QWebEnginePagePrivate::widgetChanged(RenderWidgetHostViewQtDelegate *newWid
bindPageAndWidget(q, static_cast<RenderWidgetHostViewQtDelegateWidget *>(newWidgetBase));
}
+void QWebEnginePagePrivate::findTextFinished(const QWebEngineFindTextResult &result)
+{
+ Q_Q(QWebEnginePage);
+ Q_EMIT q->findTextFinished(result);
+}
+
void QWebEnginePagePrivate::ensureInitialized() const
{
if (!adapter->isInitialized())
@@ -798,6 +806,16 @@ QWebEnginePage::QWebEnginePage(QObject* parent)
}
/*!
+ \fn void QWebEnginePage::findTextFinished(const QWebEngineFindTextResult &result)
+ \since 5.14
+
+ This signal is emitted when a search string search on a page is completed. \a result is
+ the result of the string search.
+
+ \sa findText()
+*/
+
+/*!
\fn void QWebEnginePage::printRequested()
\since 5.12
diff --git a/src/webenginewidgets/api/qwebenginepage.h b/src/webenginewidgets/api/qwebenginepage.h
index 736d7ed69..cd012ea70 100644
--- a/src/webenginewidgets/api/qwebenginepage.h
+++ b/src/webenginewidgets/api/qwebenginepage.h
@@ -62,6 +62,7 @@ class QWebChannel;
class QWebEngineCertificateError;
class QWebEngineClientCertificateSelection;
class QWebEngineContextMenuData;
+class QWebEngineFindTextResult;
class QWebEngineFullScreenRequest;
class QWebEngineHistory;
class QWebEnginePage;
@@ -369,6 +370,8 @@ Q_SIGNALS:
void lifecycleStateChanged(LifecycleState state);
void recommendedStateChanged(LifecycleState state);
+ void findTextFinished(const QWebEngineFindTextResult &result);
+
protected:
virtual QWebEnginePage *createWindow(WebWindowType type);
virtual QStringList chooseFiles(FileSelectionMode mode, const QStringList &oldFiles, const QStringList &acceptedMimeTypes);
diff --git a/src/webenginewidgets/api/qwebenginepage_p.h b/src/webenginewidgets/api/qwebenginepage_p.h
index a8cde8199..fae97b9fa 100644
--- a/src/webenginewidgets/api/qwebenginepage_p.h
+++ b/src/webenginewidgets/api/qwebenginepage_p.h
@@ -72,6 +72,7 @@ class WebContentsAdapter;
}
QT_BEGIN_NAMESPACE
+class QWebEngineFindTextResult;
class QWebEngineHistory;
class QWebEnginePage;
class QWebEngineProfile;
@@ -162,6 +163,7 @@ public:
ClientType clientType() override { return QtWebEngineCore::WebContentsAdapterClient::WidgetsClient; }
void interceptRequest(QWebEngineUrlRequestInfo &) override;
void widgetChanged(QtWebEngineCore::RenderWidgetHostViewQtDelegate *newWidget) override;
+ void findTextFinished(const QWebEngineFindTextResult &result) override;
QtWebEngineCore::ProfileAdapter *profileAdapter() override;
QtWebEngineCore::WebContentsAdapter *webContentsAdapter() override;
diff --git a/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc b/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc
index 99bbc5162..64fe4c9cd 100644
--- a/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc
+++ b/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc
@@ -489,6 +489,7 @@
/*!
\fn void QWebEnginePage::findText(const QString &subString, QWebEnginePage::FindFlags options = FindFlags(), const QWebEngineCallback<bool> &resultCallback = QWebEngineCallback<bool>())
Finds the specified string, \a subString, in the page, using the given \a options.
+ The findTextFinished() signal is emitted when a string search is completed.
To clear the search highlight, just pass an empty string.
@@ -501,6 +502,8 @@
For example:
\snippet qtwebengine_qwebenginepage_snippet.cpp 0
+
+ \sa findTextFinished()
*/
/*!
diff --git a/tests/auto/quick/publicapi/tst_publicapi.cpp b/tests/auto/quick/publicapi/tst_publicapi.cpp
index f464d58d0..9f7dfa8ad 100644
--- a/tests/auto/quick/publicapi/tst_publicapi.cpp
+++ b/tests/auto/quick/publicapi/tst_publicapi.cpp
@@ -35,6 +35,7 @@
#include <QtTest/QtTest>
#include <QtWebEngine/QQuickWebEngineProfile>
#include <QtWebEngine/QQuickWebEngineScript>
+#include <QtWebEngineCore/QWebEngineFindTextResult>
#include <QtWebEngineCore/QWebEngineNotification>
#include <QtWebEngineCore/QWebEngineQuotaRequest>
#include <QtWebEngineCore/QWebEngineRegisterProtocolHandlerRequest>
@@ -85,6 +86,7 @@ static const QList<const QMetaObject *> typesToCheck = QList<const QMetaObject *
<< &QWebEngineQuotaRequest::staticMetaObject
<< &QWebEngineRegisterProtocolHandlerRequest::staticMetaObject
<< &QWebEngineNotification::staticMetaObject
+ << &QWebEngineFindTextResult::staticMetaObject
;
static QList<const char *> knownEnumNames = QList<const char *>();
@@ -276,6 +278,8 @@ static const QStringList expectedAPI = QStringList()
<< "QQuickWebEngineFileDialogRequest.dialogAccept(QStringList) --> void"
<< "QQuickWebEngineFileDialogRequest.dialogReject() --> void"
<< "QQuickWebEngineFileDialogRequest.mode --> FileMode"
+ << "QWebEngineFindTextResult.numberOfMatches --> int"
+ << "QWebEngineFindTextResult.activeMatchOrdinal --> int"
<< "QQuickWebEngineFormValidationMessageRequest.Hide --> RequestType"
<< "QQuickWebEngineFormValidationMessageRequest.Move --> RequestType"
<< "QQuickWebEngineFormValidationMessageRequest.Show --> RequestType"
@@ -694,6 +698,7 @@ static const QStringList expectedAPI = QStringList()
<< "QQuickWebEngineView.findText(QString) --> void"
<< "QQuickWebEngineView.findText(QString,FindFlags) --> void"
<< "QQuickWebEngineView.findText(QString,FindFlags,QJSValue) --> void"
+ << "QQuickWebEngineView.findTextFinished(QWebEngineFindTextResult) --> void"
<< "QQuickWebEngineView.formValidationMessageRequested(QQuickWebEngineFormValidationMessageRequest*) --> void"
<< "QQuickWebEngineView.fullScreenCancelled() --> void"
<< "QQuickWebEngineView.fullScreenRequested(QQuickWebEngineFullScreenRequest) --> void"
diff --git a/tests/auto/quick/qmltests/data/tst_findText.qml b/tests/auto/quick/qmltests/data/tst_findText.qml
index 14053a675..040d324e6 100644
--- a/tests/auto/quick/qmltests/data/tst_findText.qml
+++ b/tests/auto/quick/qmltests/data/tst_findText.qml
@@ -38,9 +38,16 @@ TestWebEngineView {
property int matchCount: 0
property bool findFailed: false
+ SignalSpy {
+ id: findTextSpy
+ target: webEngineView
+ signalName: "findTextFinished"
+ }
+
function clear() {
findFailed = false
matchCount = -1
+ findTextSpy.clear()
}
function findCallbackCalled() { return matchCount != -1 }
@@ -104,6 +111,9 @@ TestWebEngineView {
webEngineView.findText("Hello", findFlags, webEngineView.findTextCallback)
tryCompare(webEngineView, "matchCount", 1)
verify(!findFailed)
+ tryCompare(findTextSpy, "count", 1)
+ compare(findTextSpy.signalArguments[0][0].numberOfMatches, 1)
+ compare(findTextSpy.signalArguments[0][0].activeMatchOrdinal, 1)
}
function test_findTextCaseInsensitive() {
@@ -115,6 +125,9 @@ TestWebEngineView {
webEngineView.findText("heLLo", findFlags, webEngineView.findTextCallback)
tryCompare(webEngineView, "matchCount", 1)
verify(!findFailed)
+ tryCompare(findTextSpy, "count", 1)
+ compare(findTextSpy.signalArguments[0][0].numberOfMatches, 1)
+ compare(findTextSpy.signalArguments[0][0].activeMatchOrdinal, 1)
}
function test_findTextManyMatches() {
@@ -126,6 +139,9 @@ TestWebEngineView {
webEngineView.findText("bla", findFlags, webEngineView.findTextCallback)
tryCompare(webEngineView, "matchCount", 100, 20000)
verify(!findFailed)
+ tryCompare(findTextSpy, "count", 1)
+ compare(findTextSpy.signalArguments[0][0].numberOfMatches, 100)
+ compare(findTextSpy.signalArguments[0][0].activeMatchOrdinal, 1)
}
@@ -138,6 +154,9 @@ TestWebEngineView {
webEngineView.findText("heLLo", findFlags, webEngineView.findTextCallback)
tryCompare(webEngineView, "matchCount", 0)
verify(findFailed)
+ tryCompare(findTextSpy, "count", 1)
+ compare(findTextSpy.signalArguments[0][0].numberOfMatches, 0)
+ compare(findTextSpy.signalArguments[0][0].activeMatchOrdinal, 0)
}
function test_findTextNotFound() {
@@ -149,6 +168,9 @@ TestWebEngineView {
webEngineView.findText("string-that-is-not-threre", findFlags, webEngineView.findTextCallback)
tryCompare(webEngineView, "matchCount", 0)
verify(findFailed)
+ tryCompare(findTextSpy, "count", 1)
+ compare(findTextSpy.signalArguments[0][0].numberOfMatches, 0)
+ compare(findTextSpy.signalArguments[0][0].activeMatchOrdinal, 0)
}
function test_findTextAfterNotFound() {
@@ -160,6 +182,9 @@ TestWebEngineView {
webEngineView.findText("hello", findFlags, webEngineView.findTextCallback)
tryCompare(webEngineView, "matchCount", 0)
verify(findFailed)
+ tryCompare(findTextSpy, "count", 1)
+ compare(findTextSpy.signalArguments[0][0].numberOfMatches, 0)
+ compare(findTextSpy.signalArguments[0][0].activeMatchOrdinal, 0)
webEngineView.url = Qt.resolvedUrl("test1.html")
verify(webEngineView.waitForLoadSucceeded())
@@ -168,6 +193,9 @@ TestWebEngineView {
webEngineView.findText("hello", findFlags, webEngineView.findTextCallback)
tryCompare(webEngineView, "matchCount", 1)
verify(!findFailed)
+ tryCompare(findTextSpy, "count", 1)
+ compare(findTextSpy.signalArguments[0][0].numberOfMatches, 1)
+ compare(findTextSpy.signalArguments[0][0].activeMatchOrdinal, 1)
}
function test_findTextInModifiedDOMAfterNotFound() {
@@ -182,6 +210,9 @@ TestWebEngineView {
webEngineView.findText("hello", findFlags, webEngineView.findTextCallback)
tryCompare(webEngineView, "matchCount", 0, 20000)
verify(findFailed)
+ tryCompare(findTextSpy, "count", 1)
+ compare(findTextSpy.signalArguments[0][0].numberOfMatches, 0)
+ compare(findTextSpy.signalArguments[0][0].activeMatchOrdinal, 0)
runJavaScript("document.body.innerHTML = 'blahellobla'");
tryVerify(function() { return getBodyInnerHTML() == "blahellobla"; }, 20000);
@@ -190,6 +221,9 @@ TestWebEngineView {
webEngineView.findText("hello", findFlags, webEngineView.findTextCallback)
tryCompare(webEngineView, "matchCount", 1)
verify(!findFailed)
+ tryCompare(findTextSpy, "count", 1)
+ compare(findTextSpy.signalArguments[0][0].numberOfMatches, 1)
+ compare(findTextSpy.signalArguments[0][0].activeMatchOrdinal, 1)
}
function test_findTextInterruptedByLoad() {
@@ -227,5 +261,55 @@ TestWebEngineView {
webEngineView.findText('New page', findFlags, webEngineView.findTextCallback)
tryCompare(webEngineView, 'matchCount', 1)
}
+
+ function test_findTextActiveMatchOrdinal() {
+ webEngineView.loadHtml(
+ "<html><body>" +
+ "foo bar foo bar foo" +
+ "</body></html>");
+ verify(webEngineView.waitForLoadSucceeded());
+
+ // Iterate over all "foo" matches.
+ webEngineView.clear();
+ for (var i = 1; i <= 3; ++i) {
+ webEngineView.findText("foo");
+ findTextSpy.wait();
+ compare(findTextSpy.count, i);
+ compare(findTextSpy.signalArguments[i-1][0].numberOfMatches, 3);
+ compare(findTextSpy.signalArguments[i-1][0].activeMatchOrdinal, i);
+ }
+
+ // The last match is followed by the fist one.
+ webEngineView.clear();
+ webEngineView.findText("foo");
+ findTextSpy.wait();
+ compare(findTextSpy.count, 1);
+ compare(findTextSpy.signalArguments[0][0].numberOfMatches, 3);
+ compare(findTextSpy.signalArguments[0][0].activeMatchOrdinal, 1);
+
+ // The first match is preceded by the last one.
+ webEngineView.clear();
+ webEngineView.findText("foo", WebEngineView.FindBackward);
+ findTextSpy.wait();
+ compare(findTextSpy.count, 1);
+ compare(findTextSpy.signalArguments[0][0].numberOfMatches, 3);
+ compare(findTextSpy.signalArguments[0][0].activeMatchOrdinal, 3);
+
+ // Finding another word resets the activeMatchOrdinal.
+ webEngineView.clear();
+ webEngineView.findText("bar");
+ findTextSpy.wait();
+ compare(findTextSpy.count, 1);
+ compare(findTextSpy.signalArguments[0][0].numberOfMatches, 2);
+ compare(findTextSpy.signalArguments[0][0].activeMatchOrdinal, 1);
+
+ // If no match activeMatchOrdinal is 0.
+ webEngineView.clear();
+ webEngineView.findText("bla");
+ findTextSpy.wait();
+ compare(findTextSpy.count, 1);
+ compare(findTextSpy.signalArguments[0][0].numberOfMatches, 0);
+ compare(findTextSpy.signalArguments[0][0].activeMatchOrdinal, 0);
+ }
}
}
diff --git a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp
index 7e9815298..dbb15ba10 100644
--- a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp
+++ b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp
@@ -47,6 +47,7 @@
#include <qnetworkreply.h>
#include <qnetworkrequest.h>
#include <qwebenginedownloaditem.h>
+#include <qwebenginefindtextresult.h>
#include <qwebenginefullscreenrequest.h>
#include <qwebenginehistory.h>
#include <qwebenginenotification.h>
@@ -128,6 +129,7 @@ private Q_SLOTS:
void findTextResult();
void findTextSuccessiveShouldCallAllCallbacks();
void findTextCalledOnMatch();
+ void findTextActiveMatchOrdinal();
void deleteQWebEngineViewTwice();
void loadSignalsOrder_data();
void loadSignalsOrder();
@@ -942,18 +944,24 @@ void tst_QWebEnginePage::findText()
// Invoking a stopFinding operation will not change or clear the currently selected text,
// if nothing was found beforehand.
{
- CallbackSpy<bool> spy;
- m_view->findText("", 0, spy.ref());
- QVERIFY(spy.wasCalled());
+ CallbackSpy<bool> callbackSpy;
+ QSignalSpy signalSpy(m_view->page(), &QWebEnginePage::findTextFinished);
+ m_view->findText("", 0, callbackSpy.ref());
+ QVERIFY(callbackSpy.wasCalled());
+ QCOMPARE(signalSpy.count(), 1);
QTRY_COMPARE(m_view->selectedText(), QString("foo bar"));
}
// Invoking a startFinding operation with text that won't be found, will clear the current
// selection.
{
- CallbackSpy<bool> spy;
- m_view->findText("Will not be found", 0, spy.ref());
- QCOMPARE(spy.waitForResult(), false);
+ CallbackSpy<bool> callbackSpy;
+ QSignalSpy signalSpy(m_view->page(), &QWebEnginePage::findTextFinished);
+ m_view->findText("Will not be found", 0, callbackSpy.ref());
+ QCOMPARE(callbackSpy.waitForResult(), false);
+ QTRY_COMPARE(signalSpy.count(), 1);
+ auto result = signalSpy.takeFirst().value(0).value<QWebEngineFindTextResult>();
+ QCOMPARE(result.numberOfMatches(), 0);
QTRY_VERIFY(m_view->selectedText().isEmpty());
}
@@ -964,24 +972,36 @@ void tst_QWebEnginePage::findText()
// Invoking a startFinding operation with text that will be found, will clear the current
// selection as well.
{
- CallbackSpy<bool> spy;
- m_view->findText("foo", 0, spy.ref());
- QVERIFY(spy.waitForResult());
+ CallbackSpy<bool> callbackSpy;
+ QSignalSpy signalSpy(m_view->page(), &QWebEnginePage::findTextFinished);
+ m_view->findText("foo", 0, callbackSpy.ref());
+ QVERIFY(callbackSpy.waitForResult());
+ QTRY_COMPARE(signalSpy.count(), 1);
QTRY_VERIFY(m_view->selectedText().isEmpty());
}
// Invoking a stopFinding operation after text was found, will set the selected text to the
// found text.
{
- CallbackSpy<bool> spy;
- m_view->findText("", 0, spy.ref());
- QTRY_VERIFY(spy.wasCalled());
+ CallbackSpy<bool> callbackSpy;
+ QSignalSpy signalSpy(m_view->page(), &QWebEnginePage::findTextFinished);
+ m_view->findText("", 0, callbackSpy.ref());
+ QTRY_VERIFY(callbackSpy.wasCalled());
+ QTRY_COMPARE(signalSpy.count(), 1);
QTRY_COMPARE(m_view->selectedText(), QString("foo"));
}
}
void tst_QWebEnginePage::findTextResult()
{
+ QSignalSpy findTextSpy(m_view->page(), &QWebEnginePage::findTextFinished);
+ auto signalResult = [&findTextSpy]() -> QVector<int> {
+ if (findTextSpy.count() != 1)
+ return QVector<int>({-1, -1});
+ auto r = findTextSpy.takeFirst().value(0).value<QWebEngineFindTextResult>();
+ return QVector<int>({ r.numberOfMatches(), r.activeMatchOrdinal() });
+ };
+
// findText will abort in blink if the view has an empty size.
m_view->resize(800, 600);
m_view->show();
@@ -991,15 +1011,21 @@ void tst_QWebEnginePage::findTextResult()
QTRY_COMPARE(loadSpy.count(), 1);
QCOMPARE(findTextSync(m_page, ""), false);
+ QCOMPARE(signalResult(), QVector<int>({0, 0}));
const QStringList words = { "foo", "bar" };
for (const QString &subString : words) {
QCOMPARE(findTextSync(m_page, subString), true);
+ QCOMPARE(signalResult(), QVector<int>({1, 1}));
+
QCOMPARE(findTextSync(m_page, ""), false);
+ QCOMPARE(signalResult(), QVector<int>({0, 0}));
}
QCOMPARE(findTextSync(m_page, "blahhh"), false);
+ QCOMPARE(signalResult(), QVector<int>({0, 0}));
QCOMPARE(findTextSync(m_page, ""), false);
+ QCOMPARE(signalResult(), QVector<int>({0, 0}));
}
void tst_QWebEnginePage::findTextSuccessiveShouldCallAllCallbacks()
@@ -1035,6 +1061,7 @@ void tst_QWebEnginePage::findTextCalledOnMatch()
m_view->setHtml(QString("<html><head></head><body><div>foo bar</div></body></html>"));
QTRY_COMPARE(loadSpy.count(), 1);
+ // CALLBACK
bool callbackCalled = false;
m_view->page()->findText("foo", 0, [this, &callbackCalled](bool found) {
QVERIFY(found);
@@ -1045,6 +1072,68 @@ void tst_QWebEnginePage::findTextCalledOnMatch()
});
});
QTRY_VERIFY(callbackCalled);
+
+ // SIGNAL
+ int findTextFinishedCount = 0;
+ connect(m_view->page(), &QWebEnginePage::findTextFinished, [this, &findTextFinishedCount](QWebEngineFindTextResult result) {
+ QCOMPARE(result.numberOfMatches(), 1);
+ if (findTextFinishedCount == 0)
+ m_view->page()->findText("bar");
+ findTextFinishedCount++;
+ });
+
+ m_view->page()->findText("foo");
+ QTRY_COMPARE(findTextFinishedCount, 2);
+}
+
+void tst_QWebEnginePage::findTextActiveMatchOrdinal()
+{
+ QSignalSpy loadSpy(m_view->page(), &QWebEnginePage::loadFinished);
+ QSignalSpy findTextSpy(m_view->page(), &QWebEnginePage::findTextFinished);
+ QWebEngineFindTextResult result;
+
+ // findText will abort in blink if the view has an empty size.
+ m_view->resize(800, 600);
+ m_view->show();
+ m_view->setHtml(QString("<html><head></head><body><div>foo bar foo bar foo</div></body></html>"));
+ QTRY_COMPARE(loadSpy.count(), 1);
+
+ // Iterate over all "foo" matches.
+ for (int i = 1; i <= 3; ++i) {
+ m_view->page()->findText("foo", 0);
+ QTRY_COMPARE(findTextSpy.count(), 1);
+ result = findTextSpy.takeFirst().value(0).value<QWebEngineFindTextResult>();
+ QCOMPARE(result.numberOfMatches(), 3);
+ QCOMPARE(result.activeMatchOrdinal(), i);
+ }
+
+ // The last match is followed by the fist one.
+ m_view->page()->findText("foo", 0);
+ QTRY_COMPARE(findTextSpy.count(), 1);
+ result = findTextSpy.takeFirst().value(0).value<QWebEngineFindTextResult>();
+ QCOMPARE(result.numberOfMatches(), 3);
+ QCOMPARE(result.activeMatchOrdinal(), 1);
+
+ // The first match is preceded by the last one.
+ m_view->page()->findText("foo", QWebEnginePage::FindBackward);
+ QTRY_COMPARE(findTextSpy.count(), 1);
+ result = findTextSpy.takeFirst().value(0).value<QWebEngineFindTextResult>();
+ QCOMPARE(result.numberOfMatches(), 3);
+ QCOMPARE(result.activeMatchOrdinal(), 3);
+
+ // Finding another word resets the activeMatchOrdinal.
+ m_view->page()->findText("bar", 0);
+ QTRY_COMPARE(findTextSpy.count(), 1);
+ result = findTextSpy.takeFirst().value(0).value<QWebEngineFindTextResult>();
+ QCOMPARE(result.numberOfMatches(), 2);
+ QCOMPARE(result.activeMatchOrdinal(), 1);
+
+ // If no match activeMatchOrdinal is 0.
+ m_view->page()->findText("bla", 0);
+ QTRY_COMPARE(findTextSpy.count(), 1);
+ result = findTextSpy.takeFirst().value(0).value<QWebEngineFindTextResult>();
+ QCOMPARE(result.numberOfMatches(), 0);
+ QCOMPARE(result.activeMatchOrdinal(), 0);
}
static QWindow *findNewTopLevelWindow(const QWindowList &oldTopLevelWindows)