Add an optional label to pictures (#349)

A picture can now carry a caption, set from its properties panel
("Libellé"). It is drawn centred under the picture at the folio's
normal text size whatever the picture's scale, turns with it, and
moves, copies and prints with it because the picture itself paints it.
Clicking the caption selects the picture.

Saved as a "label" attribute on <image>, written only when non-empty:
a project without labels saves byte-for-byte as before, and older
versions open a labelled project and simply ignore the caption.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01G2d2Zi8BfrYRPX88zhaoFG
This commit is contained in:
ispyisail
2026-09-27 16:12:51 +13:00
parent d7036ad807
commit 5120feb417
5 changed files with 149 additions and 5 deletions
+24
View File
@@ -64,16 +64,21 @@ void ImagePropertiesWidget::setImageItem(DiagramImageItem *image)
this->setEnabled(true);
if (m_image == image) return;
if (m_image)
{
disconnect(m_image, &DiagramImageItem::transformChanged, this, &ImagePropertiesWidget::updateUi);
disconnect(m_image, &DiagramImageItem::labelChanged, this, &ImagePropertiesWidget::updateUi);
}
m_image = image;
connect(m_image, &DiagramImageItem::transformChanged, this, &ImagePropertiesWidget::updateUi);
connect(m_image, &DiagramImageItem::labelChanged, this, &ImagePropertiesWidget::updateUi);
m_movable = image->isMovable();
m_scaleX = m_image->scaleFactorX();
m_scaleY = m_image->scaleFactorY();
m_rotation = m_image->rotationAngle();
m_skewX = m_image->skewX();
m_skewY = m_image->skewY();
m_label = m_image->label();
updateUi();
}
@@ -101,6 +106,7 @@ void ImagePropertiesWidget::apply()
m_rotation = m_image->rotationAngle();
m_skewX = m_image->skewX();
m_skewY = m_image->skewY();
m_label = m_image->label();
}
/**
@@ -116,6 +122,7 @@ void ImagePropertiesWidget::reset()
m_image->setRotationAngle(m_rotation);
m_image->setSkewX(m_skewX);
m_image->setSkewY(m_skewY);
m_image->setLabel(m_label);
m_image->setMovable(m_movable);
updateUi();
}
@@ -138,6 +145,7 @@ bool ImagePropertiesWidget::setLiveEdit(bool live_edit)
connect (ui->m_angle_sb, &QDoubleSpinBox::editingFinished, this, &ImagePropertiesWidget::apply);
connect (ui->m_skew_x_sb, &QDoubleSpinBox::editingFinished, this, &ImagePropertiesWidget::apply);
connect (ui->m_skew_y_sb, &QDoubleSpinBox::editingFinished, this, &ImagePropertiesWidget::apply);
connect (ui->m_label_le, &QLineEdit::editingFinished, this, &ImagePropertiesWidget::apply);
}
else
{
@@ -146,6 +154,7 @@ bool ImagePropertiesWidget::setLiveEdit(bool live_edit)
disconnect (ui->m_angle_sb, &QDoubleSpinBox::editingFinished, this, &ImagePropertiesWidget::apply);
disconnect (ui->m_skew_x_sb, &QDoubleSpinBox::editingFinished, this, &ImagePropertiesWidget::apply);
disconnect (ui->m_skew_y_sb, &QDoubleSpinBox::editingFinished, this, &ImagePropertiesWidget::apply);
disconnect (ui->m_label_le, &QLineEdit::editingFinished, this, &ImagePropertiesWidget::apply);
}
return true;
@@ -191,6 +200,19 @@ QUndoCommand* ImagePropertiesWidget::associatedUndo() const
chain("skewX", m_skewX, newSkewX, tr("Modifier l'inclinaison d'une image"));
chain("skewY", m_skewY, newSkewY, tr("Modifier l'inclinaison d'une image"));
// Not through chain(): a string cannot be animated.
const QString newLabel = ui->m_label_le->text();
if (newLabel != m_label)
{
if (undo)
new QPropertyUndoCommand(m_image, "label", m_label, newLabel, undo);
else
{
undo = new QPropertyUndoCommand(m_image, "label", m_label, newLabel);
undo->setText(tr("Modifier le libellé d'une image"));
}
}
return undo;
}
@@ -221,6 +243,8 @@ void ImagePropertiesWidget::updateUi()
ui->m_skew_x_sb->setValue(m_image->skewX());
ui->m_skew_y_sb->setValue(m_image->skewY());
ui->m_lock_pos_cb->setChecked(!m_image->isMovable());
if (ui->m_label_le->text() != m_image->label())
ui->m_label_le->setText(m_image->label());
}
/**
+1
View File
@@ -70,6 +70,7 @@ class ImagePropertiesWidget : public PropertiesEditorWidget
qreal m_rotation;
qreal m_skewX;
qreal m_skewY;
QString m_label;
// Guards the width/height spinboxes' mutual updates when
// "Conserver les proportions" is checked, so setting one
// programmatically in response to the other doesn't re-trigger
+16 -2
View File
@@ -152,14 +152,28 @@
</property>
</widget>
</item>
<item row="6" column="0" colspan="2">
<item row="6" column="0">
<widget class="QLabel" name="label_label">
<property name="text">
<string>Libellé</string>
</property>
</widget>
</item>
<item row="6" column="1" colspan="2">
<widget class="QLineEdit" name="m_label_le">
<property name="toolTip">
<string>Texte affiché sous l'image. Il suit l'image quand elle est déplacée, copiée ou tournée.</string>
</property>
</widget>
</item>
<item row="7" column="0" colspan="2">
<widget class="QCheckBox" name="m_lock_pos_cb">
<property name="text">
<string>Verrouiller la position</string>
</property>
</widget>
</item>
<item row="7" column="0">
<item row="8" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>