fakevim: use QTextDocument's undo/redo operations

this has several advantages compared to an undo/redo stack private to fakevim:
- change marks in document correspond to actual changes
- mouse pasting does not invalidate the fakevim undo/redo stack
- menu commands (such as undo/redo from the Edit menu) do not invalidate the fakevim undo/redo stack
- possible other changes not caused by fakevim do not invalidate fakevim undo/redo stack

it is pretty bad if the fakevim undo/redo stack becomes invalid, as applying these invalid
undo/redo operations corrupts the document
This commit is contained in:
Martin Aumueller
2009-02-09 08:45:02 +01:00
parent 137ba736a7
commit bf3c4a1562

View File

@@ -312,6 +312,7 @@ public:
QStack<EditOperation> m_undoStack; QStack<EditOperation> m_undoStack;
QStack<EditOperation> m_redoStack; QStack<EditOperation> m_redoStack;
QStack<int> m_undoGroupStack; QStack<int> m_undoGroupStack;
QMap<int, int> m_undoCursorPosition;
// extra data for '.' // extra data for '.'
QString m_dotCommand; QString m_dotCommand;
@@ -416,7 +417,14 @@ bool FakeVimHandler::Private::handleEvent(QKeyEvent *ev)
&& (ev->modifiers() & Qt::ShiftModifier) == 0) { && (ev->modifiers() & Qt::ShiftModifier) == 0) {
key += 32; key += 32;
} }
m_undoCursorPosition[EDITOR(document())->revision()] = m_tc.position();
if (m_mode == InsertMode)
m_tc.joinPreviousEditBlock();
else
m_tc.beginEditBlock();
bool handled = handleKey(key, um, ev->text()); bool handled = handleKey(key, um, ev->text());
m_tc.endEditBlock();
// We fake vi-style end-of-line behaviour // We fake vi-style end-of-line behaviour
m_fakeEnd = (atEndOfLine() && m_mode == CommandMode); m_fakeEnd = (atEndOfLine() && m_mode == CommandMode);
@@ -2012,6 +2020,11 @@ QWidget *FakeVimHandler::Private::editor() const
void FakeVimHandler::Private::undo() void FakeVimHandler::Private::undo()
{ {
EDITOR(undo());
int rev = EDITOR(document())->revision();
if (m_undoCursorPosition.contains(rev))
m_tc.setPosition(m_undoCursorPosition[rev]);
#if 0
if (m_undoStack.isEmpty()) { if (m_undoStack.isEmpty()) {
showBlackMessage(tr("Already at oldest change")); showBlackMessage(tr("Already at oldest change"));
} else { } else {
@@ -2033,10 +2046,22 @@ void FakeVimHandler::Private::undo()
m_redoStack.push(op); m_redoStack.push(op);
showBlackMessage(QString()); showBlackMessage(QString());
} }
#endif
} }
void FakeVimHandler::Private::redo() void FakeVimHandler::Private::redo()
{ {
int current = EDITOR(document())->revision();
EDITOR(redo());
int rev = EDITOR(document())->revision();
if (rev == current) {
showBlackMessage(tr("Already at newest change"));
} else {
showBlackMessage(QString());
if (m_undoCursorPosition.contains(rev))
m_tc.setPosition(m_undoCursorPosition[rev]);
}
#if 0
if (m_redoStack.isEmpty()) { if (m_redoStack.isEmpty()) {
showBlackMessage(tr("Already at newest change")); showBlackMessage(tr("Already at newest change"));
} else { } else {
@@ -2058,6 +2083,7 @@ void FakeVimHandler::Private::redo()
m_undoStack.push(op); m_undoStack.push(op);
showBlackMessage(QString()); showBlackMessage(QString());
} }
#endif
} }
void FakeVimHandler::Private::recordBeginGroup() void FakeVimHandler::Private::recordBeginGroup()