Give shapes, independent texts and images a persisted uuid

Elements, conductors, terminals and tables already carry a uuid. The
drawing furniture beside them did not, so a script or the MCP server could
only name a line, a box or a note by its index in a position-sorted list,
which shifts whenever one is added or removed.

- QetShapeItem, IndependentTextItem and DiagramImageItem get uuid(),
  newUuid() and setUuid(), read from and written to a "uuid" attribute.
- A folio loaded from a file written before this (or carrying a duplicate
  uuid) derives one from the folio uuid, the item kind and its order in the
  file, so the same file gives the same uuids on every load and a re-save
  is stable -- the #754 lesson for conductors.
- Paste and folio duplication renew them, as they already do for elements
  and conductors.
- Scripting: texts(), shapes() and images() end each line with the uuid;
  textIndex(), shapeIndex() and imageIndex() turn one back into an index.
- misc/qet-mcp: qet_diff keys texts, shapes and images on uuid when both
  sides have one, so a move or edit reads as a change to that item.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
ispyisail
2026-09-27 09:54:54 +13:00
parent d7036ad807
commit a9ad6e2f34
13 changed files with 206 additions and 47 deletions
+15
View File
@@ -29,6 +29,9 @@
#include <QMessageBox>
#include "qetgraphicsitem/element.h"
#include "qetgraphicsitem/dynamicelementtextitem.h"
#include "qetgraphicsitem/diagramimageitem.h"
#include "qetgraphicsitem/independenttextitem.h"
#include "qetgraphicsitem/qetshapeitem.h"
#include "qetinformation.h"
/*
@@ -800,6 +803,18 @@ void ElementsPanelWidget::duplicateDiagram()
}
}
}
else if (auto text = dynamic_cast<IndependentTextItem *>(item)) {
// Not a database key (yet), but a script or the MCP server
// addresses a text, image or shape by it: a copy must not
// answer to its source's name.
text->newUuid();
}
else if (auto image = dynamic_cast<DiagramImageItem *>(item)) {
image->newUuid();
}
else if (auto shape = dynamic_cast<QetShapeItem *>(item)) {
shape->newUuid();
}
else if (Conductor *cond = dynamic_cast<Conductor *>(item)) {
// Same reasoning for conductors: conductor.uuid is the PRIMARY
// KEY of the conductor table, and its insert is a plain INSERT,