From 8581cd01e22c65fb45b46e704a57f34b06517642 Mon Sep 17 00:00:00 2001 From: wandererfan Date: Tue, 19 Nov 2024 17:58:08 -0500 Subject: [PATCH] [TD]prevent crash on attempt to print hidden page --- src/Mod/TechDraw/Gui/MDIViewPage.cpp | 138 +++---------- src/Mod/TechDraw/Gui/MDIViewPage.h | 7 - src/Mod/TechDraw/Gui/PagePrinter.cpp | 291 ++++++++++++++------------- src/Mod/TechDraw/Gui/PagePrinter.h | 92 ++++----- 4 files changed, 224 insertions(+), 304 deletions(-) diff --git a/src/Mod/TechDraw/Gui/MDIViewPage.cpp b/src/Mod/TechDraw/Gui/MDIViewPage.cpp index e87c38a5a4..c485671e49 100644 --- a/src/Mod/TechDraw/Gui/MDIViewPage.cpp +++ b/src/Mod/TechDraw/Gui/MDIViewPage.cpp @@ -119,14 +119,14 @@ MDIViewPage::MDIViewPage(ViewProviderPage* pageVp, Gui::Document* doc, QWidget* connectDeletedObject = appDoc->signalDeletedObject.connect(bnd); //NOLINTEND - m_pagePrinter = new PagePrinter(m_vpPage); - m_pagePrinter->setOwner(this); + // m_pagePrinter = new PagePrinter(m_vpPage); + // m_pagePrinter->setOwner(this); } MDIViewPage::~MDIViewPage() { connectDeletedObject.disconnect(); - delete m_pagePrinter; + // delete m_pagePrinter; } void MDIViewPage::setScene(QGSPage* scene, QGVPage* viewWidget) @@ -134,9 +134,9 @@ void MDIViewPage::setScene(QGSPage* scene, QGVPage* viewWidget) m_scene = scene; setCentralWidget(viewWidget);//this makes viewWidget a Qt child of MDIViewPage QObject::connect(scene, &QGSPage::selectionChanged, this, &MDIViewPage::sceneSelectionChanged); - if (m_pagePrinter) { - m_pagePrinter->setScene(m_scene); - } + // if (m_pagePrinter) { + // m_pagePrinter->setScene(m_scene); + // } } void MDIViewPage::setDocumentObject(const std::string& name) @@ -309,35 +309,6 @@ void MDIViewPage::fixSceneDependencies() /// as file name selection and error messages /// PagePrinter handles the actual printing mechanics. -/// save the page state so it can be restore after printing -void MDIViewPage::savePageExportState(ViewProviderPage* page) -{ - auto guiDoc = page->getDocument(); - if (!guiDoc) { - return; - } - m_docModStateBeforePrint = guiDoc->isModified(); -} -/// ensure that the page reverts to its normal state after any changes made for printing. -void MDIViewPage::resetPageExportState(ViewProviderPage* page) const -{ - auto pageFeature = page->getDrawPage(); - if (!pageFeature) { - // how did this happen? - return; - } - - auto guiDoc = page->getDocument(); - if (!guiDoc) { - return; - } - auto scene = page->getQGSPage(); - scene->setExportingPdf(false); - scene->setExportingSvg(false); - guiDoc->setModified(m_docModStateBeforePrint); - pageFeature->redrawCommand(); -} - /// overrides of MDIView print methods so that they print the QGraphicsScene instead /// of the COIN3d scenegraph. @@ -354,72 +325,46 @@ void MDIViewPage::printPdf() } Gui::WaitCursor wc; - auto vpp = getViewProviderPage(); - if (!vpp) { - // how did this happen? - return; - } - - savePageExportState(vpp); std::string utf8Content = fn.toUtf8().constData(); - if (m_pagePrinter) { - m_pagePrinter->printPdf(utf8Content); - resetPageExportState(vpp); - } + PagePrinter::printPdf(getViewProviderPage(), utf8Content); } void MDIViewPage::print() { - if (!m_pagePrinter) { - return; - } - - auto vpp = getViewProviderPage(); - if (!vpp) { - // how did this happen? - return; - } - - savePageExportState(vpp); - - m_pagePrinter->getPaperAttributes(); + auto pageAttr = PagePrinter::getPaperAttributes(getViewProviderPage()); QPrinter printer(QPrinter::HighResolution); printer.setFullPage(true); - if (m_pagePrinter->getPaperSize() == QPageSize::Custom) { - printer.setPageSize(QPageSize(QSizeF(m_pagePrinter->getPageWidth(), m_pagePrinter->getPageHeight()), QPageSize::Millimeter)); + if (pageAttr.pageSize() == QPageSize::Custom) { + printer.setPageSize( + QPageSize(QSizeF(pageAttr.pageWidth(), pageAttr.pageHeight()), QPageSize::Millimeter)); } else { - printer.setPageSize(QPageSize(m_pagePrinter->getPaperSize())); + printer.setPageSize(QPageSize(pageAttr.pageSize())); } - printer.setPageOrientation(m_pagePrinter->getOrientation()); + printer.setPageOrientation(pageAttr.orientation()); QPrintDialog dlg(&printer, this); if (dlg.exec() == QDialog::Accepted) { print(&printer); - resetPageExportState(vpp); } } void MDIViewPage::printPreview() { -// Base::Console().Message("MDIVP::printPreview()\n"); - - if (!m_pagePrinter) { - return; - } - m_pagePrinter->getPaperAttributes(); + auto pageAttr = PagePrinter::getPaperAttributes(getViewProviderPage()); QPrinter printer(QPrinter::HighResolution); printer.setFullPage(true); - if (m_pagePrinter->getPaperSize() == QPageSize::Custom) { - printer.setPageSize(QPageSize(QSizeF(m_pagePrinter->getPageWidth(), m_pagePrinter->getPageHeight()), QPageSize::Millimeter)); + if (pageAttr.pageSize() == QPageSize::Custom) { + printer.setPageSize( + QPageSize(QSizeF(pageAttr.pageWidth(), pageAttr.pageHeight()), QPageSize::Millimeter)); } else { - printer.setPageSize(QPageSize(m_pagePrinter->getPaperSize())); + printer.setPageSize(QPageSize(pageAttr.pageSize())); } - printer.setPageOrientation(m_pagePrinter->getOrientation()); + printer.setPageOrientation(pageAttr.orientation()); QPrintPreviewDialog dlg(&printer, this); connect(&dlg, &QPrintPreviewDialog::paintRequested, this, qOverload(&MDIViewPage::print)); @@ -429,18 +374,6 @@ void MDIViewPage::printPreview() void MDIViewPage::print(QPrinter* printer) { - // Base::Console().Message("MDIVP::print(printer)\n"); - if (!m_pagePrinter) { - return; - } - auto vpp = getViewProviderPage(); - if (!vpp) { - // how did this happen? - return; - } - savePageExportState(vpp); - - m_pagePrinter->getPaperAttributes(); // As size of the render area paperRect() should be used. When performing a real // print pageRect() may also work but the output is cropped at the bottom part. // So, independent whether pageRect() or paperRect() is used there is no scaling effect. @@ -452,7 +385,9 @@ void MDIViewPage::print(QPrinter* printer) // // When showing the preview of a print paperRect() must be used because with pageRect() // a certain scaling effect can be observed and the content becomes smaller. + QPaintEngine::Type paintType = printer->paintEngine()->type(); + auto pageAttr = PagePrinter::getPaperAttributes(getViewProviderPage()); if (printer->outputFormat() == QPrinter::NativeFormat) { QPageSize::PageSizeId psPrtSetting = printer->pageLayout().pageSize().id(); @@ -460,7 +395,7 @@ void MDIViewPage::print(QPrinter* printer) // care if it uses wrong printer settings bool doPrint = paintType != QPaintEngine::Picture; - if (doPrint && printer->pageLayout().orientation() != m_pagePrinter->getOrientation()) { + if (doPrint && printer->pageLayout().orientation() != pageAttr.orientation()) { int ret = QMessageBox::warning( this, tr("Different orientation"), tr("The printer uses a different orientation than the drawing.\n" @@ -470,7 +405,7 @@ void MDIViewPage::print(QPrinter* printer) return; } } - if (doPrint && psPrtSetting != m_pagePrinter->getPaperSize()) { + if (doPrint && psPrtSetting != pageAttr.pageSize()) { int ret = QMessageBox::warning( this, tr("Different paper size"), tr("The printer uses a different paper size than the drawing.\n" @@ -482,17 +417,12 @@ void MDIViewPage::print(QPrinter* printer) } } - if (m_pagePrinter) { - m_pagePrinter->print(printer); - resetPageExportState(vpp); - } - + PagePrinter::print(getViewProviderPage(), printer); } //static routine to print all pages in a document void MDIViewPage::printAll(QPrinter* printer, App::Document* doc) { - // Base::Console().Message("MDIVP::printAll()\n"); PagePrinter::printAll(printer, doc); } @@ -538,14 +468,9 @@ void MDIViewPage::saveSVG(std::string filename) { auto vpp = getViewProviderPage(); if (!vpp) { - // how did this happen? return; } - savePageExportState(vpp); - if (m_pagePrinter) { - m_pagePrinter->saveSVG(filename); - resetPageExportState(vpp); - } + PagePrinter::saveSVG(vpp, filename); } @@ -567,9 +492,7 @@ void MDIViewPage::saveSVG() void MDIViewPage::saveDXF(std::string filename) { - if (m_pagePrinter) { - m_pagePrinter->saveDXF(filename); - } + PagePrinter::saveDXF(getViewProviderPage(), filename); } void MDIViewPage::saveDXF() @@ -590,14 +513,9 @@ void MDIViewPage::savePDF(std::string filename) { auto vpp = getViewProviderPage(); if (!vpp) { - // how did this happen? return; } - savePageExportState(vpp); - if (m_pagePrinter) { - m_pagePrinter->savePDF(filename); - resetPageExportState(vpp); - } + PagePrinter::savePDF(vpp, filename); } void MDIViewPage::savePDF() @@ -614,7 +532,7 @@ void MDIViewPage::savePDF() savePDF(sFileName); } -/// a slot for printing all the pages +/// a slot for printing all the pages. just redirects to printAllPages void MDIViewPage::printAll() { MDIViewPage::printAllPages(); diff --git a/src/Mod/TechDraw/Gui/MDIViewPage.h b/src/Mod/TechDraw/Gui/MDIViewPage.h index 67f90b8726..404347d12c 100644 --- a/src/Mod/TechDraw/Gui/MDIViewPage.h +++ b/src/Mod/TechDraw/Gui/MDIViewPage.h @@ -100,8 +100,6 @@ public: PyObject* getPyObject() override; TechDraw::DrawPage * getPage() { return m_vpPage->getDrawPage(); } ViewProviderPage* getViewProviderPage() {return m_vpPage;} - void savePageExportState(ViewProviderPage* page); - void resetPageExportState(ViewProviderPage* page) const; void setTabText(std::string tabText); @@ -159,11 +157,6 @@ private: QList m_orderedSceneSelection; //items in selection order - void getPaperAttributes(); - PagePrinter* m_pagePrinter; - - bool m_docModStateBeforePrint{false}; - }; class MDIViewPagePy : public Py::PythonExtension diff --git a/src/Mod/TechDraw/Gui/PagePrinter.cpp b/src/Mod/TechDraw/Gui/PagePrinter.cpp index 33ea9b97b8..43ce9c8942 100644 --- a/src/Mod/TechDraw/Gui/PagePrinter.cpp +++ b/src/Mod/TechDraw/Gui/PagePrinter.cpp @@ -56,7 +56,6 @@ #include "QGSPage.h" #include "Rez.h" #include "ViewProviderPage.h" -#include "MDIViewPage.h" using namespace TechDrawGui; using namespace TechDraw; @@ -71,19 +70,6 @@ constexpr double mmPerInch = 25.4; //TYPESYSTEM_SOURCE_ABSTRACT(TechDrawGui::PagePrinter) -PagePrinter::PagePrinter(ViewProviderPage* pageVp) - : m_vpPage(pageVp), m_orientation(QPageLayout::Landscape), - m_paperSize(QPageSize::A4), m_pagewidth(0.0), m_pageheight(0.0) -{ -} - -void PagePrinter::setScene(QGSPage* scene) -{ - m_scene = scene; -} - -void PagePrinter::setDocumentName(const std::string& name) { m_documentName = name; } - //! retrieve the attributes of a DrawPage and its Template PaperAttributes PagePrinter::getPaperAttributes(TechDraw::DrawPage* dPage) @@ -99,144 +85,78 @@ PaperAttributes PagePrinter::getPaperAttributes(TechDraw::DrawPage* dPage) width = pageTemplate->Width.getValue(); height = pageTemplate->Height.getValue(); } - result.pagewidth = width; - result.pageheight = height; + // result.m_pagewidth = width; + // result.m_pageheight = height; //Qt's page size determination assumes Portrait orientation. To get the right paper size //we need to ask in the proper form. QPageSize::PageSizeId paperSizeID = QPageSize::id(QSizeF(std::min(width, height), std::max(width, height)), QPageSize::Millimeter, QPageSize::FuzzyOrientationMatch); - result.paperSize = paperSizeID; + auto paperSize = paperSizeID; - result.orientation = (QPageLayout::Orientation)dPage->getOrientation(); - if (result.paperSize == QPageSize::Ledger) { + auto orientation = (QPageLayout::Orientation)dPage->getOrientation(); + if (paperSize == QPageSize::Ledger) { // Ledger size paper orientation is reversed inside Qt - result.orientation =(QPageLayout::Orientation)(1 - result.orientation); + orientation = (QPageLayout::Orientation)(1 - orientation); } - return result; + return {orientation, paperSize, width, height}; } -void PagePrinter::getPaperAttributes() +//! retrieve the attributes of a DrawPage by its viewProvider +PaperAttributes PagePrinter::getPaperAttributes(ViewProviderPage* vpPage) { - PaperAttributes attr = getPaperAttributes(m_vpPage->getDrawPage()); - m_pagewidth = attr.pagewidth; - m_pageheight = attr.pageheight; - m_paperSize = attr.paperSize; - m_orientation = attr.orientation; + auto page = vpPage->getDrawPage(); + return getPaperAttributes(page); } + //! construct a page layout object that reflects the characteristics of a DrawPage -//static void PagePrinter::makePageLayout(TechDraw::DrawPage* dPage, QPageLayout& pageLayout, double& width, double& height) { PaperAttributes attr = getPaperAttributes(dPage); - width = attr.pagewidth; - height = attr.pageheight; - pageLayout.setPageSize(QPageSize(attr.paperSize)); - pageLayout.setOrientation(attr.orientation); + width = attr.pageWidth(); + height = attr.pageHeight(); + pageLayout.setPageSize(QPageSize(attr.pageSize())); + pageLayout.setOrientation(attr.orientation()); pageLayout.setMode(QPageLayout::FullPageMode); pageLayout.setMargins(QMarginsF()); } -/// print the Page associated with the parent MDIViewPage as a Pdf file -void PagePrinter::printPdf(std::string file) -{ - // Base::Console().Message("PP::printPdf(%s)\n", file.c_str()); - if (file.empty()) { - Base::Console().Warning("PagePrinter - no file specified\n"); - return; - } - // set up the pdfwriter - auto filespec = Base::Tools::escapeEncodeFilename(file); - filespec = DU::cleanFilespecBackslash(filespec); - QString outputFile = Base::Tools::fromStdString(filespec); - QPdfWriter pdfWriter(outputFile); - QPageLayout pageLayout = pdfWriter.pageLayout(); - auto marginsdb = pageLayout.margins(QPageLayout::Millimeter); - QString documentName = QString::fromUtf8(m_vpPage->getDrawPage()->getNameInDocument()); - pdfWriter.setTitle(documentName); - // default pdfWriter dpi is 1200. - - // set up the page layout - auto dPage = m_vpPage->getDrawPage(); - double width = A4Heightmm;//default to A4 Landscape 297 x 210 - double height = A4Widthmm; - makePageLayout(dPage, pageLayout, width, height); - pdfWriter.setPageLayout(pageLayout); - marginsdb = pageLayout.margins(QPageLayout::Millimeter); - - // first page does not respect page layout unless painter is created after - // pdfWriter layout is established. - QPainter painter(&pdfWriter); - - // render the page - m_scene->setExportingPdf(true); - QRectF sourceRect(0.0, Rez::guiX(-height), Rez::guiX(width), Rez::guiX(height)); - double dpmm = pdfWriter.resolution() / mmPerInch; - int twide = int(std::round(width * dpmm)); - int thigh = int(std::round(height * dpmm)); - QRect targetRect(0, 0, twide, thigh); - renderPage(m_vpPage, painter, sourceRect, targetRect); - m_scene->setExportingPdf(false); -} - - -/// print the Page associated with the parent MDIViewPage -void PagePrinter::print(QPrinter* printer) -{ -// Base::Console().Message("PP::print(printer)\n"); - QPageLayout pageLayout = printer->pageLayout(); - - TechDraw::DrawPage* dp = m_vpPage->getDrawPage(); - double width = A4Heightmm;//default to A4 Landscape 297 x 210 - double height = A4Widthmm; - makePageLayout(dp, pageLayout, width, height); - printer->setPageLayout(pageLayout); - - QPainter painter(printer); - - QRect targetRect = printer->pageLayout().fullRectPixels(printer->resolution()); - QRectF sourceRect(0.0, Rez::guiX(-height), Rez::guiX(width), Rez::guiX(height)); - renderPage(m_vpPage, painter, sourceRect, targetRect); -} - -//static routine to print all pages in a document +//! print all pages in a document void PagePrinter::printAll(QPrinter* printer, App::Document* doc) { - Base::Console().Message("PP::printAll()\n"); - QPageLayout pageLayout = printer->pageLayout(); std::vector docObjs = doc->getObjectsOfType(TechDraw::DrawPage::getClassTypeId()); auto firstPage = docObjs.front(); auto dPage = static_cast(firstPage); - double width = A4Heightmm;//default to A4 Landscape 297 x 210 + double width = A4Heightmm; // default to A4 Landscape 297 x 210 double height = A4Widthmm; makePageLayout(dPage, pageLayout, width, height); printer->setPageLayout(pageLayout); QPainter painter(printer); + auto ourDoc = Gui::Application::Instance->getDocument(doc); + auto docModifiedState = ourDoc->isModified(); + bool firstTime = true; for (auto& obj : docObjs) { Gui::ViewProvider* vp = Gui::Application::Instance->getViewProvider(obj); if (!vp) { - continue;// can't print this one + continue; // can't print this one } auto* vpp = dynamic_cast(vp); if (!vpp) { - continue;// can't print this one + continue; // can't print this one } - // is there always a mdi when printAll is called? - auto mdi = vpp->getMDIViewPage(); - mdi->savePageExportState(vpp); auto dPage = static_cast(obj); - double width = A4Heightmm;//default to A4 Landscape 297 x 210 + double width = A4Heightmm; // default to A4 Landscape 297 x 210 double height = A4Widthmm; makePageLayout(dPage, pageLayout, width, height); printer->setPageLayout(pageLayout); @@ -247,25 +167,27 @@ void PagePrinter::printAll(QPrinter* printer, App::Document* doc) firstTime = false; QRectF sourceRect(0.0, Rez::guiX(-height), Rez::guiX(width), Rez::guiX(height)); QRect targetRect = printer->pageLayout().fullRectPixels(printer->resolution()); - renderPage(vpp, painter, sourceRect, targetRect); - mdi->resetPageExportState(vpp); + dPage->redrawCommand(); } + + ourDoc->setModified(docModifiedState); } -//static routine to print all pages in a document to pdf +//! print all pages in a document to pdf void PagePrinter::printAllPdf(QPrinter* printer, App::Document* doc) { - // Base::Console().Message("PP::printAllPdf()\n"); double dpmm = printer->resolution() / mmPerInch; QString outputFile = printer->outputFileName(); QString documentName = QString::fromUtf8(doc->getName()); QPdfWriter pdfWriter(outputFile); - // setPdfVersion sets the printed PDF Version to comply with PDF/A-1b, more details under: https://www.kdab.com/creating-pdfa-documents-qt/ - // but this is not working as of Qt 5.12 - //printer->setPdfVersion(QPagedPaintDevice::PdfVersion_A1b); - //pdfWriter.setPdfVersion(QPagedPaintDevice::PdfVersion_A1b); + + // setPdfVersion sets the printed PDF Version to comply with PDF/A-1b, more details under: + // https://www.kdab.com/creating-pdfa-documents-qt/ but this is not working as of Qt 5.12 + // printer->setPdfVersion(QPagedPaintDevice::PdfVersion_A1b); + // pdfWriter.setPdfVersion(QPagedPaintDevice::PdfVersion_A1b); + pdfWriter.setTitle(documentName); pdfWriter.setResolution(printer->resolution()); QPageLayout pageLayout = printer->pageLayout(); @@ -285,6 +207,9 @@ void PagePrinter::printAllPdf(QPrinter* printer, App::Document* doc) // start() or end() until all the pages are printed. QPainter painter(&pdfWriter); + auto ourDoc = Gui::Application::Instance->getDocument(doc); + auto docModifiedState = ourDoc->isModified(); + bool firstTime = true; for (auto& obj : docObjs) { Gui::ViewProvider* vp = Gui::Application::Instance->getViewProvider(obj); @@ -295,12 +220,9 @@ void PagePrinter::printAllPdf(QPrinter* printer, App::Document* doc) if (!vpp) { continue;// can't print this one } - // is there always a mdi when printAll is called? - auto mdi = vpp->getMDIViewPage(); - mdi->savePageExportState(vpp); - auto scene = vpp->getQGSPage(); - scene->setExportingPdf(true); + auto ourScene = vpp->getQGSPage(); + ourScene->setExportingPdf(true); auto dPage = static_cast(obj); double width{0}; @@ -315,13 +237,16 @@ void PagePrinter::printAllPdf(QPrinter* printer, App::Document* doc) QRectF sourceRect(0.0, Rez::guiX(-height), Rez::guiX(width), Rez::guiX(height)); QRect targetRect(0, 0, width * dpmm, height * dpmm); renderPage(vpp, painter, sourceRect, targetRect); - mdi->resetPageExportState(vpp); + dPage->redrawCommand(); + ourScene->setExportingPdf(true); } + + ourDoc->setModified(docModifiedState); } -//static -//! we don't need the banner page any more + +//! we don't need the banner page any more, but it might become useful again in the future. void PagePrinter::printBannerPage(QPrinter* printer, QPainter& painter, QPageLayout& pageLayout, App::Document* doc, std::vector& docObjs) { @@ -353,11 +278,10 @@ void PagePrinter::printBannerPage(QPrinter* printer, QPainter& painter, QPageLay painter.setFont(savePainterFont);//restore the original font } -//static + void PagePrinter::renderPage(ViewProviderPage* vpp, QPainter& painter, QRectF& sourceRect, QRect& targetRect) { -// Base::Console().Message("PP::renderPage()\n"); //turn off view frames for print bool saveState = vpp->getFrameState(); vpp->setFrameState(false); @@ -381,7 +305,90 @@ void PagePrinter::renderPage(ViewProviderPage* vpp, QPainter& painter, QRectF& s vpp->getQGSPage()->refreshViews(); } -void PagePrinter::saveSVG(std::string file) + +/// print the Page associated with the view provider +void PagePrinter::print(ViewProviderPage* vpPage, QPrinter* printer) +{ + QPageLayout pageLayout = printer->pageLayout(); + + TechDraw::DrawPage* dPage = vpPage->getDrawPage(); + double width = A4Heightmm; // default to A4 Landscape 297 x 210 + double height = A4Widthmm; + makePageLayout(dPage, pageLayout, width, height); + printer->setPageLayout(pageLayout); + + QPainter painter(printer); + + auto ourScene = vpPage->getQGSPage(); + if (!printer->outputFileName().isEmpty()) { + ourScene->setExportingPdf(true); + } + auto ourDoc = Gui::Application::Instance->getDocument(dPage->getDocument()); + auto docModifiedState = ourDoc->isModified(); + + QRect targetRect = printer->pageLayout().fullRectPixels(printer->resolution()); + QRectF sourceRect(0.0, Rez::guiX(-height), Rez::guiX(width), Rez::guiX(height)); + renderPage(vpPage, painter, sourceRect, targetRect); + + ourScene->setExportingPdf(false); // doesn't hurt if not pdf + ourDoc->setModified(docModifiedState); + dPage->redrawCommand(); +} + + +/// print the Page associated with the ViewProvider as a Pdf file +void PagePrinter::printPdf(ViewProviderPage* vpPage, const std::string& file) +{ + if (file.empty()) { + Base::Console().Warning("PagePrinter - no file specified\n"); + return; + } + + auto filespec = Base::Tools::escapeEncodeFilename(file); + filespec = DU::cleanFilespecBackslash(filespec); + + // set up the pdfwriter + QString outputFile = Base::Tools::fromStdString(filespec); + QPdfWriter pdfWriter(outputFile); + QPageLayout pageLayout = pdfWriter.pageLayout(); + auto marginsdb = pageLayout.margins(QPageLayout::Millimeter); + QString documentName = QString::fromUtf8(vpPage->getDrawPage()->getNameInDocument()); + pdfWriter.setTitle(documentName); + // default pdfWriter dpi is 1200. + + // set up the page layout + auto dPage = vpPage->getDrawPage(); + double width = A4Heightmm; // default to A4 Landscape 297 x 210 + double height = A4Widthmm; + makePageLayout(dPage, pageLayout, width, height); + pdfWriter.setPageLayout(pageLayout); + marginsdb = pageLayout.margins(QPageLayout::Millimeter); + + // first page does not respect page layout unless painter is created after + // pdfWriter layout is established. + QPainter painter(&pdfWriter); + + auto ourScene = vpPage->getQGSPage(); + ourScene->setExportingPdf(true); + auto ourDoc = Gui::Application::Instance->getDocument(dPage->getDocument()); + auto docModifiedState = ourDoc->isModified(); + + // render the page + QRectF sourceRect(0.0, Rez::guiX(-height), Rez::guiX(width), Rez::guiX(height)); + double dpmm = pdfWriter.resolution() / mmPerInch; + int twide = int(std::round(width * dpmm)); + int thigh = int(std::round(height * dpmm)); + QRect targetRect(0, 0, twide, thigh); + renderPage(vpPage, painter, sourceRect, targetRect); + + ourScene->setExportingPdf(false); + ourDoc->setModified(docModifiedState); + dPage->redrawCommand(); +} + + +//! save the page associated with the view provider as an svg file +void PagePrinter::saveSVG(ViewProviderPage* vpPage, const std::string& file) { if (file.empty()) { Base::Console().Warning("PagePrinter - no file specified\n"); @@ -390,14 +397,24 @@ void PagePrinter::saveSVG(std::string file) auto filespec = Base::Tools::escapeEncodeFilename(file); filespec = DU::cleanFilespecBackslash(file); QString filename = Base::Tools::fromStdString(filespec); - if (m_scene) { - m_scene->saveSvg(filename); - } + + auto ourScene = vpPage->getQGSPage(); + ourScene->setExportingSvg(true); + auto ourDoc = vpPage->getDocument(); + auto docModifiedState = ourDoc->isModified(); + + ourScene->saveSvg(filename); + + ourScene->setExportingSvg(false); + ourDoc->setModified(docModifiedState); } -void PagePrinter::saveDXF(std::string inFileName) + +//! save the page associated with the view provider as an svg file +// Note: the dxf exporter does not modify the page, so we do not need to reset the modified flag +void PagePrinter::saveDXF(ViewProviderPage* vpPage, const std::string& inFileName) { - TechDraw::DrawPage* page = m_vpPage->getDrawPage(); + TechDraw::DrawPage* page = vpPage->getDrawPage(); std::string PageName = page->getNameInDocument(); auto filespec = Base::Tools::escapeEncodeFilename(inFileName); filespec = DU::cleanFilespecBackslash(filespec); @@ -405,21 +422,23 @@ void PagePrinter::saveDXF(std::string inFileName) Gui::Command::doCommand(Gui::Command::Doc, "import TechDraw"); Gui::Command::doCommand(Gui::Command::Doc, "TechDraw.writeDXFPage(App.activeDocument().%s, u\"%s\")", - PageName.c_str(), filespec.c_str()); + PageName.c_str(), + filespec.c_str()); Gui::Command::commitCommand(); } -void PagePrinter::savePDF(std::string file) +// this one is somewhat superfluous (just a redirect). +void PagePrinter::savePDF(ViewProviderPage* vpPage, const std::string& file) { -// Base::Console().Message("PP::savePDF(%s)\n", file.c_str()); - printPdf(file); + printPdf(vpPage, file); } + PaperAttributes::PaperAttributes() { // set default values to A4 Landscape - orientation = QPageLayout::Orientation::Landscape; - paperSize = QPageSize::A4; - pagewidth = A4Heightmm; - pageheight = A4Widthmm; + m_orientation = QPageLayout::Orientation::Landscape; + m_paperSize = QPageSize::A4; + m_pagewidth = A4Heightmm; + m_pageheight = A4Widthmm; } diff --git a/src/Mod/TechDraw/Gui/PagePrinter.h b/src/Mod/TechDraw/Gui/PagePrinter.h index 720a9723a8..ea43e94090 100644 --- a/src/Mod/TechDraw/Gui/PagePrinter.h +++ b/src/Mod/TechDraw/Gui/PagePrinter.h @@ -51,34 +51,49 @@ class TechDrawGuiExport PaperAttributes { public: PaperAttributes(); -// ~PaperAttributes() = default; + PaperAttributes(QPageLayout::Orientation orientation, + QPageSize::PageSizeId paperSize, + double pageWidth, + double pageHeight) + : m_orientation(orientation) + , m_paperSize(paperSize) + , m_pagewidth(pageWidth) + , m_pageheight(pageHeight) + {} - QPageLayout::Orientation orientation; - QPageSize::PageSizeId paperSize; - double pagewidth; - double pageheight; + QPageLayout::Orientation orientation() const + { + return m_orientation; + } + QPageSize::PageSizeId pageSize() const + { + return m_paperSize; + } + double pageWidth() const + { + return m_pagewidth; + } + double pageHeight() const + { + return m_pageheight; + } + +private: + QPageLayout::Orientation m_orientation; + QPageSize::PageSizeId m_paperSize; + double m_pagewidth; + double m_pageheight; }; class TechDrawGuiExport PagePrinter { public: - explicit PagePrinter(ViewProviderPage *page); - - void print(QPrinter* printer); - void printPdf(); - void printPdf(std::string file); - void printPreview(); - static void printAllPages(); - static void printAll(QPrinter* printer, - App::Document* doc); - static void printAllPdf(QPrinter* printer, - App::Document* doc); - // print banner page is no longer used static void printBannerPage(QPrinter* printer, QPainter& painter, QPageLayout& pageLayout, App::Document* doc, std::vector& docObjs); + static void renderPage(ViewProviderPage* vpp, QPainter& painter, QRectF& sourceRect, @@ -87,45 +102,20 @@ public: QPageLayout& pageLayout, double& width, double& height); - void saveSVG(std::string file); - void saveDXF(std::string file); - void savePDF(std::string file); - - void setDocumentName(const std::string&); - void setScene(QGSPage* scene, QGVPage* view); - void setOwner(MDIViewPage* owner) { m_owner = owner; } - void setScene(QGSPage* scene); - - - TechDraw::DrawPage * getPage() { return m_vpPage->getDrawPage(); } - - ViewProviderPage* getViewProviderPage() {return m_vpPage;} - static PaperAttributes getPaperAttributes(TechDraw::DrawPage* pageObject); - void getPaperAttributes(); - QPageLayout::Orientation getOrientation() const { return m_orientation; } - QPageSize::PageSizeId getPaperSize() const { return m_paperSize; } - double getPageWidth() const { return m_pagewidth; } - double getPageHeight() const { return m_pageheight; } + static PaperAttributes getPaperAttributes(ViewProviderPage* vpPage); -private: - std::string m_objectName; - std::string m_documentName; - QPointer m_scene; - - QString m_currentPath; - ViewProviderPage* m_vpPage; - - QPageLayout::Orientation m_orientation; - QPageSize::PageSizeId m_paperSize; - double m_pagewidth, m_pageheight; - - MDIViewPage* m_owner; + static void print(ViewProviderPage* vpPage, QPrinter* printer); + static void printPdf(ViewProviderPage* vpPage, const std::string& file); + static void printAll(QPrinter* printer, App::Document* doc); + static void printAllPdf(QPrinter* printer, App::Document* doc); + static void saveSVG(ViewProviderPage* vpPage, const std::string& file); + static void saveDXF(ViewProviderPage* vpPage, const std::string& file); + static void savePDF(ViewProviderPage* vpPage, const std::string& file); }; - -} // namespace PagePrinterGui +} // namespace TechDrawGui #endif // TECHDRAWGUI_PAGEPRINTER_H