PDF export: turn each page to its folio's orientation (#1480)

The print window exported every page in one orientation, landscape
unless changed, so a portrait folio was shrunk onto a landscape page.
With "Fit in page" on, a PDF export now turns each page to portrait or
landscape as its folio is drawn. The preview keeps one orientation
(QPrintPreviewWidget lays out every page at one paper size), and a
printer keeps it too (only Qt's PDF engine accepts a new page layout
once printing has started). The orientation chosen in the window is
put back afterwards, so it is still the one saved.

The cross-reference links took their target from painter->viewport(),
which QPainter sets once when it opens, so on a turned page they missed
their text. They now use the device's size, as render() does.

tst_printpdforientation exports through the window: an A3 landscape and
an A3 portrait folio get one page each way; tiled pages keep the chosen
orientation; and the links on examples/industrial.qet's turned pages
land where they do when the export starts portrait.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
ispyisail
2026-10-14 23:38:00 +13:00
parent 33a731b56f
commit f42958d2c2
4 changed files with 260 additions and 4 deletions
+48 -4
View File
@@ -232,6 +232,20 @@ void ProjectPrintWindow::requestPaint()
}
}
// A PDF export turns each page to its folio's orientation (#1480): a
// portrait folio gets a portrait page instead of being shrunk onto a
// landscape one. Only the real export, with one page per folio: the
// preview draws every page at one paper size, and only Qt's PDF engine
// accepts a new page layout once printing has started.
const bool per_folio_orientation = m_printing
&& m_printer->outputFormat() == QPrinter::PdfFormat
&& ui->m_fit_in_page_cb->isChecked();
const auto chosen_orientation = m_printer->pageLayout().orientation();
const auto diagrams = selectedDiagram();
if (per_folio_orientation && !diagrams.isEmpty()) {
setOrientationForDiagram(diagrams.first());
}
bool first = true;
QPainter painter(m_printer);
int annotIndex = 0;
@@ -245,12 +259,23 @@ void ProjectPrintWindow::requestPaint()
// should be fixed by original author by evaluating function-result!
(void)pdfExport;
for (auto diagram : selectedDiagram())
for (auto diagram : diagrams)
{
first ? first = false : m_printer->newPage();
if (first) {
first = false;
} else {
if (per_folio_orientation) {
setOrientationForDiagram(diagram);
}
m_printer->newPage();
}
printDiagram(diagram, ui->m_fit_in_page_cb->isChecked(), &painter, m_printer, diagramPageMap, annotIndex);
}
if (per_folio_orientation) {
m_printer->setPageOrientation(chosen_orientation);
}
// Note: do NOT call painter.end() or pdfConvertUriToGoTo() here.
// We are inside the paintRequested slot: the QPrintPreviewWidget still
// owns the paint cycle. On macOS arm64 (Metal/CALayer compositor),
@@ -259,6 +284,19 @@ void ProjectPrintWindow::requestPaint()
// pdfConvertUriToGoTo() is deferred to print() via QTimer::singleShot(0).
}
/**
* @brief ProjectPrintWindow::setOrientationForDiagram
* Turn the next page to portrait or landscape, as @diagram is drawn.
* @param diagram
*/
void ProjectPrintWindow::setOrientationForDiagram(Diagram *diagram)
{
const QRect rect = diagramRect(diagram, exportProperties());
m_printer->setPageOrientation(rect.height() > rect.width()
? QPageLayout::Portrait
: QPageLayout::Landscape);
}
/**
* @brief ProjectPrintWindow::printDiagram
* Print @diagram on the @printer
@@ -356,8 +394,12 @@ void ProjectPrintWindow::printDiagram(Diagram *diagram, bool fit_page, QPainter
// est revenu a l'identite ici. On reconstruit DONC explicitement la
// transform appliquee par :
// diagram->render(painter, QRectF(), diagram_rect, KeepAspectRatio)
// cible vide => painter->viewport() ; source = diagram_rect ; centre.
const QRectF target = QRectF(painter->viewport());
// cible vide => taille du device ; source = diagram_rect ; centre.
// The target render() used for an empty one: the device's
// size. Not painter->viewport(), which is set once when the
// painter opens and misses a page turned since (#1480).
const QRectF target(0, 0, painter->device()->width(),
painter->device()->height());
const QRectF source = QRectF(diagram_rect); // meme source que render()
// render() ANCRE en haut-gauche (pas de centrage) :
@@ -852,8 +894,10 @@ void ProjectPrintWindow::print()
const bool isPdf = (m_printer->outputFormat() == QPrinter::PdfFormat);
const QString pdfFile = isPdf ? m_printer->outputFileName() : QString();
m_printing = true;
m_preview->print(); // triggers requestPaint() synchronously; painter
// is created/destroyed inside that call
m_printing = false;
savePageSetupForCurrentPrinter();
savePrintProperties();