Draw a terminal's label and its number apart, when asked to

A terminal's label is written as it is read off the plan, "X1:1", and
the symbol draws it as one field. On a long strip that field is long
enough to reach into the next terminal, and a user who wants the number
next to the screw and the label out of the way has no way to say so.

Settings > General > Appearance now has a "Display of the terminal
labelling" group with two choices: the label and its terminal number in
one field, the way it has always been drawn, or the two split. The
first is what every drawing gets, so nothing moves until the user asks
for it, and choosing the other one redraws the drawings already open --
nothing needs to be closed and opened again.

A symbol made for the split carries a text field bound to the new
"Terminal number" information (in the element editor's list, next to
the label, and as the %{terminal_number} variable of a composite text):
the label field then shows "X1" and the number field "1", each placed
where the symbol wants it, and hideable when it must be. A symbol which
has no such field -- every symbol drawn until now -- gets the number on
its own line inside the label field, so switching the setting on can
never make a number vanish, and never needs a symbol to be touched
first. A field which becomes, or stops being, the number field tells
the label fields of its symbol to draw themselves again.

Only the drawing reacts. What the element stores, the numbering, the
sorting in the terminal strip editor, the automatic strip import and
every export keep the whole label: the split is read where the text is
drawn (Element::labelForDisplay() and friends), not where the label is
made.

The new test covers both choices, with and without the number field, a
label with no colon at all, and the way back to the whole label. The
full test suite passes (124/124).
This commit is contained in:
Kellermorph
2026-10-22 09:40:02 +02:00
parent 149d92545d
commit dfec60a3a5
12 changed files with 599 additions and 21 deletions
@@ -46,6 +46,20 @@
#include <QTextCursor>
#include <QTextDocumentFragment>
namespace {
/**
A composite text which uses the terminal number follows the label
as closely as one which uses %{label}: both are drawn from the
label of the element, and from the formula that label is made of.
*/
bool usesLabelVariables(const QString &composite_text)
{
return composite_text.contains(QLatin1String("%{label}"))
|| composite_text.contains(
QStringLiteral("%{") + QETInformation::ELMT_TERMINAL_NUMBER + QLatin1String("}"));
}
}
void DynamicElementTextItem::keyPressEvent(QKeyEvent *event)
{
if (!event->matches(QKeySequence::Paste) || m_text_from != UserText ||
@@ -401,8 +415,10 @@ Element *DynamicElementTextItem::elementUseForInfo() const
*/
void DynamicElementTextItem::refreshLabelConnection()
{
if ((m_text_from == ElementInfo && m_info_name == "label") ||
(m_text_from == CompositeText && m_composite_text.contains("%{label}")))
if ((m_text_from == ElementInfo &&
(m_info_name == QLatin1String("label")
|| m_info_name == QETInformation::ELMT_TERMINAL_NUMBER)) ||
(m_text_from == CompositeText && usesLabelVariables(m_composite_text)))
{
if((m_parent_element.data()->linkType() & Element::AllReport) ||
m_parent_element.data()->linkType() == Element::ConductorDefinition)
@@ -450,26 +466,34 @@ void DynamicElementTextItem::setTextFrom(DynamicElementTextItem::TextFrom text_f
}
else if (m_text_from == ElementInfo && elementUseForInfo())
{
if(m_info_name == "label")
if(m_info_name == QLatin1String("label")
|| m_info_name == QETInformation::ELMT_TERMINAL_NUMBER)
{
setupFormulaConnection();
updateLabel();
}
else
setPlainText(elementUseForInfo()->elementInformations().value(m_info_name).toString());
setPlainText(elementUseForInfo()->infoForDisplay(m_info_name));
if(old_text_from == UserText)
connect(elementUseForInfo(), &Element::elementInfoChange, this, &DynamicElementTextItem::elementInfoChanged);
}
else if (m_text_from == CompositeText && elementUseForInfo())
{
if(m_composite_text.contains("%{label}"))
if(usesLabelVariables(m_composite_text))
{
setupFormulaConnection();
updateLabel();
}
else
setPlainText(autonum::AssignVariables::replaceVariable(m_composite_text, elementUseForInfo()->elementInformations()));
{
//The label and the terminal number are drawn the way the
//settings say, every other information as it is stored
DiagramContext dc = elementUseForInfo()->elementInformations();
dc.addValue(QETInformation::ELMT_LABEL, elementUseForInfo()->labelForDisplay());
dc.addValue(QETInformation::ELMT_TERMINAL_NUMBER, elementUseForInfo()->terminalNumberForDisplay());
setPlainText(autonum::AssignVariables::replaceVariable(m_composite_text, dc));
}
if(old_text_from == UserText)
connect(elementUseForInfo(), &Element::elementInfoChange, this, &DynamicElementTextItem::elementInfoChanged);
@@ -478,7 +502,16 @@ void DynamicElementTextItem::setTextFrom(DynamicElementTextItem::TextFrom text_f
if(m_parent_element.data()->linkType() == Element::Master ||
m_parent_element.data()->linkType() == Element::Slave)
updateXref();
//A field which becomes, or stops being, the field for the
//terminal number changes what the label of the symbol leaves
//to it (@sa Element::labelForDisplay)
if (m_info_name == QETInformation::ELMT_TERMINAL_NUMBER
&& (m_text_from == ElementInfo || old_text_from == ElementInfo)
&& parentElement()) {
parentElement()->refreshLabelFields();
}
emit textFromChanged(m_text_from);
}
@@ -515,7 +548,8 @@ void DynamicElementTextItem::setInfoName(const QString &info_name)
m_info_name = info_name;
if(old_info_name == "label")
if(old_info_name == QLatin1String("label")
|| old_info_name == QETInformation::ELMT_TERMINAL_NUMBER)
{
clearFormulaConnection();
updateXref();
@@ -538,14 +572,25 @@ void DynamicElementTextItem::setInfoName(const QString &info_name)
conductorPropertiesChanged();
}
}
else if (m_info_name == "label" && elementUseForInfo())
else if ((m_info_name == QLatin1String("label")
|| m_info_name == QETInformation::ELMT_TERMINAL_NUMBER)
&& elementUseForInfo())
{
setupFormulaConnection();
updateLabel();
updateXref();
}
else if(elementUseForInfo() && m_text_from == DynamicElementTextItem::ElementInfo) {
setPlainText(elementUseForInfo()->elementInformations().value(info_name).toString());
setPlainText(elementUseForInfo()->infoForDisplay(info_name));
}
//A field which becomes, or stops being, the field for the
//terminal number changes what the label of the symbol leaves
//to it (@sa Element::labelForDisplay)
if (parentElement()
&& (info_name == QETInformation::ELMT_TERMINAL_NUMBER
|| old_info_name == QETInformation::ELMT_TERMINAL_NUMBER)) {
parentElement()->refreshLabelFields();
}
emit infoNameChanged(info_name);
@@ -1174,6 +1219,12 @@ void DynamicElementTextItem::elementInfoChanged()
Element *element = elementUseForInfo();
if(element) {
dc = element->elementInformations();
//The label and the terminal number are drawn the way the
//settings say (@sa QetSettings::terminalLabelSplit): a
//composite text which uses them must see the same values the
//fields bound to them show
dc.addValue(QETInformation::ELMT_LABEL, element->labelForDisplay());
dc.addValue(QETInformation::ELMT_TERMINAL_NUMBER, element->terminalNumberForDisplay());
}
QString final_text;
@@ -1183,12 +1234,13 @@ void DynamicElementTextItem::elementInfoChanged()
{
//If the info is the label, then we must make some connection
//if the label is created from a formula
if(m_info_name == "label")
if(m_info_name == QLatin1String("label")
|| m_info_name == QETInformation::ELMT_TERMINAL_NUMBER)
{
setupFormulaConnection();
if (element) {
final_text = element->actualLabel();
final_text = element->infoForDisplay(m_info_name);
}
}
else {
@@ -1199,7 +1251,7 @@ void DynamicElementTextItem::elementInfoChanged()
{
//If the composite have the label variable, we must make some
//connection if the label is created from a formula
if (m_composite_text.contains("%{label}"))
if (usesLabelVariables(m_composite_text))
setupFormulaConnection();
//A report's %{label} is where its partner is, not its own
@@ -1367,8 +1419,10 @@ void DynamicElementTextItem::removeConnectionForReportFormula(const QString &for
*/
void DynamicElementTextItem::setupFormulaConnection()
{
if ((m_text_from == ElementInfo && m_info_name == "label") ||
(m_text_from == CompositeText && m_composite_text.contains("%{label}")))
if ((m_text_from == ElementInfo &&
(m_info_name == QLatin1String("label")
|| m_info_name == QETInformation::ELMT_TERMINAL_NUMBER)) ||
(m_text_from == CompositeText && usesLabelVariables(m_composite_text)))
{
clearFormulaConnection();
@@ -1458,8 +1512,10 @@ void DynamicElementTextItem::updateReportText()
*/
void DynamicElementTextItem::updateLabel()
{
if ((m_text_from == ElementInfo && m_info_name == "label") ||
(m_text_from == CompositeText && m_composite_text.contains("%{label}")))
if ((m_text_from == ElementInfo &&
(m_info_name == QLatin1String("label")
|| m_info_name == QETInformation::ELMT_TERMINAL_NUMBER)) ||
(m_text_from == CompositeText && usesLabelVariables(m_composite_text)))
{
DiagramContext dc;
Element *element = elementUseForInfo();
@@ -1469,19 +1525,21 @@ void DynamicElementTextItem::updateLabel()
if(m_text_from == ElementInfo && element) {
QString new_label = element->actualLabel();
QString new_label = element->infoForDisplay(m_info_name);
if (toPlainText() != new_label) {
setPlainText(new_label);
}
}
else if (m_text_from == CompositeText) {
// Use actualLabel() to ensure %{label} reflects the current
// resolved label (e.g. after a folio/page-number change).
// Use the label as it must be drawn, so %{label} and
// %{terminal_number} reflect the current resolved label (e.g.
// after a folio/page-number change).
// A contact not linked to a coil has no element to read from
// (bugtracker #345): %{label} then shows empty, as it did
// before actualLabel() was used here.
if (element) {
dc.addValue(QStringLiteral("label"), element->actualLabel());
dc.addValue(QETInformation::ELMT_LABEL, element->labelForDisplay());
dc.addValue(QETInformation::ELMT_TERMINAL_NUMBER, element->terminalNumberForDisplay());
}
setPlainText(autonum::AssignVariables::replaceVariable(m_composite_text, dc));
}