From 57613ac99f6b1058c3e39ed15e6749351a9b5deb Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 20 Mar 2020 15:44:34 +0100 Subject: Add functions with callback of QWebEnginePage Provide them as user-added functions using C++ lambdas. Fixes: PYSIDE-946 Task-number: PYSIDE-1241 Change-Id: I9733bc98b3fc8b3bcf40ab4ce91ffdb84e385b93 Reviewed-by: Cristian Maureira-Fredes --- .../typesystem_webenginewidgets.xml | 24 +++- .../pyside2/PySide2/glue/qtwebenginewidgets.cpp | 157 +++++++++++++++++++++ sources/pyside2/tests/QtWebEngineWidgets/fox.html | 7 + .../pyside-474-qtwebengineview.py | 49 ++++++- 4 files changed, 229 insertions(+), 8 deletions(-) create mode 100644 sources/pyside2/PySide2/glue/qtwebenginewidgets.cpp create mode 100644 sources/pyside2/tests/QtWebEngineWidgets/fox.html diff --git a/sources/pyside2/PySide2/QtWebEngineWidgets/typesystem_webenginewidgets.xml b/sources/pyside2/PySide2/QtWebEngineWidgets/typesystem_webenginewidgets.xml index e0821a114..b18d4359a 100644 --- a/sources/pyside2/PySide2/QtWebEngineWidgets/typesystem_webenginewidgets.xml +++ b/sources/pyside2/PySide2/QtWebEngineWidgets/typesystem_webenginewidgets.xml @@ -73,6 +73,24 @@ + + + + + + + + + + + + + + + + + + @@ -94,7 +112,11 @@ - + + + + + diff --git a/sources/pyside2/PySide2/glue/qtwebenginewidgets.cpp b/sources/pyside2/PySide2/glue/qtwebenginewidgets.cpp new file mode 100644 index 000000000..5ee9f3554 --- /dev/null +++ b/sources/pyside2/PySide2/glue/qtwebenginewidgets.cpp @@ -0,0 +1,157 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt for Python. +** +** $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$ +** +****************************************************************************/ + +// @snippet qwebenginepage-findtext +auto callable = %PYARG_3; +auto callback = [callable](bool found) +{ + if (!PyCallable_Check(callable)) { + qWarning("Argument 3 of %FUNCTION_NAME must be a callable."); + return; + } + Shiboken::GilState state; + Shiboken::AutoDecRef arglist(PyTuple_New(1)); + PyTuple_SET_ITEM(arglist, 0, %CONVERTTOPYTHON[bool](found)); + Shiboken::AutoDecRef ret(PyObject_CallObject(callable, arglist)); + Py_DECREF(callable); + +}; +Py_INCREF(callable); +%CPPSELF.%FUNCTION_NAME(%1, %2, callback); +// @snippet qwebenginepage-findtext + +// @snippet qwebenginepage-print +auto printer = %PYARG_1; +auto callable = %PYARG_2; +auto callback = [printer, callable](bool succeeded) +{ + if (!PyCallable_Check(callable)) { + qWarning("Argument 2 of %FUNCTION_NAME must be a callable."); + return; + } + Shiboken::GilState state; + Shiboken::AutoDecRef arglist(PyTuple_New(1)); + PyTuple_SET_ITEM(arglist, 0, %CONVERTTOPYTHON[bool](succeeded)); + Shiboken::AutoDecRef ret(PyObject_CallObject(callable, arglist)); + Py_DECREF(callable); + Py_DECREF(printer); + +}; +Py_INCREF(printer); // Add a reference to the printer until asynchronous printing has finished +Py_INCREF(callable); +%CPPSELF.%FUNCTION_NAME(%1, callback); +// @snippet qwebenginepage-print + +// @snippet qwebenginepage-convertto +auto callable = %PYARG_1; +auto callback = [callable](const QString &text) +{ + if (!PyCallable_Check(callable)) { + qWarning("Argument 1 of %FUNCTION_NAME must be a callable."); + return; + } + Shiboken::GilState state; + Shiboken::AutoDecRef arglist(PyTuple_New(1)); + PyTuple_SET_ITEM(arglist, 0, %CONVERTTOPYTHON[QString](text)); + Shiboken::AutoDecRef ret(PyObject_CallObject(callable, arglist)); + Py_DECREF(callable); + +}; +Py_INCREF(callable); +%CPPSELF.%FUNCTION_NAME(callback); +// @snippet qwebenginepage-convertto + +// @snippet qwebenginepage-runjavascript +auto callable = %PYARG_3; +auto callback = [callable](const QVariant &result) +{ + if (!PyCallable_Check(callable)) { + qWarning("Argument 3 of %FUNCTION_NAME must be a callable."); + return; + } + Shiboken::GilState state; + Shiboken::AutoDecRef arglist(PyTuple_New(1)); + switch (result.type()) { + case QVariant::Bool: { + const bool value = result.toBool(); + PyTuple_SET_ITEM(arglist, 0, %CONVERTTOPYTHON[QString](value)); + } + break; + case QVariant::Int: + case QVariant::UInt: + case QVariant::LongLong: + case QVariant::ULongLong: + case QVariant::Double: { + const double number = result.toDouble(); + PyTuple_SET_ITEM(arglist, 0, %CONVERTTOPYTHON[double](number)); + } + break; + default: { + const QString value = result.toString(); + PyTuple_SET_ITEM(arglist, 0, %CONVERTTOPYTHON[QString](value)); + } + break; + } + // PyTuple_SET_ITEM(arglist, 0, %CONVERTTOPYTHON[bool](found)); + Shiboken::AutoDecRef ret(PyObject_CallObject(callable, arglist)); + Py_DECREF(callable); + +}; +Py_INCREF(callable); +%CPPSELF.%FUNCTION_NAME(%1, %2, callback); +// @snippet qwebenginepage-runjavascript + +// @snippet qwebenginepage-printtopdf +auto callable = %PYARG_1; +auto callback = [callable](const QByteArray &pdf) +{ + if (!PyCallable_Check(callable)) { + qWarning("Argument 1 of %FUNCTION_NAME must be a callable."); + return; + } + Shiboken::GilState state; + Shiboken::AutoDecRef arglist(PyTuple_New(1)); + PyTuple_SET_ITEM(arglist, 0, %CONVERTTOPYTHON[QByteArray](pdf)); + Shiboken::AutoDecRef ret(PyObject_CallObject(callable, arglist)); + Py_DECREF(callable); + +}; +Py_INCREF(callable); +%CPPSELF.%FUNCTION_NAME(callback, %2); +// @snippet qwebenginepage-printtopdf diff --git a/sources/pyside2/tests/QtWebEngineWidgets/fox.html b/sources/pyside2/tests/QtWebEngineWidgets/fox.html new file mode 100644 index 000000000..da873b1cc --- /dev/null +++ b/sources/pyside2/tests/QtWebEngineWidgets/fox.html @@ -0,0 +1,7 @@ + +Title + + +

The quick brown fox jumps over the lazy dog.

+ + diff --git a/sources/pyside2/tests/QtWebEngineWidgets/pyside-474-qtwebengineview.py b/sources/pyside2/tests/QtWebEngineWidgets/pyside-474-qtwebengineview.py index a40e29887..c650a21d0 100644 --- a/sources/pyside2/tests/QtWebEngineWidgets/pyside-474-qtwebengineview.py +++ b/sources/pyside2/tests/QtWebEngineWidgets/pyside-474-qtwebengineview.py @@ -28,24 +28,59 @@ from __future__ import print_function +from functools import partial import os import sys import unittest -sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) +TEST_DIR = os.path.dirname(os.path.abspath(__file__)) + +sys.path.append(os.path.dirname(TEST_DIR)) from init_paths import init_test_paths init_test_paths(False) -from PySide2 import QtWidgets -from PySide2 import QtWebEngineWidgets +from PySide2.QtCore import QCoreApplication, QSize, QUrl, Qt +from PySide2.QtWidgets import QApplication, QVBoxLayout, QWidget +from PySide2.QtWebEngineWidgets import QWebEnginePage, QWebEngineView + class MainTest(unittest.TestCase): def test_WebEngineView_findText_exists(self): - qApp = (QtWidgets.QApplication.instance() or - QtWidgets.QApplication([])) - view = QtWebEngineWidgets.QWebEngineView() - view.findText("nothing") + QCoreApplication.setAttribute(Qt.AA_EnableHighDpiScaling) + app = QApplication.instance() or QApplication() + top_level = QWidget() + layout = QVBoxLayout(top_level) + self._view = QWebEngineView() + self._view.loadFinished.connect(self.loaded) + self._view.load(QUrl.fromLocalFile(os.path.join(TEST_DIR, "fox.html"))) + self._view.setMinimumSize(QSize(400, 300)) + self._callback_count = 0 + layout.addWidget(self._view) + top_level.show() + app.exec_() + + def found_callback(self, found): + self.assertTrue(found) + self._callback_count += 1 + if self._callback_count == 2: + QCoreApplication.quit() + + def javascript_callback(self, result): + self.assertEqual(result, "Title") + self._callback_count += 1 + if self._callback_count == 2: + QCoreApplication.quit() + + def loaded(self, ok): + self.assertTrue(ok) + if not ok: + QCoreApplication.quit() + self._view.page().runJavaScript("document.title", 1, + partial(self.javascript_callback)) + self._view.findText("fox", QWebEnginePage.FindFlags(), + partial(self.found_callback)) + if __name__ == '__main__': unittest.main() -- cgit v1.2.3