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).
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
The level spinbox of the terminal strip editor allowed stages up to 6
while the strip drawing handles at most 4 stages (0 to 3), so a stage
entered there was simply not drawn. Cap the spinbox at 3 and keep the
editor consistent with the drawing and the level columns.
Opening the terminal block manager builds the folios not built yet (lazy
folios). This is done in one go without running the event loop, so the
window system said the opening message was "not responding".
- QETProject::setFolioBuildObserver(): a function called after each folio
built by buildFolios(), with the number of folios built and to build.
- The manager uses it to show "Reading folio n of N..." with a real
progress bar, and runs the event loop (without the user input) between
two folios, so the window system keeps getting answers.
- The autosave skips its turn while folios are being built, since the
event loop can now run then.
- The opening message only has a title bar: nothing to minimize, maximize
or close.
One pass of the event loop after show() was not enough: the message box
was not painted yet when the long work started (seen on Wayland), only
the busy cursor was visible.
Wait for the window of the message to be exposed by the window system
(500 ms at most), then paint it before building the manager.
Opening the terminal block manager reads every terminal of the project,
and builds the folios not built yet (lazy folios): on a big project it can
take a while, and the user could think that nothing happens.
TerminalStripEditorWindow::instance(), used by the menu action and by a
double click on a terminal strip of a folio, now shows a busy message
("Opening the terminal block manager...") and a wait cursor while the
window is built or switched to another project. Moved from the header to
the .cpp file.
The redraw on change was connected in setTerminalStrip() only, used when
an item is read from the project. An item added with the "Add terminal
strip" dialog is built with TerminalStripItem(strip), which did not
connect: it was not redrawn after the terminal strip editor was applied,
until the project was reopened.
Both constructors now go through connectStrip().
A spare (reserved) terminal is a terminal of a strip which is drawn on no
folio. RealTerminal already foresaw it ("a terminal set by user but not
present on any folio") but every terminal needed an element.
- RealTerminal::createSpare(): a terminal without element, with its own
data (label, type, function, led, informations: section, width, catalog
terminal, color, manufacturer...). Saved in the strip:
<real_terminal spare_uuid="..." type="..." function="..."><informations>
Older versions ignore these terminals.
- TerminalStrip::insertSpareTerminals() / insertTerminals(): insert at a
position of the strip. Undoable commands AddSpareTerminalsCommand and
ChangeSpareTerminalDataCommand.
- Terminal strip editor: "Add spare terminals..." button. The terminals
are inserted after the selected terminal (at the end if none), numbered
from its label ("X1:12" -> "X1:13", "X1:14", leading zeros kept), with
its properties if asked. The labels can be changed or removed in the
table, like the other cells; the Xref column shows "Spare". Moving a
spare terminal to the independent terminals removes it (undoable).
- Nomenclature: the spare terminals are in the new spare_terminal table,
added to element_nomenclature_view (UNION ALL, same columns), after the
folios, in the order of their strip. exclude_from_bom is honoured.
- The modified cells of the editor model are kept by real terminal, not by
element, since a spare terminal has none.
TerminalStripItem was connected to nothing: after applying the terminal
strip editor (width, catalog terminal, color, type...), undo or redo, the
strip drawn on the folio kept its old drawing until something else made
the scene repaint, and its bounding rect was not updated when the width of
the terminals changed.
- TerminalStrip::dataChanged() is emitted when the data of the strip is
set, and when the data of the element of one of its terminals changes
(Element::setElementData(), Element::setElementInformations()).
- TerminalStripItem connects to dataChanged(), orderChanged(),
bridgeChanged() and bridgeColorChanged() of its strip, and updates its
geometry and redraws itself.
The realistic styles drew every terminal of a strip with the clamp of the
layout (RealisticScrew or RealisticPushIn), whatever terminal was chosen:
a Phoenix Contact ST (spring) was drawn with screws in a screw layout.
Each entry of the terminal catalog now has its clamp: screw (Phoenix
Contact UT, Weidmüller WDU, ABB Entrelec M, Legrand Viking 3), spring
(Phoenix Contact ST) or push-in (WAGO TOPJOB S). A terminal chosen in the
catalog is drawn with its own clamp, the spring-cage ones like the push-in
ones; the clamp of the layout is kept for the other terminals, so a strip
mixing screw and spring terminals is drawn as it is.
The manufacturer chosen to filter the terminals of the Width column is
stored in the data of the terminal strip (information "manufacturer" of
terminal_strip_data, written only when set), and selected again when the
strip is shown in the editor. Each strip keeps its own manufacturer.
Older versions ignore this information.
TerminalStripEditor::apply() now starts from the current data of the strip
instead of a new TerminalStripData: the uuid of the strip was replaced by
a new one at each apply, and the new information would have been lost.
Several terminals of the catalog have the same width (6.2 mm: Phoenix
Contact UT 4 and ST 4; 5.2 mm: WAGO 2002 and Phoenix Contact ST 2,5...).
Only the width was stored, so on reopening the first entry with that
width was shown instead of the terminal that was chosen.
- New element information terminal_catalog_entry: the label of the
terminal chosen in the catalog (e.g. "Phoenix Contact ST 4").
- Choosing a terminal also fills the manufacturer and manufacturer
reference informations (bill of materials, %{manufacturer_reference}),
only when they are empty or still hold what the previous catalog entry
wrote: a value typed by the user is never overwritten.
- Element editor: the manufacturer and the exact terminal are restored on
reopening. A width typed by hand, or stored before this change, stays a
plain width instead of taking the first terminal with the same width.
- Terminal strip editor: new "Manufacturer" combo filtering the terminals
proposed in the Width column (with the section filter); the column shows
"6,2 - Phoenix Contact ST 4", and copy/paste keeps the terminal.
Existing projects are unchanged: without the new information, only the
width is used, as before.
ST 1,5 (4.2 mm, 1.5 mm²), ST 2,5 and ST 2,5-QUATTRO (5.2 mm, 2.5 mm²)
and ST 4 (6.2 mm, 4 mm²), next to the UT screw terminals already listed.
Widths from the Phoenix Contact catalog and data sheets (ST 2,5-QUATTRO
3031306, ST 4 3037151, ST 1,5 3031076).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
In the realistic styles, some types of terminal get the parts seen on
the real products:
- fuse terminal: black hinged fuse holder on the middle of the terminal,
with its hinge pin, a window on the fuse, a ribbed grip and, for a
fuse terminal with led, a red led
- sectional (disconnect) terminal: orange knife with its hinge and grip
- test terminal: two brass test sockets between the wire entries and
the middle band (in the middle band for a terminal with levels)
The marker tag and the type symbol are drawn on the lever. The lever is
shorter with screw clamps and stays on the middle band for a terminal
with levels.
The realistic styles don't write the xrefs, so each terminal becomes a
clickable zone, like the xref text of the schematic style:
- double-click on a terminal goes to its element on the folio
- the terminal under the mouse is outlined in blue, and a tool tip
shows its label and its xref
- the zones are exported as clickable links in the PDF
A terminal with one level is clickable on its whole body; a terminal
with levels is clickable on the rows of wire entries of each level.
Only the terminals with an xref (element placed on a folio) are
clickable. The zones use the same physical / real indexes as the
schematic style, so the double-click and the PDF export need no
other change.
Add two realistic drawing styles for the terminal strip plan, besides
the existing schematic one:
- Realistic (push-in) and Realistic (screw): the strip seen from above,
at scale (real width of each terminal), like a cabinet mounting
drawing: end stops, group marker carrier with the strip name, one row
of wire entries per level, bridge channels with red bridges, marker
tags with the terminal number, type symbol (fuse, LED, diode,
sectional, ground...), green/yellow PE and terminal color.
The style is chosen for each plan in the "Add terminal strip plan"
dialog and saved with the item (attribute draw_style of
terminal_strip_item). Items saved before keep the schematic style.
Several plans of the same strip can use different styles.
The values used by the realistic styles are in the layout (scale in
px/mm, terminal length in mm, end stops, group marker) and can be set
in the layout editor, whose style combo box only changes the preview.
Separator plates: a new "Separator plate after" check box column in
the terminal strip editor, stored in the terminal element informations
(key terminal_separator). Drawn as a plate at scale in the realistic
styles and as a thick line in the schematic style.
New files: realisticterminalstripdrawer.{h,cpp} (realistic drawing) and
terminalstripdrawerhelpers.h (helpers shared with the schematic drawer).
Every marker tag of a strip has the length of its longest terminal
number (at least two digits), so three-digit numbers are no longer
reduced. The font is still reduced if a number doesn't fit the text
zone of the layout.
- The xref is drawn as plain text, without marker tag.
- Every marker tag of the terminal numbers has the same length
(two digits), the font is reduced when the number is longer.
- The body of every terminal reserves the zone of the longest xref
of the strip, so all terminals of a strip are drawn the same way.
- Draw only the terminal number (part after the last ':'), the strip
name is already in the header; the manager and the tree still show
the full label.
- Clip texts to the width of their terminal and shrink the font in
narrow terminals so they no longer overlap.
- New housing: body with narrower wire entry caps and a slope between
them, grey by default (terminals with a color or a ground type keep
theirs); stripes are clipped to this shape.
- White marker tags behind the number and the cross reference, fitted
to the text and its alignment; black ribbed tags for isolating
(sectional) terminals.
- Clamping parts (screw in a window, castle tab, big center circle, tab,
screw) drawn in the free zone between the two tags, whatever the
layout; fewer parts if the zone is small.
- Remove the wire entry mark that overlapped the cross reference text.
- Draw only the terminal number (the part after the last ':') instead of
the full label (e.g. "1" instead of "XAUZ1:1"); the terminal manager
and tree still show the full label.
- Clip each text to the width of its terminal and shrink the font in
narrow terminals so that texts no longer overlap their neighbours.
- Remove the wire entry mark in the lower part of the terminal body,
which overlapped the cross reference text.
Extend the terminal catalog (terminalcatalog.h) with the widths of
more terminal blocks, from the catalogs of Phoenix Contact (UT),
Weidmuller (WDU), WAGO (TOPJOB S 2002/2006), ABB Entrelec (M series)
and Legrand (Viking 3). For Legrand and ABB Entrelec the value is the
pitch given by the catalog.
Each entry now carries its manufacturer, and the element properties
dialog gets a "Manufacturer" combo box before the width one. The list
of widths is filtered by manufacturer and by the selected section; if
the manufacturer has nothing for that section, all its terminals are
listed. The combo box is created by the code, no change in the .ui.
The section combo boxes of the terminal strip editor and of the
element editor now show the nearest AWG / kcmil size next to the
section in mm2, for example "2.5 mm² (AWG 14)".
The correspondence is approximate (the two systems don't have the
same steps) and is stored in TerminalCatalog::awgForSection().
The stored value is unchanged (terminal_section, in mm2).
Terminal block elements can now define, in the element properties
dialog (Terminal block element group):
- the section in mm2 (combo box with the usual sections, editable)
- the width / manufacturer reference (Weidmuller, Phoenix Contact,
WAGO, ABB Entrelec), filtered by the selected section
- the color, using the palette of the terminal strip (editable,
accepts a name, #rrggbb or #rrggbb/#rrggbb)
Values are stored in the element informations (terminal_section,
terminal_width, terminal_color) with the dot as decimal separator,
the keys already read by RealTerminal. An empty value removes the key.
The sections and the manufacturer widths move from
terminalstripmodel.cpp to the new header-only terminalcatalog.h,
shared by the terminal strip editor and the element editor.
A terminal strip saved with a terminal whose symbol is gone left that
terminal out without a word. It still does, and says so in the log.
The same happens with every folio built: the database is filled from
the document, so a symbol in the file is never missing from it.
Review of #1472 (scorpio810, point 8).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Every project now opens without building its folios; a folio is built
when it is shown or something needs its items (QETProject::lazyFolios()).
QET_LAZY_FOLIOS is gone; QET_EAGER_FOLIOS=1 builds every folio on
opening, as before, for comparisons and troubleshooting. Comments that
named the old variable now say "lazy folios"; the tests switch modes
with the new one.
The first save of a .qet as .qetz still builds every folio: a .qet does
not say which program wrote it, so its folios are written again rather
than copied. A .qetz opens and saves without building.
ctest 96/96 by default and with QET_EAGER_FOLIOS=1; 342 corpus projects
save the same in all four arms and export the same. In the GUI
(qet-gui-dialog): a 136-folio .qetz opens with no folio built, shows
folios 1 to 4, saves building none, the save = the original but the time
spent in it; a .qet opens lazily, saves as a .qetz beside it after the
notice, the .qet unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A .qetz now carries index.sqlite: the project database as QElectroTech
keeps it -- every table but the drawing items, which exist for built
folios only -- with each folio's own data (Diagram::headerXml()) and a
stamp of the schema it was written with (projectDataBase::indexFile(),
QETProject::writeContainerFile(): Save, --resave, --set-titleblock, a
script's and live mode's save). Written when every folio, symbol and wire
has a uuid of its own; a reader that does not know the entry skips it.
With QET_LAZY_FOLIOS=1, a .qetz with an index opens from it: the project
document is joined without its folios (QetContainer::join() with
folio_files), the database and the stores of symbol information and wire
properties are filled from the index (fillFromIndex()), each folio is made
from its own data and keeps the name of its part, read when the folio is
built (Diagram::deferredXml(), QETProject::readFolioPart(),
QetContainer::readFolio() -- pictures and engineering data back from
project.sqlite, QetContainerDb::restoreFolio()). A terminal strip finds its
terminals' folios in the database. Any other .qetz, or one whose index
cannot be used, is read whole as before.
The index is untrusted: refused unless written with this database's
schema, every table read a plain table (not a view), nothing in its schema
run (trusted_schema off); refused, the project is read whole. Checked: an
index of garbage, a wrong stamp, a table made a view -- each refused and
the project saved as a plain save.
The 136-folio f2099 as .qetz opens in 1.8 s (3.65 s read whole, 29 s
building every folio); what is left is mostly its 7 MB of symbol
definitions (0.8 s). The file grows from 2.6 to 5.2 MB, the index
overlapping project.sqlite until D3.
tst_lazyfolios: a .qetz opened from its index builds only the terminal
strip's folios, numbering read as when built, every folio shown in turn
draws and links as when built, the save as when built; fails when a folio
part's engineering data is not put back. Corpus, 342 projects: 340 .qetz
carry an index and open from it (2 have symbols sharing a uuid); saved
back as .qet = eager = master on all 342. Probe on industrial and f2099
.qetz: every folio as eager but the 3 render-noise folios of f2099. In a
real window the .qetz opens and pages building only shown folios and
partners. ctest 96/96 with and without QET_LAZY_FOLIOS=1.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Add ElementData::TTResistor, TTVaristor, TTTestSocket and TTDiodeReversed
(xml values "resistor", "varistor", "test_socket", "diode_reversed"),
selectable in the element editor, the terminal strip editor and the free
terminal editor, and drawn in the terminal strip plan.
Add ElementData::TTAntiParallelDiodes (xml value "antiparallel_diodes"),
selectable in the element editor, the terminal strip editor and the free
terminal editor, and drawn in the terminal strip plan as two diodes wired
in opposite directions between the top and the bottom of the terminal.
The default terminal strip layout was rebuilt at every project load,
so the font size set in the layout editor was reset to 15 px.
Add TerminalStripLayoutPattern::toXml/fromXml and
TerminalStripLayoutsHandler::toXml/fromXml, write a
<terminal_strip_layout> element in QETProject::toXml() and read it
before the diagrams are loaded. Projects without it keep the defaults.
Generated by tools/qet-en-source/regenerate.sh, not edited by hand. The
tree is the fresh conversion; this commit only joins it to the PR's
history so the branch is never force-pushed.