From c23999acd113c20da60a43f809231d8247c1c11e Mon Sep 17 00:00:00 2001 From: Levi Jetzer Date: Tue, 11 Aug 2026 16:09:34 +0200 Subject: [PATCH 1/6] Added width/height/depth properties to element definitions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds three new elementInformation keys — width, height, depth (in mm) — alongside the existing manufacturer/manufacturer_reference fields. These describe the physical dimensions of the device a symbol represents, set once per element definition. Values are restricted to plain decimal numbers via a QDoubleValidator on the information tree's item delegate (fixed-point, "." as decimal separator via QLocale::c(), independent of the UI language), so a later consumer can always parse them with toDouble() without additional sanitization. --- .../ui/elementpropertieseditorwidget.cpp | 19 ++++++++++++++++--- sources/qetinformation.cpp | 11 ++++++++++- sources/qetinformation.h | 3 +++ 3 files changed, 29 insertions(+), 4 deletions(-) diff --git a/sources/editor/ui/elementpropertieseditorwidget.cpp b/sources/editor/ui/elementpropertieseditorwidget.cpp index 6a09de091..01b4b6497 100644 --- a/sources/editor/ui/elementpropertieseditorwidget.cpp +++ b/sources/editor/ui/elementpropertieseditorwidget.cpp @@ -64,9 +64,22 @@ class EditorDelegate : public QItemDelegate { if(index.column() == 1) { - return QItemDelegate::createEditor(parent, - option, - index); + const QString key = index.sibling(index.row(), 0) + .data(Qt::UserRole).toString(); + + if (key == QETInformation::ELMT_WIDTH || + key == QETInformation::ELMT_HEIGHT || + key == QETInformation::ELMT_DEPTH) + { + auto *line_edit = new QLineEdit(parent); + auto *validator = new QDoubleValidator(0.0, 100000.0, 4, line_edit); + validator->setNotation(QDoubleValidator::StandardNotation); + validator->setLocale(QLocale::c()); + line_edit->setValidator(validator); + return line_edit; + } + + return QItemDelegate::createEditor(parent, option, index); } return nullptr; } diff --git a/sources/qetinformation.cpp b/sources/qetinformation.cpp index de28925ef..d5df1cea1 100644 --- a/sources/qetinformation.cpp +++ b/sources/qetinformation.cpp @@ -153,7 +153,10 @@ QStringList QETInformation::elementInfoKeys() ELMT_MACHINE_MANUFACTURER_REF, ELMT_SUPPLIER, ELMT_QUANTITY, - ELMT_UNITY, + ELMT_UNITY, + ELMT_WIDTH, + ELMT_HEIGHT, + ELMT_DEPTH, ELMT_AUX1, ELMT_DESCRIPTION_AUX1, ELMT_DESIGNATION_AUX1, @@ -268,6 +271,9 @@ QString QETInformation::translatedInfoKey(const QString &info) else if (info == ELMT_SUPPLIER) return QObject::tr("Fournisseur"); else if (info == ELMT_QUANTITY) return QObject::tr("Quantité"); else if (info == ELMT_UNITY) return QObject::tr("Unité"); + else if (info == ELMT_WIDTH) return QObject::tr("Largeur [mm]"); + else if (info == ELMT_HEIGHT) return QObject::tr("Hauteur [mm]"); + else if (info == ELMT_DEPTH) return QObject::tr("Profondeur [mm]"); else if (info == ELMT_LOCATION) return QObject::tr("Localisation (+)"); else if (info == COND_FUNCTION) return QObject::tr("Fonction"); else if (info == COND_TENSION_PROTOCOL) return QObject::tr("Tension / Protocole"); @@ -334,6 +340,9 @@ QStringList QETInformation::elementEditorElementInfoKeys() ELMT_SUPPLIER, ELMT_QUANTITY, ELMT_UNITY, + ELMT_WIDTH, + ELMT_HEIGHT, + ELMT_DEPTH, ELMT_AUX1, ELMT_DESCRIPTION_AUX1, ELMT_DESIGNATION_AUX1, diff --git a/sources/qetinformation.h b/sources/qetinformation.h index 2aab78e95..569d9021b 100644 --- a/sources/qetinformation.h +++ b/sources/qetinformation.h @@ -45,6 +45,9 @@ namespace QETInformation static QString ELMT_SUPPLIER = "supplier"; static QString ELMT_QUANTITY = "quantity"; static QString ELMT_UNITY = "unity"; + static QString ELMT_WIDTH = "width"; + static QString ELMT_HEIGHT = "height"; + static QString ELMT_DEPTH = "depth"; static QString ELMT_PLANT = "plant"; static QString ELMT_LOCATION = "location"; static QString ELMT_AUX1 = "auxiliary1"; From 73473222211d53e4e6c657393b25a9e50aa21c14 Mon Sep 17 00:00:00 2001 From: Levi Jetzer Date: Tue, 11 Aug 2026 18:01:10 +0200 Subject: [PATCH 2/6] Replace QDoubleValidator with QRegularExpressionValidator on width/height/depth fields The selection properties dock (elementinfopartwidget.cpp) and the element editor's information tree (elementpropertieseditorwidget.cpp's EditorDelegate) both restrict the width/height/depth fields added for cabinet layout support to numeric input via a validator. QDoubleValidator follows the system/UI locale for its decimal separator, which meant a comma was accepted as an intermediate state and left the field impossible to leave in some contexts, even though it was never a valid final value. Switch both to a QRegularExpressionValidator matching ^[0-9]*\.?[0-9]{0,4}$: "." is a literal character in the pattern, not locale-dependent, and [0-9] (rather than \d) excludes non-ASCII digits. This guarantees a value entered this way can always be read back with QString::toDouble() without locale handling. The check for which keys are numeric (QETInformation::isNumericInfoKey) is shared between both call sites; the validator setup itself stays local to each, since QETInformation intentionally has no Qt Widgets dependency. Also adds a placeholder ("ex. 80.5") and tooltip explaining the expected format. --- sources/editor/ui/elementpropertieseditorwidget.cpp | 12 +++++------- sources/ui/elementinfopartwidget.cpp | 11 +++++++++++ 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/sources/editor/ui/elementpropertieseditorwidget.cpp b/sources/editor/ui/elementpropertieseditorwidget.cpp index 01b4b6497..e04b0bc01 100644 --- a/sources/editor/ui/elementpropertieseditorwidget.cpp +++ b/sources/editor/ui/elementpropertieseditorwidget.cpp @@ -20,7 +20,6 @@ #include "../../qetapp.h" #include "../../qetinformation.h" #include "ui_elementpropertieseditorwidget.h" -#include "../../qetinformation.h" #include #include @@ -67,15 +66,14 @@ class EditorDelegate : public QItemDelegate const QString key = index.sibling(index.row(), 0) .data(Qt::UserRole).toString(); - if (key == QETInformation::ELMT_WIDTH || - key == QETInformation::ELMT_HEIGHT || - key == QETInformation::ELMT_DEPTH) + if (key == QETInformation::ELMT_WIDTH || key == QETInformation::ELMT_HEIGHT || key == QETInformation::ELMT_DEPTH) { auto *line_edit = new QLineEdit(parent); - auto *validator = new QDoubleValidator(0.0, 100000.0, 4, line_edit); - validator->setNotation(QDoubleValidator::StandardNotation); - validator->setLocale(QLocale::c()); + auto *validator = new QRegularExpressionValidator( + QRegularExpression(QStringLiteral(R"(^[0-9]*\.?[0-9]{0,4}$)")), line_edit); line_edit->setValidator(validator); + line_edit->setPlaceholderText(tr("ex. 80.5")); + line_edit->setToolTip(tr("Nombre décimal avec un point comme séparateur (ex. 80.5)")); return line_edit; } diff --git a/sources/ui/elementinfopartwidget.cpp b/sources/ui/elementinfopartwidget.cpp index 08da68d63..0132de4ca 100644 --- a/sources/ui/elementinfopartwidget.cpp +++ b/sources/ui/elementinfopartwidget.cpp @@ -18,7 +18,9 @@ #include "elementinfopartwidget.h" #include "../SearchAndReplace/searchandreplaceworker.h" +#include "../qetinformation.h" #include "ui_elementinfopartwidget.h" +#include #include @@ -43,6 +45,15 @@ ElementInfoPartWidget::ElementInfoPartWidget( ui->label_->setText(translated_key); ui->m_erase_text->setVisible(false); + if (key == QETInformation::ELMT_WIDTH || key == QETInformation::ELMT_HEIGHT || key == QETInformation::ELMT_DEPTH) + { + auto *validator = new QRegularExpressionValidator( + QRegularExpression(QStringLiteral(R"(^[0-9]*\.?[0-9]{0,4}$)")), ui->line_edit); + ui->line_edit->setValidator(validator); + ui->line_edit->setPlaceholderText(tr("ex. 80.5")); + ui->line_edit->setToolTip(tr("Nombre décimal avec un point comme séparateur (ex. 80.5)")); + } + connect(ui->line_edit, &QLineEdit::textEdited, this, &ElementInfoPartWidget::textEdited); connect(ui->line_edit, &QLineEdit::textChanged, From c6e7c5d37109b96ef05cb8f583b2f4c01d554927 Mon Sep 17 00:00:00 2001 From: Levi Jetzer Date: Tue, 11 Aug 2026 18:28:29 +0200 Subject: [PATCH 3/6] Fixed issue of taking wrong variable (key instead of key_) in elementinfopartwidget.cpp for regex checker and helping info (tooltip, placeholder) --- sources/ui/elementinfopartwidget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sources/ui/elementinfopartwidget.cpp b/sources/ui/elementinfopartwidget.cpp index 0132de4ca..dcb5f6842 100644 --- a/sources/ui/elementinfopartwidget.cpp +++ b/sources/ui/elementinfopartwidget.cpp @@ -45,7 +45,7 @@ ElementInfoPartWidget::ElementInfoPartWidget( ui->label_->setText(translated_key); ui->m_erase_text->setVisible(false); - if (key == QETInformation::ELMT_WIDTH || key == QETInformation::ELMT_HEIGHT || key == QETInformation::ELMT_DEPTH) + if (key_ == QETInformation::ELMT_WIDTH || key_ == QETInformation::ELMT_HEIGHT || key_ == QETInformation::ELMT_DEPTH) { auto *validator = new QRegularExpressionValidator( QRegularExpression(QStringLiteral(R"(^[0-9]*\.?[0-9]{0,4}$)")), ui->line_edit); From 5dbb9f28def60d3f6bc21a81d1cd5c2e5562bc6e Mon Sep 17 00:00:00 2001 From: Levi Jetzer Date: Wed, 12 Aug 2026 08:43:42 +0200 Subject: [PATCH 4/6] Fix numeric field validation gaps found in review Address feedback on the width/height/depth elementInformation fields: - The regex accepted "." alone as a complete value ([0-9]* permits zero digits on both sides), meaning a field could be committed with a literal "." saved to the XML. Require at least one digit either before or after the separator. - The same pattern was duplicated verbatim in elementinfopartwidget.cpp and elementpropertieseditorwidget.cpp's EditorDelegate. Factored into QETInformation::numericInfoPattern(), a single shared definition both call sites now use. - Tightened the pattern to at most 2 decimal places (down from 4) to match the precision actually meaningful for these fields. Not changed, by design: - Storage stays a plain string, consistent with every other numeric elementInformation field (quantity etc.) in this codebase -- values round-trip through XML text regardless, so a long/micron representation wouldn't avoid the string<->number conversion, only relocate it. - No decimal-comma normalization needed: with the fixed pattern, only digits and "." are ever accepted at the keystroke level, so an alternate separator can't enter the field in the first place. --- .../editor/ui/elementpropertieseditorwidget.cpp | 2 +- sources/qetinformation.cpp | 12 ++++++++++++ sources/qetinformation.h | 14 +++++++++----- sources/ui/elementinfopartwidget.cpp | 2 +- 4 files changed, 23 insertions(+), 7 deletions(-) diff --git a/sources/editor/ui/elementpropertieseditorwidget.cpp b/sources/editor/ui/elementpropertieseditorwidget.cpp index e04b0bc01..e63f8338f 100644 --- a/sources/editor/ui/elementpropertieseditorwidget.cpp +++ b/sources/editor/ui/elementpropertieseditorwidget.cpp @@ -70,7 +70,7 @@ class EditorDelegate : public QItemDelegate { auto *line_edit = new QLineEdit(parent); auto *validator = new QRegularExpressionValidator( - QRegularExpression(QStringLiteral(R"(^[0-9]*\.?[0-9]{0,4}$)")), line_edit); + QETInformation::numericInfoPattern(), line_edit); line_edit->setValidator(validator); line_edit->setPlaceholderText(tr("ex. 80.5")); line_edit->setToolTip(tr("Nombre décimal avec un point comme séparateur (ex. 80.5)")); diff --git a/sources/qetinformation.cpp b/sources/qetinformation.cpp index d5df1cea1..d6c2f769b 100644 --- a/sources/qetinformation.cpp +++ b/sources/qetinformation.cpp @@ -216,6 +216,18 @@ QString QETInformation::elementInfoToVar(const QString &info) return (QString ("%{void}")); } +/** + * @brief QETInformation::numericInfoPattern + * @return the pattern used to validate numeric elementInformation + * fields (currently width/height/depth): digits with an optional "." + * as decimal separator, requiring at least one digit overall so a + * lone "." can never be a complete, acceptable value on its own. + */ +QRegularExpression QETInformation::numericInfoPattern() +{ + return QRegularExpression(QStringLiteral(R"(^[0-9]+\.?[0-9]{0,2}$|^[0-9]*\.[0-9]{1,2}$)")); +} + /** * @brief QETInformation::infoToVar * @param info diff --git a/sources/qetinformation.h b/sources/qetinformation.h index 569d9021b..492258b17 100644 --- a/sources/qetinformation.h +++ b/sources/qetinformation.h @@ -18,17 +18,19 @@ #ifndef QETINFORMATION_H #define QETINFORMATION_H -#include #include +#include +#include /** * Inside this namespace you will find all information used in QElectrotech for * element, conductor and diagram. * Each information have 3 values : - * #1 the info key = the key of an information as a QString used in the code (example : label) - * #2 the info key to variable = the key in form of a variable. - * This is used by the user to replace a variable by the string of this variable (example : %{label}) - * #3 the info key translated to the current local (example label in dutch = Betriebsmittelkennzeichen) + * #1 the info key = the key of an information as a QString used in the code + * (example : label) #2 the info key to variable = the key in form of a + * variable. This is used by the user to replace a variable by the string of + * this variable (example : %{label}) #3 the info key translated to the current + * local (example label in dutch = Betriebsmittelkennzeichen) */ namespace QETInformation { @@ -158,6 +160,8 @@ namespace QETInformation QStringList elementEditorElementInfoKeys(); QString elementInfoToVar(const QString &info); + QRegularExpression numericInfoPattern(); + QStringList terminalElementInfoKeys(); QString infoToVar(const QString &info); diff --git a/sources/ui/elementinfopartwidget.cpp b/sources/ui/elementinfopartwidget.cpp index dcb5f6842..2c44e51bd 100644 --- a/sources/ui/elementinfopartwidget.cpp +++ b/sources/ui/elementinfopartwidget.cpp @@ -48,7 +48,7 @@ ElementInfoPartWidget::ElementInfoPartWidget( if (key_ == QETInformation::ELMT_WIDTH || key_ == QETInformation::ELMT_HEIGHT || key_ == QETInformation::ELMT_DEPTH) { auto *validator = new QRegularExpressionValidator( - QRegularExpression(QStringLiteral(R"(^[0-9]*\.?[0-9]{0,4}$)")), ui->line_edit); + QETInformation::numericInfoPattern(), ui->line_edit); ui->line_edit->setValidator(validator); ui->line_edit->setPlaceholderText(tr("ex. 80.5")); ui->line_edit->setToolTip(tr("Nombre décimal avec un point comme séparateur (ex. 80.5)")); From 7c941e4697dc3268a7a595ef09e5da9008335d55 Mon Sep 17 00:00:00 2001 From: Levi Jetzer Date: Fri, 21 Aug 2026 15:16:36 +0200 Subject: [PATCH 5/6] Guard numeric elementInformation fields against "." and normalize decimal comma - ElementInfoWidget::currentInfo() now skips a field whose validator hasn't accepted its text (e.g. a lone "." mid-typing), which previously stored and later parsed to 0. - New QETInformation::NumericInfoValidator rewrites "," to "." before validating, so 80,5 on a German/French keyboard no longer silently becomes 805. Used at both existing call sites. - Restored the header's #1/#2/#3 doc comment (was reflowed into a run-on paragraph by a previous edit). --- .../ui/elementpropertieseditorwidget.cpp | 4 +-- sources/qetinformation.cpp | 27 +++++++++++++++++++ sources/qetinformation.h | 17 +++++++++--- sources/ui/elementinfopartwidget.cpp | 12 +++++++-- sources/ui/elementinfopartwidget.h | 4 +-- sources/ui/elementinfowidget.cpp | 3 +++ 6 files changed, 57 insertions(+), 10 deletions(-) diff --git a/sources/editor/ui/elementpropertieseditorwidget.cpp b/sources/editor/ui/elementpropertieseditorwidget.cpp index e63f8338f..296831450 100644 --- a/sources/editor/ui/elementpropertieseditorwidget.cpp +++ b/sources/editor/ui/elementpropertieseditorwidget.cpp @@ -44,6 +44,7 @@ #include #include #include +#include /** @brief The EditorDelegate class @@ -69,8 +70,7 @@ class EditorDelegate : public QItemDelegate if (key == QETInformation::ELMT_WIDTH || key == QETInformation::ELMT_HEIGHT || key == QETInformation::ELMT_DEPTH) { auto *line_edit = new QLineEdit(parent); - auto *validator = new QRegularExpressionValidator( - QETInformation::numericInfoPattern(), line_edit); + auto *validator = new QETInformation::NumericInfoValidator(line_edit); line_edit->setValidator(validator); line_edit->setPlaceholderText(tr("ex. 80.5")); line_edit->setToolTip(tr("Nombre décimal avec un point comme séparateur (ex. 80.5)")); diff --git a/sources/qetinformation.cpp b/sources/qetinformation.cpp index d6c2f769b..83dadd0c1 100644 --- a/sources/qetinformation.cpp +++ b/sources/qetinformation.cpp @@ -228,6 +228,33 @@ QRegularExpression QETInformation::numericInfoPattern() return QRegularExpression(QStringLiteral(R"(^[0-9]+\.?[0-9]{0,2}$|^[0-9]*\.[0-9]{1,2}$)")); } +/** + @brief QETInformation::NumericInfoValidator::NumericInfoValidator + @param parent +*/ +QETInformation::NumericInfoValidator::NumericInfoValidator(QObject *parent) : + QRegularExpressionValidator(numericInfoPattern(), parent) +{ +} + +/** + @brief QETInformation::NumericInfoValidator::validate + Rewrites any "," in @a input to "." in place, then delegates to + the base class for the actual numericInfoPattern() check. @a pos + is left untouched by the rewrite itself -- replacing "," with "." + never changes the string's length, so the cursor position the + caller already tracked stays correct. + @param input the text being validated; may be rewritten + @param pos the cursor position within @a input + @return the resulting validation state +*/ +QValidator::State QETInformation::NumericInfoValidator::validate(QString &input, int &pos) const +{ + if (input.contains(QLatin1Char(','))) + input.replace(QLatin1Char(','), QLatin1Char('.')); + return QRegularExpressionValidator::validate(input, pos); +} + /** * @brief QETInformation::infoToVar * @param info diff --git a/sources/qetinformation.h b/sources/qetinformation.h index 492258b17..5ed893311 100644 --- a/sources/qetinformation.h +++ b/sources/qetinformation.h @@ -20,6 +20,7 @@ #include #include +#include #include /** @@ -27,10 +28,12 @@ * element, conductor and diagram. * Each information have 3 values : * #1 the info key = the key of an information as a QString used in the code - * (example : label) #2 the info key to variable = the key in form of a - * variable. This is used by the user to replace a variable by the string of - * this variable (example : %{label}) #3 the info key translated to the current - * local (example label in dutch = Betriebsmittelkennzeichen) + * (example : label) + * #2 the info key to variable = the key in form of a variable. This is used + * by the user to replace a variable by the string of this variable + * (example : %{label}) + * #3 the info key translated to the current local (example label in dutch = + * Betriebsmittelkennzeichen) */ namespace QETInformation { @@ -161,6 +164,12 @@ namespace QETInformation QString elementInfoToVar(const QString &info); QRegularExpression numericInfoPattern(); + class NumericInfoValidator : public QRegularExpressionValidator + { + public: + explicit NumericInfoValidator(QObject *parent = nullptr); + State validate(QString &input, int &pos) const override; + }; QStringList terminalElementInfoKeys(); diff --git a/sources/ui/elementinfopartwidget.cpp b/sources/ui/elementinfopartwidget.cpp index 2c44e51bd..d880f3b96 100644 --- a/sources/ui/elementinfopartwidget.cpp +++ b/sources/ui/elementinfopartwidget.cpp @@ -47,8 +47,7 @@ ElementInfoPartWidget::ElementInfoPartWidget( if (key_ == QETInformation::ELMT_WIDTH || key_ == QETInformation::ELMT_HEIGHT || key_ == QETInformation::ELMT_DEPTH) { - auto *validator = new QRegularExpressionValidator( - QETInformation::numericInfoPattern(), ui->line_edit); + auto *validator = new QETInformation::NumericInfoValidator(ui->line_edit); ui->line_edit->setValidator(validator); ui->line_edit->setPlaceholderText(tr("ex. 80.5")); ui->line_edit->setToolTip(tr("Nombre décimal avec un point comme séparateur (ex. 80.5)")); @@ -78,6 +77,15 @@ QString ElementInfoPartWidget::text() const return (ui->line_edit->text()); } +/** + @brief ElementInfoPartWidget::hasAcceptableInput + @return whether the line edit's current text satisfies its validator +*/ +bool ElementInfoPartWidget::hasAcceptableInput() const +{ + return ui->line_edit->hasAcceptableInput(); +} + /** @brief ElementInfoPartWidget::setText Set text to line edit diff --git a/sources/ui/elementinfopartwidget.h b/sources/ui/elementinfopartwidget.h index 5e52a066e..a79eb48d4 100644 --- a/sources/ui/elementinfopartwidget.h +++ b/sources/ui/elementinfopartwidget.h @@ -41,9 +41,9 @@ class ElementInfoPartWidget : public QWidget QWidget *parent = nullptr); ~ElementInfoPartWidget() override; - QString key () const -{return key_;} + QString key () const {return key_;} QString text () const; + bool hasAcceptableInput() const; void setText (const QString &); void setPlaceHolderText (const QString &text); void setFocusTolineEdit(); diff --git a/sources/ui/elementinfowidget.cpp b/sources/ui/elementinfowidget.cpp index 0b8a41111..ce34f34e1 100644 --- a/sources/ui/elementinfowidget.cpp +++ b/sources/ui/elementinfowidget.cpp @@ -387,6 +387,9 @@ DiagramContext ElementInfoWidget::currentInfo() const for (const auto &eipw : std::as_const(m_eipw_list)) { + if (!eipw->hasAcceptableInput()) + continue; + //add value only if they're something to store if (!eipw->text().isEmpty()) { From 02e6eceb65dfe649eee4e46d7f9c4bbac9725c8d Mon Sep 17 00:00:00 2001 From: Levi Jetzer Date: Fri, 21 Aug 2026 15:22:41 +0200 Subject: [PATCH 6/6] Reject trailing-dot input like "12." in numeric elementInformation fields numericInfoPattern()'s integer branch no longer allows an optional trailing ".", so "12." is now Intermediate rather than Acceptable -- already-built hasAcceptableInput() guard then keeps it from being stored, same as a lone ".". Previously it validated fine and got saved verbatim, silently freezing in that form since nothing ever normalized it afterward. --- sources/qetinformation.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sources/qetinformation.cpp b/sources/qetinformation.cpp index 83dadd0c1..06ac16255 100644 --- a/sources/qetinformation.cpp +++ b/sources/qetinformation.cpp @@ -225,7 +225,7 @@ QString QETInformation::elementInfoToVar(const QString &info) */ QRegularExpression QETInformation::numericInfoPattern() { - return QRegularExpression(QStringLiteral(R"(^[0-9]+\.?[0-9]{0,2}$|^[0-9]*\.[0-9]{1,2}$)")); + return QRegularExpression(QStringLiteral(R"(^[0-9]+$|^[0-9]*\.[0-9]{1,2}$)")); } /**