27#include "preferencemanager.h"
28#include "layermanager.h"
29#include "soundmanager.h"
30#include "undoredomanager.h"
31#include "selectionmanager.h"
33#include "undoredocommand.h"
34#include "legacybackupelement.h"
36#include "layerbitmap.h"
37#include "layervector.h"
38#include "layersound.h"
41#include "bitmapimage.h"
42#include "vectorimage.h"
45UndoRedoManager::UndoRedoManager(
Editor* editor) :
BaseManager(editor,
"UndoRedoManager")
47 qDebug() <<
"UndoRedoManager: created";
50UndoRedoManager::~UndoRedoManager()
52 if (!mNewBackupSystemEnabled)
56 qDebug() <<
"UndoRedoManager: destroyed";
59bool UndoRedoManager::init()
61 qDebug() <<
"UndoRedoManager: init";
63 mUndoStack.
setUndoLimit(editor()->preference()->getInt(SETTING::UNDO_REDO_MAX_STEPS));
64 mNewBackupSystemEnabled = editor()->preference()->isOn(SETTING::NEW_UNDO_REDO_SYSTEM_ON);
69void UndoRedoManager::onSettingChanged(SETTING setting)
71 if (setting == SETTING::UNDO_REDO_MAX_STEPS) {
74 qDebug() <<
"updated undo stack limit";
75 mUndoStack.
setUndoLimit(editor()->preference()->getInt(SETTING::UNDO_REDO_MAX_STEPS));
87 if (mNewBackupSystemEnabled) {
90 mLegacyBackupAtSave = mLegacyBackupList[mLegacyBackupIndex];
97 if (!mNewBackupSystemEnabled) {
105 switch (undoState->recordType)
107 case UndoRedoRecordType::KEYFRAME_MODIFY: {
108 replaceKeyFrame(*undoState, description);
112 QString reason(
"Unhandled case for: ");
113 reason.
append(description);
114 Q_ASSERT_X(
false,
"UndoRedoManager::record", qPrintable(reason));
127 if (mNewBackupSystemEnabled) {
130 if (mLegacyBackupIndex >= 0) {
131 return mLegacyBackupAtSave != mLegacyBackupList[mLegacyBackupIndex];
139 mUndoStack.
push(command);
141 emit didUpdateUndoStack();
144void UndoRedoManager::replaceKeyFrame(
const UndoSaveState& undoState,
const QString& description)
146 if (undoState.layerType == Layer::BITMAP) {
147 replaceBitmap(undoState, description);
148 }
else if (undoState.layerType == Layer::VECTOR) {
149 replaceVector(undoState, description);
158 if (undoState.keyframe ==
nullptr || undoState.layerType != Layer::BITMAP) {
return; }
166 selectionState->translation,
167 selectionState->rotationAngle,
168 selectionState->scaleX,
169 selectionState->scaleY,
170 selectionState->anchor,
175 pushCommand(element);
180 if (undoState.keyframe ==
nullptr || undoState.layerType != Layer::VECTOR) {
return; }
188 selectionState->translation,
189 selectionState->rotationAngle,
190 selectionState->scaleX,
191 selectionState->scaleY,
192 selectionState->anchor,
196 pushCommand(element);
201 if (!mNewBackupSystemEnabled) {
207 case UndoRedoRecordType::KEYFRAME_MODIFY: {
208 return savedKeyFrameState();
215const UndoSaveState* UndoRedoManager::savedKeyFrameState()
const
218 undoSaveState->recordType = UndoRedoRecordType::KEYFRAME_MODIFY;
220 const Layer* layer = editor()->layers()->currentLayer();
221 undoSaveState->layerType = layer->type();
222 undoSaveState->layerId = layer->id();
224 if (layer->type() == Layer::BITMAP || layer->type() == Layer::VECTOR) {
225 auto selectMan = editor()->select();
226 undoSaveState->selectionState = std::unique_ptr<SelectionSaveState>(
new SelectionSaveState(
227 selectMan->mySelectionRect(),
228 selectMan->myRotation(),
229 selectMan->myScaleX(),
230 selectMan->myScaleY(),
231 selectMan->myTranslation(),
232 selectMan->currentTransformAnchor())
236 const int frameIndex = editor()->currentFrame();
237 if (layer->keyExists(frameIndex))
239 undoSaveState->keyframe = std::unique_ptr<KeyFrame>(layer->getLastKeyFrameAtPosition(frameIndex)->clone());
241 else if (layer->getKeyFrameWhichCovers(frameIndex) !=
nullptr)
243 undoSaveState->keyframe = std::unique_ptr<KeyFrame>(layer->getKeyFrameWhichCovers(frameIndex)->clone());
246 return undoSaveState;
252 if (mNewBackupSystemEnabled) {
261 if (mNewBackupSystemEnabled) {
272 if (mNewBackupSystemEnabled) {
281 if (mNewBackupSystemEnabled) {
289void UndoRedoManager::updateUndoAction(
QAction* undoAction)
291 if (mNewBackupSystemEnabled) {
295 if (mLegacyBackupIndex < 0)
297 undoAction->
setText(
tr(
"Undo",
"Menu item text"));
299 qDebug() << undoAction->
text();
304 .arg(mLegacyBackupIndex + 1)
305 .arg(mLegacyBackupList.
at(mLegacyBackupIndex)->undoText));
307 .arg(mLegacyBackupIndex + 1)
308 .arg(mLegacyBackupList.
at(mLegacyBackupIndex)->undoText));
310 qDebug() << undoAction->
text();
315void UndoRedoManager::updateRedoAction(
QAction* redoAction)
317 if (mNewBackupSystemEnabled) {
321 if (mLegacyBackupIndex + 2 < mLegacyBackupList.
size())
324 .arg(mLegacyBackupIndex + 2)
325 .arg(mLegacyBackupList.
at(mLegacyBackupIndex + 1)->undoText));
330 redoAction->
setText(
tr(
"Redo",
"Menu item text"));
338 if (mNewBackupSystemEnabled) {
341 mLegacyBackupIndex = -1;
342 while (!mLegacyBackupList.
isEmpty())
344 delete mLegacyBackupList.
takeLast();
346 mLegacyLastModifiedLayer = -1;
347 mLegacyLastModifiedFrame = -1;
353void UndoRedoManager::legacyBackup(
const QString& undoText)
356 if (mNewBackupSystemEnabled) {
361 int currentFrame = editor()->currentFrame();
362 if (mLegacyLastModifiedLayer > -1 && mLegacyLastModifiedFrame > 0)
364 if (editor()->layers()->currentLayer()->type() == Layer::SOUND)
366 frame = editor()->layers()->currentLayer()->getKeyFrameWhichCovers(mLegacyLastModifiedFrame);
367 if (frame !=
nullptr)
369 legacyBackup(mLegacyLastModifiedLayer, frame->pos(), undoText);
374 legacyBackup(mLegacyLastModifiedLayer, mLegacyLastModifiedFrame, undoText);
377 if (mLegacyLastModifiedLayer != editor()->layers()->currentLayerIndex() || mLegacyLastModifiedFrame != currentFrame)
379 if (editor()->layers()->currentLayer()->type() == Layer::SOUND)
381 frame = editor()->layers()->currentLayer()->getKeyFrameWhichCovers(currentFrame);
383 if (frame !=
nullptr)
385 legacyBackup(editor()->layers()->currentLayerIndex(), frame->pos(), undoText);
390 legacyBackup(editor()->layers()->currentLayerIndex(), currentFrame, undoText);
395bool UndoRedoManager::legacyBackup(
int backupLayer,
int backupFrame,
const QString& undoText)
397 if (mNewBackupSystemEnabled) {
401 while (mLegacyBackupList.
size() - 1 > mLegacyBackupIndex && !mLegacyBackupList.
empty())
403 delete mLegacyBackupList.
takeLast();
405 while (mLegacyBackupList.
size() >= editor()->preference()->getInt(SETTING::UNDO_REDO_MAX_STEPS))
408 mLegacyBackupIndex--;
411 Layer* layer = editor()->layers()->getLayer(backupLayer);
412 int currentFrame = editor()->currentFrame();
413 if (layer !=
nullptr)
415 if (layer->type() == Layer::BITMAP)
418 if (currentFrame == 1)
420 int previous = layer->getPreviousKeyFramePosition(backupFrame);
421 bitmapImage =
static_cast<BitmapImage*
>(layer->getKeyFrameAt(previous));
423 if (bitmapImage !=
nullptr)
426 element->layerId = layer->id();
427 element->layer = backupLayer;
428 element->frame = bitmapImage->pos();
429 element->undoText = undoText;
430 element->somethingSelected = editor()->select()->somethingSelected();
431 element->mySelection = editor()->select()->mySelectionRect();
432 element->rotationAngle = editor()->select()->myRotation();
433 element->scaleX = editor()->select()->myScaleX();
434 element->scaleY = editor()->select()->myScaleY();
435 element->translation = editor()->select()->myTranslation();
436 element->selectionAnchor = editor()->select()->currentTransformAnchor();
438 mLegacyBackupList.
append(element);
439 mLegacyBackupIndex++;
446 else if (layer->type() == Layer::VECTOR)
449 if (vectorImage !=
nullptr)
452 element->layerId = layer->id();
453 element->layer = backupLayer;
454 element->frame = vectorImage->pos();
455 element->undoText = undoText;
456 element->somethingSelected = editor()->select()->somethingSelected();
457 element->mySelection = editor()->select()->mySelectionRect();
458 element->rotationAngle = editor()->select()->myRotation();
459 element->scaleX = editor()->select()->myScaleX();
460 element->scaleY = editor()->select()->myScaleY();
461 element->translation = editor()->select()->myTranslation();
462 element->selectionAnchor = editor()->select()->currentTransformAnchor();
463 mLegacyBackupList.
append(element);
464 mLegacyBackupIndex++;
471 else if (layer->type() == Layer::SOUND)
473 int previous = layer->getPreviousKeyFramePosition(backupFrame);
474 KeyFrame* key = layer->getLastKeyFrameAtPosition(backupFrame);
479 KeyFrame* previousKey = layer->getKeyFrameAt(previous);
482 if (key !=
nullptr) {
487 element->layerId = layer->id();
488 element->layer = backupLayer;
489 element->frame = backupFrame;
490 element->undoText = undoText;
491 element->fileName = clip->fileName();
492 element->originalName = clip->soundClipName();
493 mLegacyBackupList.
append(element);
494 mLegacyBackupIndex++;
504 emit didUpdateUndoStack();
511 if (mNewBackupSystemEnabled) {
515 for (
int i = 0; i < mLegacyBackupList.
size(); i++)
521 switch (backupElement->type())
523 case LegacyBackupElement::BITMAP_MODIF:
524 bitmapElement = qobject_cast<BackupLegacyBitmapElement*>(backupElement);
525 Q_ASSERT(bitmapElement);
526 if (bitmapElement->layer > layerIndex)
528 bitmapElement->layer--;
531 else if (bitmapElement->layer != layerIndex)
536 case LegacyBackupElement::VECTOR_MODIF:
537 vectorElement = qobject_cast<BackupLegacyVectorElement*>(backupElement);
538 Q_ASSERT(vectorElement);
539 if (vectorElement->layer > layerIndex)
541 vectorElement->layer--;
544 else if (vectorElement->layer != layerIndex)
549 case LegacyBackupElement::SOUND_MODIF:
550 soundElement = qobject_cast<BackupLegacySoundElement*>(backupElement);
551 Q_ASSERT(soundElement);
552 if (soundElement->layer > layerIndex)
554 soundElement->layer--;
557 else if (soundElement->layer != layerIndex)
565 if (i <= mLegacyBackupIndex)
567 mLegacyBackupIndex--;
569 delete mLegacyBackupList.
takeAt(i);
574void UndoRedoManager::restoreLegacyKey()
576 if (mNewBackupSystemEnabled) {
582 Layer* layer =
nullptr;
585 if (lastBackupElement->type() == LegacyBackupElement::BITMAP_MODIF)
588 layerIndex = lastBackupBitmapElement->layer;
589 frame = lastBackupBitmapElement->frame;
590 layer = object()->findLayerById(lastBackupBitmapElement->layerId);
592 dynamic_cast<LayerBitmap*
>(layer)->getBitmapImageAtFrame(frame)->paste(&lastBackupBitmapElement->bitmapImage);
593 editor()->setModified(layerIndex, frame);
595 if (lastBackupElement->type() == LegacyBackupElement::VECTOR_MODIF)
598 layerIndex = lastBackupVectorElement->layer;
599 frame = lastBackupVectorElement->frame;
600 layer = object()->findLayerById(layerIndex);
602 dynamic_cast<LayerVector*
>(layer)->getVectorImageAtFrame(frame)->paste(lastBackupVectorElement->vectorImage);
603 editor()->setModified(layerIndex, frame);
605 if (lastBackupElement->type() == LegacyBackupElement::SOUND_MODIF)
609 layerIndex = lastBackupSoundElement->layer;
610 frame = lastBackupSoundElement->frame;
612 strSoundFile = lastBackupSoundElement->fileName;
613 if (strSoundFile.
isEmpty())
return;
618 Status st = editor()->sound()->loadSound(clip, lastBackupSoundElement->fileName);
619 clip->setSoundClipName(lastBackupSoundElement->originalName);
622 editor()->removeKey();
623 emit editor()->layers()->currentLayerChanged(editor()->layers()->currentLayerIndex());
629void UndoRedoManager::legacyUndo()
631 if (!mLegacyBackupList.
empty() && mLegacyBackupIndex > -1)
633 if (mLegacyBackupIndex == mLegacyBackupList.
size() - 1)
636 if (lastBackupElement->type() == LegacyBackupElement::BITMAP_MODIF)
639 if (legacyBackup(lastBackupBitmapElement->layer, lastBackupBitmapElement->frame,
"NoOp"))
641 mLegacyBackupIndex--;
644 if (lastBackupElement->type() == LegacyBackupElement::VECTOR_MODIF)
647 if (legacyBackup(lastBackupVectorElement->layer, lastBackupVectorElement->frame,
"NoOp"))
649 mLegacyBackupIndex--;
652 if (lastBackupElement->type() == LegacyBackupElement::SOUND_MODIF)
655 if (legacyBackup(lastBackupSoundElement->layer, lastBackupSoundElement->frame,
"NoOp"))
657 mLegacyBackupIndex--;
662 qDebug() <<
"Undo" << mLegacyBackupIndex;
663 mLegacyBackupList[mLegacyBackupIndex]->restore(editor());
664 mLegacyBackupIndex--;
666 emit didUpdateUndoStack();
670void UndoRedoManager::legacyRedo()
672 if (!mLegacyBackupList.
empty() && mLegacyBackupIndex < mLegacyBackupList.
size() - 2)
674 mLegacyBackupIndex++;
676 mLegacyBackupList[mLegacyBackupIndex + 1]->restore(editor());
677 emit didUpdateUndoStack();
681void UndoRedoManager::rememberLastModifiedFrame(
int layerNumber,
int frameNumber)
683 if (mNewBackupSystemEnabled) {
686 mLegacyLastModifiedLayer = layerNumber;
687 mLegacyLastModifiedFrame = frameNumber;
KeyFrame * addKeyFrame(int layerNumber, int frameIndex)
Attempts to create a new keyframe at the given position and layer.
void record(const UndoSaveState *&undoState, const QString &description)
Records the given save state.
bool hasUnsavedChanges() const
Checks whether there are unsaved changes.
void sanitizeLegacyBackupElementsAfterLayerDeletion(int layerIndex)
Restores integrity of the backup elements after a layer has been deleted.
void clearStack()
Clears the undo stack.
const UndoSaveState * state(UndoRedoRecordType recordType) const
Prepares and returns a save state with the given scope.
void setIcon(const QIcon &icon)
void setIconText(const QString &text)
void setText(const QString &text)
void triggered(bool checked)
void append(const T &value)
const T & at(int i) const const
bool isEmpty() const const
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QObject * parent() const const
QString tr(const char *sourceText, const char *disambiguation, int n)
QString & append(QChar ch)
bool isEmpty() const const
QAction * createRedoAction(QObject *parent, const QString &prefix) const const
QAction * createUndoAction(QObject *parent, const QString &prefix) const const
bool isClean() const const
void push(QUndoCommand *cmd)
void setUndoLimit(int limit)
This is the main undo/redo state structure which is meant to populate whatever states that needs to b...