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);