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 <noreply@anthropic.com>
This commit is contained in:
ispyisail
2026-09-21 22:57:32 +12:00
parent f087820757
commit cd27912605
2 changed files with 61 additions and 0 deletions
+49
View File
@@ -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;
+12
View File
@@ -22,6 +22,7 @@
#include <QString>
#include <QStringList>
#include <QVariantList>
#include <QVariantMap>
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();