Position X/Y of a symbol text is the point chosen by its alignment

The text properties showed and edited the top-left corner of a text,
whatever its alignment, and changing the alignment did not move the
text. A right-aligned label next to a symbol therefore needed a
different X for every text length to keep the same gap (#1155).

Position X/Y is now the anchor point: the point of the text chosen by
the alignment (right edge for "right", middle for "centre"...). Typing a
position puts that point there, and changing the alignment moves the
text so that the new anchor point is on the same X/Y. It is the same
point that already stays fixed when the text changes.

Applies to the element text properties on a folio and to the text
field properties in the symbol editor. The saved x/y is still the
top-left corner, so projects and symbols load and save unchanged and
look the same; only the numbers shown for texts that are not top-left
aligned change.

The geometry is in textanchor.h, shared by DiagramTextItem and
PartDynamicTextField, and tested in tst_textanchor.

Not changed: static texts of the symbol editor (PartText), whose
position is tied to the font baseline; texts inside a text group, which
have no position or alignment of their own; rotation still pivots on
the top-left corner (or the centre), not on the anchor.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
ispyisail
2026-09-30 18:12:43 +13:00
parent 784a663c19
commit bdc1d5878d
9 changed files with 334 additions and 12 deletions
+15 -7
View File
@@ -303,7 +303,7 @@ QList<QStandardItem *> DynamicElementTextModel::itemsForText(
x_pos->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
QStandardItem *x_pos_a = new QStandardItem;
x_pos_a->setData(deti->pos().x(), Qt::EditRole);
x_pos_a->setData(deti->anchorPos().x(), Qt::EditRole);
x_pos_a->setData(DynamicElementTextModel::pos, Qt::UserRole+1);
x_pos_a->setFlags(Qt::ItemIsSelectable
| Qt::ItemIsEnabled
@@ -318,7 +318,7 @@ QList<QStandardItem *> DynamicElementTextModel::itemsForText(
y_pos->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
QStandardItem *y_pos_a = new QStandardItem;
y_pos_a->setData(deti->pos().y(), Qt::EditRole);
y_pos_a->setData(deti->anchorPos().y(), Qt::EditRole);
y_pos_a->setData(DynamicElementTextModel::pos, Qt::UserRole+1);
y_pos_a->setFlags(Qt::ItemIsSelectable
| Qt::ItemIsEnabled
@@ -600,9 +600,9 @@ QUndoCommand *DynamicElementTextModel::undoForEditedText(
{
QPointF p(text_qsi->child(x_txt_row,1)->data(Qt::EditRole).toDouble(),
text_qsi->child(y_txt_row,1)->data(Qt::EditRole).toDouble());
if(p != deti->pos())
if(p != deti->anchorPos())
{
QPropertyUndoCommand *quc = new QPropertyUndoCommand(deti, "pos", QVariant(deti->pos()), QVariant(p), undo);
QPropertyUndoCommand *quc = new QPropertyUndoCommand(deti, "anchorPos", QVariant(deti->anchorPos()), QVariant(p), undo);
quc->setAnimated(true, false);
quc->setText(tr("Déplacer un texte d'élément"));
}
@@ -636,7 +636,7 @@ QUndoCommand *DynamicElementTextModel::undoForEditedText(
Qt::Alignment alignment = text_qsi->child(align_txt_row, 1)->data(Qt::UserRole+2).value<Qt::Alignment>();
if (alignment != deti->alignment())
{
QPropertyUndoCommand *quc = new QPropertyUndoCommand(deti, "alignment", QVariant(deti->alignment()), QVariant(alignment), undo);
QPropertyUndoCommand *quc = new QPropertyUndoCommand(deti, "alignmentAtAnchor", QVariant(deti->alignment()), QVariant(alignment), undo);
quc->setText(tr("Modifier l'alignement d'un texte d'élément"));
}
}
@@ -1508,9 +1508,9 @@ void DynamicElementTextModel::updateDataFromText(DynamicElementTextItem *deti,
case pos:
{
if(qsi->child(x_txt_row,1))
qsi->child(x_txt_row,1)->setData(deti->pos().x(), Qt::EditRole);
qsi->child(x_txt_row,1)->setData(deti->anchorPos().x(), Qt::EditRole);
if(qsi->child(y_txt_row,1))
qsi->child(y_txt_row,1)->setData(deti->pos().y(), Qt::EditRole);
qsi->child(y_txt_row,1)->setData(deti->anchorPos().y(), Qt::EditRole);
break;
}
case frame:
@@ -1531,6 +1531,14 @@ void DynamicElementTextModel::updateDataFromText(DynamicElementTextItem *deti,
}
default:break;
}
//Rotating or resizing the text moves its anchor point (Position X/Y)
if ((type == rotation || type == textWidth)
&& qsi->child(x_txt_row,1) && qsi->child(y_txt_row,1))
{
qsi->child(x_txt_row,1)->setData(deti->anchorPos().x(), Qt::EditRole);
qsi->child(y_txt_row,1)->setData(deti->anchorPos().y(), Qt::EditRole);
}
m_block_dataChanged = false;
}