From a219c3f587a5c575a7109ca2b231555431cf8d6c Mon Sep 17 00:00:00 2001 From: Shane Ringrose Date: Thu, 11 Jun 2026 23:40:20 +1200 Subject: [PATCH] CLI: clickable cross-reference hyperlinks in PDF export MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Wire the shared PdfLinks helper into the headless --export-pdf path so CLI-exported PDFs get the same internal cross-reference / folio-report navigation as the GUI print export. For each page, after rendering, the scene-to-page geometry is rebuilt from the QPdfWriter (96 dpi, zero margins, page sized to the diagram so the scale is ~1 with no centering) — deliberately NOT reusing the QPrinter-based mapping — and passed to PdfLinks::injectCrossRefLinks(). After the painter closes, PdfLinks::convertUriToGoTo() rewrites the URI annotations into native GoTo/FitR actions. Builds on the helper extracted in the previous commit; no change to the other CLI tools. --- sources/cli_export.cpp | 55 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/sources/cli_export.cpp b/sources/cli_export.cpp index a6b85e580..ecad24d80 100644 --- a/sources/cli_export.cpp +++ b/sources/cli_export.cpp @@ -23,12 +23,16 @@ #include "dataBase/projectdatabase.h" #include "diagram.h" #include "diagramcontext.h" +#include "pdf_links.h" #include "qetgraphicsitem/conductor.h" #include "qetgraphicsitem/element.h" #include "qetgraphicsitem/terminal.h" #include "qetproject.h" #include "wiringlistexport.h" +// Private Qt PDF engine for drawHyperlink() — see pdf_links / projectprintwindow. +#include + #include #include #include @@ -37,6 +41,8 @@ #include #include #include +#include +#include #include #include #include @@ -44,6 +50,7 @@ #include #include #include +#include namespace { @@ -118,6 +125,12 @@ int exportPdf(QETProject &project, const QString &output) return 1; } + // Page numbers (1-based) for cross-reference hyperlink targets: each + // diagram is exactly one page in the CLI export (no tiling). + QMap pageMap; + for (int i = 0; i < diagrams.size(); ++i) + pageMap.insert(diagrams.at(i), i + 1); + QPdfWriter writer(output); writer.setCreator("QElectroTech"); writer.setResolution(96); @@ -145,8 +158,50 @@ int exportPdf(QETProject &project, const QString &output) const QRectF target(0, 0, writer.width(), writer.height()); renderDiagram(diagram, painter, target); + + // Inject clickable cross-reference / folio-report hyperlinks for this + // page. The geometry is rebuilt from the QPdfWriter (not a QPrinter): + // render() anchors the diagram top-left with KeepAspectRatio, and the + // page is sized to the diagram so the scale is ~1. + if (auto *engine = dynamic_cast(painter.paintEngine())) { + const QRectF source(r); + const qreal s = qMin(target.width() / source.width(), + target.height() / source.height()); + QTransform fit; + fit.translate(target.x(), target.y()); + fit.scale(s, s); + fit.translate(-source.x(), -source.y()); + + // Device pixels -> PDF points, replicating the engine's page matrix + // (72/resolution scale + Y flip; zero margins -> no paint offset). + const qreal pt_scale = 72.0 / writer.resolution(); + const qreal fullH_pt = writer.pageLayout().fullRectPoints().height(); + const bool fullPageMode = + (writer.pageLayout().mode() == QPageLayout::FullPageMode); + const QRect paintPx = + writer.pageLayout().paintRectPixels(writer.resolution()); + + PdfLinks::PageGeometry geom; + geom.sceneToDevice = fit; + geom.target = target; + geom.pageBounds = QRectF(0, 0, target.width(), target.height()); + geom.devToPdf = [=](const QPointF &d) -> QPointF { + qreal dx = d.x(), dy = d.y(); + if (!fullPageMode) { dx += paintPx.left(); dy += paintPx.top(); } + return QPointF(pt_scale * dx, fullH_pt - pt_scale * dy); + }; + geom.sourceRectOf = [](Diagram *dg) { + return QRectF(diagramRect(dg)); + }; + PdfLinks::injectCrossRefLinks(engine, diagram, geom, pageMap, output); + } } painter.end(); + + // Rewrite the URI link annotations into native internal GoTo actions, so + // the cross-references jump inside the document in any PDF viewer. + PdfLinks::convertUriToGoTo(output); + out << "Exported " << diagrams.size() << " page(s) -> " << output << "\n"; return 0; }