The crop rectangle came back as the string "x,y,width,height", which a
script had to split and parse. elementGeometry() returns a map; the
crop now does the same, and an empty map for no such image.
Suggested in the review of #1310.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
A picture remembers whether its pivot was placed by hand: a hand-placed
pivot is saved and kept through a resize, a default one is not saved
and recentres after a resize. Two actions changed that flag outside
their undo step:
- applyCrop() marked the pivot as default after moving it to the centre
of the kept region. After Ctrl+Z the pivot was back where the user
had put it, but marked as default, so the next save dropped it.
- dragging the pivot handle marked it as hand-placed. After Ctrl+Z the
pivot was back at the centre but still marked as hand-placed, so a
later resize left it at the handle's anchor corner.
pivotIsCustom becomes a property, and both actions put it into their
undo command next to rawPivot. tst_imagecropundo checks that a project
saved after undoing a crop keeps its hand-placed pivot.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The displayed pixmap and imageSource (original, crop rectangle,
transparent colours) were two undo values that had to change together,
although the pixmap follows from the source. An action that updated
one and not the other would bring back the bug fixed in #1310.
setImageSource() now recomputes the displayed pixmap, and crop, colour
key, mirror and replace push one undo step on imageSource alone. A
plain QUndoCommand holds the property change, so two identical actions
in a row stay two steps. Loading a project still shows the saved pixmap
as before.
tst_imagecropundo also checks the size of the saved picture after undo
and after redo.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
- replaceImage(), mirror() and setTransparentColor() no longer add a
dummy QUndoCommand child: the imageSource child already keeps
QPropertyUndoCommand::mergeWith() from merging two of them.
- The explanation of the position and pivot maths moves from crop() to
applyCrop(), where that code now lives; the stale older doc block of
crop() goes.
- applyCrop() returns false when nothing was cropped, and
qet.cropImage() passes that on. tst_imagecropundo checks it for the
current crop, an empty rectangle and one outside the picture.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Crop a picture as the crop tool does, in one undo step, and read its
crop rectangle back. tst_imagecropundo uses them on the real binary:
a crop that was undone is not saved, and redoing it saves it again.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>