From 65299e1178e9d6c81ac6a01d503f46bcf9d49e74 Mon Sep 17 00:00:00 2001 From: ispyisail Date: Mon, 21 Sep 2026 21:24:14 +1200 Subject: [PATCH] Let a script define and select auto-numbering autoNums(kind) list contexts and their formulas addAutoNum(kind, name, parts) define one; parts are "type[:value[:increase]]" removeAutoNum(kind, name) useConductorAutoNum(folio, n) new conductors on a folio take it Kinds are conductor, element and folio. Part types are the ones the auto-numbering dialog offers; anything NumerotationContext rejects, an unknown kind, a non-numeric increase or a missing context is refused with a reason rather than dropped. Defining and removing a context is not undoable, because the application does it through direct project calls; only the counter advance is on the undo stack. useConductorAutoNum sets both the folio's name and the project's current name, because the numbering code reads the context by one and writes the advanced counter back under the other. Verified: a "W" + unit context selected on a folio, two conductors wired, W1 and W2 in the saved file, and the context survives reload. Depends on the preceding ConductorCreator fix for the database to agree with the drawing. Co-Authored-By: Claude Sonnet 5 --- sources/scripting/qetscriptapi.cpp | 120 +++++++++++++++++++++++++++++ sources/scripting/qetscriptapi.h | 16 ++++ 2 files changed, 136 insertions(+) diff --git a/sources/scripting/qetscriptapi.cpp b/sources/scripting/qetscriptapi.cpp index 1fdc9acf9..7b1ce35d0 100644 --- a/sources/scripting/qetscriptapi.cpp +++ b/sources/scripting/qetscriptapi.cpp @@ -37,6 +37,8 @@ #include "../TerminalStrip/UndoCommand/addterminaltostripcommand.h" #include "../TerminalStrip/realterminal.h" #include "../TerminalStrip/terminalstrip.h" +#include "../autoNum/assignvariables.h" +#include "../autoNum/numerotationcontext.h" #include "../qetgraphicsitem/terminal.h" #include "../qetgraphicsitem/terminalelement.h" #include "../qetinformation.h" @@ -1453,6 +1455,124 @@ bool QetScriptApi::addTerminalToStrip(int stripIndex, int folioIndex, const QStr return real->parentStrip() == strips.at(stripIndex); } +namespace { +QHash autoNumTable(QETProject *project, const QString &kind, bool *ok) +{ + *ok = true; + if (kind == QLatin1String("conductor")) return project->conductorAutoNum(); + if (kind == QLatin1String("element")) return project->elementAutoNum(); + if (kind == QLatin1String("folio")) return project->folioAutoNum(); + *ok = false; + return {}; +} +} // namespace + +QStringList QetScriptApi::autoNums(const QString &kind) const +{ + QStringList list; + if (!m_project) return list; + bool ok; + const QHash table = autoNumTable(m_project, kind, &ok); + if (!ok) return list; + const QStringList names = table.keys(); + for (const QString &name : names) { + list << QStringLiteral("%1: formula='%2'") + .arg(name, autonum::numerotationContextToFormula(table.value(name))); + } + list.sort(); + return list; +} + +/** + @brief QetScriptApi::addAutoNum + Define (or replace) a named numbering context. Each part is + "type[:value[:increase]]"; a numeric type takes its starting value and + how much it advances by, a text type its text. Anything the + NumerotationContext rejects -- an unknown type, a non-numeric value for + a numeric type -- is refused rather than dropped. +*/ +bool QetScriptApi::addAutoNum(const QString &kind, const QString &name, const QStringList &parts) +{ + if (!m_project) return false; + if (m_project->isReadOnly()) { + log(QStringLiteral("qet.addAutoNum: project is read-only")); + return false; + } + bool ok; + autoNumTable(m_project, kind, &ok); + if (!ok) { + log(QStringLiteral("qet.addAutoNum: unknown kind '%1'; expected conductor, element or folio").arg(kind)); + return false; + } + if (name.isEmpty() || parts.isEmpty()) { + log(QStringLiteral("qet.addAutoNum: a name and at least one part are required")); + return false; + } + + NumerotationContext context; + for (const QString &part : parts) + { + const QStringList f = part.split(QLatin1Char(':')); + const QString type = f.value(0); + const QVariant value = f.size() > 1 ? QVariant(f.at(1)) : QVariant(1); + bool inc_ok = true; + const int increase = f.size() > 2 ? f.at(2).toInt(&inc_ok) : 1; + if (!context.keyIsAcceptable(type) || !inc_ok || !context.addValue(type, value, increase)) { + log(QStringLiteral("qet.addAutoNum: cannot use part '%1'").arg(part)); + return false; + } + } + + if (kind == QLatin1String("conductor")) m_project->addConductorAutoNum(name, context); + else if (kind == QLatin1String("element")) m_project->addElementAutoNum(name, context); + else m_project->addFolioAutoNum(name, context); + return true; +} + +bool QetScriptApi::removeAutoNum(const QString &kind, const QString &name) +{ + if (!m_project) return false; + if (m_project->isReadOnly()) { + log(QStringLiteral("qet.removeAutoNum: project is read-only")); + return false; + } + bool ok; + const QHash table = autoNumTable(m_project, kind, &ok); + if (!ok || !table.contains(name)) { + log(QStringLiteral("qet.removeAutoNum: no %1 auto-numbering named '%2'").arg(kind, name)); + return false; + } + if (kind == QLatin1String("conductor")) m_project->removeConductorAutoNum(name); + else if (kind == QLatin1String("element")) m_project->removeElementAutoNum(name); + else m_project->removeFolioAutoNum(name); + return true; +} + +/** + @brief QetScriptApi::useConductorAutoNum + Make new conductors on a folio take their number from a named context. + Sets both what the folio reads and the project's current name, because + ConductorAutoNumerotation reads the context by the former and writes the + advanced counter back under the latter. +*/ +bool QetScriptApi::useConductorAutoNum(int folioIndex, const QString &name) +{ + if (!m_project) return false; + if (m_project->isReadOnly()) { + log(QStringLiteral("qet.useConductorAutoNum: project is read-only")); + return false; + } + const QList diagrams = m_project->diagrams(); + if (folioIndex < 0 || folioIndex >= diagrams.count()) return false; + if (!name.isEmpty() && !m_project->conductorAutoNum().contains(name)) { + log(QStringLiteral("qet.useConductorAutoNum: no conductor auto-numbering named '%1'").arg(name)); + return false; + } + diagrams.at(folioIndex)->setConductorsAutonumName(name); + m_project->setCurrentConductorAutoNum(name); + return true; +} + int QetScriptApi::addFolio() { if (!m_project) return -1; diff --git a/sources/scripting/qetscriptapi.h b/sources/scripting/qetscriptapi.h index 72914d7c5..69c622606 100644 --- a/sources/scripting/qetscriptapi.h +++ b/sources/scripting/qetscriptapi.h @@ -156,6 +156,16 @@ class QetShapeItem; re-sorted) and does shift when one is removed. Only elements whose link type is "terminal" can be added, the same restriction the editor enforces by construction. + - @b Auto-numbering: define a named numbering context of kind + "conductor", "element" or "folio", built from parts written + "type[:value[:increase]]" -- types are the ones the auto-numbering + dialog offers (string, unit, ten, hundred, alpha, idfolio, folio, + plant, locmach, elementline, elementcolumn, elementprefix, wrap, + unitfolio, tenfolio, hundredfolio) -- and select which one a folio's + new conductors use. Defining or removing a context is not undoable, + because the application itself does it through direct project calls + and only the counter advance is on the undo stack; the numbering + actually applied to a conductor is. - @b Navigating and @b messaging: select an element, zoom the active view, and show the user a message. Deliberately narrow: selection and messaging work with no view at all (headless `--run`); zoom is a no-op @@ -283,6 +293,12 @@ class QetScriptApi : public QObject Q_INVOKABLE bool addTerminalToStrip(int stripIndex, int folioIndex, const QString &elementUuid); + // -- auto-numbering contexts (conductor, element, folio) -- + Q_INVOKABLE QStringList autoNums(const QString &kind) const; + Q_INVOKABLE bool addAutoNum(const QString &kind, const QString &name, const QStringList &parts); + Q_INVOKABLE bool removeAutoNum(const QString &kind, const QString &name); + Q_INVOKABLE bool useConductorAutoNum(int folioIndex, const QString &name); + // -- folios -- Q_INVOKABLE int addFolio(); Q_INVOKABLE bool setFolioTitle(int folioIndex, const QString &title);