From 8268df8a802a42e4eb10902b1d9c6f008b9ab0e4 Mon Sep 17 00:00:00 2001 From: Shane Ringrose Date: Sun, 21 Jun 2026 08:58:30 +1200 Subject: [PATCH] edz: name terminals terminalNr.designation (e.g. "XDI.2") MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previous logic resolved duplicate connectionDesignation values by appending sanitised description text or numeric suffixes, which was fragile and produced names an electrician could not easily map back to the physical wiring. New scheme: • terminalNr present → "XDI.2", "XRO1.3", "XPOW.1" … • terminalNr absent → designation as-is ("L1/U1", "UDC+", "PE") — these are busbar / power connections and are already globally unique • collision (malformed data) → numeric suffix as safety net The description (connectiondescription) remains as the human-readable label beside the terminal symbol, exactly as suggested by plc-user. Co-Authored-By: Claude Sonnet 4.6 --- sources/import/edz/edzelementbuilder.cpp | 70 +++++++----------------- 1 file changed, 19 insertions(+), 51 deletions(-) diff --git a/sources/import/edz/edzelementbuilder.cpp b/sources/import/edz/edzelementbuilder.cpp index 8df885efd..c9161ab50 100644 --- a/sources/import/edz/edzelementbuilder.cpp +++ b/sources/import/edz/edzelementbuilder.cpp @@ -238,63 +238,31 @@ QDomDocument EdzElementBuilder::build(const EdzPart &part) dyn.appendChild(info_name); desc.appendChild(dyn); - // Build unique terminal names. QET requires every terminal in an element - // to have a distinct name for wiring and terminal-diagram generation to - // work. EPLAN parts sometimes repeat the same connectionDesignation across - // multiple function templates (e.g. a drive with several connections named - // "1", "2", "3"). Resolve duplicates: - // 1. If a designation is unique, keep it as-is. - // 2. If duplicated, append "_" + sanitised description when that yields - // a unique result (e.g. "1_L+_P" -> "1_L_P"). - // 3. Fall back to appending "_2", "_3", … when descriptions are missing - // or still collide. - auto sanitise = [](const QString &s) -> QString { - QString out; - for (const QChar c : s) { - out += (c.isLetterOrNumber() || c == QLatin1Char('-')) ? c - : QLatin1Char('_'); - } - // Collapse consecutive underscores and strip trailing ones. - while (out.contains(QStringLiteral("__"))) - out.replace(QStringLiteral("__"), QStringLiteral("_")); - while (out.endsWith(QLatin1Char('_'))) - out.chop(1); - return out; - }; - - // Count occurrences of each raw designation. - QMap desig_count; - for (const EdzPin &p : pins) - desig_count[p.designation]++; - + // Build unique terminal names that an electrician can read directly on + // a wiring list. When a terminalNr connector label is present, prefix it: + // "XDI.2" (terminal block XDI, position 2) + // "XRO1.3" (relay output block XRO1, position 3) + // Power/busbar connections that carry no terminalNr use their designation + // as-is — these are already globally unique ("L1/U1", "UDC+", "PE", …). + // A numeric suffix is appended only if a collision still occurs, which + // should not happen with well-formed EPLAN data. QSet used_names; QVector terminal_names(n); - // Per-designation occurrence counter for the fallback suffix. - QMap desig_seen; for (int i = 0; i < n; ++i) { const EdzPin &pin = pins.at(i); - desig_seen[pin.designation]++; - - if (desig_count[pin.designation] == 1) { - // Unique designation — use directly. - terminal_names[i] = pin.designation; - } else { - // Try designation + sanitised description first. - const QString candidate = pin.description.isEmpty() - ? QString() - : pin.designation + QLatin1Char('_') + sanitise(pin.description); - if (!candidate.isEmpty() && !used_names.contains(candidate)) { - terminal_names[i] = candidate; - } else { - // Numeric suffix fallback: "1", "1_2", "1_3", … - const int occ = desig_seen[pin.designation]; - terminal_names[i] = (occ == 1) - ? pin.designation - : pin.designation + QLatin1Char('_') + QString::number(occ); - } + QString name = pin.group.isEmpty() + ? pin.designation + : pin.group + QLatin1Char('.') + pin.designation; + // Collision guard (malformed data safety net). + if (used_names.contains(name)) { + int suffix = 2; + while (used_names.contains(name + QLatin1Char('_') + QString::number(suffix))) + ++suffix; + name += QLatin1Char('_') + QString::number(suffix); } - used_names.insert(terminal_names[i]); + terminal_names[i] = name; + used_names.insert(name); } // Terminals.