Add a Show name box to the selection properties of a terminal

The box hides the name of the terminal on the sheet only: the element
keeps all of its data, and with the labelling split the terminal keeps
its number, drawn once - in its own field when the symbol has one,
alone in the label field when it has not.

Only a terminal may have its name undrawn: the box is shown for the
element type Terminal alone, and Element::labelShown() obeys the
stored information for a terminal only. The choice is stored as the
element information "label_shown" = "false" and only that, so files
of every element which still draws its name stay exactly as they are.

Multi-selection: the flag appears for terminals only and counts an
absent information as "shown", so a mixed selection shows the box
ticked only when every terminal has it ticked.

Includes four test cases: hidden name keeps the stored data, keeps
the number without a number field, leaves the number to its own
field, and a non-terminal draws its name whatever the file says.
This commit is contained in:
Kellermorph
2026-10-22 12:51:50 +02:00
parent dfec60a3a5
commit edf761c2b6
6 changed files with 238 additions and 4 deletions
+45 -1
View File
@@ -2769,7 +2769,28 @@ QString Element::actualLabel()
QString Element::labelForDisplay()
{
const QString label = actualLabel();
if (!QetSettings::terminalLabelSplit()) {
const bool split = QetSettings::terminalLabelSplit();
//The "Show name" box of the selection properties hides the name
//of this element on the sheet only: the element keeps all of its
//data, and a terminal keeps its number, drawn on its own while
//the labelling is split.
if (!labelShown())
{
if (!split) {
return QString();
}
//The number alone in the label field, but only while the
//symbol has no field of its own for it: the number is
//drawn once, wherever it is drawn at all.
const int hidden_colon = label.lastIndexOf(QLatin1Char(':'));
if (hidden_colon < 0 || hasTerminalNumberText()) {
return QString();
}
return label.mid(hidden_colon + 1);
}
if (!split) {
return label;
}
@@ -2837,6 +2858,29 @@ bool Element::hasTerminalNumberText() const
return false;
}
/**
@brief Element::labelShown
@return whether the label of this element must be drawn on the sheet.
The choice belongs to the element itself, set with the "Show name"
box of the selection properties: an element whose name is not shown
keeps all of its data, nothing is only not drawn. An element which
never got the box unticked keeps drawing its name, which is why a
missing information means true.
*/
bool Element::labelShown() const
{
//Only a terminal may have its name undrawn: an information
//which says otherwise, from whatever source, is not obeyed.
if (m_data.m_type != ElementData::Terminal) {
return true;
}
if (!m_data.m_informations.contains(QStringLiteral("label_shown"))) {
return true;
}
return QET::infoFlagIsTrue(
m_data.m_informations.value(QStringLiteral("label_shown")).toString());
}
/**
@brief Element::infoForDisplay
@return what a text field bound to @p info_name must show: the label
+1
View File
@@ -175,6 +175,7 @@ class Element : public QetGraphicsItem
QString terminalNumberForDisplay();
QString infoForDisplay(const QString &info_name);
bool hasTerminalNumberText() const;
bool labelShown() const;
/**
The fields which draw the label draw it again: called when
what they show of the label has changed under them, a
+51 -1
View File
@@ -262,6 +262,9 @@ void ElementInfoWidget::enableLiveEdit()
if (m_freeze_cb) {
connect(m_freeze_cb, &QCheckBox::clicked, this, &ElementInfoWidget::apply);
}
if (m_label_shown_cb) {
connect(m_label_shown_cb, &QCheckBox::clicked, this, &ElementInfoWidget::apply);
}
if (m_number_cb) {
connect(m_number_cb, QOverload<int>::of(&QComboBox::activated), this, &ElementInfoWidget::apply);
}
@@ -283,6 +286,9 @@ void ElementInfoWidget::disableLiveEdit()
if (m_freeze_cb) {
disconnect(m_freeze_cb, &QCheckBox::clicked, this, &ElementInfoWidget::apply);
}
if (m_label_shown_cb) {
disconnect(m_label_shown_cb, &QCheckBox::clicked, this, &ElementInfoWidget::apply);
}
if (m_number_cb) {
disconnect(m_number_cb, QOverload<int>::of(&QComboBox::activated), this, &ElementInfoWidget::apply);
}
@@ -318,6 +324,7 @@ void ElementInfoWidget::buildInterface()
setupSchemeRow();
setupNumberRow();
setupFreezeRow();
setupLabelShownRow();
m_add_custom_property_btn = new QPushButton(tr("Add a custom property"), this);
connect(m_add_custom_property_btn, &QPushButton::clicked, this, [this]() { addCustomProperty(); });
@@ -367,7 +374,8 @@ QStringList ElementInfoWidget::predefinedKeys() const
keys << QETInformation::ELMT_FORMULA_ID
<< QStringLiteral("auto_num_locked")
<< QStringLiteral("potential_isolating")
<< QStringLiteral("exclude_from_bom");
<< QStringLiteral("exclude_from_bom")
<< QStringLiteral("label_shown");
return keys;
}
@@ -672,6 +680,9 @@ void ElementInfoWidget::updateUi()
m_freeze_cb->setChecked(m_element->isFreezeLabel());
updateFreezeRow();
}
if (m_label_shown_cb) {
m_label_shown_cb->setChecked(m_element->labelShown());
}
refreshNumberRow();
updateSuggestions();
@@ -759,6 +770,13 @@ DiagramContext ElementInfoWidget::currentInfo() const
info_.addValue(QStringLiteral("exclude_from_bom"), m_exclude_from_bom_cb->isChecked() ? QStringLiteral("true") : QStringLiteral("false"));
}
// The name is drawn unless the element says otherwise: only a name
// which is not drawn needs an information, so that elements which
// draw it keep their files exactly as they are.
if (m_label_shown_cb && !m_label_shown_cb->isChecked()) {
info_.addValue(QStringLiteral("label_shown"), QStringLiteral("false"));
}
//The element keeps following its numbering scheme as long as its
//formula is left as it is; a formula edited by hand is its own.
const DiagramContext &elmt_info = m_element->elementInformations();
@@ -846,6 +864,38 @@ void ElementInfoWidget::updateFreezeRow()
updateNumberRow();
}
/**
@brief ElementInfoWidget::setupLabelShownRow
Add under the freeze box a check box which decides whether the name
of this element is drawn on the sheet: the choice belongs to the
placed element, not to the symbol, so everyone can decide for
himself.
*/
void ElementInfoWidget::setupLabelShownRow()
{
//The box means something for a terminal only, so it is drawn
//for a terminal only - the same rule as the function separation
//box just below it.
if (!m_element || m_element->elementData().m_type != ElementData::Terminal) {
return;
}
m_label_shown_cb = new QCheckBox(tr("Show name"), this);
m_label_shown_cb->setObjectName(QStringLiteral("m_label_shown_cb"));
m_label_shown_cb->setToolTip(tr("Untick to not draw the name of this element on the sheet: "
"its data is kept, and a terminal keeps its number."));
int row = ui->scroll_vlayout->indexOf(m_freeze_cb);
if (row < 0) {
ElementInfoPartWidget *label = infoPartWidgetForKey(QETInformation::ELMT_LABEL);
row = label ? ui->scroll_vlayout->indexOf(label) : -1;
}
if (row >= 0) {
ui->scroll_vlayout->insertWidget(row + 1, m_label_shown_cb);
} else {
ui->scroll_vlayout->addWidget(m_label_shown_cb);
}
}
/**
@brief ElementInfoWidget::setupNumberRow
Add under the numbering a list of the numbers the element may be given
+2
View File
@@ -76,6 +76,7 @@ class ElementInfoWidget : public AbstractElementPropertiesEditorWidget
void updateSuggestions();
void setupSchemeRow();
void setupFreezeRow();
void setupLabelShownRow();
void setupNumberRow();
void refreshNumberRow();
void updateNumberRow();
@@ -103,6 +104,7 @@ class ElementInfoWidget : public AbstractElementPropertiesEditorWidget
QCheckBox *m_exclude_from_bom_cb = nullptr;
QComboBox *m_scheme_cb = nullptr;
QCheckBox *m_freeze_cb = nullptr;
QCheckBox *m_label_shown_cb = nullptr;
QWidget *m_number_row = nullptr;
QComboBox *m_number_cb = nullptr;
int m_number_current = -1; ///< the number the element has, -1 if unknown
+19 -2
View File
@@ -75,6 +75,15 @@ quint64 s_last_session = 0;
const QString EXCLUDE_FROM_BOM = QStringLiteral("exclude_from_bom");
const QString AUTO_NUM_LOCKED = QStringLiteral("auto_num_locked");
const QString POTENTIAL_ISOLATING = QStringLiteral("potential_isolating");
//The name is drawn unless the element says otherwise (@sa
//Element::labelShown): an element which never got the box unticked
//has no information for it, and counts as "shown".
const QString LABEL_SHOWN = QStringLiteral("label_shown");
bool flagDefaultIsOn(const QString &key)
{
return key == LABEL_SHOWN;
}
QString flagText(bool on)
{
@@ -449,7 +458,8 @@ void MultiElementInfoWidget::buildInterface()
const QList<QPair<QString, QString>> flags {
{EXCLUDE_FROM_BOM, tr("Exclude from the bill of materials")},
{POTENTIAL_ISOLATING, tr("Function separation")},
{AUTO_NUM_LOCKED, tr("Exclude from automatic numbering")}
{AUTO_NUM_LOCKED, tr("Exclude from automatic numbering")},
{LABEL_SHOWN, tr("Show name")}
};
for (const auto &pair : flags)
{
@@ -588,12 +598,19 @@ void MultiElementInfoWidget::fillRows()
for (Flag *flag : std::as_const(m_flags))
{
//"Show name" means something for a terminal only, so it is
//shown for terminals only - the same rule as the two flags
//before it.
flag->check->setVisible(flag->key == EXCLUDE_FROM_BOM || all_terminals);
flag->restore->setVisible(flag->check->isVisible());
int on = 0;
for (Element *element : list) {
if (QET::infoFlagIsTrue(m_snapshot.value(element).value(flag->key).toString())) {
const QVariant value = m_snapshot.value(element).value(flag->key);
const bool is_on = value.isValid()
? QET::infoFlagIsTrue(value.toString())
: flagDefaultIsOn(flag->key);
if (is_on) {
++on;
}
}
+120
View File
@@ -19,6 +19,8 @@
#include "qetapptest.h"
#include "TerminalStrip/realterminal.h"
#include "TerminalStrip/terminalstrip.h"
#include "diagram.h"
#include "properties/elementdata.h"
#include "qetgraphicsitem/dynamicelementtextitem.h"
#include "qetgraphicsitem/element.h"
#include "qetgraphicsitem/terminal.h"
@@ -85,6 +87,28 @@ class tst_terminallabeldisplay : public QObject
return number;
}
//The "Show name" box of the selection properties, unticked: the
//element then stores the information "label_shown" = "false", the
//only thing it stores for it
static void hideName(Element *element)
{
DiagramContext dc = element->elementInformations();
dc.addValue(QStringLiteral("label_shown"), QStringLiteral("false"));
element->setElementInformations(dc);
}
//Any element of the fixture which is not a terminal and carries a
//name to draw
static Element *aNonTerminal(QETProject &project)
{
for (Diagram *diagram : project.diagrams())
for (Element *element : diagram->elements())
if (element->elementData().m_type != ElementData::Terminal
&& !element->actualLabel().isEmpty())
return element;
return nullptr;
}
private slots:
void cleanup()
{
@@ -215,6 +239,102 @@ private slots:
QCOMPARE(label->toPlainText(), QStringLiteral("X1:1"));
QCOMPARE(element->actualLabel(), QStringLiteral("X1:1"));
}
//A terminal whose name must not be drawn draws nothing of it, but
//keeps everything: the stored label is still there, and so is every
//use of it as data -- only the drawing changes
void hiddenNameKeepsEverythingStored()
{
QetSettings::setTerminalLabelSplit(false);
const QString fixture = QFINDTESTDATA("fixtures/every_feature.qet");
QETProject project(fixture);
QCOMPARE(project.state(), QETProject::Ok);
Element *element = terminalWithLabel(project, QStringLiteral("X1:1"));
QVERIFY(element);
hideName(element);
QVERIFY(!element->labelShown());
QCOMPARE(element->actualLabel(), QStringLiteral("X1:1"));
QCOMPARE(element->labelForDisplay(), QString());
DynamicElementTextItem *label = fieldBoundTo(element, QETInformation::ELMT_LABEL);
QVERIFY(label);
QCOMPARE(label->toPlainText(), QString());
}
//Hidden, and the labelling is split: the terminal keeps its number,
//drawn on its own line while the symbol has no field for it, so
//hiding the name can never hide the number
void hiddenNameKeepsTheNumberWithSplit()
{
QetSettings::setTerminalLabelSplit(true);
const QString fixture = QFINDTESTDATA("fixtures/every_feature.qet");
QETProject project(fixture);
QCOMPARE(project.state(), QETProject::Ok);
Element *element = terminalWithLabel(project, QStringLiteral("X1:1"));
QVERIFY(element);
hideName(element);
QCOMPARE(element->labelForDisplay(), QStringLiteral("1"));
QCOMPARE(element->terminalNumberForDisplay(), QStringLiteral("1"));
QCOMPARE(element->actualLabel(), QStringLiteral("X1:1"));
DynamicElementTextItem *label = fieldBoundTo(element, QETInformation::ELMT_LABEL);
QVERIFY(label);
QCOMPARE(label->toPlainText(), QStringLiteral("1"));
}
//Hidden, split, and the symbol has a field of its own for the
//number: the number is drawn in its own field, the label field
//draws nothing -- the number is never drawn twice
void hiddenNameLeavesTheNumberToItsOwnField()
{
QetSettings::setTerminalLabelSplit(true);
const QString fixture = QFINDTESTDATA("fixtures/every_feature.qet");
QETProject project(fixture);
QCOMPARE(project.state(), QETProject::Ok);
Element *element = terminalWithLabel(project, QStringLiteral("X1:1"));
QVERIFY(element);
DynamicElementTextItem *number = addNumberField(element);
hideName(element);
QCOMPARE(element->labelForDisplay(), QString());
DynamicElementTextItem *label = fieldBoundTo(element, QETInformation::ELMT_LABEL);
QVERIFY(label);
QCOMPARE(label->toPlainText(), QString());
QCOMPARE(number->toPlainText(), QStringLiteral("1"));
}
//Only a terminal may have its name undrawn: another element which
//carries the same information still draws its name, whatever the
//file says
void nonTerminalAlwaysDrawsItsName()
{
QetSettings::setTerminalLabelSplit(false);
const QString fixture = QFINDTESTDATA("fixtures/every_feature.qet");
QETProject project(fixture);
QCOMPARE(project.state(), QETProject::Ok);
Element *element = aNonTerminal(project);
QVERIFY2(element, "the fixture has an element which is no terminal");
DiagramContext dc = element->elementInformations();
dc.addValue(QStringLiteral("label_shown"), QStringLiteral("false"));
element->setElementInformations(dc);
//Whatever the file says, a non-terminal draws its name:
//the information is not obeyed, and the drawn name is the
//stored one, composed as it always is
QVERIFY(element->labelShown());
QVERIFY(!element->actualLabel().isEmpty());
QCOMPARE(element->labelForDisplay(), element->actualLabel());
}
};
QET_APP_TEST_MAIN(tst_terminallabeldisplay)