- redesign redo system
- fix: correctly restore editor's modified status when undo/redo
This commit is contained in:
parent
10631f54d7
commit
8d59bf9abb
1
NEWS.md
1
NEWS.md
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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())
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue