From 1080188f6e00ad66940f06fb4c4394a2d656bfda Mon Sep 17 00:00:00 2001 From: DaTweety <129504390+DaTweety@users.noreply.github.com> Date: Sat, 17 Oct 2026 16:44:43 +0200 Subject: [PATCH 1/3] Add %T, the target folio's title, to report and cross reference formulas A folio report could name the folio it points to by position (%f), folio number (%F), installation (%M) and location (%LM), but not by its title. EPLAN and other tools print references like "+UV1/1 Versorgung UG/EG.0", which with %T is the formula "+%LM/%F %T.%c". - FormulaContext carries the folio title, filled from the title block. - %T is replaced on its own only, not as the start of a longer word. - A report whose formula uses %T follows the target folio's title block (BorderTitleBlock::informationChanged), as %F already follows its folio number. - The report and cross reference property pages list %T. tst_reportfoliotitle checks the replacement, that %total and title block variables keep their values, and an empty title. Co-Authored-By: Claude Opus 5.5 --- sources/autoNum/assignvariables.cpp | 6 ++ sources/autoNum/assignvariables.h | 2 + .../dynamicelementtextitem.cpp | 4 + sources/ui/reportpropertiewidget.ui | 1 + sources/ui/xrefpropertieswidget.ui | 3 +- tests/qttest/CMakeLists.txt | 3 + tests/qttest/tst_reportfoliotitle.cpp | 80 +++++++++++++++++++ 7 files changed, 98 insertions(+), 1 deletion(-) create mode 100644 tests/qttest/tst_reportfoliotitle.cpp diff --git a/sources/autoNum/assignvariables.cpp b/sources/autoNum/assignvariables.cpp index 40563956c..6161fb4fd 100644 --- a/sources/autoNum/assignvariables.cpp +++ b/sources/autoNum/assignvariables.cpp @@ -17,6 +17,8 @@ */ #include "assignvariables.h" +#include + #include "../diagram.h" #include "../diagramposition.h" #include "../qetapp.h" @@ -229,6 +231,7 @@ namespace autonum FormulaContext context; const BorderTitleBlock &border = diagram->border_and_titleblock; context.folio = border.folio(); + context.folio_title = border.title(); context.folio_index = diagram->folioIndex(); context.folio_total = border.folioTotal(); context.plant = border.plant(); @@ -411,6 +414,9 @@ namespace autonum QString::number(m_context.folio_total)); m_assigned_label.replace("%M", m_context.plant); m_assigned_label.replace("%LM", m_context.locmach); + //%T on its own only, not the start of a longer word + static const QRegularExpression folio_title(QStringLiteral("%T(?![A-Za-z0-9_])")); + m_assigned_label.replace(folio_title, m_context.folio_title); QSettings settings; if (m_context.has_element) diff --git a/sources/autoNum/assignvariables.h b/sources/autoNum/assignvariables.h index 04e353274..1864f3fb3 100644 --- a/sources/autoNum/assignvariables.h +++ b/sources/autoNum/assignvariables.h @@ -69,6 +69,8 @@ namespace autonum { /// border_and_titleblock.folio(), folioIndex(), folioTotal()... QString folio; + /// the folio's title, %T + QString folio_title; int folio_index = 0; int folio_total = 0; QString plant; diff --git a/sources/qetgraphicsitem/dynamicelementtextitem.cpp b/sources/qetgraphicsitem/dynamicelementtextitem.cpp index 9512ea0e0..fcc5e4121 100644 --- a/sources/qetgraphicsitem/dynamicelementtextitem.cpp +++ b/sources/qetgraphicsitem/dynamicelementtextitem.cpp @@ -1261,6 +1261,8 @@ void DynamicElementTextItem::setConnectionForReportFormula(const QString &formul connect(other_diagram->project(), &QETProject::projectDiagramsOrderChanged, this, &DynamicElementTextItem::updateReportText); connect(other_diagram->project(), &QETProject::diagramRemoved, this, &DynamicElementTextItem::updateReportText); } + if (other_diagram && string.contains("%T")) + connect(&other_diagram->border_and_titleblock, &BorderTitleBlock::informationChanged, this, &DynamicElementTextItem::updateReportText); if (string.contains("%l")) connect(other_elmt, &Element::yChanged, this, &DynamicElementTextItem::updateReportText); if (string.contains("%c")) @@ -1286,6 +1288,8 @@ void DynamicElementTextItem::removeConnectionForReportFormula(const QString &for if (other_diagram && (string.contains("%f") || string.contains("%id"))) disconnect(other_diagram->project(), &QETProject::projectDiagramsOrderChanged, this, &DynamicElementTextItem::updateReportText); + if (other_diagram && string.contains("%T")) + disconnect(&other_diagram->border_and_titleblock, &BorderTitleBlock::informationChanged, this, &DynamicElementTextItem::updateReportText); if (string.contains("%l")) disconnect(other_element, &Element::yChanged, this, &DynamicElementTextItem::updateReportText); if (string.contains("%c")) diff --git a/sources/ui/reportpropertiewidget.ui b/sources/ui/reportpropertiewidget.ui index 4ca2b3504..019ab37ee 100644 --- a/sources/ui/reportpropertiewidget.ui +++ b/sources/ui/reportpropertiewidget.ui @@ -38,6 +38,7 @@ Create your own text using the following variables: %F: the sheet number %M: the installation %LM: the location +%T: the sheet title %l: the row number %c: the column number diff --git a/sources/ui/xrefpropertieswidget.ui b/sources/ui/xrefpropertieswidget.ui index 5e3ac7f71..31fc1f387 100644 --- a/sources/ui/xrefpropertieswidget.ui +++ b/sources/ui/xrefpropertieswidget.ui @@ -285,7 +285,8 @@ %l: the row number %c: the column number %M: the installation -%LM: the location +%LM: the location +%T: the sheet title diff --git a/tests/qttest/CMakeLists.txt b/tests/qttest/CMakeLists.txt index 6dd92f413..eb6cf36cf 100644 --- a/tests/qttest/CMakeLists.txt +++ b/tests/qttest/CMakeLists.txt @@ -278,6 +278,9 @@ target_compile_definitions(tst_multielementinfo PRIVATE # collection paths just chosen, not the ones they replace. qet_add_app_test(tst_assistantinfopaths tst_assistantinfopaths.cpp) +# %T in a report or cross reference formula is the target folio's title. +qet_add_app_test(tst_reportfoliotitle tst_reportfoliotitle.cpp) + # Escape during a picture's resize, rotate or pivot drag puts it back, keeps # it selected and records no undo step (#1414); the key goes to the view. qet_add_app_test(tst_imagehandleescape tst_imagehandleescape.cpp) diff --git a/tests/qttest/tst_reportfoliotitle.cpp b/tests/qttest/tst_reportfoliotitle.cpp new file mode 100644 index 000000000..1e0945e2f --- /dev/null +++ b/tests/qttest/tst_reportfoliotitle.cpp @@ -0,0 +1,80 @@ +/* + Copyright 2006-2026 The QElectroTech Team + This file is part of QElectroTech. + + QElectroTech is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + QElectroTech is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with QElectroTech. If not, see . +*/ +#include "qetapptest.h" +#include "autoNum/assignvariables.h" + +#include + +/** + %T in a folio report or cross reference formula is the title of the + folio the reference points to, so a reference can read like the ones + EPLAN prints: "+UV1/1 Versorgung UG/EG.0". %total and the title block + and project variables (lower case only) keep their own values. +*/ +class tst_reportfoliotitle : public QObject +{ + Q_OBJECT + + static QString label(const QString &formula, const autonum::FormulaContext &c) + { + autonum::sequentialNumbers seq; + return autonum::AssignVariables::formulaToLabel(formula, seq, c); + } + + static autonum::FormulaContext context() + { + autonum::FormulaContext c; + c.folio = QStringLiteral("1"); + c.folio_title = QStringLiteral("Versorgung UG/EG"); + c.folio_index = 2; + c.folio_total = 23; + c.locmach = QStringLiteral("UV1"); + return c; + } + +private slots: + void titleIsReplaced() + { + const QString result = label(QStringLiteral("+%LM/%F %T"), context()); + QCOMPARE(result, QStringLiteral("+UV1/1 Versorgung UG/EG")); + } + + void otherVariablesKeepTheirValue() + { + autonum::FormulaContext c = context(); + c.title_block_fields.addValue(QStringLiteral("typ"), QStringLiteral("SH363N")); + const QString result = label(QStringLiteral("%T / %total / %typ / %{typ}"), c); + QCOMPARE(result, QStringLiteral("Versorgung UG/EG / 23 / SH363N / SH363N")); + } + + void emptyTitleLeavesNothing() + { + autonum::FormulaContext c = context(); + c.folio_title.clear(); + const QString result = label(QStringLiteral("%F%T"), c); + QCOMPARE(result, QStringLiteral("1")); + } +}; + +int main(int argc, char **argv) +{ + QStandardPaths::setTestModeEnabled(true); + return QetAppTest::run(argc, argv); +} + +#include "tst_reportfoliotitle.moc" From ff65b85357b69edb8483aaf205f6aaccf69cbbb5 Mon Sep 17 00:00:00 2001 From: DaTweety <129504390+DaTweety@users.noreply.github.com> Date: Sat, 17 Oct 2026 20:22:57 +0200 Subject: [PATCH 2/3] Report composite texts: element information and the partner's label A folio report whose text is a composite text replaced only %{label} and the conductor variables. The report's own information is now replaced as well, as on any other element, so a report can name the device and terminal it leads to: "%{comment} %{label}" reads "-XS27:N +UV1/2 UG Raum - 1.1" like EPLAN's interruption points. Changing a report's information rebuilt such a text the way an ordinary element's is built, turning %{label} into the report's stored label, where its partner was when last saved. It now takes the same text updateReportText() builds. Co-Authored-By: Claude Opus 5.5 --- sources/qetgraphicsitem/dynamicelementtextitem.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/sources/qetgraphicsitem/dynamicelementtextitem.cpp b/sources/qetgraphicsitem/dynamicelementtextitem.cpp index fcc5e4121..51a14ed0b 100644 --- a/sources/qetgraphicsitem/dynamicelementtextitem.cpp +++ b/sources/qetgraphicsitem/dynamicelementtextitem.cpp @@ -1143,7 +1143,12 @@ void DynamicElementTextItem::elementInfoChanged() if (m_composite_text.contains("%{label}")) setupFormulaConnection(); - final_text = autonum::AssignVariables::replaceVariable(m_composite_text, dc); + //A report's %{label} is where its partner is, not its own + //label: the same text updateReportText() builds + if (m_parent_element && (m_parent_element.data()->linkType() & Element::AllReport)) + final_text = reportReplacedCompositeText(); + else + final_text = autonum::AssignVariables::replaceVariable(m_composite_text, dc); } else if (m_text_from == UserText) final_text = m_text; @@ -1584,6 +1589,13 @@ QString DynamicElementTextItem::reportReplacedCompositeText() const if(string.contains("%{conductor_section}")) string.replace("%{conductor_section}", ""); } + + //What is left is the report's own information, as in the + //composite text of any other element: a report can then say + //which device and terminal it leads to (%{comment}), the way + //EPLAN prints "-XS27:N 2 UG Raum - 1.1" + string = autonum::AssignVariables::replaceVariable( + string, m_parent_element.data()->elementInformations()); } return string; From ba64fd5164da2499ed5500b9931e89f78a71a826 Mon Sep 17 00:00:00 2001 From: DaTweety <129504390+DaTweety@users.noreply.github.com> Date: Sun, 18 Oct 2026 22:52:06 +0200 Subject: [PATCH 3/3] %T last: a folio title keeps the variables it contains The folio title was put into the formula before %c, %l, %prefix, the wire variables, the title block and project variables and the sequences, so a title such as "Schema %c" had them replaced inside it. It is replaced after all of them now. Co-Authored-By: Claude Opus 5.5 --- sources/autoNum/assignvariables.cpp | 9 ++++++--- tests/qttest/tst_reportfoliotitle.cpp | 12 +++++++++++- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/sources/autoNum/assignvariables.cpp b/sources/autoNum/assignvariables.cpp index 6161fb4fd..6eed17367 100644 --- a/sources/autoNum/assignvariables.cpp +++ b/sources/autoNum/assignvariables.cpp @@ -414,9 +414,6 @@ namespace autonum QString::number(m_context.folio_total)); m_assigned_label.replace("%M", m_context.plant); m_assigned_label.replace("%LM", m_context.locmach); - //%T on its own only, not the start of a longer word - static const QRegularExpression folio_title(QStringLiteral("%T(?![A-Za-z0-9_])")); - m_assigned_label.replace(folio_title, m_context.folio_title); QSettings settings; if (m_context.has_element) @@ -441,6 +438,12 @@ namespace autonum assignTitleBlockVar(); assignProjectVar(); assignSequence(); + + //The folio title last: it is free text, and a title such as + //"Schema %c" must stay as typed, not have the variables in it + //replaced. %T on its own only, not the start of a longer word. + static const QRegularExpression folio_title(QStringLiteral("%T(?![A-Za-z0-9_])")); + m_assigned_label.replace(folio_title, m_context.folio_title); } void AssignVariables::assignTitleBlockVar() diff --git a/tests/qttest/tst_reportfoliotitle.cpp b/tests/qttest/tst_reportfoliotitle.cpp index 1e0945e2f..24bd9f4f9 100644 --- a/tests/qttest/tst_reportfoliotitle.cpp +++ b/tests/qttest/tst_reportfoliotitle.cpp @@ -24,7 +24,8 @@ %T in a folio report or cross reference formula is the title of the folio the reference points to, so a reference can read like the ones EPLAN prints: "+UV1/1 Versorgung UG/EG.0". %total and the title block - and project variables (lower case only) keep their own values. + and project variables (lower case only) keep their own values, and the + title itself is free text: variables in it stay as typed. */ class tst_reportfoliotitle : public QObject { @@ -62,6 +63,15 @@ private slots: QCOMPARE(result, QStringLiteral("Versorgung UG/EG / 23 / SH363N / SH363N")); } + void titleKeepsTheVariablesItContains() + { + autonum::FormulaContext c = context(); + c.folio_title = QStringLiteral("Schema %c %F %total %{typ}"); + c.title_block_fields.addValue(QStringLiteral("typ"), QStringLiteral("SH363N")); + const QString result = label(QStringLiteral("%F %T"), c); + QCOMPARE(result, QStringLiteral("1 Schema %c %F %total %{typ}")); + } + void emptyTitleLeavesNothing() { autonum::FormulaContext c = context();