Add a terminal name check when saving an element

Discussion #1157. IEC 61666 §4.1 requires each terminal to be
identified unambiguously within its object, so two terminals of one
element must not share a name.

On save, the element editor now:
- refuses to save when two terminals share a name, lists the names
  ("N ×3") and selects those terminals;
- warns, and still saves, when a terminal has no name. Folio reports,
  conductor definitions and thumbnails are skipped.

Names are compared after trimming surrounding spaces, case sensitive.

Settings > General > Editor has a new checkbox, on by default, that
turns both checks off (elementeditor/check-terminal-names).

--check-elements applies the same rule: repeated names are a FAIL,
missing names a WARN. It ignores the setting, since it is an explicit
check. On the shipped collection this reports 82 FAILs, the elements
that repeat a terminal name today.

The rule lives in the header-only editor/terminalnamecheck.h, shared
by both, and is unit tested by tst_terminalnamecheck.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
ispyisail
2026-09-30 07:24:55 +13:00
parent f15736bff7
commit bd4d942d71
7 changed files with 242 additions and 1 deletions
+24 -1
View File
@@ -24,6 +24,7 @@
#include "dataBase/projectdatabase.h"
#include "diagram.h"
#include "diagramcontext.h"
#include "editor/terminalnamecheck.h"
#include "dxfexport.h"
#include "exportproperties.h"
#include "pdf_links.h"
@@ -513,7 +514,20 @@ int checkOneElement(const QString &path)
return 2;
}
const int terminals = root.elementsByTagName("terminal").count();
const QDomNodeList terminal_nodes = root.elementsByTagName("terminal");
const int terminals = terminal_nodes.count();
QStringList terminal_names;
for (int i = 0; i < terminals; ++i)
terminal_names << terminal_nodes.at(i).toElement().attribute("name");
// Two terminals with one name cannot be told apart in a wiring list
// (IEC 61666), the same rule the element editor applies on save.
const auto repeated = TerminalNameCheck::repeatedNames(terminal_names);
if (!repeated.isEmpty()) {
out << "FAIL " << path << " (repeated terminal names: "
<< TerminalNameCheck::describe(repeated) << ")\n";
return 2;
}
// Negative dimensions are malformed but QET still loads them; surface as a
// warning rather than a failure so this agrees with QET's own loader.
@@ -528,6 +542,15 @@ int checkOneElement(const QString &path)
return 1;
}
const QString type = root.attribute("link_type");
const int unnamed = TerminalNameCheck::unnamedCount(terminal_names);
if (unnamed && !type.endsWith("_report")
&& type != "conductor_definition" && type != "thumbnail") {
out << "WARN " << path << " (" << unnamed << " of " << terminals
<< " terminals have no name)\n";
return 1;
}
out << "OK " << path << " (" << terminals << " terminals)\n";
return 0;
}