Drop pending notices for merged #1105-#1108, #1110, #1111; project_database: terminal uuids (#1116, #1118)

ispyisail
2026-09-29 10:27:15 +13:00
parent 84d0a49841
commit 5120534cc4
4 changed files with 73 additions and 72 deletions
+4 -14
@@ -65,12 +65,6 @@ they can arrive in either order.
### Editing one member on its own
> **Status: pending.** This section describes
> [PR #1110](https://github.com/qelectrotech/qelectrotech-source-mirror/pull/1110),
> not yet merged. Nothing here works until that lands — check the PR
> before trying any of this against your own build. This section will drop
> this notice once it does.
1. Click any member: the whole group is selected, as before.
2. Click the **same or another member of that group again**, without
dragging: now only that member is selected.
@@ -91,17 +85,13 @@ What stays the same:
### Rotating a group as one piece
> **Status: pending.** This section describes
> [PR #1111](https://github.com/qelectrotech/qelectrotech-source-mirror/pull/1111),
> not yet merged. Nothing here works until that lands — check the PR
> before trying any of this against your own build. This section will drop
> this notice once it does.
With a whole group selected (and nothing else), **Space**, **Pivoter**
(*rotate*) turns the group 90° round its centre, keeping its layout —
exactly what **Shift+Space**, **Pivoter le groupe** (*rotate as group*), does.
Until this lands, Space turns each member where it stands and pulls the group
apart; use Shift+Space.
In builds before
[PR #1111](https://github.com/qelectrotech/qelectrotech-source-mirror/pull/1111)
(merged 28 September 2026), Space turns each member where it stands and
pulls the group apart; use Shift+Space there.
Any other selection rotates as before: several items that are not one group,
a group together with other items, or a single member picked out of its
+1 -2
@@ -280,8 +280,7 @@ Across the shipped examples: 3190 conductors, not one with a cable value.
is what the application does, since a wire number describes a potential.
Name a terminal carrying exactly one conductor; a terminal several
conductors meet at names none of them and is refused.
*Pending, [PR #1108](https://github.com/qelectrotech/qelectrotech-source-mirror/pull/1108):*
`set_conductor`, `move_conductor_segment` and `delete_conductor` will also
`set_conductor`, `move_conductor_segment` and `delete_conductor` also
take `"conductor": "{uuid}"` (as `qet_conductors` reports it) in place of
`element` + `terminal`, which works where two conductors meet at a
terminal, as long as one of the conductor's two terminals carries only it.
+68 -50
@@ -140,56 +140,73 @@ add an `ORDER BY`.
---
## 4. Identity, and why terminals are hard
## 4. Identity, and why terminals were hard
Rows need stable keys. Elements and diagrams have real UUIDs, so they are
fine. So do conductors drawn or saved by a recent QElectroTech — but a
conductor loaded from a file that has no `uuid` on it (every wire in an older
project) gets a **new random uuid each time the project opens**, and it is
never saved. Its `conductor` row is keyed by a uuid that will be different
next session.
fine. So do conductors drawn or saved by a recent QElectroTech. Items saved
by an older version, without a `uuid`, get one worked out when the project
opens, the same every time, and saved from then on:
> **Status: pending.** The next two points describe
> [PR #1105](https://github.com/qelectrotech/qelectrotech-source-mirror/pull/1105)
> and [PR #1107](https://github.com/qelectrotech/qelectrotech-source-mirror/pull/1107),
> not yet merged. Until they land, the paragraph above is how it works.
- A symbol gets one from its type, its position on the folio and its
rotation
([PR #1105](https://github.com/qelectrotech/qelectrotech-source-mirror/pull/1105)).
- A wire gets one from **what it connects** — the symbol and terminal at
each end — never from its place in the file or its folio's number, so
inserting or moving a folio does not change it. Once saved, reconnecting
the wire keeps it
([PR #1107](https://github.com/qelectrotech/qelectrotech-source-mirror/pull/1107)).
A worked-out uuid is never one the file already carries.
- Shapes, free texts and pictures on a folio, and the parts drawn inside a
symbol, get one from their folio, their kind and their order in the file.
Paste and folio duplication give the copies new ids. Older versions of
QElectroTech open such files and drop the attribute when they save.
### Terminals
A terminal's `uuid` belongs to the symbol's *definition*: it identifies a
terminal position in a symbol — "the top terminal of a contactor" — and is
therefore **identical across every placed instance of that symbol**. So a
terminal instance is only unique as the pair **(`uuid`, `element_uuid`)**,
which is why that pair, not `uuid` alone, is the terminal table's primary key
and what the conductor table's foreign keys reference.
The collection's symbols have carried terminal uuids since 2024, but each
project keeps its own copy of every symbol it uses, and older projects keep
the copy they were drawn with: in the 24 example projects, 706 of the 900
stored symbols had no terminal uuid. How that is handled:
- `Terminal::stableUuid()` gives a terminal without a uuid an identity
derived as a UUID v5 from its position and orientation inside its symbol —
the same basis the project format uses to match a conductor back to a
terminal. Names are deliberately left out: QElectroTech rewrites a
terminal named `_` as unnamed, and the identity would change on the first
resave.
- Since
[PR #1118](https://github.com/qelectrotech/qelectrotech-source-mirror/pull/1118),
opening a project gives every terminal of its stored symbols that has no
uuid **that same value**, and saving writes it. Nothing keyed on terminals
changes: the terminal table and the wire uuids above were already using
it. A second terminal at the same point of a symbol gets its own value
instead of sharing the first one's. The first save of an older project
rewrites its wires in the form that names terminals by uuid, which
QElectroTech has read since 0.8.0.
- A wire saved against a terminal uuid is reattached on opening to a
terminal with that uuid. Replacing a project's copy of a symbol ("Écraser
l'élément déjà intégé" — sic — when placing a changed version) keeps the old
terminal uuids for terminals at the same place
([PR #1116](https://github.com/qelectrotech/qelectrotech-source-mirror/pull/1116)),
and a wire that still cannot be reattached is listed in a warning when the
project opens, instead of disappearing silently.
> **Status: pending.** This point describes
> [PR #1122](https://github.com/qelectrotech/qelectrotech-source-mirror/pull/1122),
> not yet merged. Nothing here works until that lands — check the PR
> before trying any of this against your own build. This point will drop
> this notice once it does.
>
> - A symbol saved without a uuid gets one worked out from its type, its
> position on the folio and its rotation — the same every time the file
> opens, and saved from then on (#1105).
> - A wire saved without a uuid gets one worked out from **what it connects**
> — the symbol and terminal at each end — never from its place in the file
> or its folio's number, so inserting or moving a folio does not change it.
> It is saved from then on, so reconnecting the wire later keeps it (#1107).
> A worked-out uuid is never one the file already carries.
Since September 2026 shapes, free texts and pictures on a
folio, and the parts drawn inside a symbol: each carries a `uuid` attribute in
the saved file. An item from a file saved before then gets one worked out from
its folio, its kind and its order in the file, so opening the same file twice
gives the same ids. Paste and folio duplication give the copies new ids.
Older versions of QElectroTech open such files and drop the attribute when they
save.
Terminals are not so lucky.
`Terminal::uuid()` comes from the catalogue `.elmt` definition. It identifies
*a terminal position in a symbol* — "the top terminal of a contactor" — and is
therefore **identical across every placed instance of that symbol**. It is also
empty for every element authored before the field existed, which is most of the
installed collection.
Two consequences, both handled:
- A terminal instance is only unique as the pair **(`uuid`, `element_uuid`)**,
which is why that pair, not `uuid` alone, is the terminal table's primary key
and what the conductor table's foreign keys reference.
- `Terminal::stableUuid()` supplies an identity when the definition gives none,
derived as a UUID v5 from the terminal's local position and orientation
inside its element — the same basis the project format already uses to match
a conductor back to a terminal. Names are deliberately excluded from the
derivation, because QET rewrites a terminal named `_` as unnamed and the
identity would change on the first resave.
> - The symbol editor gives the terminals of an old symbol file the same
> worked-out uuids when it opens it, instead of random ones, so every
> copy of that symbol agrees with the projects that use it.
`projectDataBase::excludedConductorCount()` reports how many conductors could
not be keyed at all, counted from the live scene rather than the database —
@@ -197,10 +214,11 @@ not be keyed at all, counted from the live scene rather than the database —
what lets a wiring list say "N wires are missing, and here is why" instead of
presenting a short list as if it were complete.
**This is the constraint to keep in mind for any future persistence work.**
While the database is derived, a terminal whose identity is guessed from
geometry costs a cache miss. As a *file format*, the same guess becomes a
permanent, one-shot migration of everyone's projects.
**This was the constraint on any future persistence work.** While the
database is derived, a terminal whose identity is guessed from geometry costs
a cache miss; kept on disk, a guess moves whenever the terminal does. Writing
the identity into the project (#1118) turns the guess into a fact the file
keeps, which is what persisting anything keyed on terminals needs.
---
-6
@@ -145,12 +145,6 @@ attribute.
### Find a wire by its uuid
> **Status: pending.** This section describes
> [PR #1106](https://github.com/qelectrotech/qelectrotech-source-mirror/pull/1106),
> not yet merged. Nothing here works until that lands — check the PR
> before trying any of this against your own build. This section will drop
> this notice once it does.
The conductor calls name a wire by one of its ends — an element uuid and a
terminal index — which cannot tell apart two wires meeting at one terminal.
A wire's uuid names it for good: