Commit Graph

10770 Commits

Author SHA1 Message Date
Laurent Trinques 6a6e558194 Merge pull request #1584 from Kellermorph/feature/terminal-label-split
Linux build and tests / Build and test (Qt 6, Debug) (push) Failing after 1m38s
Terminal labelling: option to draw label and number apart, and a Show name box for terminals
2026-10-23 13:41:48 +02:00
Laurent Trinques 82c96b84d3 Wire numbers CSV export: write a UTF-8 BOM and drop stray pointer line
Since the Qt6 port QTextStream always writes UTF-8 (Qt5 used the
locale codec, ANSI on Windows). Without a BOM Excel opens the file as
ANSI, so any non-ASCII character in a wire number is mangled, e.g. an
en dash prefix "–010" becomes "–010" (forum topic 3221).
Write a BOM, as the parts list export already does.

Also `stream << &Qt::endl(stream)` streamed the address of the
stream, adding a bogus last line like "0xa78cffb090"; wiresNum()
already terminates every line, so just drop it.
2026-10-23 13:29:23 +02:00
Kellermorph 129648f92a Keep the terminal number out of the element properties
The properties window builds a row for every element info key, so it
also offered an editable "Terminal number" row -- both for one element
and for several at once. The number is not a property of the element
but derived from its label: typing there stored a value nothing reads,
and the export has no column for it either (previous commit).

Both windows skip the key now, the way they skip exclude_from_bom.
The key itself stays an element info key, so the element editor keeps
offering %{terminal_number} as a text variable.

The test builds both windows for a terminal of the fixture and looks
at the rows they offer.
2026-10-23 13:21:29 +02:00
Kellermorph f6be424cad Keep the terminal number out of the export columns
Manual testing found that the CSV export of the project offered the
terminal number as a column, and failed when it was chosen. The export
takes its columns from the element info keys, but the query behind the
nomenclature has no terminal_number column, so the query breaks.

The widget which offers the columns skips the keys it cannot query
(formula and exclude_from_bom) and skips the terminal number with them,
with a comment saying why.

The key itself stays an element info key: the element editor keeps
offering %{terminal_number} as a text variable, and the label keeps
splitting into label and number the way it was drawn.
2026-10-23 13:02:17 +02:00
ispyisail f68927d0a4 Merge pull request #1592 from ispyisail/refactor/qetz-reader-writer
Move reading and writing a .qetz file into classes of their own
2026-10-23 23:01:34 +13:00
ispyisail 93157a579d Move reading and writing a .qetz out of QETProject
QETZ-DB-FIRST stage 3a. QETProject::openFile() unzipped and joined a .qetz
itself and kept what it held beside the document in three members of its
own (the entries, each folio's part, the pictures), and writeContainer()
split and zipped it. Both now live in their own classes under
sources/container: QetzReader reads a .qet or a .qetz and keeps what a
.qetz holds for as long as the project is open; QetzWriter writes the
document as a .qetz.

No behaviour change: the same calls in the same order. This is the seam
stage 3b needs, where opening fills the working database straight from
project.sqlite instead of rebuilding it from the joined XML.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 18:31:37 +13:00
ispyisail 38107d4d73 Merge pull request #1590 from ispyisail/feature/element-state-db
Store each symbol's contact type in the project database
2026-10-23 18:04:55 +13:00
ispyisail 5c2726d34b Move a symbol's kind information through the project database
QETZ-DB-FIRST 2d-2a: the first half of 2d-2 (QETZ-DB-FIRST-2D-SCOPE.md).
A symbol's kind information (NO/NC/SW/power and the like, baked into its
own definition and never edited after it is built -- the data
CrossRefItem::NOElements()/NCElements() read, through the already
@deprecated Element::kindInformations(), to classify a linked contact)
had no database-backed form at all: nothing could query it without
walking a live Element*.

Add an element_kind_information table, written through from
projectDataBase::placeElement()/unplaceElement() (the same hooks that
already write element_information), with Element::kindInformations() now
reading the store first -- same shape as elementInformations()/
ownInformations(). Added Element::ownKindInformations() as the raw
member accessor, mirroring ownInformations(), so storeElementKindInformation()
is called with the member value rather than the store-reading getter
(the same stale-echo trap storeBorder()/storeFolioNumber() avoid).

No automated test existed for cross-reference text or kind information
at all; added tst_elementkindinformation (a hand-written embedded-symbol
project, checked through the database via qet.query()) before touching
anything cross-reference-shaped, per the re-scoping in
QETZ-DB-FIRST-2D-SCOPE.md.

crossrefitem.cpp itself is untouched here: switching
NOElements()/NCElements() to read through this store is 2d-2b, once this
lands.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-23 13:29:07 +13:00
ispyisail 2ae9196a09 Merge pull request #1589 from ispyisail/feature/folio-number-db
Linux build and tests / Build and test (Qt 6, Debug) (push) Failing after 2m6s
Move a folio's number and total through the project database
2026-10-23 13:11:58 +13:00
ispyisail 44c96a4c95 Move a folio's number and total through the project database
QETZ-DB-FIRST 2d-1: the first sub-stage of 2d (QETZ-DB-FIRST-2D-SCOPE.md).
A folio's 1-based position among the project's folios, and the project's
folio count, were purely computed on the fly from QETProject's live
m_diagrams_list (QETProject::folioIndex(), updateDiagramsFolioData()) and
cached only as BorderTitleBlock's own folio_index_/folio_total_ members --
never in projectDataBase, so nothing could query a folio's number without
walking the live project.

Add a folio_number table (diagram_uuid, folio_index, folio_total), written
through from two places: BorderTitleBlock::setFolioData() (every live
folio add/remove/reorder, same point that already sets the members), and
projectDataBase::populateFromDocument() (straight from the document for a
folio not yet built, same habit as folio_titleblock/folio_border). Added
BorderTitleBlock::folioIndex() as a public getter alongside the existing
folioTotal(), both now reading the store first like the other title-block
and border accessors added in stage 2c.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-23 07:26:45 +13:00
ispyisail df73934bfb Merge pull request #1586 from ispyisail/feature/folio-border-db
Linux build and tests / Build and test (Qt 6, Debug) (push) Failing after 1m41s
Move a folio's border dimensions into the project database
2026-10-23 06:34:42 +13:00
Kellermorph 208b5e1570 Leave the German translation file to lupdate
The review asked to keep hand-written entries out of the .ts: the file
is generated, and hand edits are lost with the next lupdate run anyway.
The strings of the labelling setting pick up their translation with the
next translation round.
2026-10-22 18:40:27 +02:00
Kellermorph 86563850f8 Move the terminal labelling setting into the project
The review asked for it, and it is the right place: the same file must
draw the same way on every machine which opens it, so how a terminal
writes its label belongs to the project, not to the application's own
settings.

The choice lives with the other display options of the sheets, in the
project properties (General page), and is saved in the project as
<terminal_labelling split="true"/> -- written only when on, so a
project with it off saves byte for byte as before. Reading it is a
member of the project now: no QSettings built per text refresh any
more, and switching it redraws the labels of the drawings already open.

The application setting (QetSettings, the General configuration page)
is gone with it, and the test reads the project's own value.
2026-10-22 18:40:19 +02:00
Kellermorph 790497978a Split the labelling of terminal symbols only
An element of any other type draws its label as a whole, whatever the
labelling setting says: the colon in a label like "-K1:13" is part of
that label, not a terminal number waiting to be split off. Only an
element whose data says it is a terminal is ever drawn split.

The test picks a non-terminal whose own label field draws the label it
is given -- not a report (its label is where its partner is), not a
slave (its label follows its master) and not a numbered symbol (a
formula composes its label): those draw texts of their own the split
never touches.
2026-10-22 18:33:06 +02:00
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
Kellermorph 337502edfc Take the label field off the sheet while the name is hidden
An element whose name must not be drawn left its label field behind
as an empty frame: selected along with the element, ready to click,
drawing nothing. The field now follows the Show name box both ways:

- a field bound to the label is hidden while Element::labelShown()
  says no, and shown again the moment the box is ticked again, both
  through the same signals which refresh the text (elementInfoChange,
  the label connection refresh, binding the field to another
  information), so it can never get stuck on one side;
- a hidden field is deselected and gets no resize handles, and one
  which comes back gets its handles back when its element is still
  selected;
- every other field, composite texts included, is drawn as always,
  and the data of the element never changes - only the drawing.

Adds a test: the field is visible, goes away with the name, and
comes back with it.
2026-10-22 13:18:55 +02:00
Kellermorph edf761c2b6 Add a Show name box to the selection properties of a terminal
The box hides the name of the terminal on the sheet only: the element
keeps all of its data, and with the labelling split the terminal keeps
its number, drawn once - in its own field when the symbol has one,
alone in the label field when it has not.

Only a terminal may have its name undrawn: the box is shown for the
element type Terminal alone, and Element::labelShown() obeys the
stored information for a terminal only. The choice is stored as the
element information "label_shown" = "false" and only that, so files
of every element which still draws its name stay exactly as they are.

Multi-selection: the flag appears for terminals only and counts an
absent information as "shown", so a mixed selection shows the box
ticked only when every terminal has it ticked.

Includes four test cases: hidden name keeps the stored data, keeps
the number without a number field, leaves the number to its own
field, and a non-terminal draws its name whatever the file says.
2026-10-22 12:51:50 +02:00
ispyisail 489676b155 Move a folio's border dimensions into the project database
Adds a folio_border table and wires BorderTitleBlock's column/row
grid (counts, widths, header sizes, display flags) through it, the
same way folio_titleblock already covers the title block itself.
Closes the one gap DB-ACCESSORS 4.6 found still living only in the
folio's own XML.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-22 22:55:38 +13:00
Laurent Trinques b98193dbe2 Merge pull request #1580 from ispyisail/doc/install-msys2-kf6
Linux build and tests / Build and test (Qt 6, Debug) (push) Failing after 18m33s
Document KDE Frameworks for Windows builds through MSYS2 UCRT64
2026-10-22 11:08:26 +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
Kellermorph dfec60a3a5 Draw a terminal's label and its number apart, when asked to
A terminal's label is written as it is read off the plan, "X1:1", and
the symbol draws it as one field. On a long strip that field is long
enough to reach into the next terminal, and a user who wants the number
next to the screw and the label out of the way has no way to say so.

Settings > General > Appearance now has a "Display of the terminal
labelling" group with two choices: the label and its terminal number in
one field, the way it has always been drawn, or the two split. The
first is what every drawing gets, so nothing moves until the user asks
for it, and choosing the other one redraws the drawings already open --
nothing needs to be closed and opened again.

A symbol made for the split carries a text field bound to the new
"Terminal number" information (in the element editor's list, next to
the label, and as the %{terminal_number} variable of a composite text):
the label field then shows "X1" and the number field "1", each placed
where the symbol wants it, and hideable when it must be. A symbol which
has no such field -- every symbol drawn until now -- gets the number on
its own line inside the label field, so switching the setting on can
never make a number vanish, and never needs a symbol to be touched
first. A field which becomes, or stops being, the number field tells
the label fields of its symbol to draw themselves again.

Only the drawing reacts. What the element stores, the numbering, the
sorting in the terminal strip editor, the automatic strip import and
every export keep the whole label: the split is read where the text is
drawn (Element::labelForDisplay() and friends), not where the label is
made.

The new test covers both choices, with and without the number field, a
label with no colon at all, and the way back to the whole label. The
full test suite passes (124/124).
2026-10-22 10:01:12 +02:00
ispyisail bd70fc8b20 INSTALL.md: KF6 is packaged in MSYS2 UCRT64; use it as the nightly does
The Windows section said KDE Frameworks are not prebuilt for Windows by any
route and that KF6 is not packaged in MSYS2, so every Windows build was told
to use -DBUILD_WITH_KF=OFF. MSYS2 packages kcoreaddons and kwidgetsaddons for
its UCRT64 and CLANG64 environments (not MINGW64), and
.github/workflows/windows-build.yml builds with them (-DBUILD_WITH_KF=ON
-DBUILD_KF=OFF).

Switch the MSYS2 recipe from MINGW64 to UCRT64 with the workflow's packages and
options. This also adds qt6-svg, a required Qt component the old package list
left out. MINGW64 users are told to drop the KDE packages and build with
-DBUILD_WITH_KF=OFF, as before.

Reported in discussion #1565.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 20:37:48 +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
Laurent Trinques 06d31d9921 Update Windows CI/CD
Linux build and tests / Build and test (Qt 6, Debug) (push) Failing after 1m54s
nightly-qt6
2026-10-21 15:33:41 +02:00
ispyisail 139993a691 Merge pull request #1575 from ispyisail/fix/1571-element-cache-lock
Linux build and tests / Build and test (Qt 6, Debug) (push) Failing after 1m44s
Fix #1571: collection freezes while another QElectroTech is open
2026-10-21 22:30:41 +13: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 7d75c72f97 tests: give tst_lazyfolios room for real ASan runtime
Rows-only numbering reads cost roughly 2x master's wall-clock under
ASan (~2065s measured solo on an idle machine, vs master's
~1038-1071s). Two timeouts were tight enough to fail on that
legitimate cost alone: the script's own subprocess timeout and
ctest's TIMEOUT property for the test. Raised both with real margin.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-21 21:43:31 +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 f4a7d5ebbb Merge pull request #1574 from ispyisail/refactor/autonum-save-from-db
Save the project's numbering schemes from the project database
2026-10-21 21:39:36 +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 672ba7c409 Merge pull request #1568 from ispyisail/refactor/autonum-through-db
Linux build and tests / Build and test (Qt 6, Debug) (push) Failing after 1m54s
Keep the project's numbering schemes in the project database
2026-10-21 14:39:34 +13:00
ispyisail 025bd0a57e tst_elementautonumids: the numbering rows test on a one-folio project
A --run script is stopped after 30 s: on industrial.qet the 23 saves
took 23 s natively and did not finish under AddressSanitizer.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 06:54:50 +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