Commit Graph

5088 Commits

Author SHA1 Message Date
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 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 833ed0f523 Keep in a .qetz what QElectroTech cannot compute for a symbol it cannot build
The .qetz leaves out of its folios what QElectroTech computes when it
builds them (format 4): a symbol's terminal list and information texts,
a wire's description of its ends. A symbol whose definition the project
does not hold is never built, so none of it came back: through a .qetz,
the symbols and wires kept by the previous commit lost their terminal
lists, texts and end labels. QetContainer::dropComputed() now leaves a
symbol whose definition is not in the project's collection
(embeddedDefinitions()), and the wires ending on it, as they are.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 17:21:45 +13:00
ispyisail 92ee1b6617 Name a missing definition in the warning about wires not loaded
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 16:48:40 +13:00
ispyisail 0bcd0ca4b6 Keep the symbols and wires a folio cannot load, and save them back
Opening a project dropped, with only a debug line, a symbol whose
definition could not be found (missing from the project's collection and
from the library) and every wire on it; and a wire whose terminal could
not be matched, after the symbol's definition was redrawn. The next save
wrote the project without them. One save of a forum upload whose
collection was incomplete kept 1 of 219 symbols and none of its 299 wires.

A folio now keeps what it could not load as it was read
(Diagram::m_kept_symbols, m_kept_wires) and writes it back when it is
saved whole (Diagram::writeKept()):
- a symbol, its terminals given ids after those of the folio's symbols;
- a wire, an end found written from its terminal as Conductor::toXml()
  does, an end not found as the symbol and terminal uuids it names; for a
  wire saved by legacy ids, the terminal's uuid derived from where it was
  saved (Element::savedTerminalUuid(), out of matchMovedTerminals()), so
  it joins again once the definition has it there. A wire whose ends
  cannot be read, or an end naming no terminal of the file, is kept so
  that it joins nothing.
A symbol kept counts as waiting (projectDataBase::waitingSymbols()), so a
partner keeps its link to it. The open warning now lists the symbols not
loaded too, and says both are kept.

Once the definition is back, the symbol and its wires are built again:
741.qet with one transistor definition removed (8 symbols, 33 wires on
them) saves all 67 wires, and with the definition put back opens with
all 65 symbols and 67 wires, the same folio as before.

tst_resaveunchanged::unloadableItemsKept: fixtures/coil_contact_wired.qet
(coil, linked contact, two wires; built with the script API) with the
coil's definition removed, or the contact's terminals moved and given new
uuids: both symbols, wires and links saved, a second save the same, and
the coil's definition put back gives the undamaged project's symbols and
wires. Fails on master (1 symbol; 0 wires).

FINDINGS F127, F128.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 16:45:55 +13:00
ispyisail 6dce85f2fb Merge pull request #1526 from DaTweety/feature/script-add-cable
Scripting and qet MCP: draw a cable across conductors
2026-10-19 16:21:26 +13:00
ispyisail b4d69f176a Merge pull request #1536 from DaTweety/fix/new-wire-inherits-potential
A new wire takes the potential it reaches through terminals and reports
2026-10-19 16:21:10 +13:00
ispyisail 266d1e2573 Merge pull request #1540 from hairykiwi/fix/elements-panel-crashes
Guard elements-panel auto-select against a detached project item
2026-10-19 16:00:33 +13:00
ispyisail 1e988eadfd Merge pull request #1490 from Kellermorph/fix-textposition
Stop a folio report's text jumping when the report is not linked
2026-10-19 15:49:13 +13:00
ispyisail 3abaf21302 Merge pull request #1543 from ispyisail/fix/save-keeps-qet
Linux build and tests / Build and test (Qt 6, Debug) (push) Failing after 1m54s
Fix Save writing a .qetz beside an opened .qet: keep the .qet
2026-10-19 15:07:41 +13:00
ispyisail 171a597b12 Merge pull request #1546 from ispyisail/refactor/link-from-db-rows
Link symbols on folios opened later from the project database
2026-10-19 15:07:21 +13:00
ispyisail 4d61909fd1 Merge pull request #1545 from ispyisail/refactor/save-links-from-db
Fix removed folios leaving links to their symbols in the saved file
2026-10-19 15:07:03 +13:00
ispyisail 9421aff1b2 Merge pull request #1525 from DaTweety/feature/report-folio-title
Reports: %T for the target folio's title, element info in composite texts
2026-10-19 14:46:10 +13:00
ispyisail 3ce605b57a Merge pull request #1528 from DaTweety/fix/tray-icon-name
Show the logo in the Linux system tray
2026-10-19 14:29:21 +13:00
ispyisail afe2138feb Merge pull request #1542 from plc-user/master
PartArc: normalize start and span to have positive values in element-file
2026-10-19 14:17:57 +13:00
ispyisail 9a41e01187 Link a symbol built to its partners from the project database's rows
A symbol built after opening (lazy folios) links to the partners its
link rows name, and to the symbols whose rows name it; its file's list
only adds what the rows miss. The rows keep a partner on a folio not
built until it is built, in its saved place, so a symbol no longer keeps
a list of its own: the list read from the file is dropped once opening
has filled the database. pendingLinks(), waitingLinks(),
keepsSavedLinks(), linksToSave() and QETProject::waitingLinkTargets()
go; the callers that asked a symbol for its waiting partners ask the
database (waitingPartners()).

When its links change, a symbol's rows are written from its built
partners and the waiting partners its rows held, in their order
(rowsToWrite()), so a full rewrite of the table keeps them too.

A symbol built alone as a partner on a folio not built
(Diagram::buildSymbols()) counts as built: its rows are kept, it is not
waiting (waitingSymbols(), waitingPartners()), so saving does not build
its folio, and removing it does not remove the rows naming it. A row
naming a placed symbol that has not linked yet (its folio being built)
is kept too. At opening the database holds no link until its fill
(forgetLinks()); the symbols read their files' lists until then, and the
fill takes their order: a symbol's own rows, its list, then the rows
naming it. The symbols waiting on folios not built are cached and
updated as folios are built.

QET_CHECK_LINK_ROWS now checks the rows against the links: each built
partner in its order, no other row but to a folio not built.

tst_resaveunchanged::undoKeepsLinksToUnbuiltFolios: m_000 opened with
lazy folios, a contact, its folio or its coil's folio (not built)
removed, then undone: every link saved as before.

QETZ-DB-FIRST stage 2a-3.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 10:47:41 +13:00
DaTweety 308cf4b551 Tray icon: each size at device pixel ratio 1, comment indentation
On a HiDPI screen QIcon::pixmap() returns each requested size at the
screen's ratio, so the sizes handed to the tray no longer matched
16 ... 256. Requested at 1.0, as ProjectFileGP in qeticons.cpp does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 22:57:21 +02:00
DaTweety ba64fd5164 %T last: a folio title keeps the variables it contains
The folio title was put into the formula before %c, %l, %prefix, the
wire variables, the title block and project variables and the
sequences, so a title such as "Schema %c" had them replaced inside it.
It is replaced after all of them now.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 22:52:06 +02:00
DaTweety 7fa242a55f Keep a potential's wire number for a new wire drawn from a cable core
inheritedProperties() cleared the text of a conductor held by a cable,
on the premise that CableManager writes the core label into it. It
writes it into m_cable only (Conductor::setCableReference()); the text
is the potential's real wire number. Clearing it lost a typed number on
the new wire and made distinctProperties() see a choice between ""
and the number where the potentials agreed. The text is now cleared only
when it repeats the core label.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 22:46:25 +02:00
Kellermorph f32df521fc Terminal strip: limit the level spinbox to the drawn stages
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.
2026-10-18 21:13:53 +02:00
Laurent Trinques 24c90cc049 Terminal block manager: show the folios being read, stay responsive
Linux build and tests / Build and test (Qt 6, Debug) (push) Failing after 1m41s
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.
2026-10-18 17:33:18 +02:00
Laurent Trinques 662a0c8f5c Terminal block manager: really show the opening message
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.
2026-10-18 17:06:39 +02:00
Laurent Trinques 89bf07f5c7 Terminal block manager: say that it is opening
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.
2026-10-18 17:01:59 +02:00
Laurent Trinques ff18467117 Terminal strip item: also redraw an item just added to a folio
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().
2026-10-18 16:53:31 +02:00
Laurent Trinques 015811d243 Terminal strip editor: add spare terminals, numbered, counted in the nomenclature
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.
2026-10-18 16:34:41 +02:00
Laurent Trinques ddc71553e2 Terminal strip item: redraw the strip as soon as it changes
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.
2026-10-18 16:06:59 +02:00
Laurent Trinques cbe41aeebf Previous versions: avoid the trigraph warnings of the file name pattern
The glob "????-??-?? ??-??-??" contains the trigraph "??-", which GCC
reports with -Wtrigraphs (8 warnings). The pattern is now written with
"\?" escapes, in one place; it is the same string.
2026-10-18 16:01:58 +02:00
Laurent Trinques ea2acfcaeb Realistic terminal strip: draw the clamp of the terminal chosen in the catalog
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.
2026-10-18 15:48:00 +02:00
Laurent Trinques f7196c48e1 Terminal strip editor: remember the manufacturer filter of each strip
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.
2026-10-18 15:48:00 +02:00
Laurent Trinques 851ddfad16 Terminal catalog: remember the chosen terminal, not only its width
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.
2026-10-18 15:48:00 +02:00
Laurent Trinques 41339869a6 Add Traditional Chinese (zh_TW) translation, draft converted from qet_zh.ts with OpenCC s2twp, to be reviewed 2026-10-18 15:07:11 +02:00
plc-user 3a92ec3fb1 PartArc: normalize start and span to have posive values in element-file 2026-10-18 15:01:21 +02:00
ispyisail b473a07b7d Save a symbol's links from the project database
A symbol's <links_uuids> are now what the project database's link rows
list for it, in their order (projectDataBase::savedLinks()), instead of
a list the save built itself from the symbol's partners: QETZ-DB-FIRST
stage 2a, the save reads links from the database. A symbol the database
does not hold (saved outside a project) still lists them itself.

The rows leave out a partner the project no longer has, so removing a
folio with every folio built no longer saves links to its symbols, as
lazy folios already did (the links part of F113). Every other save is
unchanged.

tst_resaveunchanged removedFolioLeavesNoLinkToIt: affuteuse_250h with
every folio built, folio 3 removed: 4 links named symbols no longer in
the file, none now.

Needs #1522 (each symbol its own uuid) and #1523 (rows in saved order);
local only until both are merged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XCdg2Er2vYhB8Vwa5G7fSR
2026-10-19 01:50:35 +13:00
Laurent Trinques a98f8e33be Merge pull request #1530 from DaTweety/fix/continuity-cable-cores
Continuity check: conductors in different cables are no divergence
2026-10-18 14:45:26 +02:00
hairykiwi 64869810cd Guard elements-panel project-open auto-select against a detached item
- ElementsPanel::addProject auto-selects the first diagram via
  setCurrentItem(qtwi_project->child(0)). When a project is opened before
  the panel's first reload() has created its title-block collection items,
  indexOfTopLevelItem(common_tbt_collection_item_) returns -1 and the
  preceding insertChild() leaves qtwi_project detached from the tree model.
- The unguarded auto-select leaves a detached/invalid current item -- an
  intermittent SIGSEGV in QTreeModel::index()/parent() on some builds; on
  current master with Qt 6.11.2 the test shows the invalid selection without
  a fault. Calling setCurrentItem() on an item the QTreeModel does not own is
  unsafe; guard the auto-select with qtwi_project->treeWidget() so it runs
  only when the item is attached.
- No behavioural change in the normal case: reload() re-adds the project
  attached shortly after and performs the selection then.
- Pre-existing since a82f6de23 ("Add highlight current page in ProjectView").

Assisted-by: Claude Code
Signed-off-by: hairykiwi <174199+hairykiwi@users.noreply.github.com>
2026-10-18 13:44:35 +01:00
ispyisail 89c3979957 Fix Save writing a .qetz beside an opened .qet: keep the .qet
A project opened from a .qet was saved as a .qetz beside it, with a
notice, and the .qet left as it was: a project kept in git did not stay
a .qet. Save now writes the format the project was opened in; only Save
As changes it (scorpio810, discussion #1512). A .qetz is saved as a
.qetz as before.

The save-beside path goes: the flag set on opening, the .qetz path made
from the .qet's, write()'s switch to it and back on failure, and the
notice and replace question in ProjectView::doSave().

tst_resaveunchanged::qetSavedAsQetzBeside becomes qetSavedAsQet: Save of
an opened .qet writes no .qetz and the .qet holds what a plain save of
it holds (it fails without the fix: a .qetz is written beside).
tst_changedondisk makes its .qetz with Save As, as Save no longer does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 22:56:22 +13:00
DaTweety 7d966a0ed4 Show the logo in the Linux system tray
The tray icon was QET::Icons::QETLogo, which comes from QElectroTech's
own icon theme bundled in its resources and so carries the theme name
"qet". On Linux Qt's StatusNotifierItem then sends only that name, and
the panel -- another process, without those resources -- cannot resolve
it: KDE Plasma showed an empty slot. Seen on D-Bus as IconName "qet"
and no IconPixmap.

The tray now gets an icon made of the logo's pixmaps only (16 to
256 px), which the tray sends as pixels. Checked on Plasma: IconName
is empty and IconPixmap carries the eight sizes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 11:47:49 +02:00
DaTweety a8463288aa Continuity check: conductors in different cables are no divergence
checkContinuity() reported potential_mismatch on "cable" whenever the
conductors of one potential ran in different cables. A conductor held
by a cable carries its own core's label in the cable field (15W1:BN,
written by CableManager); a potential spread over several cables is the
normal case, e.g. a neutral fed from a terminal strip into each room.
On a house installation every N and PE potential was flagged.

Conductors held by a cable are left out of the cable comparison; the
free-text cable field of other conductors is still compared.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 11:47:49 +02:00
DaTweety 83607c0b76 Terminal catalog: add the Phoenix Contact ST spring-cage terminals
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>
2026-10-18 11:47:49 +02:00
DaTweety 04716b0731 Scripting and qet MCP: draw a cable across conductors
qet.addCable(folio, designation, type, coreColors, length, x1, y1, x2, y2)
does what the cable tool does after its dialog: a new cable whose trunk
is the line between the two points, every conductor the line crosses
taking the next core in order along the line, with the colour coreColors
lists at that place. One undo step, through AddCableCommand. An empty
designation takes the next free name. A conductor another cable already
holds is refused rather than taken away, since a script cannot be asked
the question the dialog asks. qet.cables() lists the project's cables.

The qet MCP server gains the add_cable op for qet_edit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 11:47:48 +02:00
DaTweety ff65b85357 Report composite texts: element information and the partner's label
A folio report whose text is a composite text replaced only %{label}
and the conductor variables. The report's own information is now
replaced as well, as on any other element, so a report can name the
device and terminal it leads to: "%{comment} %{label}" reads
"-XS27:N +UV1/2 UG Raum - 1.1" like EPLAN's interruption points.

Changing a report's information rebuilt such a text the way an ordinary
element's is built, turning %{label} into the report's stored label,
where its partner was when last saved. It now takes the same text
updateReportText() builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 11:47:48 +02:00
DaTweety 1080188f6e Add %T, the target folio's title, to report and cross reference formulas
A folio report could name the folio it points to by position (%f), folio
number (%F), installation (%M) and location (%LM), but not by its title.
EPLAN and other tools print references like "+UV1/1 Versorgung UG/EG.0",
which with %T is the formula "+%LM/%F %T.%c".

- FormulaContext carries the folio title, filled from the title block.
- %T is replaced on its own only, not as the start of a longer word.
- A report whose formula uses %T follows the target folio's title block
  (BorderTitleBlock::informationChanged), as %F already follows its
  folio number.
- The report and cross reference property pages list %T.

tst_reportfoliotitle checks the replacement, that %total and title
block variables keep their values, and an empty title.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 11:47:48 +02:00
ispyisail a715ff25ff Merge pull request #1534 from ispyisail/feat/multi-symbol-info
Add editing the information of several symbols at once (#1439)
2026-10-18 22:31:36 +13:00
ispyisail ff1a81d85d Fix the Selection properties panel losing the height the user gave it
The panel shrank to its title bar whenever the selection had nothing it
could edit (a click on an empty spot, several elements, a mix of items):
its content layout used QLayout::SetMaximumSize, and an empty vertical
layout's maximum height is 0. The other right-hand panels took the room,
and when an element was selected again the panels were split again from
their size hints, so the height the user had dragged the panel to was
lost (reported by ankostis in #1439).

With the default size constraint the panel keeps its height and stays
blank while there is nothing to edit. The element, wire, text and shape
editors draw the same: their screenshots in a 730-860 px tall panel are
pixel-identical before and after.

Test: tst_selectionpanelheight (on master the height goes from 560 to
19 px).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 22:29:54 +13:00
DaTweety a0e2193971 Joining potentials: agreeing ones leave nothing to choose
ConductorCreator asked which potential's properties to keep whenever a
new wire joined two potentials, even when they agreed in every
property; headless (scripting, qet MCP) such a wire was refused. Only
distinct properties are offered now, and with one left the wire takes it.

A potential's properties seen through one of a cable's cores carried
the core with them -- cable, cable uuid, core slot, and the core label
CableManager writes as text -- so a new wire claimed to be that core.
They are cleared; the text is left to the formula.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 11:21:09 +02:00
DaTweety fa498a3d20 A new wire takes the potential of a terminal it reaches through another
ConductorCreator::existingPotential() looked for an existing potential
only at the terminals being wired and, for a report, at its partner's
first conductor. A wire drawn to the free side of a terminal element
whose other side is wired, or to the far side of such a chain, found
none and got the folio's default properties: the neutral after a
terminal strip came out solid and unnumbered while relatedPotentialConductors()
counts it as part of the dashed, numbered N potential.

Each terminal is now followed through relatedPotentialTerminal() -- the
rule relatedPotentialConductors() applies -- until a wired terminal is
found, and two terminals on one potential count once.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 11:10:10 +02:00
ispyisail 389dae2079 Merge pull request #1521 from ispyisail/fix/joined-wire-uuid
Fix a deleted symbol's joining wire getting a random uuid on every run
2026-10-18 21:54:26 +13:00
ispyisail e46492d575 Merge pull request #1524 from ispyisail/fix/1495-element-editor-zoom-content
Fix #1495: show the symbol editor's fit button as Zoom content
2026-10-18 21:53:54 +13:00