Commit Graph

4690 Commits

Author SHA1 Message Date
Laurent Trinques 1c09c4e391 Merge pull request #1282 from arummler/formula-improvements
Auto numeration: a lot of changes for elements, condutors, sheets
2026-10-04 11:52:56 +02:00
Laurent Trinques bbb8e5d2e2 Tested in list display on a real project: neighbouring references on the same row were raised alternately (980 / 927 / 980...) although nothing visibly overlapped.
Linux build and tests / Build and test (Qt 6, Debug) (push) Failing after 1m52s
Cause: in list mode `drawAsContacts()` adds a margin (`adjust(-30, -4, 4, 4)`) to `boundingRect()`, and the horizontal test in `stackAtBottom()` uses that rect. Two lists overlapping only inside the empty margin (1.4 units in my log) count as overlapping. `gap` only changes how far the raised ones move, not which ones.

Fix: test the content only in list mode (`rect.adjust(30, 0, -4, 0)`), with the two margins as constants shared with `drawAsContacts()`.

Result: all references stay at the bottom (980 -> 980), none raised by mistake, also when moving an element sideways.

Checked: [to complete: same-column coils in list mode still stack, cross mode unchanged]
2026-10-04 09:32:12 +02:00
Laurent Trinques ac2f360910 Merge pull request #1302 from ispyisail/fix/1252-parttext-align-while-typing
Fix #1252: aligned static text drifts while typing in the element editor
2026-10-04 07:38:51 +02:00
Laurent Trinques 7bd9979777 Merge pull request #1303 from ispyisail/fix/text-group-dangling-xref-connection
Fix a crash in Project properties after a text group is deleted
2026-10-04 07:37:27 +02:00
Laurent Trinques faa0ca92a5 Merge pull request #1301 from ispyisail/fix/zoom-content-hidden-items
Fix #1281: Zoom to content includes hidden wire texts
2026-10-04 07:35:52 +02:00
Laurent Trinques 8a275be6da Merge pull request #1299 from ispyisail/fix/1280-junction-dot-potential
Fix #1280: missing junction dot where wires share a line
2026-10-04 07:34:46 +02:00
ispyisail e055438f30 Fix a crash when cross-reference settings change after a text group is deleted
A text group kept at the bottom of the page, on a master element,
connects to its project's XRefPropertiesChanged with a lambda that has
no context object. The connection belongs to the project, so it
outlives the group: once the group is deleted (paste a coil, undo,
then make any other edit), changing a cross-reference setting in the
project properties calls QTimer::singleShot() on the freed group and
QElectroTech crashes.

Pass the group as the context of that connection and of the
linkedElementChanged one beside it, so Qt removes both when the group
goes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 14:59:10 +13:00
ispyisail 9d7fac1f53 Element editor: keep a static text's alignment while typing (#1252)
startEdition() records the bounding rect, but the aligned point was only
restored in endEdition(), so a right/centre/bottom-aligned text grew from
its old left/top edge while being typed into and jumped into place when
the edition ended. Re-anchor after every content change during inline
edition.

endEdition() now always clears previous_text, which marks an edition in
progress. It used to stay set after an edition that left the text
unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 12:06:55 +13:00
Andre Rummler 8eb2024bb1 Fix jump to element search. 2026-10-04 01:04:44 +02:00
ispyisail cbacd2bb62 Merge pull request #1283 from jp2images/svg-icons-c
Linux build and tests / Build and test (Qt 6, Debug) (push) Failing after 1m39s
Finish the SVG icons and fix the icon licenses in ico/copyright (#1063, #1269)
2026-10-04 11:45:07 +13:00
ispyisail 2ff0f0d860 Merge pull request #1300 from arummler/fix-qobject
Fix missing Q_OBJECT
2026-10-04 11:44:13 +13:00
ispyisail 6f5db879c1 Zoom to content: count only visible items
itemsBoundingRect() also counts hidden items. The text of a single-line
wire, and the wire texts hidden by "one text per potential", are never
positioned again and can sit far outside the drawing, so Zoom to content
zoomed out to include them. On photovoltaique.qet 14 such texts reach
x = -729 and the zoom covered 2421x924 instead of 1135x648.

Add Diagram::visibleItemsBoundingRect() and use it for Zoom to content,
the scene rect and the borderless export. Zoom to content now goes through
zoomToRect(), which re-centres after the scroll bars appear; before, the
view could stay scrolled to the top-left with part of the content cut off.

Fixes #1281

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 11:23:26 +13:00
Andre Rummler 30281032e4 Fix missing Q_OBJECT. Required to pull declaration into the header. 2026-10-04 00:11:38 +02:00
ispyisail bec0f1c7b4 Fix #1280: junction dot missing where a wire's corner meets a wire it is not wired to
A conductor draws a junction dot at each of its bends that lies on
another conductor. It only looked at the conductors on its own two
terminals, so a bend lying on a conductor of the same potential that
shares no terminal with it got no dot. Dragging the horizontal parts of
a chain of conductors onto one line, as in the report, does exactly that.

Look at every conductor of the potential on the folio instead
(relatedPotentialConductors(false)). The folio scene uses NoIndex, so a
scene lookup at each bend scans every item and made export of the
366-conductor Polonez example 60% slower; walking the potential costs
nothing measurable there (2.08 s vs 2.11 s) or on a 153-conductor
potential (0.97 s both).

The test for one other conductor moves into bendMakesJunction(). It
also stops a point being appended once per matching segment: master drew
the dot above K2 in the fixture ten times.

Across the 23 examples (133 folios) exported to SVG, 6 dots are added,
all at T-joints that had none, and none removed.

tst_junctiondots exports fixtures/junction_dot_shared_potential.qet and
checks for both dots; it fails on master with the dot above K3 missing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 10:57:27 +13:00
ispyisail 69aed0cf84 Merge pull request #1287 from ispyisail/fix/xref-bottom-stack
Fix cross-references printing over each other at the folio bottom (#1178)
2026-10-04 10:55:24 +13:00
ispyisail 30d29b933a Stack cross-references snapped to the bottom of a folio instead of overlapping (#1178)
With "snap to bottom", each master's cross was centred under it at the
bottom of the folio on its own, so two coils in one column drew their
crosses on the same spot and the references printed over each other.

The crosses of a folio are now placed together: when two would overlap,
the one of the higher element goes above the other, so a column of
coils gets its crosses in the same order. Crosses that do not overlap
stay where they were. Moving an element sideways now re-places them
too, since it can move a cross into or out of another's column.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 08:54:13 +13:00
ispyisail ef96b7d948 Give a repeatable PDF the same document id however the project was made (#1178)
With SOURCE_DATE_EPOCH set, the document id came from the project's uuid
and a hash of the .qet file. A project generated again from the same
data has new uuids, so its PDF differed in the id alone (XMP DocumentID
and trailer /ID, 120 bytes) although every page was the same.

Qt now writes a fixed placeholder id, and once the file is written the
placeholder is replaced with an id derived from the bytes of the PDF:
the same pages give the same id. Same length, so no offset changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 08:54:13 +13:00
Jeff Patterson da90cb8452 Served the remaining Breeze icons from ico/breeze and dropped unused icon files (#1269)
The search panel's close button and the five KDE Breeze icons that sat in
ico/breeze-icons/ now come from ico/breeze/, with 16, 22 and 32 px art.
André's three SVGs moved from ico/generated/ to ico/scalable/. Removed the
18 .svgz files and the QETIcon and QETOxygenLogo icons nothing used.
2026-10-03 12:20:38 -05:00
Andre Rummler d76f3528ae AutoNum: a lot of changes
Schemas now get saved with a UUID and do not have to be looked up according to the form. They can be renamed and it gets reflected in existing elements. The GUI for
editing them is now much easier, e.g. forms can be reshuffled. A formula can be applied. Many options now also for conductors and sheets.
2026-10-03 18:09:33 +02:00
Laurent Trinques 3bf1a7b86b Merge pull request #1273 from ispyisail/feature/wires-per-terminal-chains
Linux build and tests / Build and test (Qt 6, Debug) (push) Failing after 1m48s
Wire terminals in a chain, not a star, under a wire limit
2026-10-03 16:56:02 +02:00
Laurent Trinques 389fd454da Merge pull request #1278 from ispyisail/fix/301-dxf-picture-warning
Fix DXF export warning about pictures hidden by View > Show (#301)
2026-10-03 16:38:42 +02:00
Laurent Trinques dedd3b6d03 Merge pull request #1272 from ispyisail/feature/wires-per-terminal
Add an optional limit on wires per terminal (discussion #1158)
2026-10-03 16:35:10 +02:00
ispyisail 9e3376919c Merge branch 'feature/wires-per-terminal' into feature/wires-per-terminal-chains
# Conflicts:
#	sources/wiringrules.cpp
2026-10-04 01:43:37 +13:00
ispyisail 3150b42087 Warn with a pop-up, not a box, when a wires-per-terminal rule is turned on
Review of #1272: scorpio810 asked for a warning box for users; the inline
box added in 9a55939bb is replaced by a pop-up, as the element editor
gives for unnamed terminals. When OK in Settings > General or in Project
properties turns a rule on (a limit where there was none, or one wire
per folio report), a warning says the rules are experimental, may change
with settings to redo if wires and conductors become separate objects,
and can all be turned off in Settings > General. OK goes on. Changing a
limit that was already on, or turning rules off, shows nothing.

tst_wiringrules: when the warning is due (WiringRules::turnsRuleOn()).
Checked in the GUI from both pages, and that a plain OK shows nothing.

English for translators: "Warning"; "The wires-per-terminal rules are an
experimental feature. They count wires as QElectroTech represents them
today. They could change, and your settings need redoing, if wires and
conductors become separate objects in a future version. All these rules
can be turned off in Configure QElectroTech > General."

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015FPuYPS4T7QuEwjNu22rXD
2026-10-04 01:43:21 +13:00
ispyisail fc4e589d60 View > Show: no DXF picture warning when pictures are hidden
The DXF export warns that pictures become outlines. Pictures hidden by
View > Show are left out of the export, so they no longer trigger it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 01:32:03 +13:00
ispyisail 79b595d66d Merge branch 'feature/wires-per-terminal' into feature/wires-per-terminal-chains 2026-10-04 01:13:09 +13:00
ispyisail 9a55939bb4 Warn that the wires-per-terminal rules are experimental
Review of #1272 (scorpio810, after arummler's note that the rules would
need redesigning if wires and conductors become separate objects): a
warning box, with the standard warning icon, at the top of the rules in
Settings > General and in Project properties. It says the feature is
experimental, counts wires as QElectroTech models them today, and that
the rules, and the user's settings, could change if wires and conductors
are separated.

English for translators: "Experimental feature. These rules count wires
as QElectroTech represents them today; they could change, and your
settings need redoing, if wires and conductors become separate objects
in a future version."

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015FPuYPS4T7QuEwjNu22rXD
2026-10-04 01:13:09 +13:00
Laurent Trinques 5044d3d235 Merge pull request #1270 from ispyisail/fix/script-delete-element-wires
Fix qet.deleteElement() leaving the symbol's wires in the project
2026-10-03 13:54:21 +02:00
ispyisail 17e9f53b81 View > Show: keep the wire text of a potential when its wire is deleted
With "one text per potential", deleting the wire that carries the text
moves it to another wire of the potential, but only if the text
isVisible(). While wire texts were hidden by View > Show none was, so the
text was never moved and the potential came back with no text.

ShownKinds::wantsVisible() also counts a text hidden only by its kind.
Also drop the always-true/false enum range checks clang warned about.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 00:07:16 +13:00
ispyisail efd37538e0 Settings > General: widen the wire limit box so "Sans limite" fits
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015FPuYPS4T7QuEwjNu22rXD
2026-10-03 23:51:14 +13:00
ispyisail b5845b44a3 Merge branch 'feature/wires-per-terminal' into feature/wires-per-terminal-chains 2026-10-03 23:51:14 +13:00
ispyisail 3a04a42da8 Merge branch 'feature/wires-per-terminal' into feature/wires-per-terminal-chains
# Conflicts:
#	tests/qttest/tst_wiringrules.cpp
2026-10-03 23:17:49 +13:00
ispyisail 7ba820f8f0 Set the wires-per-terminal limits for the application, a project can override
The limits were per project only. They are now set once in Settings >
General, under the master switch: the most wires per terminal and "one
wire per folio report". Every project follows them.

Project properties > "Conducteurs par borne" gets "Utiliser les réglages
de l'application", ticked by default, showing the application's values
greyed. Unticked, the project keeps its own values, saved in the project
as before, so a drawing that needs its own limit carries it to any
computer. A project's own "no limit" overrides an application limit too.

QETProject::wiringRules() now returns the rules in force (the project's
own, or the application's), so the code that checks a wire is unchanged;
projectWiringRules() returns what the project itself stores. A project
that follows the application still writes nothing, so it saves exactly as
before.

tst_wiringrules: which rules win, the save round trip of a project's own
"no rule", and through the real binary that the application's limit
refuses a wire unless the project overrides it or the master switch is
off (checked to fail with the application's rules ignored). ctest 55/55.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015FPuYPS4T7QuEwjNu22rXD
2026-10-03 23:16:43 +13:00
ispyisail 2e2801b617 Fix qet.deleteElement() leaving the element's wires on the folio
qet.deleteElement() built its DeleteQGraphicsItemCommand from the element
alone. The Delete key's selection also carries the wires on the element's
terminals (DiagramContent's conductors to update), and the command removes
those with it. From a script they stayed: still listed by
qet.conductorUuids(), still saved, attached to an element that was gone.

The wires on the element's terminals now go into the command, as for the
Delete key. tst_scriptconductoruuid checks that no wire is left with an
end on the deleted element (it failed before this change: 1 left).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015FPuYPS4T7QuEwjNu22rXD
2026-10-03 22:26:51 +13:00
ispyisail 5d27ed8156 Wire terminals one after another under a wires-per-terminal limit
Discussion #1158, stacked on the limit itself. Two of QElectroTech's own
tools wire several terminals as a star, every terminal to one of them:
"create wires in a drawn polygon" (also qet.addConductor()), and deleting
a symbol, which rewires the far ends to keep the potential. Six terminals
give the hub five wires, which the project's limit forbids.

When the project sets a limit (and the master switch is on), both now
wire the terminals one after another instead, from the top left one to
the nearest not yet wired (WiringRules::chainOrder()). The polygon tool
also skips a wire whose terminal is already full. Without a limit, both
build the star as before.

tst_wiringrules: the chain order, and through the real binary that
deleting a symbol wired to four others leaves them with at most two
wires each under a limit, three on one of them without (checked to fail
with chaining turned off).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015FPuYPS4T7QuEwjNu22rXD
2026-10-03 21:49:06 +13:00
ispyisail ee8e7c3450 Fix qet.deleteElement() leaving the element's wires on the folio
qet.deleteElement() built its DeleteQGraphicsItemCommand from the element
alone. The Delete key's selection also carries the wires on the element's
terminals (DiagramContent's conductors to update), and the command removes
those with it. From a script they stayed: still listed by
qet.conductorUuids(), still saved, attached to an element that was gone.

The wires on the element's terminals now go into the command, as for the
Delete key. tst_scriptconductoruuid checks that no wire is left with an
end on the deleted element (it failed before this change: 1 left).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015FPuYPS4T7QuEwjNu22rXD
2026-10-03 21:49:06 +13:00
ispyisail 20e134f2bd Add a wires-per-terminal limit, with an application master switch
Discussion #1158: a real terminal takes one or two wires (four with
double ferrules), a folio report is a virtual point that carries one, but
QElectroTech lets any number of wires be connected anywhere.

Project properties > General gets a "Conducteurs par borne" group:
- the most wires a terminal may take (0, the default, is no limit);
- "one wire per folio report".
When set, a new wire that would go past the limit is refused: the
terminal shows red while dragging, as for any refused link, and a tooltip
says why on release. Auto-connect on placing, moving or multi-pasting a
symbol skips full terminals, and qet.addConductor() refuses with its own
message. Wires already drawn, opening, pasting and undo are never
refused.

Settings > General gets a master switch, on by default, that turns every
rule of this feature off in every project; the project group is greyed
with a note while it is off.

The rules live in wiringrules.cpp. The project setting is saved as
<wiring_rules .../> only when a rule is on, so a project that never used
it saves exactly as before; an older version drops it, which means "off".

tst_wiringrules covers the rules, the save round trip and, through the
real binary, that a wire past the limit is refused unless the master
switch is off (checked to fail with the limit check removed).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015FPuYPS4T7QuEwjNu22rXD
2026-10-03 21:42:12 +13:00
ispyisail 649f06b3b8 Add View > Show to hide texts, shapes, pictures by kind (bugtracker #301)
A submenu under View (Affichage > Afficher) with one tick per kind:
symbol texts, wire texts, free texts, shapes, pictures, tables and
cross-references. Unticking one hides it on every folio of every open
project; the status bar says how many kinds are hidden. Session only,
not saved in the project.

Each item is tagged with its kind by its constructor (ShownKinds::tag),
so an item created while its kind is hidden starts hidden whatever
created it. A tag rather than type(): the cross-reference under a
contact's label is a plain QGraphicsTextItem.

Items that already hide themselves (wire text switched off, one text per
potential, a cross-reference snapped elsewhere) now go through
ShownKinds::setVisible(): the kind state can only veto a show, and
apply() re-shows only what it hid itself (hidden_key), never what an
item hid. Conductor::updateTextVisibility() replaces the same visibility
rule pasted in diagrampropertiesdialog.cpp and qetscriptapi.cpp.

Hidden items are not selectable (Qt), so Select All, copy and delete
skip them. Print, PDF and image export render the scene and leave them
out; the DXF export walks items itself and skips them through
ShownKinds::isHidden(). CrossRefItem::linkedChanged() keeps following
its slaves while hidden only by kind, so its label is right when shown.

Known limitation: QGraphicsScene::itemsBoundingRect() still counts hidden
items, so Zoom to fit and borderless image export keep their space.

Verified: tst_shownkinds (12 cases, two mutation checks) and ctest 55/55;
GUI hide/show of symbol texts, wire texts (incl. one text per potential),
free texts, shapes and cross-references returns pixel-identical folios;
with nothing hidden, --export-dxf of the 24 examples is byte-identical to
master (133 files) and --export-pdf renders identically (133 pages).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015FPuYPS4T7QuEwjNu22rXD
2026-10-03 19:44:12 +13:00
ispyisail cc23cf820f Scripting: add terminalPosition() and conductorPath()
A script laying out a drawing could read where a symbol is
(elementGeometry) but not where its terminals are, so it could not place
one symbol with a terminal exactly in line with another's -- the one
thing that makes the wire between them straight. And it could read a
wire's drawn path only through conductorSegments(), which names the wire
by a terminal and so refuses any terminal carrying two wires: 282 of the
3120 wires in the shipped examples.

terminalPosition(folio, element, terminal) returns where a wire docks on
the terminal, in folio coordinates, and which way it leaves (n/e/s/w,
the element's rotation included). conductorPath(folio, uuid) returns any
wire's drawn path as points, by its uuid.

tst_scriptlayoutreads checks the two against each other on every wire of
a fixture: each path starts and ends where its terminals' positions say,
and leaves each the way it faces; where conductorSegments() can name a
wire, both give the same points; and a quarter turn turns the facing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015FPuYPS4T7QuEwjNu22rXD
2026-10-03 13:26:34 +13:00
ispyisail 18568dfd53 Merge pull request #1263 from ispyisail/fix/1238-empty-xrefpos
Linux build and tests / Build and test (Qt 6, Debug) (push) Failing after 1m59s
Fix #1238: cross-reference drawn over the contact's label
2026-10-03 11:01:58 +13:00
ispyisail 9749985089 Fix #1238: cross-reference drawn over the label in older projects
XRefProperties read the stored cross-reference position with
QMetaEnum::keyToValue() and cast the result straight to
Qt::AlignmentFlag. An empty value gives -1. Earlier versions saved
xrefpos="" into projects and the settings file (18 of the 29 shipped
examples that carry cross-reference settings have it), and -1 matches
no branch of DynamicElementTextItem::setXref_item(), so the
cross-reference stayed at (0,0): the top-left corner of the label,
on top of it.

fromXml() fell back to AlignBottom only when the attribute was
missing, and fromSettings() only when the key was missing (#296), so
an empty value kept producing the bad position and was saved back
empty on every save.

Both now go through one helper that returns AlignBottom for an empty,
unknown, or not-offered value. The next save writes "AlignBottom", so
affected projects heal once resaved.

tst_xrefpos covers fromXml(), fromSettings() and the rewrite on save;
it fails 5 of 14 cases without this change. Exporting
examples/2612_ats_singlephase.qet to SVG before and after shows every
slave cross-reference moving from over its label to below it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ELKpbGxqJd7EFiTUypBtVe
2026-10-03 10:18:06 +13:00
Laurent Trinques e1f14e4b2f Merge pull request #1258 from ispyisail/fix/route-close-symbols
Fix wire routing looping between close symbols (#1178)
2026-10-02 23:15:33 +02:00
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
Laurent Trinques ff64fdcb00 Merge pull request #1256 from ispyisail/fix/route-review-followups
Fix the follow-ups from the review of wire routing (#1245)
2026-10-02 23:14:51 +02:00
Laurent Trinques e42d09da45 Merge pull request #1255 from ispyisail/fix/pdf-link-order
Fix PDF cross-reference links coming out in a different order each run
2026-10-02 23:14:31 +02:00
Laurent Trinques 12ca26420b Merge pull request #1262 from ispyisail/fix/cli-common-elements-dir
Fix --common-elements-dir being ignored by --run and the export
2026-10-02 23:06:15 +02:00
Laurent Trinques 7d61acebd9 Merge pull request #1260 from ispyisail/fix/live-mode-polish
Fix live mode's English text, settings path and screenshot (#1178)
2026-10-02 23:02:54 +02:00
Laurent Trinques 69a71d775f Merge pull request #1254 from ispyisail/fix/settings-dir-macos
Fix #1246: QET_SETTINGS_DIR reads the wrong folder on macOS
2026-10-02 22:58:14 +02:00
ispyisail 5ed5eb82ee Honour --common-elements-dir and the other folder options in headless runs
Reported on #1178. Two things kept --common-elements-dir from working for
--run and the command-line export:

- main() runs both before QETApp exists, and only QETApp::parseArguments()
  applied the folder options, so they were ignored. The application of
  those options is now QETApp::applyDirectoryArguments(), static, and the
  two headless branches call it too. They also drop the options from the
  arguments they pass on: the export reads its project and output by
  position, so "--export-pdf --common-elements-dir=X p.qet out.pdf" took
  the option for the project ("Project not found").
- commonElementsDir() read the saved collection path before the
  command-line one, so a user's own setting beat a folder given for this
  run. The command line now comes first, in the GUI too.

Tested with a --run script adding a symbol that exists only in a given
folder: master fails with or without a saved collection path; this
resolves it, before or after --run, and over a saved path to another
folder. Without the option it still fails, and a saved path to the
folder still works.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ELKpbGxqJd7EFiTUypBtVe
2026-10-03 09:33:24 +13: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