diff options
-rw-r--r-- | examples/webenginewidgets/demobrowser/browsermainwindow.cpp | 22 | ||||
-rw-r--r-- | examples/webenginewidgets/demobrowser/browsermainwindow.h | 2 | ||||
-rw-r--r-- | src/core/print_view_manager_qt.cpp | 118 | ||||
-rw-r--r-- | src/core/print_view_manager_qt.h | 10 | ||||
-rw-r--r-- | src/core/web_contents_adapter.cpp | 19 | ||||
-rw-r--r-- | src/core/web_contents_adapter.h | 1 | ||||
-rw-r--r-- | src/core/web_contents_adapter_client.h | 1 | ||||
-rw-r--r-- | src/webengine/api/qquickwebengineview.cpp | 28 | ||||
-rw-r--r-- | src/webengine/api/qquickwebengineview_p.h | 3 | ||||
-rw-r--r-- | src/webengine/api/qquickwebengineview_p_p.h | 1 | ||||
-rw-r--r-- | src/webengine/doc/src/webengineview.qdoc | 20 | ||||
-rw-r--r-- | src/webenginewidgets/api/qwebenginepage.cpp | 33 | ||||
-rw-r--r-- | src/webenginewidgets/api/qwebenginepage.h | 8 | ||||
-rw-r--r-- | src/webenginewidgets/api/qwebenginepage_p.h | 1 | ||||
-rw-r--r-- | src/webenginewidgets/doc/src/qwebengineview_lgpl.qdoc | 9 | ||||
-rw-r--r-- | tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp | 15 | ||||
-rw-r--r-- | tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp | 25 |
17 files changed, 249 insertions, 67 deletions
diff --git a/examples/webenginewidgets/demobrowser/browsermainwindow.cpp b/examples/webenginewidgets/demobrowser/browsermainwindow.cpp index e3c7c466d..e72a2b5fe 100644 --- a/examples/webenginewidgets/demobrowser/browsermainwindow.cpp +++ b/examples/webenginewidgets/demobrowser/browsermainwindow.cpp @@ -701,6 +701,21 @@ void BrowserMainWindow::slotFilePrint() #endif } +void BrowserMainWindow::slotHandlePdfPrinted(const QByteArray& result) +{ + if (!result.size()) + return; + + QFile file(m_printerOutputFileName); + + m_printerOutputFileName.clear(); + if (!file.open(QFile::WriteOnly)) + return; + + file.write(result.data(), result.size()); + file.close(); +} + void BrowserMainWindow::slotFilePrintToPDF() { #ifndef QT_NO_PRINTER @@ -709,10 +724,13 @@ void BrowserMainWindow::slotFilePrintToPDF() QPrinter printer; QPrintDialog *dialog = new QPrintDialog(&printer, this); dialog->setWindowTitle(tr("Print Document")); - if (dialog->exec() != QDialog::Accepted || printer.outputFileName().isEmpty()) + if (dialog->exec() != QDialog::Accepted || printer.outputFileName().isEmpty() || !m_printerOutputFileName.isEmpty()) return; - currentTab()->page()->printToPDF(printer.outputFileName(), printer.pageLayout()); + m_printerOutputFileName = printer.outputFileName(); + + currentTab()->page()->printToPdf(printer.pageLayout(), invoke(this, &BrowserMainWindow::slotHandlePdfPrinted)); + #endif // QT_NO_PRINTER } diff --git a/examples/webenginewidgets/demobrowser/browsermainwindow.h b/examples/webenginewidgets/demobrowser/browsermainwindow.h index 2e1d178d7..9fb6b0851 100644 --- a/examples/webenginewidgets/demobrowser/browsermainwindow.h +++ b/examples/webenginewidgets/demobrowser/browsermainwindow.h @@ -138,6 +138,7 @@ private slots: void slotOpenActionUrl(QAction *action); void slotShowWindow(); void slotSwapFocus(); + void slotHandlePdfPrinted(const QByteArray&); #if defined(QWEBENGINEPAGE_PRINT) void printRequested(QWebEngineFrame *frame); @@ -180,6 +181,7 @@ private: QIcon m_stopIcon; QString m_lastSearch; + QString m_printerOutputFileName; friend class BrowserApplication; }; diff --git a/src/core/print_view_manager_qt.cpp b/src/core/print_view_manager_qt.cpp index ab14329ac..4cb0e06eb 100644 --- a/src/core/print_view_manager_qt.cpp +++ b/src/core/print_view_manager_qt.cpp @@ -57,17 +57,28 @@ DEFINE_WEB_CONTENTS_USER_DATA_KEY(QtWebEngineCore::PrintViewManagerQt); namespace { -static int request_id = 0; static const qreal kMicronsToMillimeter = 1000.0f; -static scoped_refptr<base::RefCountedBytes> -GetDataFromHandle(base::SharedMemoryHandle handle, uint32_t data_size) { +static std::vector<char> +GetStdVectorFromHandle(base::SharedMemoryHandle handle, uint32_t data_size) { scoped_ptr<base::SharedMemory> shared_buf( new base::SharedMemory(handle, true)); if (!shared_buf->Map(data_size)) { - NOTREACHED(); - return NULL; + return std::vector<char>(); + } + + char* data = static_cast<char*>(shared_buf->memory()); + return std::vector<char>(data, data + data_size); +} + +static scoped_refptr<base::RefCountedBytes> +GetBytesFromHandle(base::SharedMemoryHandle handle, uint32_t data_size) { + scoped_ptr<base::SharedMemory> shared_buf( + new base::SharedMemory(handle, true)); + + if (!shared_buf->Map(data_size)) { + return NULL; } unsigned char* data = static_cast<unsigned char*>(shared_buf->memory()); @@ -77,8 +88,7 @@ GetDataFromHandle(base::SharedMemoryHandle handle, uint32_t data_size) { // Write the PDF file to disk. static void SavePdfFile(scoped_refptr<base::RefCountedBytes> data, - const base::FilePath& path, - const base::Callback<void(bool)>& callback) { + const base::FilePath& path) { DCHECK_CURRENTLY_ON(content::BrowserThread::FILE); DCHECK_GT(data->size(), 0U); @@ -87,17 +97,17 @@ static void SavePdfFile(scoped_refptr<base::RefCountedBytes> data, base::File file(path, base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE); - bool ok = file.IsValid() && metafile.SaveTo(&file); - - if (!callback.is_null()) { - content::BrowserThread::PostTask(content::BrowserThread::UI, - FROM_HERE, - base::Bind(callback, ok)); - } + if (file.IsValid()) + metafile.SaveTo(&file); } static void applyQPageLayoutSettingsToDictionary(const QPageLayout& pageLayout, base::DictionaryValue& print_settings) { + // TO DO: Check if we can use the request ID from Qt here somehow. + static int internalRequestId = 0; + + print_settings.SetBoolean(printing::kIsFirstRequest, internalRequestId++ == 0); + print_settings.SetInteger(printing::kPreviewRequestID, internalRequestId); //Set page size attributes, chromium expects these in micrometers QSizeF pageSizeInMilimeter = pageLayout.pageSize().size(QPageSize::Millimeter); scoped_ptr<base::DictionaryValue> sizeDict(new base::DictionaryValue); @@ -107,9 +117,6 @@ static void applyQPageLayoutSettingsToDictionary(const QPageLayout& pageLayout, print_settings.SetBoolean(printing::kSettingLandscape, pageLayout.orientation() == QPageLayout::Landscape); - print_settings.SetInteger(printing::kPreviewRequestID, request_id++); - print_settings.SetBoolean(printing::kIsFirstRequest, request_id != 0); - // The following are standard settings that Chromium expects to be set. print_settings.SetBoolean(printing::kSettingPrintToPDF, true); print_settings.SetBoolean(printing::kSettingCloudPrintDialog, false); @@ -144,21 +151,51 @@ PrintViewManagerQt::~PrintViewManagerQt() #if defined(ENABLE_BASIC_PRINTING) bool PrintViewManagerQt::PrintToPDF(const QPageLayout &pageLayout, const QString &filePath) { - return PrintToPDFWithCallback(pageLayout, filePath, base::Callback<void(bool)>()); + if (m_printSettings || !filePath.length()) + return false; + + m_pdfOutputPath = toFilePath(filePath); + if (!PrintToPDFInternal(pageLayout)) { + resetPdfState(); + return false; + } + return true; } -bool PrintViewManagerQt::PrintToPDFWithCallback(const QPageLayout &pageLayout, const QString &filePath, base::Callback<void(bool)> callback) +bool PrintViewManagerQt::PrintToPDFWithCallback(const QPageLayout &pageLayout, const PrintToPDFCallback& callback) { + if (callback.is_null()) + return false; + // If there already is a pending print in progress, don't try starting another one. - if (m_printSettings) + if (m_printSettings) { + content::BrowserThread::PostTask(content::BrowserThread::UI, + FROM_HERE, + base::Bind(callback, std::vector<char>())); return false; + } + m_pdfPrintCallback = callback; + if (!PrintToPDFInternal(pageLayout)) { + content::BrowserThread::PostTask(content::BrowserThread::UI, + FROM_HERE, + base::Bind(callback, std::vector<char>())); + + resetPdfState(); + return false; + } + return true; +} + +bool PrintViewManagerQt::PrintToPDFInternal(const QPageLayout &pageLayout) +{ + if (!pageLayout.isValid()) + return false; m_printSettings.reset(new base::DictionaryValue()); applyQPageLayoutSettingsToDictionary(pageLayout, *m_printSettings); - m_pdfOutputPath = toFilePath(filePath); - return Send(new PrintMsg_InitiatePrintPreview(routing_id(), false)); } + #endif // defined(ENABLE_BASIC_PRINTING) // PrintedPagesSource implementation. @@ -208,24 +245,23 @@ void PrintViewManagerQt::OnMetafileReadyForPrinting( { StopWorker(params.document_cookie); - scoped_refptr<base::RefCountedBytes> data_bytes = - GetDataFromHandle(params.metafile_data_handle, params.data_size); - if (!data_bytes || !data_bytes->size()) { - resetPdfState(); - return; - } - // Create local copies so we can reset the state and take a new pdf print job. - base::Callback<void(bool)> pdf_print_callback = m_pdfPrintCallback; + base::Callback<void(const std::vector<char>&)> pdf_print_callback = m_pdfPrintCallback; base::FilePath pdfOutputPath = m_pdfOutputPath; - // Save the PDF file to disk and then execute the callback. - content::BrowserThread::PostTask(content::BrowserThread::FILE, - FROM_HERE, - base::Bind(&SavePdfFile, data_bytes, pdfOutputPath, - pdf_print_callback)); - resetPdfState(); + + if (!pdf_print_callback.is_null()) { + std::vector<char> data_vector = GetStdVectorFromHandle(params.metafile_data_handle, params.data_size); + content::BrowserThread::PostTask(content::BrowserThread::UI, + FROM_HERE, + base::Bind(pdf_print_callback, data_vector)); + } else { + scoped_refptr<base::RefCountedBytes> data_bytes = GetBytesFromHandle(params.metafile_data_handle, params.data_size); + content::BrowserThread::PostTask(content::BrowserThread::FILE, + FROM_HERE, + base::Bind(&SavePdfFile, data_bytes, pdfOutputPath)); + } } void PrintViewManagerQt::OnDidShowPrintDialog() @@ -241,12 +277,22 @@ void PrintViewManagerQt::DidStartLoading() // Cancels the print job. void PrintViewManagerQt::NavigationStopped() { + if (!m_pdfPrintCallback.is_null()) { + content::BrowserThread::PostTask(content::BrowserThread::UI, + FROM_HERE, + base::Bind(m_pdfPrintCallback, std::vector<char>())); + } resetPdfState(); } void PrintViewManagerQt::RenderProcessGone(base::TerminationStatus status) { PrintViewManagerBaseQt::RenderProcessGone(status); + if (!m_pdfPrintCallback.is_null()) { + content::BrowserThread::PostTask(content::BrowserThread::UI, + FROM_HERE, + base::Bind(m_pdfPrintCallback, std::vector<char>())); + } resetPdfState(); } diff --git a/src/core/print_view_manager_qt.h b/src/core/print_view_manager_qt.h index 6ef7ec754..88a499f1b 100644 --- a/src/core/print_view_manager_qt.h +++ b/src/core/print_view_manager_qt.h @@ -80,11 +80,11 @@ class PrintViewManagerQt { public: ~PrintViewManagerQt() override; - + typedef base::Callback<void(const std::vector<char> &result)> PrintToPDFCallback; #if defined(ENABLE_BASIC_PRINTING) // Method to print a page to a Pdf document with page size \a pageSize in location \a filePath. bool PrintToPDF(const QPageLayout& pageLayout, const QString& filePath); - bool PrintToPDFWithCallback(const QPageLayout& pageLayout, const QString& filePath, base::Callback<void(bool)> callback); + bool PrintToPDFWithCallback(const QPageLayout& pageLayout, const PrintToPDFCallback& callback); #endif // ENABLE_BASIC_PRINTING // PrintedPagesSource implementation. @@ -108,8 +108,12 @@ protected: void OnRequestPrintPreview(const PrintHostMsg_RequestPrintPreview_Params&); void OnMetafileReadyForPrinting(const PrintHostMsg_DidPreviewDocument_Params& params); +#if defined(ENABLE_BASIC_PRINTING) + bool PrintToPDFInternal(const QPageLayout &); +#endif // + base::FilePath m_pdfOutputPath; - base::Callback<void(bool)> m_pdfPrintCallback; + PrintToPDFCallback m_pdfPrintCallback; private: friend class content::WebContentsUserData<PrintViewManagerQt>; diff --git a/src/core/web_contents_adapter.cpp b/src/core/web_contents_adapter.cpp index cfd970a20..71d2172fe 100644 --- a/src/core/web_contents_adapter.cpp +++ b/src/core/web_contents_adapter.cpp @@ -180,6 +180,13 @@ static void callbackOnEvaluateJS(WebContentsAdapterClient *adapterClient, quint6 adapterClient->didRunJavaScript(requestId, fromJSValue(result)); } +static void callbackOnPrintingFinished(WebContentsAdapterClient *adapterClient, int requestId, const std::vector<char>& result) +{ + if (requestId) { + adapterClient->didPrintPage(requestId, QByteArray(result.data(), result.size())); + } +} + static content::WebContents *createBlankWebContents(WebContentsAdapterClient *adapterClient, content::BrowserContext *browserContext) { content::WebContents::CreateParams create_params(browserContext, NULL); @@ -912,6 +919,18 @@ void WebContentsAdapter::printToPDF(const QPageLayout &pageLayout, const QString #endif // if defined(ENABLE_BASIC_PRINTING) } +quint64 WebContentsAdapter::printToPDFCallbackResult(const QPageLayout &pageLayout) +{ +#if defined(ENABLE_BASIC_PRINTING) + Q_D(WebContentsAdapter); + PrintViewManagerQt::PrintToPDFCallback callback = base::Bind(&callbackOnPrintingFinished, d->adapterClient, d->nextRequestId); + PrintViewManagerQt::FromWebContents(webContents())->PrintToPDFWithCallback(pageLayout, callback); + return d->nextRequestId++; +#else + return 0; +#endif // if defined(ENABLE_BASIC_PRINTING) +} + QPointF WebContentsAdapter::lastScrollOffset() const { Q_D(const WebContentsAdapter); diff --git a/src/core/web_contents_adapter.h b/src/core/web_contents_adapter.h index 44f50e429..600e759e2 100644 --- a/src/core/web_contents_adapter.h +++ b/src/core/web_contents_adapter.h @@ -172,6 +172,7 @@ public: void leaveDrag(); void initUpdateDragCursorMessagePollingTimer(); void printToPDF(const QPageLayout&, const QString&); + quint64 printToPDFCallbackResult(const QPageLayout &); // meant to be used within WebEngineCore only content::WebContents *webContents() const; diff --git a/src/core/web_contents_adapter_client.h b/src/core/web_contents_adapter_client.h index a5c7a756b..9d2054859 100644 --- a/src/core/web_contents_adapter_client.h +++ b/src/core/web_contents_adapter_client.h @@ -237,6 +237,7 @@ public: virtual void didFetchDocumentMarkup(quint64 requestId, const QString& result) = 0; virtual void didFetchDocumentInnerText(quint64 requestId, const QString& result) = 0; virtual void didFindText(quint64 requestId, int matchCount) = 0; + virtual void didPrintPage(quint64 requestId, const QByteArray &result) = 0; virtual void passOnFocus(bool reverse) = 0; // returns the last QObject (QWidget/QQuickItem) based object in the accessibility // hierarchy before going into the BrowserAccessibility tree diff --git a/src/webengine/api/qquickwebengineview.cpp b/src/webengine/api/qquickwebengineview.cpp index 914b602ce..6d1060661 100644 --- a/src/webengine/api/qquickwebengineview.cpp +++ b/src/webengine/api/qquickwebengineview.cpp @@ -1008,6 +1008,15 @@ void QQuickWebEngineViewPrivate::didFindText(quint64 requestId, int matchCount) args.append(QJSValue(matchCount)); callback.call(args); } + +void QQuickWebEngineViewPrivate::didPrintPage(quint64 requestId, const QByteArray &result) +{ + QJSValue callback = m_callbacks.take(requestId); + QJSValueList args; + args.append(QJSValue(result.data())); + callback.call(args); +} + void QQuickWebEngineViewPrivate::showValidationMessage(const QRect &anchor, const QString &mainText, const QString &subText) { #ifdef ENABLE_QML_TESTSUPPORT_API @@ -1184,15 +1193,30 @@ bool QQuickWebEngineView::wasRecentlyAudible() return d->adapter->wasRecentlyAudible(); } -void QQuickWebEngineView::printToPDF(const QString &filePath, PrintedPageSizeId pageSizeId, PrintedPageOrientation orientation) +void QQuickWebEngineView::printToPdf(const QString& filePath, PrintedPageSizeId pageSizeId, PrintedPageOrientation orientation) { - Q_D(QQuickWebEngineView); + Q_D(const QQuickWebEngineView); QPageSize layoutSize(static_cast<QPageSize::PageSizeId>(pageSizeId)); QPageLayout::Orientation layoutOrientation = static_cast<QPageLayout::Orientation>(orientation); QPageLayout pageLayout(layoutSize, layoutOrientation, QMarginsF(0.0, 0.0, 0.0, 0.0)); + d->adapter->printToPDF(pageLayout, filePath); } +void QQuickWebEngineView::printToPdf(PrintedPageSizeId pageSizeId, PrintedPageOrientation orientation, const QJSValue &callback) +{ + Q_D(QQuickWebEngineView); + QPageSize layoutSize(static_cast<QPageSize::PageSizeId>(pageSizeId)); + QPageLayout::Orientation layoutOrientation = static_cast<QPageLayout::Orientation>(orientation); + QPageLayout pageLayout(layoutSize, layoutOrientation, QMarginsF(0.0, 0.0, 0.0, 0.0)); + + if (callback.isUndefined()) + return; + + quint64 requestId = d->adapter->printToPDFCallbackResult(pageLayout); + d->m_callbacks.insert(requestId, callback); +} + bool QQuickWebEngineView::isFullScreen() const { Q_D(const QQuickWebEngineView); diff --git a/src/webengine/api/qquickwebengineview_p.h b/src/webengine/api/qquickwebengineview_p.h index 9433a2150..390b46429 100644 --- a/src/webengine/api/qquickwebengineview_p.h +++ b/src/webengine/api/qquickwebengineview_p.h @@ -472,7 +472,8 @@ public Q_SLOTS: Q_REVISION(3) bool isAudioMuted() const; Q_REVISION(3) void setAudioMuted(bool muted); Q_REVISION(3) bool wasRecentlyAudible(); - Q_REVISION(3) void printToPDF(const QString &filePath, PrintedPageSizeId pageSizeId = PrintedPageSizeId::A4, PrintedPageOrientation orientation = PrintedPageOrientation::Portrait); + Q_REVISION(3) void printToPdf(const QString &filePath, PrintedPageSizeId pageSizeId = PrintedPageSizeId::A4, PrintedPageOrientation orientation = PrintedPageOrientation::Portrait); + Q_REVISION(3) void printToPdf(PrintedPageSizeId pageSizeId = PrintedPageSizeId::A4, PrintedPageOrientation orientation = PrintedPageOrientation::Portrait, const QJSValue &callback = QJSValue()); private Q_SLOTS: void lazyInitialize(); diff --git a/src/webengine/api/qquickwebengineview_p_p.h b/src/webengine/api/qquickwebengineview_p_p.h index 29fa9e881..05c2228c4 100644 --- a/src/webengine/api/qquickwebengineview_p_p.h +++ b/src/webengine/api/qquickwebengineview_p_p.h @@ -160,6 +160,7 @@ public: virtual void didFetchDocumentMarkup(quint64, const QString&) Q_DECL_OVERRIDE { } virtual void didFetchDocumentInnerText(quint64, const QString&) Q_DECL_OVERRIDE { } virtual void didFindText(quint64, int) Q_DECL_OVERRIDE; + virtual void didPrintPage(quint64 requestId, const QByteArray &result) Q_DECL_OVERRIDE; virtual void passOnFocus(bool reverse) Q_DECL_OVERRIDE; virtual void javaScriptConsoleMessage(JavaScriptConsoleMessageLevel level, const QString& message, int lineNumber, const QString& sourceID) Q_DECL_OVERRIDE; virtual void authenticationRequired(QSharedPointer<QtWebEngineCore::AuthenticationDialogController>) Q_DECL_OVERRIDE; diff --git a/src/webengine/doc/src/webengineview.qdoc b/src/webengine/doc/src/webengineview.qdoc index 6a4e2ffef..3af5e35da 100644 --- a/src/webengine/doc/src/webengineview.qdoc +++ b/src/webengine/doc/src/webengineview.qdoc @@ -856,7 +856,7 @@ \omitvalue NPageSize \omitvalue NPaperSize - \sa WebEngineView::printToPDF() + \sa WebEngineView::printToPdf() */ /*! @@ -872,7 +872,7 @@ \value Landscape The document will be created using landscape orientation. - \sa WebEngineView::printToPDF() + \sa WebEngineView::printToPdf() */ /*! @@ -944,14 +944,26 @@ */ /*! - \qmlmethod void WebEngineView::printToPDF(const QString &filePath, PrintedPageSizeId pageSizeId, PrintedPageOrientation orientation) + \qmlmethod void WebEngineView::printToPdf(const QString &filePath, PrintedPageSizeId pageSizeId, PrintedPageOrientation orientation) \since QtWebEngine 1.3 - Prints the WebEngineView's current contents to a PDF document and stores it under \a filePath. The document's size will be determined + Prints the WebEngineView's current content to a PDF document and stores it under \a filePath. The document's size will be determined by the value of \a pageSizeId and its orientation will be determined using \a orientation. */ /*! + \qmlmethod void WebEngineView::printToPdf(PrintedPageSizeId pageSizeId, PrintedPageOrientation orientation, variant resultCallback) + \since QtWebEngine 1.3 + + Prints the WebEngineView's current content to a PDF document and returns it in a byte array. The document's size will be determined + by the value of \a pageSizeId and its orientation will be determined using \a orientation. + + The \a resultCallback must take a string parameter. This string will contain the document's data upon successful printing and an empty + string otherwise. +*/ + + +/*! \qmlsignal void WebEngineView::wasRecentlyAudibleChanged(bool wasRecentlyAudible) \since QtWebEngine 1.3 diff --git a/src/webenginewidgets/api/qwebenginepage.cpp b/src/webenginewidgets/api/qwebenginepage.cpp index 3115340ef..27ed7fca6 100644 --- a/src/webenginewidgets/api/qwebenginepage.cpp +++ b/src/webenginewidgets/api/qwebenginepage.cpp @@ -314,6 +314,11 @@ void QWebEnginePagePrivate::didFindText(quint64 requestId, int matchCount) m_callbacks.invoke(requestId, matchCount > 0); } +void QWebEnginePagePrivate::didPrintPage(quint64 requestId, const QByteArray &result) +{ + m_callbacks.invoke(requestId, result); +} + void QWebEnginePagePrivate::passOnFocus(bool reverse) { if (view) @@ -1633,12 +1638,38 @@ QSizeF QWebEnginePage::contentsSize() const return d->adapter->lastContentsSize(); } -void QWebEnginePage::printToPDF(const QString &filePath, const QPageLayout &pageLayout) +/*! + 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. + + If a file already exists at the provided file path, it will be overwritten. + \since 5.7 +*/ +void QWebEnginePage::printToPdf(const QString &filePath, const QPageLayout &pageLayout) { Q_D(const QWebEnginePage); d->adapter->printToPDF(pageLayout, filePath); } + +/*! + \fn void QWebEnginePage::printToPdf(const QPageLayout &pageLayout, FunctorOrLambda resultCallback) + 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. + + \since 5.7 +*/ +void QWebEnginePage::printToPdf(const QPageLayout &pageLayout, const QWebEngineCallback<const QByteArray&> &resultCallback) +{ + Q_D(QWebEnginePage); + quint64 requestId = d->adapter->printToPDFCallbackResult(pageLayout); + d->m_callbacks.registerCallback(requestId, resultCallback); +} + QT_END_NAMESPACE #include "moc_qwebenginepage.cpp" diff --git a/src/webenginewidgets/api/qwebenginepage.h b/src/webenginewidgets/api/qwebenginepage.h index 20fff3ab4..ad399a7a5 100644 --- a/src/webenginewidgets/api/qwebenginepage.h +++ b/src/webenginewidgets/api/qwebenginepage.h @@ -268,8 +268,12 @@ public: void setAudioMuted(bool muted); bool wasRecentlyAudible(); - void printToPDF(const QString &filePath, const QPageLayout &layout = QPageLayout()); - + void printToPdf(const QString &filePath, const QPageLayout &layout); +#ifdef Q_QDOC + void printToPdf(const QPageLayout &layout, FunctorOrLambda resultCallback); +#else + void printToPdf(const QPageLayout &layout, const QWebEngineCallback<const QByteArray&> &resultCallback); +#endif Q_SIGNALS: void loadStarted(); void loadProgress(int progress); diff --git a/src/webenginewidgets/api/qwebenginepage_p.h b/src/webenginewidgets/api/qwebenginepage_p.h index 6d4b857eb..b08c19821 100644 --- a/src/webenginewidgets/api/qwebenginepage_p.h +++ b/src/webenginewidgets/api/qwebenginepage_p.h @@ -112,6 +112,7 @@ public: virtual void didFetchDocumentMarkup(quint64 requestId, const QString& result) Q_DECL_OVERRIDE; virtual void didFetchDocumentInnerText(quint64 requestId, const QString& result) Q_DECL_OVERRIDE; virtual void didFindText(quint64 requestId, int matchCount) Q_DECL_OVERRIDE; + virtual void didPrintPage(quint64 requestId, const QByteArray &result) Q_DECL_OVERRIDE; virtual void passOnFocus(bool reverse) Q_DECL_OVERRIDE; virtual void javaScriptConsoleMessage(JavaScriptConsoleMessageLevel level, const QString& message, int lineNumber, const QString& sourceID) Q_DECL_OVERRIDE; virtual void authenticationRequired(QSharedPointer<QtWebEngineCore::AuthenticationDialogController>) Q_DECL_OVERRIDE; diff --git a/src/webenginewidgets/doc/src/qwebengineview_lgpl.qdoc b/src/webenginewidgets/doc/src/qwebengineview_lgpl.qdoc index 624381a42..07fb5f1cd 100644 --- a/src/webenginewidgets/doc/src/qwebengineview_lgpl.qdoc +++ b/src/webenginewidgets/doc/src/qwebengineview_lgpl.qdoc @@ -255,15 +255,6 @@ */ /*! - \fn void QWebEngineView::printToPDF(const QString &filePath, const QPageLayout &layout) - \since 5.7 - Renders the current contents of the view 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 layout. - - If a file already exists at the provided file path, it will be overwritten. -*/ - -/*! \fn void QWebEngineView::stop() Convenience slot that stops loading the document. diff --git a/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp b/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp index 4430bdae0..f2f5b31f9 100644 --- a/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp +++ b/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp @@ -60,7 +60,7 @@ private Q_SLOTS: void inputMethod(); void inputMethodHints(); void basicRenderingSanity(); - void printToPDF(); + void printToPdf(); private: inline QQuickWebEngineView *newWebEngineView(); @@ -462,7 +462,7 @@ void tst_QQuickWebEngineView::inputMethodHints() #endif } -void tst_QQuickWebEngineView::printToPDF() +void tst_QQuickWebEngineView::printToPdf() { QTemporaryDir tempDir(QDir::tempPath() + "/tst_qwebengineview-XXXXXX"); QVERIFY(tempDir.isValid()); @@ -471,9 +471,18 @@ void tst_QQuickWebEngineView::printToPDF() QVERIFY(waitForLoadSucceeded(view)); QString path = tempDir.path() + "/print_success.pdf"; - view->printToPDF(path, QQuickWebEngineView::A4, QQuickWebEngineView::Portrait); + view->printToPdf(path, QQuickWebEngineView::A4, QQuickWebEngineView::Portrait); QTest::qWait(500); QVERIFY(QFile::exists(path)); + +#if !defined(Q_OS_WIN) + path = tempDir.path() + "/print_//fail.pdf"; +#else + path = tempDir.path() + "/print_|fail.pdf"; +#endif // #if !defined(Q_OS_WIN) + view->printToPdf(path, QQuickWebEngineView::A4, QQuickWebEngineView::Portrait); + QTest::qWait(500); + QVERIFY(!QFile::exists(path)); } QTEST_MAIN(tst_QQuickWebEngineView) diff --git a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp index 270fd4458..4cfe4e580 100644 --- a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp +++ b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp @@ -20,6 +20,7 @@ */ #include "../util.h" +#include <QByteArray> #include <QClipboard> #include <QDir> #include <QGraphicsWidget> @@ -240,7 +241,7 @@ private Q_SLOTS: void toPlainTextLoadFinishedRace_data(); void toPlainTextLoadFinishedRace(); - void printToPDF(); + void printToPdf(); private: QWebEngineView* m_view; @@ -5045,7 +5046,7 @@ void tst_QWebEnginePage::toPlainTextLoadFinishedRace() QVERIFY(spy.count() == 3); } -void tst_QWebEnginePage::printToPDF() +void tst_QWebEnginePage::printToPdf() { QTemporaryDir tempDir(QDir::tempPath() + "/tst_qwebengineview-XXXXXX"); QVERIFY(tempDir.isValid()); @@ -5055,9 +5056,25 @@ void tst_QWebEnginePage::printToPDF() QTRY_VERIFY(spy.count() == 1); QPageLayout layout(QPageSize(QPageSize::A4), QPageLayout::Portrait, QMarginsF(0.0, 0.0, 0.0, 0.0)); - QString path = tempDir.path() + "/print_success.pdf"; - page.printToPDF(path, layout); + QString path = tempDir.path() + "/print_1_success.pdf"; + page.printToPdf(path, layout); QTRY_VERIFY(QFile::exists(path)); + +#if !defined(Q_OS_WIN) + path = tempDir.path() + "/print_//2_failed.pdf"; +#else + path = tempDir.path() + "/print_|2_failed.pdf"; +#endif + page.printToPdf(path, QPageLayout()); + QTRY_VERIFY(!QFile::exists(path)); + + CallbackSpy<QByteArray> successfulSpy; + page.printToPdf(layout, successfulSpy.ref()); + QTRY_VERIFY(successfulSpy.waitForResult().length() > 0); + + CallbackSpy<QByteArray> failedInvalidLayoutSpy; + page.printToPdf(QPageLayout(), failedInvalidLayoutSpy.ref()); + QTRY_VERIFY(!failedInvalidLayoutSpy.waitForResult().length() > 0); } QTEST_MAIN(tst_QWebEnginePage) |