- redesign redo system

- fix: correctly restore editor's modified status when undo/redo
This commit is contained in:
Roy Qu 2022-07-06 14:11:32 +08:00
parent 10631f54d7
commit 8d59bf9abb
5 changed files with 238 additions and 137 deletions

View File

@ -11,6 +11,7 @@ Red Panda C++ Version 1.1.4
- fix: undo chains - fix: undo chains
- enhancement: prevent group undo when caret position changed - enhancement: prevent group undo when caret position changed
- fix: undo link break may lose leading spaces - fix: undo link break may lose leading spaces
- fix: correctly restore editor's modified status when undo/redo
Red Panda C++ Version 1.1.3 Red Panda C++ Version 1.1.3

View File

@ -80,8 +80,8 @@ SynEdit::SynEdit(QWidget *parent) : QAbstractScrollArea(parent),
mUndoList = std::make_shared<SynEditUndoList>(); mUndoList = std::make_shared<SynEditUndoList>();
mUndoList->connect(mUndoList.get(), &SynEditUndoList::addedUndo, this, &SynEdit::onUndoAdded); mUndoList->connect(mUndoList.get(), &SynEditUndoList::addedUndo, this, &SynEdit::onUndoAdded);
mRedoList = std::make_shared<SynEditUndoList>(); mRedoList = std::make_shared<SynEditRedoList>();
mRedoList->connect(mRedoList.get(), &SynEditUndoList::addedUndo, this, &SynEdit::onRedoAdded); // mRedoList->connect(mRedoList.get(), &SynEditUndoList::addedUndo, this, &SynEdit::onRedoAdded);
mForegroundColor=palette().color(QPalette::Text); mForegroundColor=palette().color(QPalette::Text);
mBackgroundColor=palette().color(QPalette::Base); mBackgroundColor=palette().color(QPalette::Base);
@ -353,7 +353,7 @@ bool SynEdit::canUndo() const
bool SynEdit::canRedo() const bool SynEdit::canRedo() const
{ {
return !mReadOnly && mRedoList->canUndo(); return !mReadOnly && mRedoList->canRedo();
} }
int SynEdit::maxScrollWidth() const int SynEdit::maxScrollWidth() const
@ -3089,7 +3089,7 @@ void SynEdit::doPasteFromClipboard()
BufferCoord vEndOfBlock = blockEnd(); BufferCoord vEndOfBlock = blockEnd();
mBlockBegin = vStartOfBlock; mBlockBegin = vStartOfBlock;
mBlockEnd = vEndOfBlock; mBlockEnd = vEndOfBlock;
qDebug()<<textToLines(text); // qDebug()<<textToLines(text);
setSelTextPrimitive(splitStrings(text)); setSelTextPrimitive(splitStrings(text));
mUndoList->endBlock(); mUndoList->endBlock();
} }
@ -3428,7 +3428,7 @@ void SynEdit::updateModifiedStatus()
bool oldModified = mModified; bool oldModified = mModified;
mModified = !mUndoList->initialState(); mModified = !mUndoList->initialState();
setModified(mModified); setModified(mModified);
qDebug()<<mModified<<oldModified; // qDebug()<<mModified<<oldModified;
if (oldModified!=mModified) if (oldModified!=mModified)
emit statusChanged(SynStatusChange::scModifyChanged); emit statusChanged(SynStatusChange::scModifyChanged);
} }
@ -4294,31 +4294,15 @@ void SynEdit::doUndo()
return; return;
//Remove Group Break; //Remove Group Break;
if (mUndoList->lastChangeReason() == SynChangeReason::GroupBreak) { while (mUndoList->lastChangeReason() == SynChangeReason::GroupBreak) {
int OldBlockNumber = mRedoList->blockChangeNumber();
auto action = finally([&,this]{
mRedoList->setBlockChangeNumber(OldBlockNumber);
});
PSynEditUndoItem item = mUndoList->popItem(); PSynEditUndoItem item = mUndoList->popItem();
mRedoList->setBlockChangeNumber(item->changeNumber()); mRedoList->addRedo(item);
mRedoList->addGroupBreak();
} }
PSynEditUndoItem item = mUndoList->peekItem(); PSynEditUndoItem item = mUndoList->peekItem();
if (item) { if (item) {
size_t oldChangeNumber = item->changeNumber(); size_t oldChangeNumber = item->changeNumber();
size_t saveChangeNumber = mRedoList->blockChangeNumber();
mRedoList->setBlockChangeNumber(item->changeNumber());
{ {
auto action = finally([&,this] {
mRedoList->setBlockChangeNumber(saveChangeNumber);
});
//skip group chain breakers
if (mUndoList->lastChangeReason()==SynChangeReason::GroupBreak) {
while (!mUndoList->isEmpty() && mUndoList->lastChangeReason()==SynChangeReason::GroupBreak) {
doUndoItem();
}
}
SynChangeReason lastChange = mUndoList->lastChangeReason(); SynChangeReason lastChange = mUndoList->lastChangeReason();
bool keepGoing; bool keepGoing;
do { do {
@ -4339,6 +4323,8 @@ void SynEdit::doUndo()
} while (keepGoing); } while (keepGoing);
} }
} }
updateModifiedStatus();
onChanged();
} }
void SynEdit::doUndoItem() void SynEdit::doUndoItem()
@ -4359,43 +4345,47 @@ void SynEdit::doUndoItem()
mOptions.setFlag(eoScrollPastEol); mOptions.setFlag(eoScrollPastEol);
switch(item->changeReason()) { switch(item->changeReason()) {
case SynChangeReason::Caret: case SynChangeReason::Caret:
mRedoList->addChange( mRedoList->addRedo(
item->changeReason(), item->changeReason(),
caretXY(), caretXY(),
caretXY(), QStringList(), caretXY(), QStringList(),
item->changeSelMode()); item->changeSelMode(),
item->changeNumber());
internalSetCaretXY(item->changeStartPos()); internalSetCaretXY(item->changeStartPos());
break; break;
case SynChangeReason::LeftTop: case SynChangeReason::LeftTop:
BufferCoord p; BufferCoord p;
p.ch = leftChar(); p.ch = leftChar();
p.line = topLine(); p.line = topLine();
mRedoList->addChange( mRedoList->addRedo(
item->changeReason(), item->changeReason(),
p, p,
p, QStringList(), p, QStringList(),
item->changeSelMode()); item->changeSelMode(),
item->changeNumber());
setLeftChar(item->changeStartPos().ch); setLeftChar(item->changeStartPos().ch);
setTopLine(item->changeStartPos().line); setTopLine(item->changeStartPos().line);
break; break;
case SynChangeReason::Selection: case SynChangeReason::Selection:
mRedoList->addChange( mRedoList->addRedo(
item->changeReason(), item->changeReason(),
mBlockBegin, mBlockBegin,
mBlockEnd, mBlockEnd,
QStringList(), QStringList(),
item->changeSelMode()); item->changeSelMode(),
item->changeNumber());
setCaretAndSelection(caretXY(), item->changeStartPos(), item->changeEndPos()); setCaretAndSelection(caretXY(), item->changeStartPos(), item->changeEndPos());
break; break;
case SynChangeReason::Insert: { case SynChangeReason::Insert: {
QStringList tmpText = getContent(item->changeStartPos(),item->changeEndPos(),item->changeSelMode()); QStringList tmpText = getContent(item->changeStartPos(),item->changeEndPos(),item->changeSelMode());
doDeleteText(item->changeStartPos(),item->changeEndPos(),item->changeSelMode()); doDeleteText(item->changeStartPos(),item->changeEndPos(),item->changeSelMode());
mRedoList->addChange( mRedoList->addRedo(
item->changeReason(), item->changeReason(),
item->changeStartPos(), item->changeStartPos(),
item->changeEndPos(), item->changeEndPos(),
tmpText, tmpText,
item->changeSelMode()); item->changeSelMode(),
item->changeNumber());
internalSetCaretXY(item->changeStartPos()); internalSetCaretXY(item->changeStartPos());
break; break;
} }
@ -4403,23 +4393,25 @@ void SynEdit::doUndoItem()
setBlockBegin(BufferCoord{item->changeStartPos().ch, item->changeStartPos().line-1}); setBlockBegin(BufferCoord{item->changeStartPos().ch, item->changeStartPos().line-1});
setBlockEnd(BufferCoord{item->changeEndPos().ch, item->changeEndPos().line-1}); setBlockEnd(BufferCoord{item->changeEndPos().ch, item->changeEndPos().line-1});
doMoveSelDown(); doMoveSelDown();
mRedoList->addChange( mRedoList->addRedo(
item->changeReason(), item->changeReason(),
item->changeStartPos(), item->changeStartPos(),
item->changeEndPos(), item->changeEndPos(),
item->changeText(), item->changeText(),
item->changeSelMode()); item->changeSelMode(),
item->changeNumber());
break; break;
case SynChangeReason::MoveSelectionDown: case SynChangeReason::MoveSelectionDown:
setBlockBegin(BufferCoord{item->changeStartPos().ch, item->changeStartPos().line+1}); setBlockBegin(BufferCoord{item->changeStartPos().ch, item->changeStartPos().line+1});
setBlockEnd(BufferCoord{item->changeEndPos().ch, item->changeEndPos().line+1}); setBlockEnd(BufferCoord{item->changeEndPos().ch, item->changeEndPos().line+1});
doMoveSelUp(); doMoveSelUp();
mRedoList->addChange( mRedoList->addRedo(
item->changeReason(), item->changeReason(),
item->changeStartPos(), item->changeStartPos(),
item->changeEndPos(), item->changeEndPos(),
item->changeText(), item->changeText(),
item->changeSelMode()); item->changeSelMode(),
item->changeNumber());
break; break;
case SynChangeReason::Delete: { case SynChangeReason::Delete: {
// If there's no selection, we have to set // If there's no selection, we have to set
@ -4431,12 +4423,13 @@ void SynEdit::doUndoItem()
item->changeStartPos().line, item->changeStartPos().line,
item->changeEndPos().line); item->changeEndPos().line);
internalSetCaretXY(item->changeEndPos()); internalSetCaretXY(item->changeEndPos());
mRedoList->addChange( mRedoList->addRedo(
item->changeReason(), item->changeReason(),
item->changeStartPos(), item->changeStartPos(),
item->changeEndPos(), item->changeEndPos(),
item->changeText(), item->changeText(),
item->changeSelMode()); item->changeSelMode(),
item->changeNumber());
ensureCursorPosVisible(); ensureCursorPosVisible();
break; break;
} }
@ -4456,12 +4449,13 @@ void SynEdit::doUndoItem()
mDocument->deleteAt(mCaretY); mDocument->deleteAt(mCaretY);
doLinesDeleted(mCaretY, 1); doLinesDeleted(mCaretY, 1);
} }
mRedoList->addChange( mRedoList->addRedo(
item->changeReason(), item->changeReason(),
item->changeStartPos(), item->changeStartPos(),
item->changeEndPos(), item->changeEndPos(),
item->changeText(), item->changeText(),
item->changeSelMode()); item->changeSelMode(),
item->changeNumber());
break; break;
} }
default: default:
@ -4479,51 +4473,38 @@ void SynEdit::doRedo()
if (!item) if (!item)
return; return;
size_t oldChangeNumber = item->changeNumber(); size_t oldChangeNumber = item->changeNumber();
size_t saveChangeNumber = mUndoList->blockChangeNumber();
mUndoList->setBlockChangeNumber(item->changeNumber());
{
auto action = finally([&,this]{
mUndoList->setBlockChangeNumber(saveChangeNumber);
});
//skip group chain breakers
if (mRedoList->lastChangeReason()==SynChangeReason::GroupBreak) {
while (!mRedoList->isEmpty() && mRedoList->lastChangeReason()==SynChangeReason::GroupBreak) {
doRedoItem();
}
}
SynChangeReason lastChange = mRedoList->lastChangeReason();
bool keepGoing;
do {
doRedoItem();
item = mRedoList->peekItem();
if (!item)
keepGoing = false;
else {
if (item->changeNumber() == oldChangeNumber)
keepGoing = true;
else {
keepGoing = (mOptions.testFlag(eoGroupUndo) &&
(lastChange == item->changeReason()));
}
oldChangeNumber=item->changeNumber();
lastChange = item->changeReason();
}
} while (keepGoing);
//skip group chain breakers
while (mRedoList->lastChangeReason()==SynChangeReason::GroupBreak) {
PSynEditUndoItem item = mRedoList->popItem();
mUndoList->restoreChange(item);
} }
//Remove Group Break SynChangeReason lastChange = mRedoList->lastChangeReason();
if (mRedoList->lastChangeReason() == SynChangeReason::GroupBreak) { bool keepGoing;
int OldBlockNumber = mUndoList->blockChangeNumber(); do {
item = mRedoList->popItem(); doRedoItem();
{ item = mRedoList->peekItem();
auto action2=finally([&,this]{ if (!item)
mUndoList->setBlockChangeNumber(OldBlockNumber); keepGoing = false;
}); else {
mUndoList->setBlockChangeNumber(item->changeNumber()); if (item->changeNumber() == oldChangeNumber)
mUndoList->addGroupBreak(); keepGoing = true;
else {
keepGoing = (mOptions.testFlag(eoGroupUndo) &&
(lastChange == item->changeReason()));
} }
updateModifiedStatus(); oldChangeNumber=item->changeNumber();
lastChange = item->changeReason();
}
} while (keepGoing);
//restore Group Break
while (mRedoList->lastChangeReason()==SynChangeReason::GroupBreak) {
PSynEditUndoItem item = mRedoList->popItem();
mUndoList->restoreChange(item);
} }
updateModifiedStatus();
onChanged();
} }
void SynEdit::doRedoItem() void SynEdit::doRedoItem()
@ -4545,33 +4526,36 @@ void SynEdit::doRedoItem()
}); });
switch(item->changeReason()) { switch(item->changeReason()) {
case SynChangeReason::Caret: case SynChangeReason::Caret:
mUndoList->addChange( mUndoList->restoreChange(
item->changeReason(), item->changeReason(),
caretXY(), caretXY(),
caretXY(), caretXY(),
QStringList(), QStringList(),
mActiveSelectionMode); mActiveSelectionMode,
item->changeNumber());
internalSetCaretXY(item->changeStartPos()); internalSetCaretXY(item->changeStartPos());
break; break;
case SynChangeReason::LeftTop: case SynChangeReason::LeftTop:
BufferCoord p; BufferCoord p;
p.ch = leftChar(); p.ch = leftChar();
p.line = topLine(); p.line = topLine();
mUndoList->addChange( mUndoList->restoreChange(
item->changeReason(), item->changeReason(),
p, p,
p, QStringList(), p, QStringList(),
item->changeSelMode()); item->changeSelMode(),
item->changeNumber());
setLeftChar(item->changeStartPos().ch); setLeftChar(item->changeStartPos().ch);
setTopLine(item->changeStartPos().line); setTopLine(item->changeStartPos().line);
break; break;
case SynChangeReason::Selection: case SynChangeReason::Selection:
mUndoList->addChange( mUndoList->restoreChange(
item->changeReason(), item->changeReason(),
mBlockBegin, mBlockBegin,
mBlockEnd, mBlockEnd,
QStringList(), QStringList(),
mActiveSelectionMode); mActiveSelectionMode,
item->changeNumber());
setCaretAndSelection( setCaretAndSelection(
caretXY(), caretXY(),
item->changeStartPos(), item->changeStartPos(),
@ -4581,23 +4565,25 @@ void SynEdit::doRedoItem()
setBlockBegin(BufferCoord{item->changeStartPos().ch, item->changeStartPos().line}); setBlockBegin(BufferCoord{item->changeStartPos().ch, item->changeStartPos().line});
setBlockEnd(BufferCoord{item->changeEndPos().ch, item->changeEndPos().line}); setBlockEnd(BufferCoord{item->changeEndPos().ch, item->changeEndPos().line});
doMoveSelUp(); doMoveSelUp();
mUndoList->addChange( mUndoList->restoreChange(
item->changeReason(), item->changeReason(),
item->changeStartPos(), item->changeStartPos(),
item->changeEndPos(), item->changeEndPos(),
item->changeText(), item->changeText(),
item->changeSelMode()); item->changeSelMode(),
item->changeNumber());
break; break;
case SynChangeReason::MoveSelectionDown: case SynChangeReason::MoveSelectionDown:
setBlockBegin(BufferCoord{item->changeStartPos().ch, item->changeStartPos().line}); setBlockBegin(BufferCoord{item->changeStartPos().ch, item->changeStartPos().line});
setBlockEnd(BufferCoord{item->changeEndPos().ch, item->changeEndPos().line}); setBlockEnd(BufferCoord{item->changeEndPos().ch, item->changeEndPos().line});
doMoveSelDown(); doMoveSelDown();
mUndoList->addChange( mUndoList->restoreChange(
item->changeReason(), item->changeReason(),
item->changeStartPos(), item->changeStartPos(),
item->changeEndPos(), item->changeEndPos(),
item->changeText(), item->changeText(),
item->changeSelMode()); item->changeSelMode(),
item->changeNumber());
break; break;
case SynChangeReason::Insert: case SynChangeReason::Insert:
setCaretAndSelection( setCaretAndSelection(
@ -4608,25 +4594,26 @@ void SynEdit::doRedoItem()
item->changeStartPos().line, item->changeStartPos().line,
item->changeEndPos().line); item->changeEndPos().line);
internalSetCaretXY(item->changeEndPos()); internalSetCaretXY(item->changeEndPos());
mUndoList->addChange(item->changeReason(), mUndoList->restoreChange(item->changeReason(),
item->changeStartPos(), item->changeStartPos(),
item->changeEndPos(), item->changeEndPos(),
QStringList(), QStringList(),
item->changeSelMode()); item->changeSelMode(),
item->changeNumber());
break; break;
case SynChangeReason::Delete: { case SynChangeReason::Delete: {
doDeleteText(item->changeStartPos(),item->changeEndPos(),item->changeSelMode()); doDeleteText(item->changeStartPos(),item->changeEndPos(),item->changeSelMode());
mUndoList->addChange(item->changeReason(), item->changeStartPos(), mUndoList->restoreChange(item->changeReason(), item->changeStartPos(),
item->changeEndPos(),item->changeText(), item->changeEndPos(),item->changeText(),
item->changeSelMode()); item->changeSelMode(),item->changeNumber());
internalSetCaretXY(item->changeStartPos()); internalSetCaretXY(item->changeStartPos());
break; break;
}; };
case SynChangeReason::LineBreak: { case SynChangeReason::LineBreak: {
BufferCoord CaretPt = item->changeStartPos(); BufferCoord CaretPt = item->changeStartPos();
mUndoList->addChange(item->changeReason(), item->changeStartPos(), mUndoList->restoreChange(item->changeReason(), item->changeStartPos(),
item->changeEndPos(),item->changeText(), item->changeEndPos(),item->changeText(),
item->changeSelMode()); item->changeSelMode(),item->changeNumber());
setCaretAndSelection(CaretPt, CaretPt, CaretPt); setCaretAndSelection(CaretPt, CaretPt, CaretPt);
commandProcessor(SynEditorCommand::ecLineBreak); commandProcessor(SynEditorCommand::ecLineBreak);
break; break;
@ -6591,8 +6578,6 @@ int SynEdit::charWidth() const
void SynEdit::setUndoLimit(int size) void SynEdit::setUndoLimit(int size)
{ {
mUndoList->setMaxUndoActions(size); mUndoList->setMaxUndoActions(size);
mRedoList->setMaxUndoActions(size);
} }
int SynEdit::charsInWindow() const int SynEdit::charsInWindow() const
@ -6909,12 +6894,6 @@ void SynEdit::setTopLine(int Value)
} }
} }
void SynEdit::onRedoAdded()
{
updateModifiedStatus();
onChanged();
}
void SynEdit::onGutterChanged() void SynEdit::onGutterChanged()
{ {
if (mGutter.showLineNumbers() && mGutter.autoSize()) if (mGutter.showLineNumbers() && mGutter.autoSize())

View File

@ -633,7 +633,7 @@ private slots:
void onLinesDeleted(int index, int count); void onLinesDeleted(int index, int count);
void onLinesInserted(int index, int count); void onLinesInserted(int index, int count);
void onLinesPutted(int index, int count); void onLinesPutted(int index, int count);
void onRedoAdded(); //void onRedoAdded();
void onScrollTimeout(); void onScrollTimeout();
void onDraggingScrollTimeout(); void onDraggingScrollTimeout();
void onUndoAdded(); void onUndoAdded();
@ -687,7 +687,7 @@ private:
bool mCaretUseTextColor; bool mCaretUseTextColor;
QColor mActiveLineColor; QColor mActiveLineColor;
PSynEditUndoList mUndoList; PSynEditUndoList mUndoList;
PSynEditUndoList mRedoList; PSynEditRedoList mRedoList;
QPoint mMouseDownPos; QPoint mMouseDownPos;
bool mHideSelection; bool mHideSelection;
int mMouseWheelAccumulator; int mMouseWheelAccumulator;

View File

@ -840,16 +840,17 @@ SynEditUndoList::SynEditUndoList():QObject()
mInsideRedo = false; mInsideRedo = false;
mBlockChangeNumber=0; mBlockChangeNumber=0;
mBlockLockCount=0; mBlockLock=0;
mFullUndoImposible=false; mFullUndoImposible=false;
mBlockCount=0; mBlockCount=0;
mLastPoppedItemChangeNumber=0; mLastPoppedItemChangeNumber=0;
mInitialChangeNumber = 0; mInitialChangeNumber = 0;
mLastRestoredItemChangeNumber=0;
} }
void SynEditUndoList::addChange(SynChangeReason AReason, const BufferCoord &AStart, void SynEditUndoList::addChange(SynChangeReason reason, const BufferCoord &startPos,
const BufferCoord &AEnd, const QStringList& ChangeText, const BufferCoord &endPos, const QStringList& changeText,
SynSelectionMode SelMode) SynSelectionMode selMode)
{ {
int changeNumber; int changeNumber;
if (inBlock()) { if (inBlock()) {
@ -857,15 +858,41 @@ void SynEditUndoList::addChange(SynChangeReason AReason, const BufferCoord &ASta
} else { } else {
changeNumber = getNextChangeNumber(); changeNumber = getNextChangeNumber();
} }
PSynEditUndoItem newItem = std::make_shared<SynEditUndoItem>(
reason,
selMode,startPos,endPos,changeText,
changeNumber);
// qDebug()<<"add change"<<changeNumber<<(int)reason;
mItems.append(newItem);
ensureMaxEntries();
if (reason!=SynChangeReason::GroupBreak && !inBlock()) {
mBlockCount++;
// qDebug()<<"add"<<mBlockCount;
emit addedUndo();
}
}
void SynEditUndoList::restoreChange(SynChangeReason AReason, const BufferCoord &AStart, const BufferCoord &AEnd, const QStringList &ChangeText, SynSelectionMode SelMode, size_t changeNumber)
{
PSynEditUndoItem newItem = std::make_shared<SynEditUndoItem>(AReason, PSynEditUndoItem newItem = std::make_shared<SynEditUndoItem>(AReason,
SelMode,AStart,AEnd,ChangeText, SelMode,AStart,AEnd,ChangeText,
changeNumber); changeNumber);
mItems.append(newItem); restoreChange(newItem);
}
void SynEditUndoList::restoreChange(PSynEditUndoItem item)
{
size_t changeNumber = item->changeNumber();
mItems.append(item);
ensureMaxEntries(); ensureMaxEntries();
if (AReason!=SynChangeReason::GroupBreak && !inBlock()) { if (changeNumber>mNextChangeNumber)
mNextChangeNumber=changeNumber;
if (changeNumber!=mLastRestoredItemChangeNumber) {
// qDebug()<<"restore"<<mBlockCount;
mBlockCount++; mBlockCount++;
emit addedUndo(); emit addedUndo();
} }
mLastRestoredItemChangeNumber=changeNumber;
} }
void SynEditUndoList::addGroupBreak() void SynEditUndoList::addGroupBreak()
@ -880,8 +907,11 @@ void SynEditUndoList::addGroupBreak()
void SynEditUndoList::beginBlock() void SynEditUndoList::beginBlock()
{ {
mBlockLockCount++; // qDebug()<<"begin block";
mBlockChangeNumber = getNextChangeNumber(); if (mBlockLock==0)
mBlockChangeNumber = getNextChangeNumber();
mBlockLock++;
} }
void SynEditUndoList::clear() void SynEditUndoList::clear()
@ -890,19 +920,22 @@ void SynEditUndoList::clear()
mFullUndoImposible = false; mFullUndoImposible = false;
mInitialChangeNumber=0; mInitialChangeNumber=0;
mLastPoppedItemChangeNumber=0; mLastPoppedItemChangeNumber=0;
mLastRestoredItemChangeNumber=0;
mBlockCount=0; mBlockCount=0;
mBlockLockCount=0; mBlockLock=0;
} }
void SynEditUndoList::endBlock() void SynEditUndoList::endBlock()
{ {
if (mBlockLockCount > 0) { // qDebug()<<"end block";
mBlockLockCount--; if (mBlockLock > 0) {
if (mBlockLockCount == 0) { mBlockLock--;
if (mBlockLock == 0) {
size_t iBlockID = mBlockChangeNumber; size_t iBlockID = mBlockChangeNumber;
mBlockChangeNumber = 0; mBlockChangeNumber = 0;
if (mItems.count() > 0 && peekItem()->changeNumber() == iBlockID) { if (mItems.count() > 0 && peekItem()->changeNumber() == iBlockID) {
mBlockCount++; mBlockCount++;
// qDebug()<<"end block"<<mBlockCount;
emit addedUndo(); emit addedUndo();
} }
} }
@ -911,7 +944,7 @@ void SynEditUndoList::endBlock()
bool SynEditUndoList::inBlock() bool SynEditUndoList::inBlock()
{ {
return mBlockLockCount>0; return mBlockLock>0;
} }
unsigned int SynEditUndoList::getNextChangeNumber() unsigned int SynEditUndoList::getNextChangeNumber()
@ -946,10 +979,12 @@ PSynEditUndoItem SynEditUndoList::popItem()
return PSynEditUndoItem(); return PSynEditUndoItem();
else { else {
PSynEditUndoItem item = mItems.last(); PSynEditUndoItem item = mItems.last();
if (mLastPoppedItemChangeNumber!=item->changeNumber()) { // qDebug()<<"popped"<<item->changeNumber()<<item->changeText()<<(int)item->changeReason()<<mLastPoppedItemChangeNumber;
if (mLastPoppedItemChangeNumber!=item->changeNumber() && item->changeReason()!=SynChangeReason::GroupBreak) {
mBlockCount--; mBlockCount--;
// qDebug()<<"pop"<<mBlockCount;
if (mBlockCount<0) { if (mBlockCount<0) {
qDebug()<<"block count calculation error"; // qDebug()<<"block count calculation error";
mBlockCount=0; mBlockCount=0;
} }
} }
@ -999,16 +1034,6 @@ void SynEditUndoList::setInitialState()
mInitialChangeNumber = peekItem()->changeNumber(); mInitialChangeNumber = peekItem()->changeNumber();
} }
int SynEditUndoList::blockChangeNumber() const
{
return mBlockChangeNumber;
}
void SynEditUndoList::setBlockChangeNumber(int blockChangeNumber)
{
mBlockChangeNumber = blockChangeNumber;
}
bool SynEditUndoList::insideRedo() const bool SynEditUndoList::insideRedo() const
{ {
return mInsideRedo; return mInsideRedo;
@ -1030,10 +1055,12 @@ void SynEditUndoList::ensureMaxEntries()
mFullUndoImposible = true; mFullUndoImposible = true;
while (mBlockCount > mMaxUndoActions && !mItems.isEmpty()) { while (mBlockCount > mMaxUndoActions && !mItems.isEmpty()) {
//remove all undo item in block //remove all undo item in block
size_t changeNumber = mItems.front()->changeNumber(); PSynEditUndoItem item = mItems.front();
size_t changeNumber = item->changeNumber();
while (mItems.count()>0 && mItems.front()->changeNumber() == changeNumber) while (mItems.count()>0 && mItems.front()->changeNumber() == changeNumber)
mItems.removeFirst(); mItems.removeFirst();
mBlockCount--; if (item->changeReason()!=SynChangeReason::GroupBreak)
mBlockCount--;
} }
} }
} }
@ -1079,3 +1106,69 @@ SynChangeReason SynEditUndoItem::changeReason() const
{ {
return mChangeReason; return mChangeReason;
} }
SynEditRedoList::SynEditRedoList()
{
}
void SynEditRedoList::addRedo(SynChangeReason AReason, const BufferCoord &AStart, const BufferCoord &AEnd, const QStringList &ChangeText, SynSelectionMode SelMode, size_t changeNumber)
{
PSynEditUndoItem newItem = std::make_shared<SynEditUndoItem>(
AReason,
SelMode,AStart,AEnd,ChangeText,
changeNumber);
mItems.append(newItem);
}
void SynEditRedoList::addRedo(PSynEditUndoItem item)
{
mItems.append(item);
}
void SynEditRedoList::clear()
{
mItems.clear();
}
SynChangeReason SynEditRedoList::lastChangeReason()
{
if (mItems.count() == 0)
return SynChangeReason::Nothing;
else
return mItems.last()->changeReason();
}
bool SynEditRedoList::isEmpty()
{
return mItems.isEmpty();
}
PSynEditUndoItem SynEditRedoList::peekItem()
{
if (mItems.count() == 0)
return PSynEditUndoItem();
else
return mItems.last();
}
PSynEditUndoItem SynEditRedoList::popItem()
{
if (mItems.count() == 0)
return PSynEditUndoItem();
else {
PSynEditUndoItem item = mItems.last();
mItems.removeLast();
return item;
}
}
bool SynEditRedoList::canRedo()
{
return mItems.count()>0;
}
int SynEditRedoList::itemCount()
{
return mItems.count();
}

View File

@ -196,6 +196,7 @@ public:
QStringList changeText() const; QStringList changeText() const;
size_t changeNumber() const; size_t changeNumber() const;
}; };
using PSynEditUndoItem = std::shared_ptr<SynEditUndoItem>; using PSynEditUndoItem = std::shared_ptr<SynEditUndoItem>;
class SynEditUndoList : public QObject { class SynEditUndoList : public QObject {
@ -206,6 +207,11 @@ public:
void addChange(SynChangeReason AReason, const BufferCoord& AStart, const BufferCoord& AEnd, void addChange(SynChangeReason AReason, const BufferCoord& AStart, const BufferCoord& AEnd,
const QStringList& ChangeText, SynSelectionMode SelMode); const QStringList& ChangeText, SynSelectionMode SelMode);
void restoreChange(SynChangeReason AReason, const BufferCoord& AStart, const BufferCoord& AEnd,
const QStringList& ChangeText, SynSelectionMode SelMode, size_t changeNumber);
void restoreChange(PSynEditUndoItem item);
void addGroupBreak(); void addGroupBreak();
void beginBlock(); void beginBlock();
void endBlock(); void endBlock();
@ -224,9 +230,6 @@ public:
bool initialState(); bool initialState();
void setInitialState(); void setInitialState();
int blockChangeNumber() const;
void setBlockChangeNumber(int blockChangeNumber);
bool insideRedo() const; bool insideRedo() const;
void setInsideRedo(bool insideRedo); void setInsideRedo(bool insideRedo);
@ -240,9 +243,10 @@ protected:
unsigned int getNextChangeNumber(); unsigned int getNextChangeNumber();
protected: protected:
size_t mBlockChangeNumber; size_t mBlockChangeNumber;
int mBlockLockCount; int mBlockLock;
int mBlockCount; // count of action blocks; int mBlockCount; // count of action blocks;
size_t mLastPoppedItemChangeNumber; size_t mLastPoppedItemChangeNumber;
size_t mLastRestoredItemChangeNumber;
bool mFullUndoImposible; bool mFullUndoImposible;
QVector<PSynEditUndoItem> mItems; QVector<PSynEditUndoItem> mItems;
int mMaxUndoActions; int mMaxUndoActions;
@ -251,6 +255,30 @@ protected:
bool mInsideRedo; bool mInsideRedo;
}; };
class SynEditRedoList : public QObject {
Q_OBJECT
public:
explicit SynEditRedoList();
void addRedo(SynChangeReason AReason, const BufferCoord& AStart, const BufferCoord& AEnd,
const QStringList& ChangeText, SynSelectionMode SelMode, size_t changeNumber);
void addRedo(PSynEditUndoItem item);
void clear();
SynChangeReason lastChangeReason();
bool isEmpty();
PSynEditUndoItem peekItem();
PSynEditUndoItem popItem();
bool canRedo();
int itemCount();
protected:
QVector<PSynEditUndoItem> mItems;
};
using PSynEditUndoList = std::shared_ptr<SynEditUndoList>; using PSynEditUndoList = std::shared_ptr<SynEditUndoList>;
using PSynEditRedoList = std::shared_ptr<SynEditRedoList>;
#endif // SYNEDITSTRINGLIST_H #endif // SYNEDITSTRINGLIST_H