Handling PDF: Difference between revisions

From Qt Wiki
Jump to navigation Jump to search
(Add "cleanup" tag)
 
(21 intermediate revisions by 6 users not shown)
Line 1: Line 1:
{{Cleanup | reason=Auto-imported from ExpressionEngine.}}
{{Ambox|text=TODO: Tips for implementing a custom interactive viewer, using Qt and the PDF parsing and rendering libraries mentioned above}}
 
{{LangSwitch}}
__TOC__
[[Category:Developing_with_Qt]]
[[Category:Developing_with_Qt]]
[toc align_right="yes" depth="2"]
This page discusses various available options for working with [http://en.wikipedia.org/wiki/Portable_Document_Format Portable Document Format (PDF)] [en.wikipedia.org] documents in your Qt application. Please also read the general considerations outlined on the [[Handling_Document_Formats | Handling Document Formats]] page.
 
= Handling PDF =
 
This page discusses various available options for working with "Portable Document Format (PDF)":http://en.wikipedia.org/wiki/Portable_Document_Format documents in your Qt application. Please also read the general considerations outlined on the [[Handling_Document_Formats | Handling Document Formats]] page.
 
p{width:60%;border:solid 1px #99a;background:#eef;color:#335;padding:2pt 4pt;font-size:0.9em;line-height:150%;font-style:italic}. Note that this information is collaboratively collected by the community, with no promise of completeness or correctness. In particular, use your own research and judgment when evaluating third-party libraries or tools!


== Reading / Writing ==
== Reading / Writing ==
Line 14: Line 9:
=== Using QPrinter ===
=== Using QPrinter ===


For {color:#709}creating PDF documents from scratch, you can use Qt's built-in print support which also allows "printing" to PDF files. To do so you can set up a [[Doc:QPrinter]] instance like this: <code>QPrinter printer(QPrinter::HighResolution);
For <span style="color:#800080">  creating</span> PDF documents from scratch, you can use Qt's built-in print support which also allows "printing" to PDF files. To do so you can set up a {{DocLink|QPrinter}} instance like this: <code>QPrinter printer(QPrinter::HighResolution);
printer.setOutputFormat(QPrinter::PdfFormat);
printer.setOutputFormat(QPrinter::PdfFormat);
printer.setOutputFileName("path/to/file.pdf");</code> Since QPrinter inherits [[Doc:QPaintDevice]], anything that supports outputting graphical content to a QPaintDevice (or has convenience API for printing with QPrinter) can thus be used for generating PDFs:
printer.setOutputFileName("path/to/file.pdf");</code> Since QPrinter inherits {{DocLink|QPaintDevice}}, anything that supports outputting graphical content to a QPaintDevice (or has convenience API for printing with QPrinter) can thus be used for generating PDFs:


* '''''manual QPainter painting'''''
* '''''manual QPainter painting'''''
The most basic (but not necessarily simplest) way of creating PDF documents with QPrinter is by manually painting the document's content with Qt's "Arthur paint system":/doc/qt-4.8/qt4-arthur.html.
The most basic (but not necessarily simplest) way of creating PDF documents with QPrinter is by manually painting the document's content with Qt's {{DocLink|QtDesigner-ArthurPlugin-Example||Arthur paint system}}.
Just pass the QPrinter object as a reference to the constructor of [[Doc:QPainter]] (or, alternatively, to "QPainter::begin":/doc/qt-4.8/qpainter.html#begin for an already existing QPainter) and then perform any painting operations with that QPainter instance like you usually would (with intermittent calls to "QPrinter::newPage":/doc/qt-4.8/qprinter.html#newPage whenever you want to move on to the next PDF page).
Just pass the QPrinter object as a reference to the constructor of {{DocLink|PaintSystem.html||QPainter}} (or, alternatively, to {{DocLink|QPainter|begin|QPainter::begin()}} for an already existing QPainter) and then perform any painting operations with that QPainter instance like you usually would (with intermittent calls to {{DocLink|QPrinter|newPage|QPrinter::newPage()}} whenever you want to move on to the next PDF page).


* '''''Scribe'''''
* '''''Scribe'''''
For a more high-level API for creating structured rich-text documents, use Qt's Scribe framework (see [[Handling_Document_Formats | Handling Document Formats]]). You can export the whole document or a part of it to PDF with "QTextDocument::print":/doc/qt-4.8/qtextdocument.html#print or "QTextEdit::print":/doc/qt-4.8/qtextedit.html#print (again, using a QPrinter object set up as shown above).
For a more high-level API for creating structured rich-text documents, use Qt's Scribe framework (see [[Handling Document Formats]]), which is based on a cursor interface that mimics the behavior of a cursor in a text editor. You can export the whole document with {{DocLink|QTextDocument|print|QTextDocument::print()}}, or a part of it with {{DocLink|QTextEdit|print|QTextEdit::print()}} (see [[Exporting a document to PDF]] for more details).


* '''''Graphics View'''''
* '''''Graphics View'''''
Qt's "Graphics View framework":/doc/qt-4.8/graphicsview.html can be a more suitable alternative for creating PDF documents with content that is mainly based on arbitrarily positioned and transformed 2D graphical items rather than continuous flowed rich text.
Qt's {{DocLink|GraphicsView||Graphics View framework}} can be a more suitable alternative for creating PDF documents with content that is mainly based on arbitrarily positioned and transformed 2D graphical items rather than continuous flowed rich text.
To export the content of a graphics scene or view (or a part of it) to PDF, you need to manually initialize a QPainter configured to paint on a PDF-creating QPrinter (as described above), and pass it to "QGraphicsScene::render":/doc/qt-4.8/qgraphicsscene.html#render or "QGraphicsView::render":/doc/qt-4.8/qgraphicsview.html#render.
To export the content of a graphics scene or view (or a part of it) to PDF, you need to manually initialize a QPainter configured to paint on a PDF-creating QPrinter (as described above), and pass it to {{DocLink|QGraphicsScene|render|QGraphicsScene::render()}} or {{DocLink|QGraphicsView|render|QGraphicsView::render()}}.


=== Using third-party libraries ===
=== Using third-party libraries ===


If you need more control over the output when {color:#709}creating PDF documents, or you need to {color:#709}parse existing PDF documents (anything from extracting specific information to assembling a full in-memory document object tree) and maybe even {color:#709}modify their structure or content before writing them back to disk, refer to third-party PDF reading/writing libraries:
If you need more control over the output when <span style="color:#800080">creating</span> PDF documents, or you need to <span style="color:#800080">parse</span> existing PDF documents (anything from extracting specific information to assembling a full in-memory document object tree) and maybe even <span style="color:#800080">modify</span> their structure or content before writing them back to disk, refer to third-party PDF reading/writing libraries:


table{width:95%;margin-left:2.5%}.
{| class="wikitable"
| |''. API |''. {color:#709}parsing |''. {color:#709}modifying |''. {color:#709}creating |''. platforms |''. license |
|
| "'''poppler-qt4'''":http://freedesktop.org/wiki/Software/poppler | C+''/Qt | {color:#580}yes | {color:#920}? | {color:#920}? | Win, Mac?, Linux, … | GPL v2'' {color:#458}[strong copyleft] |
! style="text-align:left;"| API
| "'''Hummus'''":http://pdfhummus.com/ | C++ | {color:#580}yes | {color:#580}yes | {color:#580}yes | Win, Mac, Linux | Apache 2.0 {color:#458}[permissive] |
! style="text-align:left; color:#800080"| parsing
| "'''PoDoFo'''":http://podofo.sourceforge.net | C++ | {color:#580}yes | {color:#580}yes | {color:#580}yes | Win, Mac, Linux | LGPL {color:#458}[weak copyleft] |
! style="text-align:left; color:#800080"| modifying
! style="text-align:left; color:#800080"| creating
! style="text-align:left;"| platforms
! style="text-align:left;"| license
|-
| style="text-align:left;"| [http://freedesktop.org/wiki/Software/poppler '''poppler-qt4'''] [freedesktop.org]
| C+''/Qt
| yes
| ?
| ?
| Win, Mac?, Linux, …
| GPL v2+ <span style="color:Navy">  [strong copyleft] </span>
|-
| style="text-align:left;"| [http://pdfhummus.com/ '''Hummus'''] [pdfhummus.com]
| C++
| yes
| yes
| yes
| Win, Mac, Linux
| Apache 2.0 <span style="color:Navy"> [permissive] </span>
|-
| style="text-align:left;"| [http://podofo.sourceforge.net '''PoDoFo'''] [podofo.sourceforge.net]
| C++
| yes
| yes
| yes
| Win, Mac, Linux
| LGPL <span style="color:Navy"> [weak copyleft] </span>
|}


=== Using batch conversion tools ===
=== Using batch conversion tools ===


If all else fails, there is always the option of using an existing tool to automatically convert between PDF files and a more manageable format, and let your Qt application read/write that format instead. The conversion tool could be bundled with your application or specified as a prerequisite, and controlled via [[Doc:QProcess]]. Some possibilities are:
If all else fails, there is always the option of using an existing tool to automatically convert between PDF files and a more manageable format, and let your Qt application read/write that format instead. The conversion tool could be bundled with your application or specified as a prerequisite, and controlled via [http://doc.qt.io/qt-5/qprocess.html QProcess]. Some possibilities are:
 
 
{| class="wikitable"
|
! style="text-align:left;"| executable names
! style="text-align:left;"| .pdf to:
! style="text-align:left;"| … to .pdf
! style="text-align:left;"| platforms
! style="text-align:left;"| license
|-
| style="text-align:left;"| [http://freedesktop.org/wiki/Software/poppler/ '''poppler-utils '''] [freedesktop.org]
| pdftotext, pdftocairo, pdftohtml
| .txt .svg .html …
| -
| Win, Mac?, Linux, …
| GPL v2+ <span style="color:Navy">  [strong copyleft] </span>
|-
| style="text-align:left;"| [http://inkscape.org/ '''Inkscape'''] [inkscape.org]
| inkscape
| .svg …
| .svg …
| Win, Mac, Linux, …
| GPL v2 <span style="color:Navy"> [strong copyleft] </span>
|}
 
== Rendering ==


table{width:95%;margin-left:2.5%}.
=== Using QtPDF ===
|''. |''. executable names |''. {font-family:monospace}.pdf to: |''. … to {font-family:monospace}.pdf |''. platforms |''. license |
| "'''poppler-utils'''":http://freedesktop.org/wiki/Software/poppler | pdftotext, pdftocairo, pdftohtml | {font-family:monospace}.txt .svg .html … | {font-family:monospace}-% | Win, Mac?, Linux, … | GPL v2+ {color:#458}[strong copyleft]|
| "'''Inkscape'''":http://inkscape.org | inkscape | {font-family:monospace}.svg … | {font-family:monospace}.svg … | Win, Mac, Linux, … | GPL v2 {color:#458}[strong copyleft]|


h2. Rendering
The QtPDF module is a wrapper around PDFium which supports rendering, navigating pages, bookmarks, links, document metadata, search, text selection and copying to the clipboard.  It includes an image plugin so that most image-viewing applications can view PDF files too (however most of those do not have multi-frame image support, so they will only render the first page).  At this point, more of the feature set is complete for Qt Quick applications than for widget-based ones; but both are possible.  It was introduced as a Qt Labs module in [http://blog.qt.io/blog/2017/01/30/new-qtpdf-qtlabs-module/ this blog post].  Since then, Qt Quick support has been added; and now the source code lives in the qtwebengine repository.  It is supported on all platforms that support Qt WebEngine, plus iOS.  You can build it using [[QtPDF Build Instructions|these instructions]].  Binary builds are also provided via Marketplace:  https://marketplace.qt.io/products/qtpdf  It's available under GPL, LGPL and commercial licenses.


h3. Using third-party libraries/tools
=== Using third-party libraries/tools ===


For rendering pages or elements from existing PDF documents to image files or in-memory pixmaps (useful e.g. for thumbnail generation or implementing custom viewers), third-party libraries can be used:
For rendering pages or elements from existing PDF documents to image files or in-memory pixmaps (useful e.g. for thumbnail generation or implementing custom viewers), third-party libraries can be used:


table{width:95%;margin-left:2.5%}.
 
| |''. API |''. can render |''. output to |''. platforms |''. license |
{| class="wikitable"
| "'''poppler-qt4'''":http://freedesktop.org/wiki/Software/poppler | C+''/Qt | pages, …? | QImage | Win, Mac?, Linux, … | GPL v2'' {color:#458}[strong copyleft] |
|
| "'''muPDF'''":http://mupdf.com | C | pages | RGBA byte array | Win, Mac, Linux, … | GPL v3+ {color:#458}[strong copyleft]; or commercial |
! style="text-align:left;"| API
! style="text-align:left;"| can render
! style="text-align:left;"| output to
! style="text-align:left;"| platforms
! style="text-align:left;"| license
|-
| [http://freedesktop.org/wiki/Software/poppler '''poppler-qt4'''] [freedesktop.org]
| C++/Qt
| pages, …?
| QImage
| Win, Mac?, Linux, …
| GPL v2 <span style="color:Navy"> [strong copyleft] </span>
|-
| [http://freedesktop.org/wiki/Software/poppler '''poppler-qt5'''] [freedesktop.org]
| C++/Qt
| pages, …?
| QImage
| Win, Mac?, Linux, …
| GPL v2 <span style="color:Navy"> [strong copyleft] </span>
|-
| [http://mupdf.com '''muPDF'''] [mupdf.com]
| C  
| pages
| RGBA byte array  
| Win, Mac, Linux, …
| GPL v3+ <span style="color:Navy"> [strong copyleft]; </span> or commercial
|}


Alternatively, the task can be delegated to existing command-line tools:
Alternatively, the task can be delegated to existing command-line tools:


table{width:95%;margin-left:2.5%}.
{| class="wikitable"
| |''. executable names |''. can render |''. output to |''. platforms |''. license |
|
| "'''poppler-utils'''":http://freedesktop.org/wiki/Software/poppler | pdftocairo, pdftoppm, pdfimages | pages, image elements | {font-family:monospace}.png .jpg .svg .ppm … | Win, Mac?, Linux, … | GPL v2+ {color:#458}[strong copyleft]|
! style="text-align:left;"| executable names
| "'''muPDF'''":http://mupdf.com | pdfdraw | pages | {font-family:monospace}.png, .ppm, .pgm, .pam, .pbm | Win, Mac, Linux, … | GPL v3+ {color:#458}[strong copyleft]; or commercial |
! style="text-align:left;"| can render
! style="text-align:left;"| output to
! style="text-align:left;"| platforms
! style="text-align:left;"| license
|-
| [http://freedesktop.org/wiki/Software/poppler '''poppler-utils'''] [freedesktop.org]
| pdftocairo, pdftoppm, pdfimages
| pages, image elements
| .png .jpg .svg .ppm …
| Win, Mac?, Linux, …
| GPL v2+ <span style="color:Navy"> [strong copyleft] </span>
|-
| [http://mupdf.com '''muPDF'''] [mupdf.com]
| pdfdraw
| pages
| .png, .ppm, .pgm, .pam, .pbm
| Win, Mac, Linux, …
| GPL v3+ <span style="color:Navy"> [strong copyleft]; </span> or commercial  
|}
 
== Interactive Viewing ==
=== Using QtPDF ===


h2. Interactive Viewing
The [[QtPDF_Build_Instructions|QtPDF module]] includes example PDF viewers which can be adapted and incorporated into Qt Quick or widget-based applications.


h3. Calling an external viewer application
=== Calling an external viewer application ===


If your application merely needs to let the user view/read certain PDF documents on demand, displaying them within the UI of the application itself might not be necessary, and delegating the task to an existing viewer application can be a viable option.
If your application merely needs to let the user view/read certain PDF documents on demand, displaying them within the UI of the application itself might not be necessary, and delegating the task to an existing viewer application can be a viable option.


Many users have already chosen and installed a stand-alone PDF viewer according to their personal preferences, so simply letting the operating system open the PDF file with whatever it considers the default viewer for such files, might be the easiest (and potentially most user-friendly) choice.
Many users have already chosen and installed a stand-alone PDF viewer according to their personal preferences, so simply letting the operating system open the PDF file with whatever it considers the default viewer for such files, might be the easiest (and potentially most user-friendly) choice.
To do so, simply pass the PDF file's URL to "QDesktopServices::openUrl":/doc/qt-4.8/qdesktopservices.html#openUrl. If you're downloading the file from the Internet, store it on disk using [[Doc:QTemporaryFile]] first, since not all viewers can handle remote URLs.
To do so, simply pass the PDF file's URL to [http://doc.qt.io/qt-4.8/qdesktopservices.html#openUrl QDesktopServices::openUrl]. If you're downloading the file from the Internet, store it on disk using [http://doc.qt.io/qt-5/qtemporaryfile.html QTemporaryFile] first, since not all viewers can handle remote URLs.


h3. Using a third-party Qt widget
=== Using a third-party Qt widget ===


The following widgets provide native PDF viewing for Qt applications:
The following widgets provide native PDF viewing for Qt applications:


table{width:95%;margin-left:2.5%}.
{| class="wikitable"
| |''. class name |''. platforms |''. license |
|
| "'''XpdfWidget/Qt'''":http://www.glyphandcog.com/XpdfWidgetQt.html | XpdfWidget | Win, Mac, Linux, … | commercial |
! style="text-align:left;"| class name
! style="text-align:left;"| platforms
! style="text-align:left;"| license
|-
| [http://www.glyphandcog.com/XpdfWidgetQt.html '''XpdfWidget/Qt'''] [glyphandcog.com]
| XpdfWidget
| Win, Mac, Linux, …
| commercial
|}


h3. Embedding a third-party ActiveX control
=== Embedding a third-party ActiveX control ===


If you are exclusively targeting the Windows platform, you can embed an existing ActiveX component for viewing PDFs in your Qt applications by instantiating it as a [[Doc:QAxWidget]] (see "Qt's ActiveX Framework":/doc/qt-4.8/activeqt.html).
If you are exclusively targeting the Windows platform, you can embed an existing ActiveX component for viewing PDFs in your Qt applications by instantiating it as a [http://doc.qt.io/qt-5/qaxwidget.html QAxWidget] (see [http://doc.qt.io/qt-4.8/activeqt.html Qt's ActiveX Framework]).


The following PDF viewers provide such an ActiveX control:
The following PDF viewers provide such an ActiveX control:


table{width:95%;margin-left:2.5%}.
{| class="wikitable"
| |''. DLL file |''. ActiveX control name |''. platforms |''. license |
|
| "'''Adobe Reader'''":http://get.adobe.com/reader/ | Acropdf.dll | {font-family:monospace}AxAcroPDFLib.AxAcroPDF | Win, Mac, Linux, … | {color:#458}freeware''(for commercial redistribution see "here":http://www.adobe.com/products/reader/distribution.html)_ |
! style="text-align:left;"| DLL file
! style="text-align:left;"| ActiveX control name
! style="text-align:left;"| platforms
! style="text-align:left;"| license
|-
| [http://get.adobe.com/reader/ '''Adobe Reader'''] [get.adobe.com]
| Acropdf.dll
| AxAcroPDFLib.AxAcroPDF
| Win, Mac, Linux, …
| <span style="color:Navy"> freeware </span> ''(for commercial redistribution see [http://www.adobe.com/products/reader/distribution.html here]) [adobe.com])''
|}


In the case of the Adobe Reader control, opening a PDF file is done with:
In the case of the Adobe Reader control, opening a PDF file is done with:
<code>dynamicCall("LoadFile(const QString)", pathToFile)<code>
<code>dynamicCall("LoadFile(const QString)", pathToFile)</code>


h3. Embedding a third-party browser plugin
=== Embedding a third-party browser plugin ===


A more cross-platform technology for embedding reusable components is the "NPAPI":http://en.wikipedia.org/wiki/NPAPI browser plugin architecture- which Qt's WebKit-based browser framework "happens to support":/doc/qt-4.8/qtwebkit.html#netscape-plugin-support. You'll need to set up a simple HTML page containing appropriate{font-family:monospace}<embed&amp;amp;gt;…</embed&amp;amp;gt;% tags, and let a [[Doc:QWebView]] display it (with "QWebSettings::PluginsEnabled":/doc/qt-4.8/qwebsettings.html#WebAttribute-enum set to true).
A more cross-platform technology for embedding reusable components is the [http://en.wikipedia.org/wiki/NPAPI NPAPI] [en.wikipedia.org] browser plugin architecture- which Qt's WebKit-based browser framework [http://doc.qt.io/qt-5/qtwebkitwidgets-index.html happens to support]. You'll need to set up a simple HTML page containing appropriate embed>…</embed> tags, and let a [http://doc.qt.io/qt-5/qwebview.html QWebView] display it (with [http://doc.qt.io/qt-4.8/qwebsettings.html#WebAttribute-enum QWebSettings::PluginsEnabled].


The following applications provide a reusable NPAPI plugin for viewing PDF:
The following applications provide a reusable NPAPI plugin for viewing PDF:


table{width:95%;margin-left:2.5%}.
{| class="wikitable"
| |''. plugin name |''. platforms |''. license |
|
| "'''Adobe Reader'''":http://get.adobe.com/reader/ | nppdf | Win, Mac, (Linux)[1], … | {color:#458}freeware''(for commercial redistribution see "here":http://www.adobe.com/products/reader/distribution.html)_ |
! style="text-align:left;"| plugin name
! style="text-align:left;"| platforms
! style="text-align:left;"| license
|-
| [http://get.adobe.com/reader/ '''Adobe Reader'''] [get.adobe.com]
| nppdf
| Win, Mac, (Linux)¹, …  
| <span style="color:Navy"> freeware </span>''(for commercial redistribution see [http://www.adobe.com/products/reader/distribution.html here] [adobe.com])''
|}


fn1{font-size:0.9em;line-height:150%;font-style:italic;margin-left:0.5em;margin-right:0.5em;color:#555}. While in theory it should work on all Desktop platforms, application developers have "reported problems":/forums/viewthread/14055 in trying to get it to work with Qt Webkit on Linux.
<small>  ¹''While in theory it should work on all Desktop platforms, application developers have "reported problems":/forums/viewthread/14055 in trying to get it to work with Qt Webkit on Linux. '' </small>


As an alternative to using QWebView for running the plugin, it is possible to use a third-party solution that allows embedding NPAPI plugins in a Qt application without the overhead of a full web browser instance:
As an alternative to using QWebView for running the plugin, it is possible to use a third-party solution that allows embedding NPAPI plugins in a Qt application without the overhead of a full web browser instance:


table{width:95%;margin-left:2.5%}.
{| class="wikitable"
| |''. component type |''. has special convenience API for |''. platforms |''. license |
|
| "'''QtitanMultimedia'''":http://www.devmachines.com/products/qtitanmultimedia-overview.html | QWidget | Adobe Reader, … | Win, Linux | {color:#458}commercial |
! style="text-align:left;"| component type
 
! style="text-align:left;"| has special convenience API for
=== Implementing a custom viewer ===
! style="text-align:left;"| platforms
 
! style="text-align:left;"| license
p{border:dashed 1px #a94;background:#fbf3dd;color:#530;padding:2pt 4pt;margin-left:2pt;margin-right:2pt;font-size:0.9em;line-height:150%;font-style:italic}. TODO: Tips for implementing a custom interactive viewer, using Qt and the PDF parsing and rendering libraries mentioned above
|-
 
| [http://www.devmachines.com/products/qtitanmultimedia-overview.html '''QtitanMultimedia'''] [devmachines.com]
p{color:#fff;border-bottom:solid 1px #ccc}. .
| QWidget
| Adobe Reader, …
| Win, Linux
| <span style="color:Navy"> commercial </span>
|}


== See Also ==
== See Also ==


* [[Handling_Document_Formats | Handling Document Formats]]
* [[Handling Document Formats]]
** ''other "text document" formats:''
* [[Handling HTML]]
*** [[Handling_HTML | HTML]]
* [[Handling Microsoft Excel file format]]
*** [[Handling_RTF | RTF]]
*** [[Handling_Microsoft_Word_(file_format) | Microsoft Word]]
*** [[Handling_OpenDocument_Text | OpenDocument Text]]

Latest revision as of 13:41, 28 May 2020

TODO: Tips for implementing a custom interactive viewer, using Qt and the PDF parsing and rendering libraries mentioned above

En Ar Bg De El Es Fa Fi Fr Hi Hu It Ja Kn Ko Ms Nl Pl Pt Ru Sq Th Tr Uk Zh

This page discusses various available options for working with Portable Document Format (PDF) [en.wikipedia.org] documents in your Qt application. Please also read the general considerations outlined on the Handling Document Formats page.

Reading / Writing

Using QPrinter

For creating PDF documents from scratch, you can use Qt's built-in print support which also allows "printing" to PDF files. To do so you can set up a QPrinter instance like this:

QPrinter printer(QPrinter::HighResolution);
printer.setOutputFormat(QPrinter::PdfFormat);
printer.setOutputFileName("path/to/file.pdf");

Since QPrinter inherits QPaintDevice, anything that supports outputting graphical content to a QPaintDevice (or has convenience API for printing with QPrinter) can thus be used for generating PDFs:

  • manual QPainter painting

The most basic (but not necessarily simplest) way of creating PDF documents with QPrinter is by manually painting the document's content with Qt's Arthur paint system. Just pass the QPrinter object as a reference to the constructor of QPainter (or, alternatively, to QPainter::begin() for an already existing QPainter) and then perform any painting operations with that QPainter instance like you usually would (with intermittent calls to QPrinter::newPage() whenever you want to move on to the next PDF page).

  • Scribe

For a more high-level API for creating structured rich-text documents, use Qt's Scribe framework (see Handling Document Formats), which is based on a cursor interface that mimics the behavior of a cursor in a text editor. You can export the whole document with QTextDocument::print(), or a part of it with QTextEdit::print() (see Exporting a document to PDF for more details).

  • Graphics View

Qt's Graphics View framework can be a more suitable alternative for creating PDF documents with content that is mainly based on arbitrarily positioned and transformed 2D graphical items rather than continuous flowed rich text. To export the content of a graphics scene or view (or a part of it) to PDF, you need to manually initialize a QPainter configured to paint on a PDF-creating QPrinter (as described above), and pass it to QGraphicsScene::render() or QGraphicsView::render().

Using third-party libraries

If you need more control over the output when creating PDF documents, or you need to parse existing PDF documents (anything from extracting specific information to assembling a full in-memory document object tree) and maybe even modify their structure or content before writing them back to disk, refer to third-party PDF reading/writing libraries:

API parsing modifying creating platforms license
poppler-qt4 [freedesktop.org] C+/Qt yes ? ? Win, Mac?, Linux, … GPL v2+ [strong copyleft]
Hummus [pdfhummus.com] C++ yes yes yes Win, Mac, Linux Apache 2.0 [permissive]
PoDoFo [podofo.sourceforge.net] C++ yes yes yes Win, Mac, Linux LGPL [weak copyleft]

Using batch conversion tools

If all else fails, there is always the option of using an existing tool to automatically convert between PDF files and a more manageable format, and let your Qt application read/write that format instead. The conversion tool could be bundled with your application or specified as a prerequisite, and controlled via QProcess. Some possibilities are:


executable names .pdf to: … to .pdf platforms license
poppler-utils [freedesktop.org] pdftotext, pdftocairo, pdftohtml .txt .svg .html … - Win, Mac?, Linux, … GPL v2+ [strong copyleft]
Inkscape [inkscape.org] inkscape .svg … .svg … Win, Mac, Linux, … GPL v2 [strong copyleft]

Rendering

Using QtPDF

The QtPDF module is a wrapper around PDFium which supports rendering, navigating pages, bookmarks, links, document metadata, search, text selection and copying to the clipboard. It includes an image plugin so that most image-viewing applications can view PDF files too (however most of those do not have multi-frame image support, so they will only render the first page). At this point, more of the feature set is complete for Qt Quick applications than for widget-based ones; but both are possible. It was introduced as a Qt Labs module in this blog post. Since then, Qt Quick support has been added; and now the source code lives in the qtwebengine repository. It is supported on all platforms that support Qt WebEngine, plus iOS. You can build it using these instructions. Binary builds are also provided via Marketplace: https://marketplace.qt.io/products/qtpdf It's available under GPL, LGPL and commercial licenses.

Using third-party libraries/tools

For rendering pages or elements from existing PDF documents to image files or in-memory pixmaps (useful e.g. for thumbnail generation or implementing custom viewers), third-party libraries can be used:


API can render output to platforms license
poppler-qt4 [freedesktop.org] C++/Qt pages, …? QImage Win, Mac?, Linux, … GPL v2 [strong copyleft]
poppler-qt5 [freedesktop.org] C++/Qt pages, …? QImage Win, Mac?, Linux, … GPL v2 [strong copyleft]
muPDF [mupdf.com] C pages RGBA byte array Win, Mac, Linux, … GPL v3+ [strong copyleft]; or commercial

Alternatively, the task can be delegated to existing command-line tools:

executable names can render output to platforms license
poppler-utils [freedesktop.org] pdftocairo, pdftoppm, pdfimages pages, image elements .png .jpg .svg .ppm … Win, Mac?, Linux, … GPL v2+ [strong copyleft]
muPDF [mupdf.com] pdfdraw pages .png, .ppm, .pgm, .pam, .pbm Win, Mac, Linux, … GPL v3+ [strong copyleft]; or commercial

Interactive Viewing

Using QtPDF

The QtPDF module includes example PDF viewers which can be adapted and incorporated into Qt Quick or widget-based applications.

Calling an external viewer application

If your application merely needs to let the user view/read certain PDF documents on demand, displaying them within the UI of the application itself might not be necessary, and delegating the task to an existing viewer application can be a viable option.

Many users have already chosen and installed a stand-alone PDF viewer according to their personal preferences, so simply letting the operating system open the PDF file with whatever it considers the default viewer for such files, might be the easiest (and potentially most user-friendly) choice. To do so, simply pass the PDF file's URL to QDesktopServices::openUrl. If you're downloading the file from the Internet, store it on disk using QTemporaryFile first, since not all viewers can handle remote URLs.

Using a third-party Qt widget

The following widgets provide native PDF viewing for Qt applications:

class name platforms license
XpdfWidget/Qt [glyphandcog.com] XpdfWidget Win, Mac, Linux, … commercial

Embedding a third-party ActiveX control

If you are exclusively targeting the Windows platform, you can embed an existing ActiveX component for viewing PDFs in your Qt applications by instantiating it as a QAxWidget (see Qt's ActiveX Framework).

The following PDF viewers provide such an ActiveX control:

DLL file ActiveX control name platforms license
Adobe Reader [get.adobe.com] Acropdf.dll AxAcroPDFLib.AxAcroPDF Win, Mac, Linux, … freeware (for commercial redistribution see here) [adobe.com])

In the case of the Adobe Reader control, opening a PDF file is done with:

dynamicCall("LoadFile(const QString)", pathToFile)

Embedding a third-party browser plugin

A more cross-platform technology for embedding reusable components is the NPAPI [en.wikipedia.org] browser plugin architecture- which Qt's WebKit-based browser framework happens to support. You'll need to set up a simple HTML page containing appropriate embed>…</embed> tags, and let a QWebView display it (with QWebSettings::PluginsEnabled.

The following applications provide a reusable NPAPI plugin for viewing PDF:

plugin name platforms license
Adobe Reader [get.adobe.com] nppdf Win, Mac, (Linux)¹, … freeware (for commercial redistribution see here [adobe.com])

¹While in theory it should work on all Desktop platforms, application developers have "reported problems":/forums/viewthread/14055 in trying to get it to work with Qt Webkit on Linux.

As an alternative to using QWebView for running the plugin, it is possible to use a third-party solution that allows embedding NPAPI plugins in a Qt application without the overhead of a full web browser instance:

component type has special convenience API for platforms license
QtitanMultimedia [devmachines.com] QWidget Adobe Reader, … Win, Linux commercial

See Also