From 41e1ac9e6e1f1d98a5901253e89d7b524d3cdf6b Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Wed, 21 Jul 2021 11:32:35 +0200 Subject: Return printToPdf to QWebEnginePage It doesn't use QPrinter and can be done using QtGui classes only. Change-Id: I0e14563c1bb5e93d9803bb1a807f702b1a2a5315 Reviewed-by: Qt CI Bot Reviewed-by: Kirill Burtsev (cherry picked from commit b405ed26336a44ad4f359cdb4e1909e31c113cd4) Reviewed-by: Qt Cherry-pick Bot --- src/core/api/qwebenginepage.cpp | 96 ++++++++++++++++++++++++++++++++++++++++- src/core/api/qwebenginepage.h | 12 ++++++ src/core/api/qwebenginepage_p.h | 7 ++- 3 files changed, 113 insertions(+), 2 deletions(-) (limited to 'src/core/api') diff --git a/src/core/api/qwebenginepage.cpp b/src/core/api/qwebenginepage.cpp index c17276a1f..17e138920 100644 --- a/src/core/api/qwebenginepage.cpp +++ b/src/core/api/qwebenginepage.cpp @@ -321,6 +321,8 @@ void QWebEnginePagePrivate::loadFinished(QWebEngineLoadingInfo info) void QWebEnginePagePrivate::didPrintPageToPdf(const QString &filePath, bool success) { + Q_Q(QWebEnginePage); + Q_EMIT q->pdfPrintingFinished(filePath, success); if (view) view->didPrintPageToPdf(filePath, success); } @@ -470,8 +472,28 @@ void QWebEnginePagePrivate::didFetchDocumentInnerText(quint64 requestId, const Q void QWebEnginePagePrivate::didPrintPage(quint64 requestId, QSharedPointer result) { +#if QT_CONFIG(webengine_printing_and_pdf) + Q_Q(QWebEnginePage); + + // If no currentPrinter is set that means that were printing to PDF only. + if (!currentPrinter) { + if (!result.data()) + return; + if (auto callback = m_pdfResultCallbacks.take(requestId)) + callback(*(result.data())); + return; + } + if (view) - view->didPrintPage(requestId, result); + view->didPrintPage(currentPrinter, result); + else + currentPrinter = nullptr; +#else + // we should never enter this branch, but just for safe-keeping... + Q_UNUSED(result); + if (auto callback = m_pdfResultCallbacks.take(requestId)) + callback(QByteArray()); +#endif } bool QWebEnginePagePrivate::passOnFocus(bool reverse) @@ -1688,6 +1710,10 @@ void QWebEnginePagePrivate::setToolTip(const QString &toolTipText) void QWebEnginePagePrivate::printRequested() { + Q_Q(QWebEnginePage); + QTimer::singleShot(0, q, [q]() { + Q_EMIT q->printRequested(); + }); if (view) view->printRequested(); } @@ -2233,6 +2259,74 @@ QSizeF QWebEnginePage::contentsSize() const \sa createWindow(), QWebEngineNewWindowRequest::openIn() */ +/*! + \fn void QWebEnginePage::pdfPrintingFinished(const QString &filePath, bool success) + + This signal is emitted when printing the web page into a PDF file has + finished. + \a filePath will contain the path the file was requested to be created + at, and \a success will be \c true if the file was successfully created and + \c false otherwise. + + \sa printToPdf() +*/ + +/*! + Renders the current content of the page into a PDF document and saves it + in the location specified in \a filePath. + The page size and orientation of the produced PDF document are taken from + the values specified in \a pageLayout, while the range of pages printed is + taken from \a ranges with the default being printing all pages. + + This method issues an asynchronous request for printing the web page into + a PDF and returns immediately. + To be informed about the result of the request, connect to the signal + pdfPrintingFinished(). + + If a file already exists at the provided file path, it will be overwritten. + \sa pdfPrintingFinished() +*/ +void QWebEnginePage::printToPdf(const QString &filePath, const QPageLayout &layout, const QPageRanges &ranges) +{ +#if QT_CONFIG(webengine_printing_and_pdf) + Q_D(QWebEnginePage); + d->ensureInitialized(); + d->adapter->printToPDF(layout, ranges, filePath); +#else + Q_UNUSED(filePath); + Q_UNUSED(layout); + Q_UNUSED(ranges); +#endif +} + +/*! + Renders the current content of the page into a PDF document and returns a byte array containing the PDF data + as parameter to \a resultCallback. + The page size and orientation of the produced PDF document are taken from the values specified in \a pageLayout, + while the range of pages printed is taken from \a ranges with the default being printing all pages. + + The \a resultCallback must take a const reference to a QByteArray as parameter. If printing was successful, this byte array + will contain the PDF data, otherwise, the byte array will be empty. + + \warning We guarantee that the callback (\a resultCallback) is always called, but it might be done + during page destruction. When QWebEnginePage is deleted, the callback is triggered with an invalid + value and it is not safe to use the corresponding QWebEnginePage or QWebEngineView instance inside it. +*/ +void QWebEnginePage::printToPdf(const std::function &resultCallback, const QPageLayout &layout, const QPageRanges &ranges) +{ + Q_D(QWebEnginePage); +#if QT_CONFIG(webengine_printing_and_pdf) + d->ensureInitialized(); + quint64 requestId = d->adapter->printToPDFCallbackResult(layout, ranges); + d->m_pdfResultCallbacks.insert(requestId, resultCallback); +#else + Q_UNUSED(layout); + Q_UNUSED(ranges); + if (resultCallback) + resultCallback(QByteArray()); +#endif +} + /*! \internal */ diff --git a/src/core/api/qwebenginepage.h b/src/core/api/qwebenginepage.h index 1bdcf6539..9f35cffeb 100644 --- a/src/core/api/qwebenginepage.h +++ b/src/core/api/qwebenginepage.h @@ -49,6 +49,8 @@ #include #include #include +#include +#include #include @@ -301,6 +303,13 @@ public: bool recentlyAudible() const; qint64 renderProcessPid() const; + void printToPdf(const QString &filePath, + const QPageLayout &layout = QPageLayout(QPageSize(QPageSize::A4), QPageLayout::Portrait, QMarginsF()), + const QPageRanges &ranges = {}); + void printToPdf(const std::function &resultCallback, + const QPageLayout &layout = QPageLayout(QPageSize(QPageSize::A4), QPageLayout::Portrait, QMarginsF()), + const QPageRanges &ranges = {}); + void setInspectedPage(QWebEnginePage *page); QWebEnginePage *inspectedPage() const; void setDevToolsPage(QWebEnginePage *page); @@ -355,6 +364,9 @@ Q_SIGNALS: void recentlyAudibleChanged(bool recentlyAudible); void renderProcessPidChanged(qint64 pid); + void pdfPrintingFinished(const QString &filePath, bool success); + void printRequested(); + void visibleChanged(bool visible); void lifecycleStateChanged(LifecycleState state); diff --git a/src/core/api/qwebenginepage_p.h b/src/core/api/qwebenginepage_p.h index f9eb2ad71..40b6ddd29 100644 --- a/src/core/api/qwebenginepage_p.h +++ b/src/core/api/qwebenginepage_p.h @@ -70,6 +70,7 @@ class WebContentsAdapter; } QT_BEGIN_NAMESPACE +class QPrinter; class QWebEngineFindTextResult; class QWebEngineHistory; class QWebEnginePage; @@ -102,7 +103,7 @@ public: virtual void unhandledKeyEvent(QKeyEvent *event) = 0; virtual bool passOnFocus(bool reverse) = 0; virtual QObject *accessibilityParentObject() = 0; - virtual void didPrintPage(quint64 requestId, QSharedPointer result) = 0; + virtual void didPrintPage(QPrinter *&printer, QSharedPointer result) = 0; virtual void didPrintPageToPdf(const QString &filePath, bool success) = 0; virtual void printRequested() = 0; }; @@ -222,9 +223,13 @@ public: qreal defaultZoomFactor; QTimer wasShownTimer; QtWebEngineCore::RenderWidgetHostViewQtDelegateWidget *widget = nullptr; +#if QT_CONFIG(webengine_printing_and_pdf) + QPrinter *currentPrinter = nullptr; +#endif mutable QMap> m_variantCallbacks; mutable QMap> m_stringCallbacks; + QMap> m_pdfResultCallbacks; mutable QAction *actions[QWebEnginePage::WebActionCount]; }; -- cgit v1.2.3