Fix a crop in progress outliving an undo or the picture's removal

While a picture was being cropped on the folio:

- Ctrl+Z or Ctrl+Y of an earlier crop of the same picture left the
  crop handles where they were, 10 px beside the frame for a crop
  that starts at (10, 10).
- undoing the picture's insertion dropped the crop but left the
  picture as the folio's keyboard item, also after a redo put it
  back.

setImageSource() and leaving the scene now end the crop without
applying it. Nothing is pushed on the undo stack from there, since
both can run inside an undo command. Delete and cut are unchanged:
they deselect the picture first, which applies the crop as its own
undo step before theirs.

No file-format change. Not covered by an automated test: crop mode
needs a folio and its view, which a test can only get from the
application object library of #1431. Checked with a throw-away test
on a local merge of both branches.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Beat Hangartner
2026-10-10 10:55:13 +02:00
parent 8261524208
commit 446479e8d2
@@ -281,6 +281,11 @@ void DiagramImageItem::setPixmap(const QPixmap &pixmap) {
*/
void DiagramImageItem::setImageSource(const ImageSource &source)
{
// An undo or redo that changes the picture under a crop being edited
// ends that crop: its frame and its preview were made for the source
// that is replaced here. Nothing is applied, since this may run
// inside an undo command.
finishCropMode(false);
m_base_pixmap = source.base;
m_crop_rect = source.crop;
m_transparent_colors = source.colors;
@@ -1626,6 +1631,13 @@ QVariant DiagramImageItem::itemChange(GraphicsItemChange change, const QVariant
if (!m_deferHandleReposition)
repositionHandles();
}
else if (change == ItemSceneChange)
{
// Leaving the folio (undoing the picture's insertion, for one)
// drops a crop in progress while diagram() is still there to
// give the keys back to the view.
finishCropMode(false);
}
else if (change == ItemSceneHasChanged)
{
if (!scene())