summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--examples/webenginewidgets/html2pdf/html2pdf.cpp14
-rw-r--r--examples/webenginewidgets/printme/printhandler.cpp4
-rw-r--r--src/core/api/CMakeLists.txt6
-rw-r--r--src/core/api/qwebenginepage.cpp186
-rw-r--r--src/core/api/qwebenginepage.h8
-rw-r--r--src/core/api/qwebenginepage_p.h6
-rw-r--r--src/core/printing/printer_worker.cpp52
-rw-r--r--src/core/printing/printer_worker.h13
-rw-r--r--src/webenginewidgets/CMakeLists.txt5
-rw-r--r--src/webenginewidgets/api/qwebengineview.cpp126
-rw-r--r--src/webenginewidgets/api/qwebengineview.h7
-rw-r--r--src/webenginewidgets/api/qwebengineview_p.h8
-rw-r--r--tests/auto/widgets/printing/tst_printing.cpp42
13 files changed, 215 insertions, 262 deletions
diff --git a/examples/webenginewidgets/html2pdf/html2pdf.cpp b/examples/webenginewidgets/html2pdf/html2pdf.cpp
index e9fc69534..1b52d69b1 100644
--- a/examples/webenginewidgets/html2pdf/html2pdf.cpp
+++ b/examples/webenginewidgets/html2pdf/html2pdf.cpp
@@ -52,7 +52,7 @@
#include <QCommandLineParser>
#include <QFile>
#include <QTextStream>
-#include <QWebEnginePage>
+#include <QWebEngineView>
#include <functional>
@@ -73,23 +73,23 @@ private slots:
private:
QString m_inputPath;
QString m_outputPath;
- QScopedPointer<QWebEnginePage> m_page;
+ QScopedPointer<QWebEngineView> m_view;
};
Html2PdfConverter::Html2PdfConverter(QString inputPath, QString outputPath)
: m_inputPath(move(inputPath))
, m_outputPath(move(outputPath))
- , m_page(new QWebEnginePage)
+ , m_view(new QWebEngineView)
{
- connect(m_page.data(), &QWebEnginePage::loadFinished,
+ connect(m_view.data(), &QWebEngineView::loadFinished,
this, &Html2PdfConverter::loadFinished);
- connect(m_page.data(), &QWebEnginePage::pdfPrintingFinished,
+ connect(m_view.data(), &QWebEngineView::pdfPrintingFinished,
this, &Html2PdfConverter::pdfPrintingFinished);
}
int Html2PdfConverter::run()
{
- m_page->load(QUrl::fromUserInput(m_inputPath));
+ m_view->load(QUrl::fromUserInput(m_inputPath));
return QApplication::exec();
}
@@ -102,7 +102,7 @@ void Html2PdfConverter::loadFinished(bool ok)
return;
}
- m_page->printToPdf(m_outputPath);
+ m_view->printToPdf(m_outputPath);
}
void Html2PdfConverter::pdfPrintingFinished(const QString &filePath, bool success)
diff --git a/examples/webenginewidgets/printme/printhandler.cpp b/examples/webenginewidgets/printme/printhandler.cpp
index 3534c155b..58114a610 100644
--- a/examples/webenginewidgets/printme/printhandler.cpp
+++ b/examples/webenginewidgets/printme/printhandler.cpp
@@ -66,7 +66,7 @@ void PrintHandler::setView(QWebEngineView *view)
{
Q_ASSERT(!m_view);
m_view = view;
- connect(view->page(), &QWebEnginePage::printRequested, this, &PrintHandler::printPreview);
+ connect(view, &QWebEngineView::printRequested, this, &PrintHandler::printPreview);
}
void PrintHandler::print()
@@ -83,7 +83,7 @@ void PrintHandler::printDocument(QPrinter *printer)
QEventLoop loop;
bool result;
auto printPreview = [&](bool success) { result = success; loop.quit(); };
- m_view->page()->print(printer, std::move(printPreview));
+ m_view->print(printer, std::move(printPreview));
loop.exec();
if (!result) {
QPainter painter;
diff --git a/src/core/api/CMakeLists.txt b/src/core/api/CMakeLists.txt
index bf2008ebd..4074bdb51 100644
--- a/src/core/api/CMakeLists.txt
+++ b/src/core/api/CMakeLists.txt
@@ -2,7 +2,7 @@ if(NOT DEFINED WEBENGINE_ROOT_SOURCE_DIR)
get_filename_component(WEBENGINE_ROOT_SOURCE_DIR "${CMAKE_CURRENT_LIST_DIR}/../../.." REALPATH)
endif()
find_package(Qt6 ${PROJECT_VERSION} REQUIRED COMPONENTS Gui Network OpenGL Quick)
-find_package(Qt6 ${PROJECT_VERSION} QUIET OPTIONAL_COMPONENTS PrintSupport WebChannel Positioning)
+find_package(Qt6 ${PROJECT_VERSION} QUIET OPTIONAL_COMPONENTS WebChannel Positioning)
include(${WEBENGINE_ROOT_SOURCE_DIR}/cmake/Functions.cmake)
get_configure_mode(configureMode)
@@ -65,10 +65,6 @@ qt_skip_warnings_are_errors(WebEngineCore)
make_install_only(WebEngineCore)
make_config_for_gn(WebEngineCore gn_config)
-qt_internal_extend_target(WebEngineCore CONDITION QT_FEATURE_webengine_printing_and_pdf
- PUBLIC_LIBRARIES
- Qt::PrintSupport
-)
qt_internal_extend_target(WebEngineCore CONDITION QT_FEATURE_webengine_webchannel
PUBLIC_LIBRARIES
Qt::WebChannel
diff --git a/src/core/api/qwebenginepage.cpp b/src/core/api/qwebenginepage.cpp
index 548457349..f04a0943c 100644
--- a/src/core/api/qwebenginepage.cpp
+++ b/src/core/api/qwebenginepage.cpp
@@ -48,9 +48,6 @@
#include "find_text_helper.h"
#include "file_picker_controller.h"
#include "javascript_dialog_controller.h"
-#if QT_CONFIG(webengine_printing_and_pdf)
-#include "printing/printer_worker.h"
-#endif
#include "qwebenginecertificateerror.h"
#include "qwebenginefindtextresult.h"
#include "qwebenginefullscreenrequest.h"
@@ -79,13 +76,10 @@
#include <QIcon>
#include <QLoggingCategory>
#include <QMimeData>
-#if QT_CONFIG(webengine_printing_and_pdf)
-#include <QPrinter>
-#include <QThread>
-#endif
#include <QTimer>
#include <QUrl>
+
QT_BEGIN_NAMESPACE
using namespace QtWebEngineCore;
@@ -182,9 +176,6 @@ QWebEnginePagePrivate::QWebEnginePagePrivate(QWebEngineProfile *_profile)
, webChannelWorldId(QWebEngineScript::MainWorld)
, defaultAudioMuted(false)
, defaultZoomFactor(1.0)
-#if QT_CONFIG(webengine_printing_and_pdf)
- , currentPrinter(nullptr)
-#endif
{
memset(actions, 0, sizeof(actions));
@@ -340,8 +331,8 @@ void QWebEnginePagePrivate::loadFinished(bool success, const QUrl &url, bool isE
void QWebEnginePagePrivate::didPrintPageToPdf(const QString &filePath, bool success)
{
- Q_Q(QWebEnginePage);
- Q_EMIT q->pdfPrintingFinished(filePath, success);
+ if (view)
+ view->didPrintPageToPdf(filePath, success);
}
void QWebEnginePagePrivate::focusContainer()
@@ -486,38 +477,8 @@ void QWebEnginePagePrivate::didFetchDocumentInnerText(quint64 requestId, const Q
void QWebEnginePagePrivate::didPrintPage(quint64 requestId, QSharedPointer<QByteArray> 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;
- m_callbacks.invoke(requestId, *(result.data()));
- return;
- }
-
- QThread *printerThread = new QThread;
- QObject::connect(printerThread, &QThread::finished, printerThread, &QThread::deleteLater);
- printerThread->start();
-
- PrinterWorker *printerWorker = new PrinterWorker(result, currentPrinter);
- QObject::connect(printerWorker, &PrinterWorker::resultReady, q, [requestId, this](bool success) {
- currentPrinter = nullptr;
- m_callbacks.invoke(requestId, success);
- });
-
- QObject::connect(printerWorker, &PrinterWorker::resultReady, printerThread, &QThread::quit);
- QObject::connect(printerThread, &QThread::finished, printerWorker, &PrinterWorker::deleteLater);
-
- printerWorker->moveToThread(printerThread);
- QMetaObject::invokeMethod(printerWorker, "print");
-
-#else
- // we should never enter this branch, but just for safe-keeping...
- Q_UNUSED(result);
- m_callbacks.invoke(requestId, QByteArray());
-#endif
+ if (view)
+ view->didPrintPage(requestId, result);
}
bool QWebEnginePagePrivate::passOnFocus(bool reverse)
@@ -780,15 +741,6 @@ QWebEnginePage::QWebEnginePage(QObject* parent)
\sa findText()
*/
-/*!
- \fn void QWebEnginePage::printRequested()
- \since 5.12
-
- This signal is emitted when the JavaScript \c{window.print()} method is called.
- Typically, the signal handler can simply call printToPdf().
-
- \sa printToPdf()
-*/
/*!
\enum QWebEnginePage::RenderProcessTerminationStatus
@@ -854,19 +806,6 @@ QWebEnginePage::QWebEnginePage(QObject* parent)
*/
/*!
- \fn void QWebEnginePage::pdfPrintingFinished(const QString &filePath, bool success)
- \since 5.9
-
- 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()
-*/
-
-/*!
\property QWebEnginePage::scrollPosition
\since 5.7
@@ -1752,10 +1691,8 @@ 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();
}
void QWebEnginePagePrivate::lifecycleStateChanged(LifecycleState state)
@@ -2268,115 +2205,6 @@ QSizeF QWebEnginePage::contentsSize() const
}
/*!
- 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.
-
- 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.
- \since 5.7
- \sa pdfPrintingFinished()
-*/
-void QWebEnginePage::printToPdf(const QString &filePath, const QPageLayout &pageLayout)
-{
-#if QT_CONFIG(webengine_printing_and_pdf)
- Q_D(const QWebEnginePage);
- if (d->currentPrinter) {
- qWarning("Cannot print to PDF while at the same time printing on printer %ls", qUtf16Printable(d->currentPrinter->printerName()));
- return;
- }
- d->ensureInitialized();
- d->adapter->printToPDF(pageLayout, filePath);
-#else
- Q_UNUSED(filePath);
- Q_UNUSED(pageLayout);
-#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.
-
- 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.
-
- \since 5.7
-*/
-void QWebEnginePage::printToPdf(const QWebEngineCallback<const QByteArray&> &resultCallback, const QPageLayout &pageLayout)
-{
- Q_D(QWebEnginePage);
-#if QT_CONFIG(webengine_printing_and_pdf)
- if (d->currentPrinter) {
- qWarning("Cannot print to PDF while at the same time printing on printer %ls", qUtf16Printable(d->currentPrinter->printerName()));
- d->m_callbacks.invokeEmpty(resultCallback);
- return;
- }
- d->ensureInitialized();
- quint64 requestId = d->adapter->printToPDFCallbackResult(pageLayout);
- d->m_callbacks.registerCallback(requestId, resultCallback);
-#else
- Q_UNUSED(pageLayout);
- d->m_callbacks.invokeEmpty(resultCallback);
-#endif
-}
-
-/*!
- Renders the current content of the page into a temporary PDF document, then prints it using \a printer.
-
- The settings for creating and printing the PDF document will be retrieved from the \a printer
- object.
- It is the users responsibility to ensure the \a printer remains valid until \a resultCallback
- has been called.
-
- \note Printing runs on the browser process, which is by default not sandboxed.
-
- The \a resultCallback must take a boolean as parameter. If printing was successful, this
- boolean will have the value \c true, otherwise, its value will be \c false.
-
- \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.
-
- \note This function rasterizes the result when rendering onto \a printer. Please consider raising
- the default resolution of \a printer to at least 300 DPI or using printToPdf() to produce
- PDF file output more effectively.
-
- \since 5.8
-*/
-void QWebEnginePage::print(QPrinter *printer, const QWebEngineCallback<bool> &resultCallback)
-{
- Q_D(QWebEnginePage);
-#if QT_CONFIG(webengine_printing_and_pdf)
- if (d->currentPrinter) {
- qWarning("Cannot print page on printer %ls: Already printing on %ls.", qUtf16Printable(printer->printerName()), qUtf16Printable(d->currentPrinter->printerName()));
- d->m_callbacks.invokeDirectly(resultCallback, false);
- return;
- }
- d->currentPrinter = printer;
- d->ensureInitialized();
- quint64 requestId = d->adapter->printToPDFCallbackResult(printer->pageLayout(),
- printer->colorMode() == QPrinter::Color,
- false);
- d->m_callbacks.registerCallback(requestId, resultCallback);
-#else
- Q_UNUSED(printer);
- d->m_callbacks.invokeDirectly(resultCallback, false);
-#endif
-}
-
-
-/*!
\fn void QWebEnginePage::newWindowRequested(WebEngineNewViewRequest &request)
\since 6.2
diff --git a/src/core/api/qwebenginepage.h b/src/core/api/qwebenginepage.h
index c0c970207..94a78aa67 100644
--- a/src/core/api/qwebenginepage.h
+++ b/src/core/api/qwebenginepage.h
@@ -55,7 +55,6 @@
QT_BEGIN_NAMESPACE
class QMenu;
-class QPrinter;
class QContextMenuBuilder;
class QWebChannel;
@@ -302,10 +301,6 @@ public:
bool recentlyAudible() const;
qint64 renderProcessPid() const;
- void printToPdf(const QString &filePath, const QPageLayout &layout = QPageLayout(QPageSize(QPageSize::A4), QPageLayout::Portrait, QMarginsF()));
- void printToPdf(const QWebEngineCallback<const QByteArray&> &resultCallback, const QPageLayout &layout = QPageLayout(QPageSize(QPageSize::A4), QPageLayout::Portrait, QMarginsF()));
- void print(QPrinter *printer, const QWebEngineCallback<bool> &resultCallback);
-
void setInspectedPage(QWebEnginePage *page);
QWebEnginePage *inspectedPage() const;
void setDevToolsPage(QWebEnginePage *page);
@@ -360,9 +355,6 @@ 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 d2c246397..a830028f8 100644
--- a/src/core/api/qwebenginepage_p.h
+++ b/src/core/api/qwebenginepage_p.h
@@ -104,6 +104,9 @@ public:
virtual void unhandledKeyEvent(QKeyEvent *event) = 0;
virtual bool passOnFocus(bool reverse) = 0;
virtual QObject *accessibilityParentObject() = 0;
+ virtual void didPrintPage(quint64 requestId, QSharedPointer<QByteArray> result) = 0;
+ virtual void didPrintPageToPdf(const QString &filePath, bool success) = 0;
+ virtual void printRequested() = 0;
};
class Q_WEBENGINECORE_PRIVATE_EXPORT QWebEnginePagePrivate : public QtWebEngineCore::WebContentsAdapterClient
@@ -225,9 +228,6 @@ public:
mutable QtWebEngineCore::CallbackDirectory m_callbacks;
mutable QAction *actions[QWebEnginePage::WebActionCount];
-#if QT_CONFIG(webengine_printing_and_pdf)
- QPrinter *currentPrinter;
-#endif
};
QT_END_NAMESPACE
diff --git a/src/core/printing/printer_worker.cpp b/src/core/printing/printer_worker.cpp
index cbd6b8da3..411e326c3 100644
--- a/src/core/printing/printer_worker.cpp
+++ b/src/core/printing/printer_worker.cpp
@@ -42,12 +42,12 @@
#include "printing/pdfium_document_wrapper_qt.h"
#include <QPainter>
-#include <QPrinter>
+#include <QPagedPaintDevice>
namespace QtWebEngineCore {
-PrinterWorker::PrinterWorker(QSharedPointer<QByteArray> data, QPrinter *printer)
- : m_data(data), m_printer(printer)
+PrinterWorker::PrinterWorker(QSharedPointer<QByteArray> data, QPagedPaintDevice *device)
+ : m_data(data), m_device(device)
{
}
@@ -56,16 +56,16 @@ PrinterWorker::~PrinterWorker() { }
void PrinterWorker::print()
{
if (!m_data->size()) {
- qWarning("Failure to print on printer %ls: Print result data is empty.",
- qUtf16Printable(m_printer->printerName()));
+ qWarning("Failed to print: Print result data is empty.");
Q_EMIT resultReady(false);
return;
}
PdfiumDocumentWrapperQt pdfiumWrapper(m_data->constData(), m_data->size());
- int toPage = m_printer->toPage();
- int fromPage = m_printer->fromPage();
+ const QPageRanges ranges = m_device->pageRanges();
+ int toPage = ranges.firstPage();
+ int fromPage = ranges.lastPage();
bool ascendingOrder = true;
if (fromPage == 0 && toPage == 0) {
@@ -75,62 +75,50 @@ void PrinterWorker::print()
fromPage = qMax(1, fromPage);
toPage = qMin(pdfiumWrapper.pageCount(), toPage);
- if (m_printer->pageOrder() == QPrinter::LastPageFirst) {
+ if (!m_firstPageFirst) {
qSwap(fromPage, toPage);
ascendingOrder = false;
}
int pageCopies = 1;
- int documentCopies = 1;
-
- if (!m_printer->supportsMultipleCopies())
- documentCopies = m_printer->copyCount();
-
- if (m_printer->collateCopies()) {
- pageCopies = documentCopies;
- documentCopies = 1;
+ if (m_collateCopies) {
+ pageCopies = m_documentCopies;
+ m_documentCopies = 1;
}
- qreal resolution = m_printer->resolution() / 72.0; // pdfium uses points so 1/72 inch
+ qreal resolution = m_deviceResolution / 72.0; // pdfium uses points so 1/72 inch
QPainter painter;
- for (int printedDocuments = 0; printedDocuments < documentCopies; printedDocuments++) {
+ for (int printedDocuments = 0; printedDocuments < m_documentCopies; printedDocuments++) {
if (printedDocuments > 0)
- m_printer->newPage();
+ m_device->newPage();
int currentPageIndex = fromPage;
for (int i = 0; true; i++) {
QSizeF documentSize = (pdfiumWrapper.pageSize(currentPageIndex - 1) * resolution);
bool isLandscape = documentSize.width() > documentSize.height();
- m_printer->setPageOrientation(isLandscape ? QPageLayout::Landscape
+ m_device->setPageOrientation(isLandscape ? QPageLayout::Landscape
: QPageLayout::Portrait);
- QRectF pageRect = m_printer->pageRect(QPrinter::DevicePixel);
+ QRectF pageRect = m_device->pageLayout().pageSize().rectPixels(m_deviceResolution);
documentSize = documentSize.scaled(pageRect.size(), Qt::KeepAspectRatio);
// setPageOrientation has to be called before qpainter.begin() or before
// qprinter.newPage() so correct metrics is used, therefore call begin now for only
// first page
- if (!painter.isActive() && !painter.begin(m_printer)) {
- qWarning("Failure to print on printer %ls: Could not open printer for painting.",
- qUtf16Printable(m_printer->printerName()));
+ if (!painter.isActive() && !painter.begin(m_device)) {
+ qWarning("Failure to print on device: Could not open printer for painting.");
Q_EMIT resultReady(false);
return;
}
if (i > 0)
- m_printer->newPage();
+ m_device->newPage();
for (int printedPages = 0; printedPages < pageCopies; printedPages++) {
- if (m_printer->printerState() == QPrinter::Aborted
- || m_printer->printerState() == QPrinter::Error) {
- Q_EMIT resultReady(false);
- return;
- }
-
if (printedPages > 0)
- m_printer->newPage();
+ m_device->newPage();
QImage currentImage = pdfiumWrapper.pageAsQImage(
currentPageIndex - 1, documentSize.width(), documentSize.height());
diff --git a/src/core/printing/printer_worker.h b/src/core/printing/printer_worker.h
index 9d1192bd2..3681312a9 100644
--- a/src/core/printing/printer_worker.h
+++ b/src/core/printing/printer_worker.h
@@ -51,12 +51,12 @@
#ifndef PRINTER_WORKER_H
#define PRINTER_WORKER_H
-#include "qtwebenginecoreglobal_p.h"
+#include <QtWebEngineCore/private/qtwebenginecoreglobal_p.h>
#include <QSharedPointer>
QT_BEGIN_NAMESPACE
-class QPrinter;
+class QPagedPaintDevice;
QT_END_NAMESPACE
namespace QtWebEngineCore {
@@ -65,9 +65,14 @@ class Q_WEBENGINECORE_PRIVATE_EXPORT PrinterWorker : public QObject
{
Q_OBJECT
public:
- PrinterWorker(QSharedPointer<QByteArray> data, QPrinter *printer);
+ PrinterWorker(QSharedPointer<QByteArray> data, QPagedPaintDevice *device);
virtual ~PrinterWorker();
+ int m_deviceResolution;
+ bool m_firstPageFirst;
+ int m_documentCopies;
+ bool m_collateCopies;
+
public Q_SLOTS:
void print();
@@ -78,7 +83,7 @@ private:
Q_DISABLE_COPY(PrinterWorker)
QSharedPointer<QByteArray> m_data;
- QPrinter *m_printer;
+ QPagedPaintDevice *m_device;
};
} // namespace QtWebEngineCore
diff --git a/src/webenginewidgets/CMakeLists.txt b/src/webenginewidgets/CMakeLists.txt
index f37948c8c..425eb1d73 100644
--- a/src/webenginewidgets/CMakeLists.txt
+++ b/src/webenginewidgets/CMakeLists.txt
@@ -29,3 +29,8 @@ qt_internal_add_module(WebEngineWidgets
Qt::WebEngineCore
)
make_install_only(WebEngineWidgets)
+
+qt_internal_extend_target(WebEngineWidgets CONDITION QT_FEATURE_webengine_printing_and_pdf
+ PUBLIC_LIBRARIES
+ Qt::PrintSupport
+)
diff --git a/src/webenginewidgets/api/qwebengineview.cpp b/src/webenginewidgets/api/qwebengineview.cpp
index 9ce954e06..a34c841e3 100644
--- a/src/webenginewidgets/api/qwebengineview.cpp
+++ b/src/webenginewidgets/api/qwebengineview.cpp
@@ -80,6 +80,13 @@
#include <QStyle>
#include <QGuiApplication>
+#if QT_CONFIG(webengine_printing_and_pdf)
+#include "printing/printer_worker.h"
+
+#include <QPrinter>
+#include <QThread>
+#endif
+
QT_BEGIN_NAMESPACE
void QWebEngineViewPrivate::pageChanged(QWebEnginePage *oldPage, QWebEnginePage *newPage)
@@ -344,7 +351,13 @@ static QAccessibleInterface *webAccessibleFactory(const QString &, QObject *obje
#endif // QT_NO_ACCESSIBILITY
QWebEngineViewPrivate::QWebEngineViewPrivate()
- : page(0), m_dragEntered(false), m_ownsPage(false), m_contextRequest(nullptr)
+ : page(0)
+ , m_dragEntered(false)
+ , m_ownsPage(false)
+ , m_contextRequest(nullptr)
+#if QT_CONFIG(webengine_printing_and_pdf)
+ , currentPrinter(nullptr)
+#endif
{
#ifndef QT_NO_ACCESSIBILITY
QAccessible::installFactory(&webAccessibleFactory);
@@ -495,6 +508,61 @@ QObject *QWebEngineViewPrivate::accessibilityParentObject()
return q;
}
+void QWebEngineViewPrivate::didPrintPage(quint64 requestId, QSharedPointer<QByteArray> result)
+{
+#if QT_CONFIG(webengine_printing_and_pdf)
+ Q_Q(QWebEngineView);
+
+ // If no currentPrinter is set that means that were printing to PDF only.
+ if (!currentPrinter) {
+ if (!result.data())
+ return;
+ page->d_ptr->m_callbacks.invoke(requestId, *(result.data()));
+ return;
+ }
+
+ QThread *printerThread = new QThread;
+ QObject::connect(printerThread, &QThread::finished, printerThread, &QThread::deleteLater);
+ printerThread->start();
+
+ QtWebEngineCore::PrinterWorker *printerWorker = new QtWebEngineCore::PrinterWorker(result, currentPrinter);
+ printerWorker->m_deviceResolution = currentPrinter->resolution();
+ printerWorker->m_firstPageFirst = currentPrinter->pageOrder() == QPrinter::FirstPageFirst;
+ printerWorker->m_documentCopies = currentPrinter->copyCount();
+ printerWorker->m_collateCopies = currentPrinter->collateCopies();
+
+ QObject::connect(printerWorker, &QtWebEngineCore::PrinterWorker::resultReady, q, [requestId, this](bool success) {
+ currentPrinter = nullptr;
+ page->d_ptr->m_callbacks.invoke(requestId, success);
+ });
+
+ QObject::connect(printerWorker, &QtWebEngineCore::PrinterWorker::resultReady, printerThread, &QThread::quit);
+ QObject::connect(printerThread, &QThread::finished, printerWorker, &QtWebEngineCore::PrinterWorker::deleteLater);
+
+ printerWorker->moveToThread(printerThread);
+ QMetaObject::invokeMethod(printerWorker, "print");
+
+#else
+ // we should never enter this branch, but just for safe-keeping...
+ Q_UNUSED(result);
+ page->d_ptr->m_callbacks.invoke(requestId, QByteArray());
+#endif
+}
+
+void QWebEngineViewPrivate::didPrintPageToPdf(const QString &filePath, bool success)
+{
+ Q_Q(QWebEngineView);
+ Q_EMIT q->pdfPrintingFinished(filePath, success);
+}
+
+void QWebEngineViewPrivate::printRequested()
+{
+ Q_Q(QWebEngineView);
+ QTimer::singleShot(0, q, [q]() {
+ Q_EMIT q->printRequested();
+ });
+}
+
bool QWebEngineViewPrivate::isVisible() const
{
Q_Q(const QWebEngineView);
@@ -878,6 +946,62 @@ QWebEngineContextMenuRequest *QWebEngineView::lastContextMenuRequest() const
return d->m_contextRequest;
}
+void QWebEngineView::printToPdf(const QString &filePath, const QPageLayout &layout)
+{
+#if QT_CONFIG(webengine_printing_and_pdf)
+ Q_D(QWebEngineView);
+ if (d->currentPrinter) {
+ qWarning("Cannot print to PDF while printing at the same time.");
+ return;
+ }
+ page()->d_ptr->ensureInitialized();
+ page()->d_ptr->adapter->printToPDF(layout, filePath);
+#else
+ Q_UNUSED(filePath);
+ Q_UNUSED(layout);
+#endif
+}
+
+void QWebEngineView::printToPdf(const QWebEngineCallback<const QByteArray&> &resultCallback, const QPageLayout &layout)
+{
+#if QT_CONFIG(webengine_printing_and_pdf)
+ Q_D(QWebEngineView);
+ if (d->currentPrinter) {
+ qWarning("Cannot print to PDF while printing at the same time.");
+ page()->d_ptr->m_callbacks.invokeEmpty(resultCallback);
+ return;
+ }
+ page()->d_ptr->ensureInitialized();
+ quint64 requestId = page()->d_ptr->adapter->printToPDFCallbackResult(layout);
+ page()->d_ptr->m_callbacks.registerCallback(requestId, resultCallback);
+#else
+ Q_UNUSED(layout);
+ page()->d_ptr->m_callbacks.invokeEmpty(resultCallback);
+#endif
+}
+
+void QWebEngineView::print(QPrinter *printer, const QWebEngineCallback<bool> &resultCallback)
+{
+#if QT_CONFIG(webengine_printing_and_pdf)
+ Q_D(QWebEngineView);
+ if (d->currentPrinter) {
+ qWarning("Cannot print page on printer %ls: Already printing on a device.", qUtf16Printable(printer->printerName()));
+ page()->d_ptr->m_callbacks.invokeDirectly(resultCallback, false);
+ return;
+ }
+
+ d->currentPrinter = printer;
+ page()->d_ptr->ensureInitialized();
+ quint64 requestId = page()->d_ptr->adapter->printToPDFCallbackResult(printer->pageLayout(),
+ printer->colorMode() == QPrinter::Color,
+ false);
+ page()->d_ptr->m_callbacks.registerCallback(requestId, resultCallback);
+#else
+ Q_UNUSED(printer);
+ page()->d_ptr->m_callbacks.invokeDirectly(resultCallback, false);
+#endif
+}
+
#ifndef QT_NO_ACCESSIBILITY
bool QWebEngineViewAccessible::isValid() const
{
diff --git a/src/webenginewidgets/api/qwebengineview.h b/src/webenginewidgets/api/qwebengineview.h
index d7f9d6a45..136df0b93 100644
--- a/src/webenginewidgets/api/qwebengineview.h
+++ b/src/webenginewidgets/api/qwebengineview.h
@@ -51,6 +51,7 @@
QT_BEGIN_NAMESPACE
class QContextMenuEvent;
+class QPrinter;
class QUrl;
class QWebEnginePage;
class QWebEngineSettings;
@@ -107,6 +108,10 @@ public:
#endif
QWebEngineContextMenuRequest *lastContextMenuRequest() const;
+ void printToPdf(const QString &filePath, const QPageLayout &layout = QPageLayout(QPageSize(QPageSize::A4), QPageLayout::Portrait, QMarginsF()));
+ void printToPdf(const QWebEngineCallback<const QByteArray&> &resultCallback, const QPageLayout &layout = QPageLayout(QPageSize(QPageSize::A4), QPageLayout::Portrait, QMarginsF()));
+ void print(QPrinter *printer, const QWebEngineCallback<bool> &resultCallback);
+
public Q_SLOTS:
void stop();
void back();
@@ -124,6 +129,8 @@ Q_SIGNALS:
void iconChanged(const QIcon&);
void renderProcessTerminated(QWebEnginePage::RenderProcessTerminationStatus terminationStatus,
int exitCode);
+ void pdfPrintingFinished(const QString &filePath, bool success);
+ void printRequested();
protected:
virtual QWebEngineView *createWindow(QWebEnginePage::WebWindowType type);
diff --git a/src/webenginewidgets/api/qwebengineview_p.h b/src/webenginewidgets/api/qwebengineview_p.h
index 40f195522..71e7d04f7 100644
--- a/src/webenginewidgets/api/qwebengineview_p.h
+++ b/src/webenginewidgets/api/qwebengineview_p.h
@@ -58,6 +58,7 @@
#include <QtWidgets/qaccessiblewidget.h>
namespace QtWebEngineCore {
+class QPrinter;
class RenderWidgetHostViewQtDelegateWidget;
class RenderWidgetHostViewQtDelegate;
}
@@ -92,6 +93,10 @@ public:
QWebEngineContextMenuRequest *lastContextMenuRequest() const override;
QWebEnginePage *createPageForWindow(QWebEnginePage::WebWindowType type) override;
QObject *accessibilityParentObject() override;
+ void didPrintPage(quint64 requestId, QSharedPointer<QByteArray> result) override;
+ void didPrintPageToPdf(const QString &filePath, bool success) override;
+ void printRequested() override;
+
QWebEngineViewPrivate();
virtual ~QWebEngineViewPrivate();
static void bindPageAndView(QWebEnginePage *page, QWebEngineView *view);
@@ -108,6 +113,9 @@ public:
bool m_dragEntered;
mutable bool m_ownsPage;
QWebEngineContextMenuRequest *m_contextRequest;
+#if QT_CONFIG(webengine_printing_and_pdf)
+ QPrinter *currentPrinter;
+#endif
};
#ifndef QT_NO_ACCESSIBILITY
diff --git a/tests/auto/widgets/printing/tst_printing.cpp b/tests/auto/widgets/printing/tst_printing.cpp
index d1542af23..3f1344ed4 100644
--- a/tests/auto/widgets/printing/tst_printing.cpp
+++ b/tests/auto/widgets/printing/tst_printing.cpp
@@ -27,7 +27,7 @@
****************************************************************************/
#include <QtWebEngineCore/private/qtwebenginecoreglobal_p.h>
-#include <QWebEnginePage>
+#include <QWebEngineView>
#include <QTemporaryDir>
#include <QTest>
#include <QSignalSpy>
@@ -53,15 +53,15 @@ void tst_Printing::printToPdfBasic()
{
QTemporaryDir tempDir(QDir::tempPath() + "/tst_qwebengineview-XXXXXX");
QVERIFY(tempDir.isValid());
- QWebEnginePage page;
- QSignalSpy spy(&page, &QWebEnginePage::loadFinished);
- page.load(QUrl("qrc:///resources/basic_printing_page.html"));
+ QWebEngineView view;
+ QSignalSpy spy(&view, &QWebEngineView::loadFinished);
+ view.load(QUrl("qrc:///resources/basic_printing_page.html"));
QTRY_VERIFY(spy.count() == 1);
- QSignalSpy savePdfSpy(&page, &QWebEnginePage::pdfPrintingFinished);
+ QSignalSpy savePdfSpy(&view, &QWebEngineView::pdfPrintingFinished);
QPageLayout layout(QPageSize(QPageSize::A4), QPageLayout::Portrait, QMarginsF(0.0, 0.0, 0.0, 0.0));
QString path = tempDir.path() + "/print_1_success.pdf";
- page.printToPdf(path, layout);
+ view.printToPdf(path, layout);
QTRY_VERIFY2(savePdfSpy.count() == 1, "Printing to PDF file failed without signal");
QList<QVariant> successArguments = savePdfSpy.takeFirst();
@@ -73,7 +73,7 @@ void tst_Printing::printToPdfBasic()
#else
path = tempDir.path() + "/print_|2_failed.pdf";
#endif
- page.printToPdf(path, QPageLayout());
+ view.printToPdf(path, QPageLayout());
QTRY_VERIFY2(savePdfSpy.count() == 1, "Printing to PDF file failed without signal");
QList<QVariant> failedArguments = savePdfSpy.takeFirst();
@@ -81,29 +81,29 @@ void tst_Printing::printToPdfBasic()
QVERIFY2(failedArguments.at(1).toBool() == false, "Printing to PDF file succeeded though it should fail");
CallbackSpy<QByteArray> successfulSpy;
- page.printToPdf(successfulSpy.ref(), layout);
+ view.printToPdf(successfulSpy.ref(), layout);
QVERIFY(successfulSpy.waitForResult().length() > 0);
CallbackSpy<QByteArray> failedInvalidLayoutSpy;
- page.printToPdf(failedInvalidLayoutSpy.ref(), QPageLayout());
+ view.printToPdf(failedInvalidLayoutSpy.ref(), QPageLayout());
QCOMPARE(failedInvalidLayoutSpy.waitForResult().length(), 0);
}
void tst_Printing::printRequest()
{
- QWebEnginePage webPage;
+ QWebEngineView view;
QPageLayout layout(QPageSize(QPageSize::A4), QPageLayout::Portrait, QMarginsF(0.0, 0.0, 0.0, 0.0));
- QSignalSpy loadFinishedSpy(&webPage, &QWebEnginePage::loadFinished);
- QSignalSpy printRequestedSpy(&webPage, &QWebEnginePage::printRequested);
- QSignalSpy savePdfSpy(&webPage, &QWebEnginePage::pdfPrintingFinished);
+ QSignalSpy loadFinishedSpy(&view, &QWebEngineView::loadFinished);
+ QSignalSpy printRequestedSpy(&view, &QWebEngineView::printRequested);
+ QSignalSpy savePdfSpy(&view, &QWebEngineView::pdfPrintingFinished);
CallbackSpy<QByteArray> resultSpy;
- webPage.load(QUrl("qrc:///resources/basic_printing_page.html"));
+ view.load(QUrl("qrc:///resources/basic_printing_page.html"));
QTRY_VERIFY(loadFinishedSpy.count() == 1);
- webPage.runJavaScript("window.print()");
+ view.page()->runJavaScript("window.print()");
QTRY_VERIFY(printRequestedSpy.count() == 1);
//check if printing still works
- webPage.printToPdf(resultSpy.ref(), layout);
+ view.printToPdf(resultSpy.ref(), layout);
const QByteArray data = resultSpy.waitForResult();
QVERIFY(data.length() > 0);
}
@@ -113,16 +113,16 @@ void tst_Printing::printToPdfPoppler()
{
// check if generated pdf is correct by searching for a know string on the page
using namespace poppler;
- QWebEnginePage webPage;
+ QWebEngineView view;
QPageLayout layout(QPageSize(QPageSize::A4), QPageLayout::Portrait, QMarginsF(0.0, 0.0, 0.0, 0.0));
- QSignalSpy spy(&webPage, &QWebEnginePage::loadFinished);
- QSignalSpy savePdfSpy(&webPage, &QWebEnginePage::pdfPrintingFinished);
+ QSignalSpy spy(&view, &QWebEngineView::loadFinished);
+ QSignalSpy savePdfSpy(&view, &QWebEngineView::pdfPrintingFinished);
CallbackSpy<QByteArray> resultSpy;
- webPage.load(QUrl("qrc:///resources/basic_printing_page.html"));
+ view.load(QUrl("qrc:///resources/basic_printing_page.html"));
QTRY_VERIFY(spy.count() == 1);
- webPage.printToPdf(resultSpy.ref(), layout);
+ view.printToPdf(resultSpy.ref(), layout);
const QByteArray data = resultSpy.waitForResult();
QVERIFY(data.length() > 0);