From f087820757c3fdb88c99f7289d553fe336026fd1 Mon Sep 17 00:00:00 2001 From: ispyisail Date: Mon, 21 Sep 2026 22:51:55 +1200 Subject: [PATCH] Let a script rename the project and reshape a folio's frame setProjectTitle(title) folioBorder(folio, prop) setFolioBorder(folio, prop, value) The frame is the grid of columns and rows around a folio: columns, column-width, display-columns, rows, row-height, display-rows -- the six fields the folio properties panel offers -- through ChangeBorderCommand, so it undoes like a hand edit. The title block's header sizes, which the panel does not offer, are left alone. Changing the project title is not undoable, because the application sets it directly too. Counts are 1 to 99 and sizes 1 to 1000. The panel's upper limits are the same; its lower limit is 0, which is not offered: a grid with no columns has no use here and 0 was not tested, so it is refused rather than assumed safe. The extremes that are offered (99 x 99 cells, widths from 1 to 1000) were exported to PNG without a hang or crash. Fractions, out of range values, an unknown property and a bad folio are refused with a reason. Verified: ten columns of 40 and four rows of 100, undo of the last change, and the folio and the renamed project read back after a reload. My first reload check read the wrong folio and briefly looked like the border was not persisted; the file itself had the right values. Co-Authored-By: Claude Sonnet 5 --- sources/scripting/qetscriptapi.cpp | 95 ++++++++++++++++++++++++++++++ sources/scripting/qetscriptapi.h | 12 ++++ 2 files changed, 107 insertions(+) diff --git a/sources/scripting/qetscriptapi.cpp b/sources/scripting/qetscriptapi.cpp index ba0a3bf60..745b35ec7 100644 --- a/sources/scripting/qetscriptapi.cpp +++ b/sources/scripting/qetscriptapi.cpp @@ -41,6 +41,7 @@ #include "../TerminalStrip/terminalstrip.h" #include "../autoNum/assignvariables.h" #include "../autoNum/numerotationcontext.h" +#include "../borderproperties.h" #include "../diagramcommands.h" #include "../qetgraphicsitem/terminal.h" #include "../qetgraphicsitem/terminalelement.h" @@ -2283,6 +2284,100 @@ QStringList QetScriptApi::duplicateElements(int fromFolioIndex, const QStringLis return created; } +bool QetScriptApi::setProjectTitle(const QString &title) +{ + if (!m_project) return false; + if (m_project->isReadOnly()) { + log(QStringLiteral("qet.setProjectTitle: project is read-only")); + return false; + } + m_project->setTitle(title); + return m_project->title() == title; +} + +namespace { +const QStringList &folioBorderNames() +{ + static const QStringList n{QStringLiteral("columns"), QStringLiteral("column-width"), + QStringLiteral("display-columns"), QStringLiteral("rows"), QStringLiteral("row-height"), + QStringLiteral("display-rows")}; + return n; +} +} // namespace + +QString QetScriptApi::folioBorder(int folioIndex, const QString &property) const +{ + if (!m_project) return QString(); + const QList diagrams = m_project->diagrams(); + if (folioIndex < 0 || folioIndex >= diagrams.count()) return QString(); + const BorderProperties b = diagrams.at(folioIndex)->border_and_titleblock.exportBorder(); + if (property == QLatin1String("columns")) return QString::number(b.columns_count); + if (property == QLatin1String("column-width")) return QString::number(b.columns_width); + if (property == QLatin1String("display-columns")) return b.display_columns ? QStringLiteral("true") : QStringLiteral("false"); + if (property == QLatin1String("rows")) return QString::number(b.rows_count); + if (property == QLatin1String("row-height")) return QString::number(b.rows_height); + if (property == QLatin1String("display-rows")) return b.display_rows ? QStringLiteral("true") : QStringLiteral("false"); + return QString(); +} + +/** + @brief QetScriptApi::setFolioBorder + Change one field of a folio's frame through ChangeBorderCommand, as the + folio properties panel does. Counts are whole numbers from 1 to 99 and + sizes are from 1 to 1000. The panel's own upper limits are 99 and 1000; + its lower limit is 0, which is deliberately not offered -- a grid with + no columns, or columns of no width, has no use here and 0 was not + tested, so it is left refused rather than assumed safe. The extremes + that are offered (99 x 99 cells, widths from 1 to 1000) were exported to + PNG and did not hang or crash. +*/ +bool QetScriptApi::setFolioBorder(int folioIndex, const QString &property, const QString &value) +{ + if (!m_project) return false; + const QString caller = QStringLiteral("setFolioBorder"); + if (m_project->isReadOnly()) { + log(QStringLiteral("qet.%1: project is read-only").arg(caller)); + return false; + } + if (!folioBorderNames().contains(property)) { + log(QStringLiteral("qet.%1: unknown property '%2'; expected one of %3") + .arg(caller, property, folioBorderNames().join(QStringLiteral(", ")))); + return false; + } + const QList diagrams = m_project->diagrams(); + if (folioIndex < 0 || folioIndex >= diagrams.count()) return false; + Diagram *diagram = diagrams.at(folioIndex); + + const BorderProperties old_b = diagram->border_and_titleblock.exportBorder(); + BorderProperties new_b = old_b; + bool ok = false; + if (property == QLatin1String("columns") || property == QLatin1String("rows")) { + const int n = value.toInt(&ok); + if (!ok || n < 1 || n > 99) { + log(QStringLiteral("qet.%1: %2 must be a whole number from 1 to 99, not '%3'").arg(caller, property, value)); + return false; + } + (property == QLatin1String("columns") ? new_b.columns_count : new_b.rows_count) = n; + } else if (property == QLatin1String("column-width") || property == QLatin1String("row-height")) { + const double d = value.toDouble(&ok); + if (!ok || d < 1 || d > 1000) { + log(QStringLiteral("qet.%1: %2 must be a number from 1 to 1000, not '%3'").arg(caller, property, value)); + return false; + } + (property == QLatin1String("column-width") ? new_b.columns_width : new_b.rows_height) = d; + } else { + const QString v = value.toLower(); + if (v != QLatin1String("true") && v != QLatin1String("false")) { + log(QStringLiteral("qet.%1: %2 is true or false, not '%3'").arg(caller, property, value)); + return false; + } + (property == QLatin1String("display-columns") ? new_b.display_columns : new_b.display_rows) = (v == QLatin1String("true")); + } + if (new_b == old_b) return true; + m_project->undoStack()->push(new ChangeBorderCommand(diagram, old_b, new_b)); + return true; +} + int QetScriptApi::addFolio() { if (!m_project) return -1; diff --git a/sources/scripting/qetscriptapi.h b/sources/scripting/qetscriptapi.h index 6b446da15..276a07663 100644 --- a/sources/scripting/qetscriptapi.h +++ b/sources/scripting/qetscriptapi.h @@ -203,6 +203,13 @@ class DynamicElementTextItem; cannot be told apart. A conductor is copied only if both its ends are among the copied elements. The previous selection is put back afterwards, since copying works by selecting. + - @b Project title and folio frame: setProjectTitle(), and the grid that + frames each folio -- columns and rows, their size, and whether the + headers show (columns, column-width, display-columns, rows, row-height, + display-rows) -- through ChangeBorderCommand. These are the six fields + the folio properties panel offers; the title block's header sizes, + which it does not, are left alone. Changing the project title is not + undoable: the application sets it directly too. - @b Images: place a picture from a file. The pixels are copied into the project, which stores them inline in the .qet -- the saved file does not refer to the original path, so it opens on another machine, @@ -398,6 +405,11 @@ class QetScriptApi : public QObject Q_INVOKABLE QStringList duplicateElements(int fromFolioIndex, const QStringList &elementUuids, int toFolioIndex, double x, double y); + // -- the project title, and each folio's frame (grid of columns and rows) -- + Q_INVOKABLE bool setProjectTitle(const QString &title); + Q_INVOKABLE QString folioBorder(int folioIndex, const QString &property) const; + Q_INVOKABLE bool setFolioBorder(int folioIndex, const QString &property, const QString &value); + // -- folios -- Q_INVOKABLE int addFolio(); Q_INVOKABLE bool setFolioTitle(int folioIndex, const QString &title);