Add a wires-per-terminal limit, with an application master switch

Discussion #1158: a real terminal takes one or two wires (four with
double ferrules), a folio report is a virtual point that carries one, but
QElectroTech lets any number of wires be connected anywhere.

Project properties > General gets a "Conducteurs par borne" group:
- the most wires a terminal may take (0, the default, is no limit);
- "one wire per folio report".
When set, a new wire that would go past the limit is refused: the
terminal shows red while dragging, as for any refused link, and a tooltip
says why on release. Auto-connect on placing, moving or multi-pasting a
symbol skips full terminals, and qet.addConductor() refuses with its own
message. Wires already drawn, opening, pasting and undo are never
refused.

Settings > General gets a master switch, on by default, that turns every
rule of this feature off in every project; the project group is greyed
with a note while it is off.

The rules live in wiringrules.cpp. The project setting is saved as
<wiring_rules .../> only when a rule is on, so a project that never used
it saves exactly as before; an older version drops it, which means "off".

tst_wiringrules covers the rules, the save round trip and, through the
real binary, that a wire past the limit is refused unless the master
switch is off (checked to fail with the limit check removed).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015FPuYPS4T7QuEwjNu22rXD
This commit is contained in:
ispyisail
2026-10-03 21:42:12 +13:00
parent 6144da0f91
commit 20e134f2bd
15 changed files with 615 additions and 3 deletions
+51 -1
View File
@@ -26,6 +26,9 @@
#include "../qetgraphicsitem/conductor.h"
#include "../qetgraphicsitem/element.h"
#include "conductortextitem.h"
#include "../wiringrules.h"
#include <QToolTip>
#include <QtCore/qnumeric.h>
#include <utility>
@@ -610,7 +613,22 @@ void Terminal::mouseReleaseEvent(QGraphicsSceneMouseEvent *e)
other_terminal -> m_hovered = false;
//We stop her if we can't link this terminal with other terminal
if (!canBeLinkedTo(other_terminal)) return;
if (!canBeLinkedTo(other_terminal))
{
//Say why when it is the wire limit (discussion #1158): a red
//terminal alone does not tell the user what to do instead.
const Terminal *full = !hasRoomForWire() ? this
: !other_terminal->hasRoomForWire() ? other_terminal
: nullptr;
if (full) {
QToolTip::showText(e->screenPos(),
tr("Cette borne a déjà %n conducteur(s), la limite du projet. "
"Ajoutez une borne pour raccorder un conducteur de plus.",
"wire refused by the wires-per-terminal limit",
full->wireLimit()));
}
return;
}
//Create conductor
Conductor *new_conductor = new Conductor(this, other_terminal);
@@ -692,6 +710,7 @@ bool Terminal::isLinkedTo(Terminal *other_terminal) {
Reasons for not linable:
- \p other_terminal is this terminal
- this terminal is already connected to \p other_terminal
- either terminal already has as many wires as the project allows
@param other_terminal
@return true if this terminal can be linked to other_terminal,
otherwise false
@@ -701,9 +720,40 @@ bool Terminal::canBeLinkedTo(Terminal *other_terminal)
if (other_terminal == this || isLinkedTo(other_terminal))
return false;
if (!hasRoomForWire() || !other_terminal->hasRoomForWire())
return false;
return true;
}
/**
@brief Terminal::wireLimit
@return the most wires this terminal may take under its project's
wiring rules (discussion #1158), 0 for no limit.
*/
int Terminal::wireLimit() const
{
const Diagram *parent_diagram = diagram();
if (!parent_diagram || !parent_diagram->project()) {
return 0;
}
const Element *element = parentElement();
const bool is_report = element
&& (element->linkType() & (Element::NextReport | Element::PreviousReport));
return WiringRules::limit(parent_diagram->project()->wiringRules(),
WiringRules::masterEnabled(),
is_report);
}
/**
@brief Terminal::hasRoomForWire
@return true if one more wire may be connected to this terminal
*/
bool Terminal::hasRoomForWire() const
{
return WiringRules::hasRoom(wireLimit(), conductorsCount());
}
/**
@brief Terminal::conductors
@return La liste des conducteurs lies a cette borne