Commit Graph

5146 Commits

Author SHA1 Message Date
Laurent Trinques b099c65115 Fix #1562: cross-references settings squeezed on a low screen
On a 1080p screen with display scaling (QT_SCALE_FACTOR=1.25, or
Windows at 125 %), the "Representation" group of the Cross-references
tab in Settings > New project was drawn with its widgets on top of
each other.

The tab widget of that page had a minimum size of 800 x 650 set by
hand. A minimum height set by hand replaces the one computed from the
tabs, so the dialog's scroll area, which is there for low screens,
believed 650 px were enough and never scrolled, while the
cross-references tab needs more. Keep the minimum width only: the
tabs' own minimum height now applies and the dialog scrolls instead.
2026-10-22 16:55:21 +02:00
Laurent Trinques f8e9a1a457 Merge pull request #1582 from ispyisail/fix/1579-changed-on-disk-network-share
Fix #1579: false "changed on disk" warning on network shares
2026-10-22 16:15:56 +02:00
ispyisail 56b24aaa0e Merge pull request #1581 from ispyisail/refactor/autonum-folio-counter
Keep a folio's own numbering counters in the project database
2026-10-22 21:44:58 +13:00
ispyisail 3da3a78850 Fix #1579: no false "changed on disk" warning on a network share
On a CIFS/SMB share every save asked "Someone else changed the file on
disk", because the size and modification time read straight after
saving can be the client's cached values, not the server's final ones,
and the next save demanded an exact match.

The size and time are still the quick check. When they differ, the file
now counts as changed only if its content differs from what this QET
last read or wrote (a SHA-1 kept at open and after each save). A real
change by someone else still asks; the same bytes with a new time do
not.

tst_changedondisk: sameContentNewTimeSaves fails before and passes
after; the two conflict cases now move a symbol so the content really
changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 21:36:24 +13:00
Laurent Trinques 149d92545d Merge pull request #1577 from Kellermorph/integration/terminal-manager-upstream
Linux build and tests / Build and test (Qt 6, Debug) (push) Failing after 2m12s
Terminal strip editor: automatic cable entry, plan order, target box, Target column and speed-ups
2026-10-22 06:01:59 +02:00
ispyisail 6225b20f32 Populate folio_counter rows from the document, not just write-through
Habit 4: a folio that is only parsed, never built into a live
Diagram scene by a numbering edit, still needs its folio_counter
rows. Diagram::folioSequentialsFromXml() now writes the rows it
just parsed, the same way insertFolioSeqHash() does for an edit
made in a built scene.

Adds the fixture used to prove this: folio_counters_multi.qet, 3
folios, an element and a conductor numbering scheme both using a
tenfolio part, exercising insertFolioSeqHash()'s write-through and
this load-time path. Resave-of-resave is byte-identical; ctest
clean on the 4 directly relevant tests.

Found in passing, not fixed here (pre-existing on master, outside
2b-4's scope): the conductor side's folio-sequential XML ends up
saved under <elementautonumfoliosequentials> instead of its own
<conductorautonumfoliosequentials> tag -- the fixture's 'Wires'
scheme reads back with owner=element for exactly that reason.
Worth a FINDINGS entry before anyone trusts the conductor side of
this mechanism.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-22 12:41:37 +13:00
ispyisail 8d5c164d09 Move a folio's numbering counters into the project database
QETZ-DB-FIRST stage 2b-4: the unit/ten/hundred-folio sequential
counters Diagram tracks per numbering scheme (insertFolioSeqHash())
now write through to a new folio_counter table, keyed by
(folio_uuid, owner, level, title, ord). The hashes stay the source
for now, same write-through pattern as 2b-1's numbering rows.
renameElementAutoNum()/AutoNumSchemeCommand::rename() carry the
rows along on a scheme rename.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-22 12:41:36 +13:00
ispyisail f692d2d35a Merge pull request #1578 from ispyisail/refactor/autonum-rows-only
Make the project database the only copy of the numbering schemes
2026-10-22 12:40:23 +13:00
Kellermorph 650e318e02 Answer the terminal strip editor without walking the whole strip
The editor asks its model for every cell of every row, over and over
(paint, flags, row height, resize to contents). Three answers used to
cost far more than the little they tell:

- a row was found by walking m_physical_data each time, which made a
  layout O(rows^2 * columns);
- the bridge cells walked to the head of the strip for each neighbour
  of each step, and every step filled the full row data, which reads
  the cables of the whole project (the target column of the terminal
  strip editor);
- without any bridge on the strip, that walk still ran to its end.

Rows are now found through an index filled once with m_physical_data,
the bridge walk steps from row to row and fills only the three fields
it reads (level, bridge, identity), and it is skipped when the strip
has no bridge at all.

Nothing about what the editor shows, edits or saves changes: the model
data, the bridge pixmaps and the strip order are the same, only the
time to answer is not. Measured on a 302 row strip with one bridge
(20 rounds, offscreen, off the UI): all flags 372 ms to 6.6 ms, all
display cells 1195 ms to 31 ms, all decoration 7623 ms to 106 ms
(a bridge cell 251 us to 2.5 us), about 65 times faster overall.

The full test suite passes (121/121).
2026-10-21 17:42:12 +02:00
ispyisail 2bedfaa394 Fix #1571: collection freezes while another QElectroTech is open
Every QElectroTech on a computer shares elements_cache.sqlite. The
cache set PRAGMA locking_mode = EXCLUSIVE, so a QElectroTech that had
read the file once kept it locked until it closed. A second one -- a
build in another folder, or a build beside a released version, which
SingleApplication lets run because its key includes the program's path
and version -- could not write to it: each write waited SQLite's 5 s
busy timeout and failed, on the GUI thread, twice for every symbol the
collection showed. The report's log is exactly that: an empty
QSqlError every 5.0 s for three minutes.

Use SQLite's normal locking, which holds a lock only while a statement
runs, and give this connection no busy timeout: the cache only saves
time, so a busy file is a cache miss, never a wait. Print the failing
query's error, not the connection's, which was always empty.

Measured with the real program running and a second process writing to
its cache: before, the write fails "database is locked" after 5.01 s;
after, it succeeds in 0.02 s. tst_elementcachelock opens two caches on
one file; it fails before the fix with the report's empty QSqlError.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 22:06:01 +13:00
ispyisail 8ce3b214c1 Merge pull request #1563 from DaTweety/feature/place-symbol-texts
Place symbol texts: label and notes as one block, at one of nine points
2026-10-21 21:46:42 +13:00
ispyisail e7d644003f qetproject: memoize repeated numbering title/id lookups per call
elementAutoNumIdToLink() queried numbering_scheme per symbol even when
many symbols on unbuilt folios share the same scheme; setUpFormula()
fetched the same scheme's rows twice (elementAutoNumCurrentFormula()
then elementAutoNum() separately). Both are real but didn't resolve
the tst_lazyfolios ASan timeout on their own -- see QETZ-DB-FIRST-PLAN.md's
2b-3 row for the remaining open question.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-21 21:43:31 +13:00
ispyisail 122678a797 Keep the project's numbering in the project database only
QETProject no longer holds its numbering schemes and their settings in
hashes and members of its own: every accessor reads and writes the
project database's numbering tables (QETZ-DB-FIRST stage 2b-3), which
the save already writes from. projectDataBase gains per-scheme calls
(numberingSchemes, numberingScheme, setNumberingScheme,
removeNumberingScheme, renameNumberingScheme, the scheme uuid and
title, and the settings); setNumbering() is what reading the file
writes, in one go once it is all read.

QET_CHECK_NUMBERING_ROWS goes: there is one copy left to compare. The
test now checks the scheme list after each change through the script
API, that no part row is left without its scheme, and the saved file.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 21:43:30 +13:00
ispyisail de248eb20a Merge pull request #1555 from DaTweety/fix/element-text-resize-corner
Symbol text width handles: the point the text is aligned on stays in place
2026-10-21 21:41:17 +13:00
ispyisail 76a36bc5e9 Merge pull request #1573 from ispyisail/fix/autonum-increment-width
Fix the Auto numbering Increment boxes cut off on Windows
2026-10-21 21:40:13 +13:00
ispyisail 0e5d4ad990 Merge pull request #1572 from ispyisail/fix/selection-panel-collapse
Shrink the Selection properties panel again when nothing is selected
2026-10-21 21:39:55 +13:00
ispyisail 537e3c3c10 Fix the Increment boxes of the Auto numbering panel cut off on Windows
Each Increment spin box had a fixed maximum width of 55 px. The Windows
11 style puts the up and down arrows side by side, which leaves almost
nothing of 55 px for the number (#1566). The boxes now take the width
their style asks for.

Test: tst_autonumincrementwidth runs the editor under a style that
widens spin boxes the way the Windows 11 style does and checks each
Increment box is at least as wide as the style needs: 55 px against 81
px before this change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 21:26:57 +13:00
ispyisail dc30b26dab Shrink the Selection properties panel again when nothing is selected
#1533 stopped the panel shrinking to its title bar when the selection
had nothing to edit, so that it would keep the height the user gave it
(#1439). Users want the room back for the Collections and Auto numbering
panels while nothing is selected (#1566).

The panel's layout is back to QLayout::SetMaximumSize, so the empty
panel shrinks as before. Just before its last editor goes, the panel
keeps the heights of every docked panel in its area; when an editor
comes back it gives them back with QMainWindow::resizeDocks, the call a
separator drag makes. Giving only this panel its height back fell 35 px
short in the test: the neighbours had been split again from their size
hints and gave up only part of the room.

Test: tst_selectionpanelheight now checks, twice over, that the empty
panel shrinks and that selecting an element again brings back the height
the user gave it. Without the restore the panel comes back at 470 px
instead of 560; on master the empty panel does not shrink.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 21:26:57 +13:00
ispyisail 04ad1c890a Write the project's numbering from the project database
QETZ-DB-FIRST stage 2b-2. The save writes the numbering schemes and
their settings from the project database's numbering rows (2b-1)
instead of the project's own lists. The project still keeps the rows
in step after each change, and QET_CHECK_NUMBERING_ROWS still says
whether the two agree, until the lists go (2b-3).

tst_elementautonumids::numberingRowsFollowEveryChange also checks the
saved file: the current symbol and wire numbering and the schemes. With
setCurrrentElementAutonum() not writing the rows, a save straight after
it now names the old scheme in use.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 14:40:29 +13:00
ispyisail d05cc654ad Keep the project's numbering in the project database too
QETZ-DB-FIRST stage 2b-1. The numbering schemes of wires, symbols,
folios and cables, and the settings saved with them (the scheme in use
of each kind, freezing new labels, auto-break, the cable axis and
question), get three tables of the project database: numbering_scheme,
numbering_part (one row per part, in order) and numbering_setting.
QETProject writes them when it reads its file and after each change of
its numbering, from every setter; nothing reads them yet.

The save writes the numbering through writeNumberingXml(), the code it
had moved out of writeDefaultPropertiesXml(), so the same writer can
take the rows once the save moves to them (2b-2).
QET_CHECK_NUMBERING_ROWS=1 writes the numbering from the project and
from the rows at each save and says whether the two differ.
tst_elementautonumids::numberingRowsFollowEveryChange checks it after
each of 23 changes; with one setter not writing the rows, one save
differs and it fails.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 06:54:49 +13:00
Laurent Trinques 992058348b Report jump: put the mouse pointer on the end jumped to
Linux build and tests / Build and test (Qt 6, Debug) (push) Failing after 1m41s
A double click on a linked folio report showed the other end's folio
and highlighted it, but left the mouse pointer where it was, on every
platform, while only Wayland forbids a program to move it. On Windows,
X11 and macOS the pointer is now put on the end jumped to, once the
folio shown has its size (next turn of the event loop), so that a
second double click jumps back. On Wayland the highlight alone still
shows where the jump landed.

The pointing hand over a report's label text also stayed after a
click: mousePressEvent() puts the text colour back, and the cursor was
only unset with the colour in hoverLeaveEvent(). It is now always
unset when the mouse leaves the text.
2026-10-20 19:42:23 +02:00
Kellermorph 36b1cb08ff Tell the fields of a target apart by line breaks only
A target typed in by hand was split into its fields on " / ", which
broke as soon as a field itself contained a slash: an installation
named "ASP/01" gave the box two lines with half a name in each, and
nothing to tell a separator apart from the name. Only a line break now
breaks the text into fields (RealTerminal::cableTarget()), and the
Target cell shows the fields the very same way, one line each
(modelRealTerminalData::targetText()), so the cell and the box under
the cable always read the same text.

The Target cell is edited line by line to go with that: it takes a
multi line editor where Return writes a new line, Ctrl+Return hands
the cell back to the table and Escape throws the text away
(TerminalStripModelDelegate), and the rows of the table are as tall as
the lines their cell shows, so the fields below the first one are never
cut off -- a cell without a target keeps the row it has always had.

The text copied to the clipboard keeps one line per row, the fields of
such a cell joined with " / " again, or a spreadsheet would take them
for several rows.

tst_terminalcableauto reads the three fields of a target of the
drawing back one line each, checks a "/" typed inside a field stays
part of it -- one line holding it, slashes and all -- checks the
editor of the cell is the multi line one, hands its text back
untouched, gives the cell back on Ctrl+Return while Return keeps
writing a new line, and checks the rows grow with the lines the cell
holds and shrink back afterwards. tst_cabletarget paints a strip whose
cable ends on a field containing a slash: the box is no deeper than
with one plain field.
2026-10-20 19:08:16 +02:00
Kellermorph 5baf5bec60 Set a target box lower when another one is in its way
Two cables of one strip end close to each other, and their boxes are
wider than the room between the two cables: a long Installation is
enough for that, and the two boxes ended up written the one over the
other -- a picture nobody can read, and no way to tell which box
belongs to which cable.

The boxes of a strip are now all measured before any of them is drawn,
and placed from the left to the right: a box which would reach into one
already placed is set just low enough to stand clear of it, its stub
drawn longer. Nothing is cut down to fit -- the text keeps its font and
the box keeps its width, it is the box which moves.

The strip reserves the room for the lower box too, with the same rule
and the very cells the drawing works on (Helpers::cableBoxesExtraDepth
(), both styles now build one list of cells for the painting and for
the reserved depth), so a lower box is never cut off by the drawing
area.

tst_cabletarget paints a strip with one cable ending on a target and
the same strip with a second cable ending on one: the second picture
draws a whole box lower, and the strip is deeper by exactly the room
that lower box needs.
2026-10-20 16:22:15 +02:00
Kellermorph dc92a57873 Add a Target column to the terminal strip editor
Reading where a cable lands meant going back to the drawing: the strip
editor said which cable a terminal carries and which core, but never
what the cable goes to. A single core (1x16) could not be followed
from the terminal to its piece at all.

The new Target column names it: Installation, Location and Label (BMK)
of the piece the wires land on, past this strip, joined in one line --
the very three fields the strip drawing writes in the box under its
cable, in the same order (RealTerminal::cableTarget()). It is worked
out of the project like the Cable cells and so follows their rule: a
target the drawing names is read only, for only the drawing decides
it, and a cell nothing is worked out for takes an edit, so a target
the drawing cannot find -- a cable landing on a piece with no
Installation, Location nor Label set, a cable going to another strip
-- is still worth naming by hand. The text typed in is stored in the
element (RealTerminal::cableTargetInfoKey()) and kept until a cable
works a target out again, and back once that cable goes, exactly like
a cable designation typed by hand: the automatic value is never
written, so no stale text can be left behind. The column takes the
width of its own text, so a long Installation is never cut off.

A text typed in is written the way the fields are shown in the column,
"Installation / Location / Label", and gives one line per field: the
box under the cable draws three lines without any slash in them, just
like a target worked out from the project, instead of one long line
carrying its separators as text.

tst_terminalcableauto checks the column is empty -- and editable --
without a cable, reads "Plant 7 / Cabinet 7 / -S7" with one, goes
empty -- and editable again -- when the core is removed, takes no edit
while the drawing names the target, and is headed "Target"; a second
case checks a target typed in by hand is taken by the cell, stored by
Apply, shown again by a fresh model, set aside for the read only
target of the drawing once a cable lands somewhere worth naming, and
back once that cable goes; a third one the line per field. tst_cable
target paints a strip whose cable ends on one field and the same strip
ending on three, the second box two lines deeper than the first.
2026-10-20 15:34:59 +02:00
DaTweety 1bf076eca8 Width handles: a text is not dragged narrower than its widest word
Narrower, a long word ran out of the text's box while the short lines
were still aligned inside the too narrow width: on a right aligned or
centred text a lone "1" stood in the middle under its words, and moved
on every step. Found on a real plan (-XS20, "Steckdosen Windfang, 1").
The probe checks that no line runs out of the text after narrowing, and
also for a text aligned bottom left.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 10:53:52 +02:00
DaTweety 8f2cd9f039 Width handles: read the drag in the text's coordinates as they were at the press
The text moves on every step of a drag to keep its alignment point in
place. Mapping the mouse with its current transform made the delta grow
with every step, so a right or centre aligned text ran away: 90 px of
mouse gave +1220 px of width. The probe now drags in 30 steps and checks
the width grows by exactly as much as the mouse moved.

Reported by ispyisail in the review of #1555.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 10:01:23 +02:00
DaTweety 214b0e3b7d Width handles keep the point the text is aligned on
Which point of a symbol's text stays in place while its width is
dragged now follows the text's alignment, the nine points of its
alignment dialog, rather than the handle: a text aligned top right
keeps its top right corner whichever handle is dragged, one centred
keeps its middle, and a text that wraps grows away from that point.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 10:01:23 +02:00
DaTweety 52adc8b3f8 Width handles: a text that wraps keeps its top corner in place
Narrowing a symbol's text with the left handle until it wraps onto
more lines moved it up: the point kept in place was the middle of the
opposite edge, and the middle moves down as the text grows. Keep the
top of the opposite edge instead, or the middle or the bottom for a
text aligned that way, for both handles.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 10:01:23 +02:00
DaTweety 74f908aa1e Symbol text width handles: the opposite edge stays in place
Dragging the left width handle of a symbol's text changed its width but
kept its position, which is its left edge: the right edge moved with the
drag and the text jumped away from where the user held it. Now the edge
opposite the dragged handle stays in place, as in a drawing program and
as the corner handles of a free text already do (TextResizeHandles). It
is found along the text's own baseline, so a rotated text behaves the
same. Undo restores width and position together, with TextResizeCommand.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 10:01:23 +02:00
DaTweety f828e464c4 Place symbol texts: undo puts a group's texts back where they lay
Placing a group switches its alignment, which lays its texts out anew.
Undoing to AlignJustify, the default of the "Label and comment" group,
lays out nothing, so the texts stayed at their placed offsets. The
positions of the group's texts are now part of the undo step. The probe
reproduces the case from a group with freely placed texts.

Reported by ispyisail in the review of #1563.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 10:01:17 +02:00
DaTweety 25ffa414af Place symbol texts: bigger bars in the icons, bigger grid buttons
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 10:01:17 +02:00
DaTweety 9c3c19a316 Place symbol texts: the icon shows where the texts go
Each of the nine points has its own icon: a grey square for the symbol
and two bars for the lines of text, where they will go and lined up as
they will be. The grid shows them instead of arrows, and the toolbar
button takes the icon of the point chosen last, so that one sees where
a click on it puts the texts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 10:01:17 +02:00
DaTweety 0a577eaabf Place symbol texts: label and notes as one block, at one of nine points
A new command, "Place symbol texts", for the selected symbols: their
label and the notes beside it go as one block next to the drawing of
the symbol, 3 px away, at one of the nine points of the text alignment
dialog, chosen in a 3 x 3 grid that opens from the toolbar button and
from the Edit menu. A click on the button places them at the point
chosen last (left of the symbol at first).

Left of the symbol the lines are aligned right, so that they hang on it
and a longer text grows away from it (their alignment is set too);
right of it aligned left; above, below and on it centred. The lines
keep their order and their spacing, a group of texts is placed as one
line with the same alignment, a turned symbol is placed in the folio's
directions, and everything is one undo step.

Element::drawingRect() gives the area the drawing covers, tighter than
the bounding rect, which is rounded up to the grid. A toolbar command
with a menu now shows as a button with an arrow beside it.
Translations for all languages.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 10:01:17 +02:00
Kellermorph 6e83012109 Draw the cables in the realistic style too
The strip seen from above drew no cable at all: it had no zone for one
and no code to draw it, so a strip drawn realistically told nothing
about where its cables go while the same strip drawn schematically did.

The drawing itself was already shared between nothing -- it lived in
one style only, so it is now Helpers::drawCables() with its cells, and
both styles hand it the terminals they show. The realistic style
collects one wire exit per level spread over the width of the terminal
body, all of them leaving the strip at its bottom edge, and reserves
the zone under the strip for them as soon as one terminal carries a
cable, exactly like the schematic style does.

tst_cabletarget checks the realistic style paints under the body of
the strip when a terminal carries a cable, and drops that zone when it
does not.
2026-10-20 10:00:07 +02:00
Kellermorph 79ab711d93 Size the cable target box to the cross bar
The box hugged its own text, so it stayed small whatever room the end
zone gave, and its font shrank until the three lines squeezed into it.
It now spans the cross bar the cable bundle ends on -- the width the
strip already draws there -- and keeps the font of the drawing: when
its lines (Installation, Location and Label) are longer than that cross
bar, it is the box which grows, the text is never cut down to fit a box.
The end zone of the default layout leaves the room those three lines
need at that font, so a target is not squeezed by the drawing itself.
The setting still rules it: a smaller zone shrinks the text again.

tst_cabletarget checks the box is drawn three lines tall at the font
of the drawing, and that the default zone leaves that room.
2026-10-20 10:00:07 +02:00
Kellermorph 3de7f525cc Merge M10+M9a: name the cable target, keep wire numbers out
# Conflicts:
#	sources/TerminalStrip/realterminal.cpp
#	tests/qttest/CMakeLists.txt
2026-10-20 08:07:02 +02:00
ispyisail aebe82d6c2 Merge pull request #1554 from DaTweety/feature/report-jump
Linux build and tests / Build and test (Qt 6, Debug) (push) Failing after 2m13s
Jump between folio report ends with a pointing hand and a highlight
2026-10-20 13:10:14 +13:00
ispyisail eba05bed43 Merge pull request #1537 from DaTweety/feature/nomenclature-folio-place
Nomenclature: an element is where its folio is
2026-10-20 13:10:02 +13:00
DaTweety 7a2b390b78 Report jump: show the target's whole folio, shade its texts too
Feedback on a real plan: zooming in on the end jumped to was too much.
A jump now shows the target's folio whole, as a page (the view's fit),
selects the target and shades it and its texts blue for three seconds,
so that the eye finds the label too. One function, Element::jumpTo(),
serves the double click on the arrow and on the text.

The mouse pointer is not moved onto the target: Wayland does not let a
program move the pointer.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 22:39:06 +02:00
Kellermorph 59c2776350 Merge M8: sort terminal strips into the plan's own order 2026-10-19 22:32:10 +02:00
Kellermorph b6312f1f78 Keep the wire numbers out of the terminal drawing
The number of a wire was written from its mark towards the terminal
without any regard for the room left: a colour code like 'gnge' ran
into the drawing of the terminal. The length of the wires setting
moves the mark, but every project has to be tuned to its longest
number by hand, and a short length leaves no room at all.

Shrink the font while the number is longer than the room between the
mark and the terminal, and clip away what still does not fit even at
the smallest size, so a number never crosses into the terminal -- the
wire length and the font stay the settings to make the drawing
pleasant, they are just no longer able to break it.

tst_cabletarget paints the strip with a long number and without any
and checks the two pictures are the same above the bottom of the
terminal: the number is drawn below it or not at all.
2026-10-19 22:22:40 +02:00
Kellermorph 29a8f018f4 Name where a cable goes at the end of a strip
The strip graphic fanned the wires out again after the cable, which
shows each core leaving the cable but says nothing about where it is
going -- the far end was unnamed. Keep the bundle together at the end
now: a short stub and a box with the Installation, Location and Label
(BMK) of the piece the cable lands on, the same three fields the cable
list computes for a target (cablelistrows.cpp), so the strip and the
list can never disagree.

The target is the first piece past the strip's own terminals the
wires of the cable land on, in plan order; a report is no arrival
(the cable continues on the linked sheet), several cores on one
piece are one landing, and a cable which lands on nothing but the
strip itself gets no box. The lines shrink to the end zone the
Terminal plan settings give (Cable end length), so the box never
grows past the strip the bounding rect reserved.

RealTerminal::cableTarget() works the whole out: the cable is the one
the wires drawn to the terminal carry, a name typed by hand is
looked up among the cables of the project, and the box is drawn for
the first wire of the cable group. tst_cabletarget checks the value
rule (own strip no target, spare no target, no cable no target) and
that painting with and without a target gives two different
pictures.
2026-10-19 21:43:27 +02:00
Kellermorph 123c56bb13 Sort terminal strips into the plan's own order
The strip sorted by label: X1:1, X1:2 ... with X1:N and X1:PE at the
end whatever the plan looks like, so a strip drawn across pages came
out in an order no cable follows. Sort it the way the plan is drawn
instead -- folio by folio, then left to right -- in both places that
order a strip: the auto import's own sort of the terminals it groups,
and SortTerminalStripCommand, which the import pushes for a strip it
just creates and which the editor's sort button and
qet.sortTerminalStrip() push as well. The two share one comparator
(SortTerminalStripCommand::planOrderLessThan), so they cannot fight
each other. A spare stands on no folio, has no place in the plan order
and goes last, by label; the label breaks the remaining ties, so two
terminals at the very same spot keep a stable order.
2026-10-19 20:48:06 +02:00
DaTweety 5641b031f9 Jump between folio report ends with a pointing hand and a highlight
A linked folio report now shows a pointing hand under the mouse, on its
arrow as well as on the text that shows its label (which already turned
blue), and a double click on the arrow goes to the other end, as a
double click on the text did. Before, a double click on the arrow opened
the report's properties, which stay reachable from the context menu and
the properties panel.

The end jumped to is highlighted for two seconds, with the same blue as
the hover highlight but independent of it: the hover highlight is
cleared as soon as the mouse leaves the end jumped from, so on the same
folio the user saw nothing mark where the jump landed.

The text of a linked slave that shows its master's label gets the same
blue and hand, since a double click on it already jumped to the master.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 20:12:30 +02:00
plc-user c32ebc5936 PartArc, normalize: after review 360 becomes 0 degree 2026-10-19 19:12:19 +02:00
Kellermorph bab2707fff Terminal strip editor: the cable cells follow the cables
The window stays open while the drawing is wired, so the table takes up
what the cables say on its own: each cable of the project is watched,
its change reloads the table after CableManager has worked the labels
out again, and a cable taken away empties the cells right away.

A reload never costs the user his own work: cell edits not applied yet
are kept, and a cell being typed in is left alone.

A cell worked out from a cable refuses to be written through setData(),
so the apply button, the paste and the deletion of texts leave it alone
too.
2026-10-19 19:09:50 +02:00
Kellermorph 9e37fa2ca7 Terminal strip editor: cable cells worked out from the project cables
The Cable and Color / wire number columns now show what the cables of
the project say (designation and core colour or number), worked out
from the conductors wired to the terminal, instead of only the values
typed in by hand (patch by Laurent);

Values typed in by hand are still shown, and the cells still editable,
when no cable of the project is wired to the terminal;

A value worked out from a cable is never written back into the element,
so a cable renamed or removed cannot leave a stale value behind.
2026-10-19 18:40:56 +02:00
Laurent Trinques 758703f50e Merge pull request #1560 from frakbenparker/perf/assignvariables-qsettings
AssignVariables: open QSettings only for element formulas
2026-10-19 18:27:47 +02:00
Laurent Trinques a12fb43bcb Merge pull request #1550 from Kellermorph/auto-terminalstrip
Terminal strip: create the strips from the free terminals' labels
2026-10-19 18:14:13 +02:00
Laurent Trinques e7a168d1f9 Merge pull request #1556 from ispyisail/test/round-trip-gate
Test the round trip between .qet and .qetz in CI
2026-10-19 17:23:51 +02:00