mirror of
https://github.com/qelectrotech/qelectrotech-source-mirror.git
synced 2026-08-22 16:44:14 +02:00
Give every terminal an identity, not only uuid-aware ones
The conductor table keyed on Terminal::uuid(), which comes from the catalog .elmt definition and is empty for every element authored before that field existed. A conductor was dropped unless *both* its terminals had one, so the tables this slice adds were empty on almost every project in existence: examples corpus conductor rows in the database industrial.qet 0 of 671 affuteuse_250h.qet 0 of 263 tremie_vibrante.qet 0 of 77 741.qet 0 of 67 Across the 23 example projects, 16 of the 20 that contain conductors have zero terminal uuids -- 2366 of 3002 conductors -- and overall coverage is 7.3%. Meanwhile --export-cables, already on master, lists all 671 conductors of industrial.qet from the document. A feature that only works on newly authored elements is not one users can rely on. Terminal::stableUuid() returns the terminal's own uuid when it has one and otherwise derives one from its local position and orientation inside its element. That is not an invented scheme: it is what the project format already does. TerminalData::fromXml() says so where it parses the field -- "if the attribute not exists, means, the element is created with an older version of qet. So use the legacy approach to identify terminals" -- and the legacy approach is the terminal's position. m_pos is read from the definition and is not touched by moving the element on a folio, so the identity survives loads, saves and folio moves. Derived values are UUID v5 in a fixed namespace, so they are reproducible without being stored, and cannot collide with the v4 uuids the element editor generates. Every project in the corpus now has exactly as many conductor rows as the document has conductors -- 20 of 20 measured, 0 mismatches. (schema_indus.qet is excluded: it blocks on a modal dialog at zero CPU under any CLI flag, the pre-existing hang PR #661 addresses.) Two things this deliberately does not key on: - The terminal name. It is not stable: QET rewrites a terminal named "_" as unnamed, which would have silently changed the identity of 1421 of industrial.qet's 1790 terminals on their first resave. Measured across the corpus, dropping it costs nothing -- geometry alone yields exactly the same three collisions -- and it means renaming a terminal no longer changes what it is. - Uniqueness in the face of a definition that declares two terminals at the same point and orientation. Three cases exist in the whole corpus. They merge to a single terminal row, which is harmless: two terminals identical in position and orientation are indistinguishable in every observable respect, and every conductor on either still resolves to the right element and terminal name. Both affected projects (industrial, perceuse) return their full conductor count. The only conductor still skipped is one whose terminal has no parent element, which has no identity to key on at all. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -817,6 +817,60 @@ QUuid Terminal::uuid() const
|
||||
return d->m_uuid;
|
||||
}
|
||||
|
||||
/**
|
||||
@brief Terminal::stableUuid
|
||||
An identity for this terminal that exists on every element, not only on
|
||||
those saved by a uuid-aware element editor.
|
||||
|
||||
uuid() comes from the catalog .elmt definition and is empty for every
|
||||
element authored before that field existed -- which is most of the
|
||||
installed base. Anything keyed on uuid() alone therefore cannot see those
|
||||
elements at all.
|
||||
|
||||
When there is no uuid, derive one from the terminal's local position and
|
||||
orientation inside its element. That is not an arbitrary choice: it is the
|
||||
same thing the project format itself uses to match a conductor back to a
|
||||
terminal ("each connection is made by using the local position of the
|
||||
terminal and a dynamic id" -- TerminalData::m_uuid). m_pos is the position
|
||||
read from the definition and is not touched by moving the element on the
|
||||
folio, so the result is stable across loads, saves and folio moves, and it
|
||||
is unique within an element except where a definition genuinely declares
|
||||
two terminals at the same point -- three cases in the whole example corpus,
|
||||
and harmless, because two terminals sharing a position and orientation are
|
||||
indistinguishable in every observable respect: they merge to one terminal
|
||||
row and every conductor on either of them still resolves to the right
|
||||
element and name.
|
||||
|
||||
Derived values are UUID v5 in a fixed namespace, so they are reproducible
|
||||
without being written to the file, and cannot collide with the v4 uuids
|
||||
the element editor generates.
|
||||
|
||||
@return the terminal's own uuid when it has one, otherwise a derived one
|
||||
*/
|
||||
QUuid Terminal::stableUuid() const
|
||||
{
|
||||
if (!d->m_uuid.isNull()) {
|
||||
return d->m_uuid;
|
||||
}
|
||||
|
||||
//Fixed namespace for terminal identities derived from geometry.
|
||||
static const QUuid derived_ns(QStringLiteral("{6b1f6d1e-6a1a-5f7e-9a3d-9c0a5b2d7e11}"));
|
||||
|
||||
//Position and orientation only. The name is deliberately excluded: it
|
||||
//is not stable across a save cycle -- QET rewrites a terminal named
|
||||
//"_" as unnamed, which would silently change the identity of 1421 of
|
||||
//industrial.qet's 1790 terminals on the first resave. It is also not
|
||||
//needed: keying on geometry alone produces exactly the same number of
|
||||
//collisions across the example corpus, and it means renaming a
|
||||
//terminal does not change what it is.
|
||||
const QString key = QStringLiteral("%1|%2|%3")
|
||||
.arg(d->m_pos.x(), 0, 'f', 4)
|
||||
.arg(d->m_pos.y(), 0, 'f', 4)
|
||||
.arg(static_cast<int>(d->m_orientation));
|
||||
|
||||
return QUuid::createUuidV5(derived_ns, key);
|
||||
}
|
||||
|
||||
QString Terminal::name() const
|
||||
{
|
||||
if (d->m_use_master_label && parent_element_) {
|
||||
|
||||
@@ -75,6 +75,7 @@ class Terminal : public QGraphicsObject
|
||||
Diagram *diagram () const;
|
||||
Element *parentElement () const;
|
||||
QUuid uuid () const;
|
||||
QUuid stableUuid () const;
|
||||
QString name () const;
|
||||
QString baseName () const;
|
||||
TerminalData::Type terminalType() const;
|
||||
|
||||
Reference in New Issue
Block a user