Commit Graph

13 Commits

Author SHA1 Message Date
Laurent Trinques d8add2b8a0 Merge pull request #1257 from ispyisail/feature/pdf-reproducible
Add repeatable PDF export when SOURCE_DATE_EPOCH is set
2026-10-02 23:15:05 +02:00
ispyisail 8361a1efce Build and work on Qt before 6.8
QPdfWriter::setDocumentId() is new in Qt 6.8, QTimeZone::UTC in 6.5 and
QHashSeed in 6.2, so the build failed on Qt 6.4 (Ubuntu 24.04). Qt before
6.8 also writes no /ModDate and no XMP metadata, and setDocumentDate()
then gave up and left the time of the export in the file. Those two are
now rewritten when present, and no document id is set where Qt writes
none.

tst_pdfreproducible also checks that the xref table still matches the
file after the dates are rewritten.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PJw3u5AdKQgQVPug8CzuMQ
2026-10-03 09:30:11 +13:00
ispyisail 51d20abca4 Write the same PDF for the same project when SOURCE_DATE_EPOCH is set
Two exports of one project differed in the creation and modification
dates (the time of the export, in local time) and in the document id
(random). With SOURCE_DATE_EPOCH set (reproducible-builds.org),
--export-pdf now uses the time it names, in UTC, and a document id
derived from the project: version 5 of the project uuid with the
SHA-256 of the project file, so it is the same for the same file and
changes when the file does. Qt has no setter for the dates, so
PdfLinks::setDocumentDate() rewrites them in the document information
and the XMP metadata after the file is written, fixing the XMP /Length
and shifting the xref table. Without the variable nothing changes.

Only --export-pdf reads it; the print window's PDF export does not, as
a person exporting by hand wants the real date.

qet_export (misc/qet-mcp) gains "reproducible" and "source_date_epoch".
It reports whether the build honoured the variable, since an older one
ignores it.

tst_pdfreproducible exports examples/741.qet four times and requires
identical bytes and the epoch's date; it fails with either this change
or the hash seed fix reverted. Projects with cross-reference links also
need their links in a fixed order, which is a separate fix.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 07:50:28 +13:00
ispyisail 8e6dc1a849 Write a PDF's cross-reference links in the same order in every run
injectCrossRefLinks() drew each link as it found it: the contacts of a
cross-reference come from a QMultiMap keyed by Element pointer, and the
scene's items in stacking order. Both change from run to run, so the same
project exported twice gave two different PDFs whose only difference was
the order of the link annotations.

The links are now collected and drawn sorted by their rectangle on the
page (top, left, bottom, right), with the target as the tie-break. The
links themselves are unchanged. The print window's PDF export goes
through the same function.

tst_pdflinkorder exports examples/industrial.qet five times in separate
processes and requires the same links in the same order. It fails on
the old code (lists differ at index 2).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 07:24:46 +13:00
ispyisail 4f309770f0 Fix bugtracker #340: small PDF text drawn too bold in Adobe Acrobat
Qt 6 declares the PDF/X namespace (pdfxid) in the XMP metadata of every
PDF it writes, even when the file is not PDF/X. Adobe Acrobat then draws
small text too bold at some zoom levels. Qt only needs the declaration
for PDF/X-4 output, which QElectroTech never asks for.

Blank the declaration out after export, in place with spaces so no
offsets move, in both the export window and the --export-pdf path.
Diagnosis and the Acrobat testing by Alf, bugtracker #340.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01G2d2Zi8BfrYRPX88zhaoFG
2026-09-25 20:44:02 +12:00
plc-user 2e49f4588a fix problem with PDF-links in files with brackets in name 2026-08-24 18:24:30 +02:00
Laurent Trinques 265ec12351 Merge pull request #739 from Kellermorph/info-box-pdf
Export component info as invisible PDF text annotations
2026-08-20 23:31:09 +02:00
Kellermorph 4572fca31f fix2 2026-08-20 13:30:22 +02:00
Kellermorph b8df298953 fix 2026-08-20 11:21:22 +02:00
Kellermorph f0348a7cd8 fix 2026-08-14 08:58:36 +02:00
Kellermorph 67b1665b36 Export component info as invisible PDF text annotations 2026-08-13 11:54:33 +02:00
Shane Ringrose 206c37f620 cmake(qt6): verify Qt6::GuiPrivate at configure time, drop #warning
<private/qpdf_p.h> (QPdfEngine::drawHyperlink) needs Qt's private GUI
module, previously flagged only by a #warning at compile time.

Qt >= 6.7 ships GuiPrivate as a proper find_package component, but some
distro packages (e.g. Ubuntu's qt6-base-private-dev, Qt 6.8.3) do not
install Qt6GuiPrivateConfig.cmake and only provide the implicit
Qt6::GuiPrivate target created alongside Qt6::Gui. Requesting the
component unconditionally would therefore break distro-Qt builds.

Instead: try the component quietly, then hard-verify the Qt6::GuiPrivate
target exists after the main find_package, failing at configure time
with an actionable message if the private headers are missing. The
compile-time #warning in pdf_links.cpp and projectprintwindow.cpp is
now redundant and removed.

Verified: cmake configure + compile of both translation units on
Ubuntu 25.04 / Qt 6.8.3 (system KF6), cmake configure on Qt 5.15.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-12 12:29:56 +02:00
Shane Ringrose 6b3b55b0e1 PDF links: extract pdf_links.{cpp,h} shared helper
Move the PDF cross-reference hyperlink logic out of ProjectPrintWindow
into a standalone translation unit so it can be reused (the CLI PDF
export will call it next):

- injectCrossRefLinks(): emits the URI link annotations for a diagram's
  cross-references and folio reports. The scene-to-page mapping is passed
  in as a PageGeometry (transform + devToPdf + source-rect lookup) so each
  caller supplies its own correct geometry, rather than the helper assuming
  a QPrinter.
- convertUriToGoTo(): the PDF post-processor, moved verbatim.

ProjectPrintWindow stays a pure caller: it builds its PageGeometry from the
printer page layout exactly as before and calls the helper. No behavioural
change to GUI PDF export; no class-structure changes.

Per review guidance on #483.
2026-06-11 23:48:14 +12:00