Commit Graph

10771 Commits

Author SHA1 Message Date
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 9827a12841 Merge M2: the terminal strip cable cells follow the cables 2026-10-19 22:32:05 +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
Laurent Trinques aa7f328aeb Update translations files 2026-10-19 22:04:05 +02:00
Laurent Trinques 3a863d4b09 Update translations files 2026-10-19 21:59:21 +02:00
Laurent Trinques d2bacfd526 Update translations files 2026-10-19 21:46:18 +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
Laurent Trinques adf3ea301c Update translations files
Linux build and tests / Build and test (Qt 6, Debug) (push) Failing after 1m52s
2026-10-19 20:01:16 +02:00
Laurent Trinques ee227a007e Update translations files 2026-10-19 19:28:16 +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 94a929c8c0 Add tst_terminalcableauto: the terminal strip cable cells from a cable
Three cases against fixtures/every_feature.qet (strip X1, wired
terminals, no cable): a wired terminal shows cable and core, the cells
go read only and nothing is written into the element; a core without a
colour is shown as its number; a value typed in by hand stays when no
cable is wired and comes back unchanged once the cable is gone.
2026-10-19 18:49:36 +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
Laurent Trinques a9715b5bf6 Merge pull request #1559 from DaTweety/feature/folio-crosshair
Folio-wide crosshair under the mouse (Display menu)
2026-10-19 17:21:08 +02:00
Laurent Trinques f5ffbd6a9c Merge pull request #1557 from ispyisail/fix/spacemouse-scan-only-3d-mice
Fix the 3D mouse search asking every device for its name (#1553)
2026-10-19 17:17:37 +02:00
DaTweety 4f0c493a7f Nomenclature: an element is where its folio is
element_nomenclature_view gave an element's own plant and location only,
which are empty unless typed into every element. A project structured by
its folios (=plant +location on the title block, %M / %LM) therefore
showed no place in the BOM, nomenclature tables and queries, although the
folio says where each device is -- the way EPLAN builds the device tag
from the page structure.

The view now falls back to the folio's plant and location when the
element has none of its own.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 15:40:29 +02:00
DaTweety f994957965 Folio-wide crosshair: translations for all languages
The menu entry and its status tip in every translation file, added by
hand next to "Display or hide the grid of sheet" so that the files are
not rewritten by lupdate. German: "Fadenkreuz über die ganze Seite".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 13:49:38 +02:00
Ramon f6c9aeb177 AssignVariables: open QSettings only for element formulas
Every formula evaluation constructed a QSettings, although only element
formulas read it (border-columns_0, for %c). Constructing QSettings is
costly, on Windows a registry lookup, and conductor labels are evaluated
in bulk: Conductor::refreshText() runs for every wire of a folio when it
is built, and for every wire of every built folio when the project or a
title block changes.

Debug build, 40 folios with 4,280 numbered wires:
- refreshText() of every wire: 1,136-1,264 ms before, 203-208 ms after
- opening the project (database fill): 2.24-2.48 s before, 1.46-1.59 s after
- building 39 lazy folios: 15.0-15.3 s before, 12.3-12.5 s after

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 13:44:08 +02:00
DaTweety 3738b3c1d8 Folio-wide crosshair under the mouse (Display menu)
A new option in the Display menu, off by default and kept in the
settings: two thin lines cross the whole folio, inside its border,
through the grid point under the mouse, so that one sees at a glance
whether symbols and terminals are in line, also while dragging them.

They are drawn by the view in drawForeground(), on screen only: no item
is added to the folio, so nothing of them is saved, exported or
printed. Only the strips the lines leave and enter are repainted, and
they go when the mouse leaves the view.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 13:20:00 +02:00
ispyisail 8fa58bd609 Fix the 3D mouse search asking every device on the PC for its name
While no 3D mouse is plugged in, which for most users is always, the
hidapi backend looks for one every 3 seconds for as long as
QElectroTech runs. It asked hidapi for every HID device,
hid_enumerate(0, 0), and on Windows hidapi reads the serial number,
manufacturer and product strings of each device that matches what it
is asked for from the device itself. So every mouse, keyboard, headset
and webcam on the PC was asked for its names every 3 seconds, on the
GUI thread. Issue #1553 reports the pointer moving by itself on Windows
since the first package with this backend; nothing else in that package
talks to devices. SDL 2.0.9 polled the same way and saw freezes and a
keyboard that kept re-initialising (libsdl-org/SDL#3071).

The scan now asks for 3Dconnexion's vendor id, and for each 3D mouse
made under Logitech's id by its product id, since most other mice and
keyboards carry Logitech's id too. That is twelve hidapi calls instead
of one, but a device that does not match is no longer asked for its
names. On Linux and macOS hidapi takes the names from the system, and
one call is cheaper than twelve (on Linux, median of 200: 5 ms against
36 ms), so the scan there is unchanged.

Where the scan is filtered, a Logitech-id device that is not one of the
eleven 3D mice on the list is no longer found, even if it reports
itself as a multi-axis controller. 3Dconnexion's own mice and keyboards,
such as the CadMouse, are still asked: their vendor id is asked for as
a whole, so that new 3D mice are found without a list.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 22:39:02 +13:00
ispyisail 5837bec4fe Merge remote-tracking branch 'upstream/master' into test/round-trip-gate 2026-10-19 22:34:36 +13:00
Kellermorph 3e2ad8c4bd Terminal strip: create the strips from the free terminals' labels
Add an automatic import which groups the free terminals of a project
by the part of their label before the first colon ("X1:2" goes to the
strip "X1"), creates the strips missing and sorts the terminals in
natural order, as one undoable step.

The import runs when the terminal block manager opens on a project and
can be run again from a new toolbar action. It only adds : the strips
already known keep their terminals and their order, and terminals
without label are left free.
2026-10-19 10:47:17 +02:00
ispyisail 4fee464919 Merge pull request #1552 from ispyisail/fix/keep-unloadable-items
Linux build and tests / Build and test (Qt 6, Debug) (push) Failing after 1m43s
Fix symbols and wires lost when their definition cannot be found
2026-10-19 20:58:13 +13:00
ispyisail 2adbc17b3c Merge pull request #1549 from ispyisail/fix/closed-project-panels
Fix a crash after closing a project without saving (forum 3215)
2026-10-19 20:39:31 +13:00
ispyisail 64e8ca0263 Merge pull request #1547 from ispyisail/feat/gost-eskd-titleblocks
Add GOST ESKD title blocks (Russian standard GOST 2.104)
2026-10-19 20:38:58 +13:00
ispyisail 289e33d06e Merge remote-tracking branch 'upstream/master' into fix/keep-unloadable-items 2026-10-19 20:21:02 +13:00
ispyisail 46d8588113 Fix a closed project staying in the element collection panel
A project opened before the element collection panel's first load is
queued until the load starts; one opened during a load goes into the
model being loaded. ElementsCollectionWidget::removeProject() only
removed the project from the model already shown, so a project closed
in either window stayed in the collection, and the next reload read the
freed project (crash in XmlElementCollection::root()).

removeProject() now also takes the project out of the queue and out of
the model being loaded. That model waits for its loading threads, which
read the project, and drops the project's items from the list applied
when the loading ends.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 18:28:35 +13:00
ispyisail 31730678c5 Fix a crash on clicking a sheet of a project closed without saving
Closing a modified project and choosing Discard left the project in the
project tree. The panel removed its item, but the project still emits
projectInformationsChanged() while it is torn down (setModified()), and
GenericPanel answered by adding the project back, with items for its
sheets. Once the project was freed, a click on one of those sheets
called diagram->showMe() on a freed Diagram: SIGSEGV in
QObjectPrivate::maybeSignalConnected(), the backtrace reported on the
forum (topic 3215).

The panel now stops listening to a project when it is closed, to its
sheets and to its embedded title block collection, before removing its
item.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 18:28:31 +13:00
ispyisail 7fcd6086a8 Test the round trip between .qet and .qetz on every example and a project using every feature
scorpio810's condition for the database as the model (#1512): a lossless
round trip between the formats, tested in CI. For every example and for
fixtures/every_feature.qet, the save stamps aside:
- a .qetz saved again is the same file;
- a .qetz saved as a .qet is the project saved straight as a .qet;
- that .qet saved as a .qetz is the project saved straight as a .qetz,
  part by part, its database row by row;
- lazy folios save what every folio built saves, in both formats.

fixtures/every_feature.qet (arummler's test file, #1512) was built through
QElectroTech's script API: four folios, numbering schemes with every kind
of part, a coil linked to three contacts, folio reports, terminals, a
cable, wires with every property, every symbol information field, symbol
texts of every source, independent texts, shapes, a curve, a picture, a
PLC master with its inputs and outputs, a terminal strip bridged, a parts
list and a folio summary, copied, rotated and mirrored symbols. What the
API cannot set was added in the form QElectroTech saves it (new-folio
defaults, a folio field of the user's, single-line wires, a wire text
moved by hand, a coloured symbol text, a text group, an old information
key, a parts list continued on a fourth folio), then QElectroTech opened
and saved it. Of every tag and attribute QElectroTech wrote saving the
341 projects of our corpus, it holds all those found in 5 or more of them
and 98.3 % of all; it also holds what none of them has (terminal strips,
PLC data, tables).

It failed before the previous commit (the .qetz saved again had its folio
parts in another order).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 18:14:49 +13:00