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; }