From cd279126052d72ac542076c03746c294cf83c669 Mon Sep 17 00:00:00 2001 From: ispyisail Date: Mon, 21 Sep 2026 22:57:32 +1200 Subject: [PATCH] Let a script read where an element is, and insert a folio at a position elementGeometry(folio, uuid) x, y, rotation, left, top, right, bottom insertFolio(position) The API could set an element's position but never read it, so a script could not lay one thing out relative to another, or check that a move had landed; verification had to go through the saved file. elementGeometry returns the origin (what setElementPosition sets), the rotation, and the box the element occupies on the folio -- its drawn extent, which sits at the element's hotspot from the origin and, once rotated, is the rotated extent. Measured on a coil whose hotspot is (17, 32): placed at (200, 300) the box is 183..223 by 268..328, exactly that far from the origin; a move of (+50, -20) shifts both together; a 90 degree turn swaps the box to 60 by 40 about an unchanged origin and 180 turns it back; and the origin agrees with the saved file (x=250 y=280, orientation 2 for 180 degrees). insertFolio puts a folio at a position (0 first, folioCount() last) through QETProject::addNewDiagram(pos), undoable. The position is checked in the binding: QETProject::addDiagram() hands it straight to QList::insert(), which is undefined past the end, so -1 and anything above the count are refused with a reason. Verified: first, middle and last insertions land in the right order, and undo and redo of an insertion restore the order. Folio reordering itself still needs the application's project view. Co-Authored-By: Claude Sonnet 5 --- sources/scripting/qetscriptapi.cpp | 49 ++++++++++++++++++++++++++++++ sources/scripting/qetscriptapi.h | 12 ++++++++ 2 files changed, 61 insertions(+) diff --git a/sources/scripting/qetscriptapi.cpp b/sources/scripting/qetscriptapi.cpp index 745b35ec7..b44b1c210 100644 --- a/sources/scripting/qetscriptapi.cpp +++ b/sources/scripting/qetscriptapi.cpp @@ -2378,6 +2378,55 @@ bool QetScriptApi::setFolioBorder(int folioIndex, const QString &property, const return true; } +/** + @brief QetScriptApi::elementGeometry + Where an element is: x and y are its origin (what setElementPosition() + sets), rotation is in degrees, and left/top/right/bottom are the box it + occupies on the folio, its drawn extent rather than its origin -- which + differs from it by the hotspot and, for a rotated element, is the + rotated extent. Empty if the element is not found. +*/ +QVariantMap QetScriptApi::elementGeometry(int folioIndex, const QString &elementUuid) const +{ + QVariantMap g; + Element *element = findElement(folioIndex, elementUuid); + if (!element) return g; + const QRectF box = element->sceneBoundingRect(); + g.insert(QStringLiteral("x"), element->pos().x()); + g.insert(QStringLiteral("y"), element->pos().y()); + g.insert(QStringLiteral("rotation"), element->rotation()); + g.insert(QStringLiteral("left"), box.left()); + g.insert(QStringLiteral("top"), box.top()); + g.insert(QStringLiteral("right"), box.right()); + g.insert(QStringLiteral("bottom"), box.bottom()); + return g; +} + +/** + @brief QetScriptApi::insertFolio + Add a folio at a position (0 is first, folioCount() is last) through + QETProject::addNewDiagram(pos) -- undoable. The position is checked + here: QETProject::addDiagram() hands it straight to QList::insert(), + which is undefined past the end. + @return the new folio's index, or -1 +*/ +int QetScriptApi::insertFolio(int position) +{ + if (!m_project) return -1; + if (m_project->isReadOnly()) { + log(QStringLiteral("qet.insertFolio: project is read-only")); + return -1; + } + if (position < 0 || position > m_project->diagrams().count()) { + log(QStringLiteral("qet.insertFolio: position %1 is outside 0..%2") + .arg(position).arg(m_project->diagrams().count())); + return -1; + } + Diagram *diagram = m_project->addNewDiagram(position); + if (!diagram) return -1; + return m_project->diagrams().indexOf(diagram); +} + int QetScriptApi::addFolio() { if (!m_project) return -1; diff --git a/sources/scripting/qetscriptapi.h b/sources/scripting/qetscriptapi.h index 276a07663..20d9f007d 100644 --- a/sources/scripting/qetscriptapi.h +++ b/sources/scripting/qetscriptapi.h @@ -22,6 +22,7 @@ #include #include #include +#include class QETProject; class DiagramView; @@ -210,6 +211,13 @@ class DynamicElementTextItem; 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 Geometry and folio order: elementGeometry() reads where an element + is -- x, y (its origin), rotation, and the box it occupies on the folio + (left, top, right, bottom) -- so a script can lay one thing out relative + to another instead of only setting absolute coordinates, and can check + that a move landed. insertFolio() puts a new folio at a position + instead of at the end, which is what reordering is mostly for while + moving an existing folio still needs the application's project view. - @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, @@ -410,8 +418,12 @@ class QetScriptApi : public QObject Q_INVOKABLE QString folioBorder(int folioIndex, const QString &property) const; Q_INVOKABLE bool setFolioBorder(int folioIndex, const QString &property, const QString &value); + // -- read an element's geometry -- + Q_INVOKABLE QVariantMap elementGeometry(int folioIndex, const QString &elementUuid) const; + // -- folios -- Q_INVOKABLE int addFolio(); + Q_INVOKABLE int insertFolio(int position); Q_INVOKABLE bool setFolioTitle(int folioIndex, const QString &title); Q_INVOKABLE bool undo();