mirror of
https://github.com/JakubMelka/PDF4QT.git
synced 2025-06-05 21:59:17 +02:00
Printing feature
This commit is contained in:
@ -224,7 +224,8 @@ qt_libraries.files = $$[QT_INSTALL_BINS]/Qt?Widgets$${SUFFIX}.dll \
|
||||
$$[QT_INSTALL_BINS]/Qt?Gui$${SUFFIX}.dll \
|
||||
$$[QT_INSTALL_BINS]/Qt?Core$${SUFFIX}.dll \
|
||||
$$[QT_INSTALL_BINS]/Qt?WinExtras$${SUFFIX}.dll \
|
||||
$$[QT_INSTALL_BINS]/Qt?Svg$${SUFFIX}.dll
|
||||
$$[QT_INSTALL_BINS]/Qt?Svg$${SUFFIX}.dll \
|
||||
$$[QT_INSTALL_BINS]/Qt?PrintSupport$${SUFFIX}.dll
|
||||
qt_libraries.path = $$DESTDIR/install
|
||||
INSTALLS += qt_libraries
|
||||
|
||||
@ -235,3 +236,7 @@ INSTALLS += qt_plugin_platform
|
||||
qt_plugin_iconengine.files = $$[QT_INSTALL_PLUGINS]/iconengines/qsvgicon$${SUFFIX}.dll
|
||||
qt_plugin_iconengine.path = $$DESTDIR/install/iconengines
|
||||
INSTALLS += qt_plugin_iconengine
|
||||
|
||||
qt_plugin_printsupport.files = $$[QT_INSTALL_PLUGINS]/printsupport/windowsprintersupport$${SUFFIX}.dll
|
||||
qt_plugin_printsupport.path = $$DESTDIR/install/printsupport
|
||||
INSTALLS += qt_plugin_printsupport
|
||||
|
@ -37,7 +37,7 @@ class PDFPrecompiledPage;
|
||||
class PDFOptionalContentActivity;
|
||||
|
||||
/// Renders the PDF page on the painter, or onto an image.
|
||||
class PDFRenderer
|
||||
class PDFFORQTLIBSHARED_EXPORT PDFRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
#
|
||||
#-------------------------------------------------
|
||||
|
||||
QT += core gui winextras
|
||||
QT += core gui winextras printsupport
|
||||
|
||||
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
|
||||
|
||||
|
@ -35,5 +35,6 @@
|
||||
<file>resources/ui.svg</file>
|
||||
<file>resources/rotate-left.svg</file>
|
||||
<file>resources/rotate-right.svg</file>
|
||||
<file>resources/print.svg</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include "pdfexecutionpolicy.h"
|
||||
#include "pdfwidgetutils.h"
|
||||
|
||||
#include <QPainter>
|
||||
#include <QSettings>
|
||||
#include <QFileDialog>
|
||||
#include <QMessageBox>
|
||||
@ -53,6 +54,8 @@
|
||||
#include <QLabel>
|
||||
#include <QDoubleSpinBox>
|
||||
#include <QDesktopServices>
|
||||
#include <QtPrintSupport/QPrinter>
|
||||
#include <QtPrintSupport/QPrintDialog>
|
||||
#include <QtConcurrent/QtConcurrent>
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
@ -109,6 +112,7 @@ PDFViewerMainWindow::PDFViewerMainWindow(QWidget* parent) :
|
||||
ui->actionCopyText->setShortcut(QKeySequence::Copy);
|
||||
ui->actionRotateRight->setShortcut(QKeySequence("Ctrl+Shift++"));
|
||||
ui->actionRotateLeft->setShortcut(QKeySequence("Ctrl+Shift+-"));
|
||||
ui->actionPrint->setShortcut(QKeySequence::Print);
|
||||
|
||||
for (QAction* action : m_recentFileManager->getActions())
|
||||
{
|
||||
@ -806,6 +810,14 @@ void PDFViewerMainWindow::updateActionsAvailability()
|
||||
const bool isBusy = m_futureWatcher.isRunning() || m_isBusy;
|
||||
const bool hasDocument = m_pdfDocument;
|
||||
const bool hasValidDocument = !isBusy && hasDocument;
|
||||
bool canPrint = false;
|
||||
if (m_pdfDocument)
|
||||
{
|
||||
const pdf::PDFObjectStorage& storage = m_pdfDocument->getStorage();
|
||||
const pdf::PDFSecurityHandler* securityHandler = storage.getSecurityHandler();
|
||||
canPrint = securityHandler->isAllowed(pdf::PDFSecurityHandler::Permission::PrintLowResolution) ||
|
||||
securityHandler->isAllowed(pdf::PDFSecurityHandler::Permission::PrintHighResolution);
|
||||
}
|
||||
|
||||
ui->actionOpen->setEnabled(!isBusy);
|
||||
ui->actionClose->setEnabled(hasValidDocument);
|
||||
@ -817,6 +829,7 @@ void PDFViewerMainWindow::updateActionsAvailability()
|
||||
ui->actionFitHeight->setEnabled(hasValidDocument);
|
||||
ui->actionRendering_Errors->setEnabled(hasValidDocument);
|
||||
ui->actionFind->setEnabled(hasValidDocument);
|
||||
ui->actionPrint->setEnabled(hasValidDocument && canPrint);
|
||||
setEnabled(!isBusy);
|
||||
}
|
||||
|
||||
@ -1158,4 +1171,109 @@ void PDFViewerMainWindow::on_actionRotateLeft_triggered()
|
||||
m_pdfWidget->getDrawWidgetProxy()->performOperation(pdf::PDFDrawWidgetProxy::RotateLeft);
|
||||
}
|
||||
|
||||
void PDFViewerMainWindow::on_actionPrint_triggered()
|
||||
{
|
||||
// Are we allowed to print in high resolution? If yes, then print in high resolution,
|
||||
// otherwise print in low resolution. If this action is triggered, then print operation
|
||||
// should be allowed (at least print in low resolution).
|
||||
const pdf::PDFObjectStorage& storage = m_pdfDocument->getStorage();
|
||||
const pdf::PDFSecurityHandler* securityHandler = storage.getSecurityHandler();
|
||||
QPrinter::PrinterMode printerMode = QPrinter::HighResolution;
|
||||
if (!securityHandler->isAllowed(pdf::PDFSecurityHandler::Permission::PrintHighResolution))
|
||||
{
|
||||
printerMode = QPrinter::ScreenResolution;
|
||||
}
|
||||
|
||||
// Run print dialog
|
||||
QPrinter printer(printerMode);
|
||||
QPrintDialog printDialog(&printer, this);
|
||||
printDialog.setOptions(QPrintDialog::PrintPageRange | QPrintDialog::PrintShowPageSize | QPrintDialog::PrintCollateCopies | QPrintDialog::PrintSelection);
|
||||
printDialog.setOption(QPrintDialog::PrintCurrentPage, m_pdfWidget->getDrawWidget()->getCurrentPages().size() == 1);
|
||||
printDialog.setMinMax(1, int(m_pdfDocument->getCatalog()->getPageCount()));
|
||||
if (printDialog.exec() == QPrintDialog::Accepted)
|
||||
{
|
||||
std::vector<pdf::PDFInteger> pageIndices;
|
||||
switch (printDialog.printRange())
|
||||
{
|
||||
case QAbstractPrintDialog::AllPages:
|
||||
{
|
||||
pageIndices.resize(m_pdfDocument->getCatalog()->getPageCount(), 0);
|
||||
std::iota(pageIndices.begin(), pageIndices.end(), 0);
|
||||
break;
|
||||
}
|
||||
|
||||
case QAbstractPrintDialog::Selection:
|
||||
case QAbstractPrintDialog::CurrentPage:
|
||||
{
|
||||
pageIndices = m_pdfWidget->getDrawWidget()->getCurrentPages();
|
||||
break;
|
||||
}
|
||||
|
||||
case QAbstractPrintDialog::PageRange:
|
||||
{
|
||||
const pdf::PDFInteger fromPage = printDialog.fromPage();
|
||||
const pdf::PDFInteger toPage = printDialog.toPage();
|
||||
const pdf::PDFInteger pageCount = toPage - fromPage + 1;
|
||||
if (pageCount > 0)
|
||||
{
|
||||
pageIndices.resize(pageCount, 0);
|
||||
std::iota(pageIndices.begin(), pageIndices.end(), fromPage - 1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
Q_ASSERT(false);
|
||||
break;
|
||||
}
|
||||
|
||||
if (pageIndices.empty())
|
||||
{
|
||||
// Nothing to be printed
|
||||
return;
|
||||
}
|
||||
|
||||
pdf::ProgressStartupInfo info;
|
||||
info.showDialog = true;
|
||||
info.text = tr("Printing document");
|
||||
m_progress->start(pageIndices.size(), qMove(info));
|
||||
printer.setFullPage(true);
|
||||
QPainter painter(&printer);
|
||||
|
||||
const pdf::PDFCatalog* catalog = m_pdfDocument->getCatalog();
|
||||
pdf::PDFDrawWidgetProxy* proxy = m_pdfWidget->getDrawWidgetProxy();
|
||||
pdf::PDFOptionalContentActivity optionalContentActivity(m_pdfDocument.data(), pdf::OCUsage::Print, nullptr);
|
||||
pdf::PDFCMSPointer cms = proxy->getCMSManager()->getCurrentCMS();
|
||||
pdf::PDFRenderer renderer(m_pdfDocument.get(), proxy->getFontCache(), cms.data(), &optionalContentActivity, proxy->getFeatures(), proxy->getMeshQualitySettings());
|
||||
|
||||
const pdf::PDFInteger lastPage = pageIndices.back();
|
||||
for (const pdf::PDFInteger pageIndex : pageIndices)
|
||||
{
|
||||
const pdf::PDFPage* page = catalog->getPage(pageIndex);
|
||||
Q_ASSERT(page);
|
||||
|
||||
QRectF mediaBox = page->getRotatedMediaBox();
|
||||
QRectF paperRect = printer.paperRect();
|
||||
QSizeF scaledSize = mediaBox.size().scaled(paperRect.size(), Qt::KeepAspectRatio);
|
||||
mediaBox.setSize(scaledSize);
|
||||
mediaBox.moveCenter(paperRect.center());
|
||||
|
||||
renderer.render(&painter, mediaBox, pageIndex);
|
||||
m_progress->step();
|
||||
|
||||
if (pageIndex != lastPage)
|
||||
{
|
||||
if (!printer.newPage())
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
painter.end();
|
||||
m_progress->finish();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace pdfviewer
|
||||
|
||||
|
@ -96,6 +96,8 @@ private slots:
|
||||
|
||||
void on_actionRotateLeft_triggered();
|
||||
|
||||
void on_actionPrint_triggered();
|
||||
|
||||
private:
|
||||
void onActionOpenTriggered();
|
||||
void onActionCloseTriggered();
|
||||
|
@ -31,6 +31,7 @@
|
||||
<addaction name="actionClose"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionSend_by_E_Mail"/>
|
||||
<addaction name="actionPrint"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionProperties"/>
|
||||
<addaction name="separator"/>
|
||||
@ -440,6 +441,15 @@
|
||||
<string>Rotate Left</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionPrint">
|
||||
<property name="icon">
|
||||
<iconset resource="pdfforqtviewer.qrc">
|
||||
<normaloff>:/resources/print.svg</normaloff>:/resources/print.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Print</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<layoutdefault spacing="6" margin="11"/>
|
||||
<resources>
|
||||
|
114
PdfForQtViewer/resources/print.svg
Normal file
114
PdfForQtViewer/resources/print.svg
Normal file
@ -0,0 +1,114 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="30mm"
|
||||
height="30mm"
|
||||
viewBox="0 0 30 30"
|
||||
version="1.1"
|
||||
id="svg5291"
|
||||
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
|
||||
sodipodi:docname="print.svg">
|
||||
<defs
|
||||
id="defs5285" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="15.839192"
|
||||
inkscape:cx="43.479195"
|
||||
inkscape:cy="22.801583"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:window-width="3840"
|
||||
inkscape:window-height="2035"
|
||||
inkscape:window-x="-13"
|
||||
inkscape:window-y="-13"
|
||||
inkscape:window-maximized="1" />
|
||||
<metadata
|
||||
id="metadata5288">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>Jakub Melka</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:creator>
|
||||
<cc:license
|
||||
rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" />
|
||||
</cc:Work>
|
||||
<cc:License
|
||||
rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#Reproduction" />
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#Distribution" />
|
||||
<cc:requires
|
||||
rdf:resource="http://creativecommons.org/ns#Notice" />
|
||||
<cc:requires
|
||||
rdf:resource="http://creativecommons.org/ns#Attribution" />
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
|
||||
<cc:requires
|
||||
rdf:resource="http://creativecommons.org/ns#ShareAlike" />
|
||||
</cc:License>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Vrstva 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(0,-267)">
|
||||
<rect
|
||||
style="fill:#000000;fill-opacity:0.9948007;stroke:#000000;stroke-width:0.37699473;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers"
|
||||
id="rect831"
|
||||
width="23.085983"
|
||||
height="7.656455"
|
||||
x="4.1268063"
|
||||
y="279.67856" />
|
||||
<rect
|
||||
style="fill:none;fill-opacity:0.9948007;stroke:#000000;stroke-width:0.7492165;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers"
|
||||
id="rect833"
|
||||
width="14.933595"
|
||||
height="2.2713938"
|
||||
x="8.1247196"
|
||||
y="287.44482" />
|
||||
<rect
|
||||
style="fill:none;fill-opacity:0.9948007;stroke:#000000;stroke-width:0.72756678;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers"
|
||||
id="rect837"
|
||||
width="17.304916"
|
||||
height="5.3208041"
|
||||
x="6.9582481"
|
||||
y="274.62485" />
|
||||
<rect
|
||||
style="fill:#ffffff;fill-opacity:0.9948007;stroke:none;stroke-width:1.1373328;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers"
|
||||
id="rect841"
|
||||
width="1.508518"
|
||||
height="1.3341492"
|
||||
x="4.8337612"
|
||||
y="280.19043" />
|
||||
<rect
|
||||
style="fill:#ffffff;fill-opacity:0.9948007;stroke:none;stroke-width:1.1373328;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers"
|
||||
id="rect841-0"
|
||||
width="1.508518"
|
||||
height="1.3341492"
|
||||
x="6.8714461"
|
||||
y="280.19043" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 4.1 KiB |
Reference in New Issue
Block a user