FakeVim: Use QTextDocument::availableUndoSteps() for undo/redo

Partially reverts commit b9cc16e405.

Using QTextDocument::revision() to keep track which undo/redo command
should be used next doesn't help much and it's more difficult to use
than QTextDocument::availableUndoSteps().

Task-number: QTCREATORBUG-9784
Change-Id: I656e1e964477de0f387c80b9384a32e0d8dab39f
Reviewed-by: hjk <hjk121@nokiamail.com>
This commit is contained in:
hluk
2013-07-20 08:36:05 +02:00
committed by hjk
parent a03112d2f6
commit d935b4cfc6

View File

@@ -288,16 +288,16 @@ typedef QHashIterator<QChar, Mark> MarksIterator;
struct State struct State
{ {
State() : revisions(0), position(), marks(), lastVisualMode(NoVisualMode), State() : revision(-1), position(), marks(), lastVisualMode(NoVisualMode),
lastVisualModeInverted(false) {} lastVisualModeInverted(false) {}
State(const CursorPosition &position, const Marks &marks, State(int revision, const CursorPosition &position, const Marks &marks,
VisualMode lastVisualMode, bool lastVisualModeInverted) : revisions(0), VisualMode lastVisualMode, bool lastVisualModeInverted) : revision(revision),
position(position), marks(marks), lastVisualMode(lastVisualMode), position(position), marks(marks), lastVisualMode(lastVisualMode),
lastVisualModeInverted(lastVisualModeInverted) {} lastVisualModeInverted(lastVisualModeInverted) {}
bool isValid() const { return position.isValid(); } bool isValid() const { return position.isValid(); }
int revisions; int revision;
CursorPosition position; CursorPosition position;
Marks marks; Marks marks;
VisualMode lastVisualMode; VisualMode lastVisualMode;
@@ -1837,7 +1837,7 @@ public:
bool passEventToEditor(QEvent &event); // Pass event to editor widget without filtering. Returns true if event was processed. bool passEventToEditor(QEvent &event); // Pass event to editor widget without filtering. Returns true if event was processed.
// undo handling // undo handling
int revision() const { return document()->revision(); } int revision() const { return document()->availableUndoSteps(); }
void undoRedo(bool undo); void undoRedo(bool undo);
void undo(); void undo();
void redo(); void redo();
@@ -1846,7 +1846,7 @@ public:
QStack<State> m_undo; QStack<State> m_undo;
QStack<State> m_redo; QStack<State> m_redo;
State m_undoState; State m_undoState;
int m_lastUndoSteps; int m_lastRevision;
// extra data for '.' // extra data for '.'
void replay(const QString &text, int repeat = 1); void replay(const QString &text, int repeat = 1);
@@ -2043,7 +2043,7 @@ FakeVimHandler::Private::Private(FakeVimHandler *parent, QWidget *widget)
connect(EDITOR(document()), SIGNAL(contentsChange(int,int,int)), connect(EDITOR(document()), SIGNAL(contentsChange(int,int,int)),
SLOT(onContentsChanged(int,int,int))); SLOT(onContentsChanged(int,int,int)));
connect(EDITOR(document()), SIGNAL(undoCommandAdded()), SLOT(onUndoCommandAdded())); connect(EDITOR(document()), SIGNAL(undoCommandAdded()), SLOT(onUndoCommandAdded()));
m_lastUndoSteps = document()->availableUndoSteps(); m_lastRevision = revision();
} }
//new Highlighter(document(), &pythonRules); //new Highlighter(document(), &pythonRules);
init(); init();
@@ -2809,7 +2809,7 @@ void FakeVimHandler::Private::pushUndoState(bool overwrite)
setMark(QLatin1Char('<'), mark(QLatin1Char('<')).position); setMark(QLatin1Char('<'), mark(QLatin1Char('<')).position);
setMark(QLatin1Char('>'), mark(QLatin1Char('>')).position); setMark(QLatin1Char('>'), mark(QLatin1Char('>')).position);
} }
m_undoState = State(m_lastChangePosition, m_marks, m_lastVisualMode, m_undoState = State(revision(), m_lastChangePosition, m_marks, m_lastVisualMode,
m_lastVisualModeInverted); m_lastVisualModeInverted);
} }
@@ -7179,7 +7179,7 @@ void FakeVimHandler::Private::endEditBlock()
QTC_ASSERT(m_editBlockLevel > 0, QTC_ASSERT(m_editBlockLevel > 0,
qDebug() << "beginEditBlock() not called before endEditBlock()!"; return); qDebug() << "beginEditBlock() not called before endEditBlock()!"; return);
--m_editBlockLevel; --m_editBlockLevel;
if (m_editBlockLevel == 0 && m_undoState.isValid() && m_undoState.revisions > 0) { if (m_editBlockLevel == 0 && m_undoState.isValid()) {
m_undo.push(m_undoState); m_undo.push(m_undoState);
m_undoState = State(); m_undoState = State();
} }
@@ -7230,40 +7230,25 @@ void FakeVimHandler::Private::onContentsChanged(int position, int charsRemoved,
m_oldPosition); m_oldPosition);
} }
} }
if (!document()->isUndoAvailable())
m_undo.clear();
const int undoSteps = document()->availableUndoSteps();
if (m_editBlockLevel == 0) {
// Break undo/redo stacks on external undo/redo.
if (m_lastUndoSteps > undoSteps && !m_undo.isEmpty()) {
if ((--m_undo.top().revisions) <= 0)
m_undo.pop();
m_redo.push(State());
} else if (m_lastUndoSteps < undoSteps && !m_redo.isEmpty()) {
if ((--m_redo.top().revisions) <= 0)
m_redo.pop();
m_undo.push(State());
}
}
m_lastUndoSteps = undoSteps;
} }
void FakeVimHandler::Private::onUndoCommandAdded() void FakeVimHandler::Private::onUndoCommandAdded()
{ {
m_redo.clear(); // Undo commands removed?
// Remember chage so it can be correctly undone/redone with undo/redo commands. if (m_lastRevision >= revision()) {
if (m_editBlockLevel == 0 && !m_undo.isEmpty()) { const int removed = m_lastRevision - revision();
if (isInsertMode()) for (int i = m_undo.size() - 1; i >= 0; --i) {
++m_undo.top().revisions; // External change in insert mode (auto-completion etc.) if ((m_undo[i].revision -= removed) < 0) {
else m_undo.remove(0, i + 1);
m_undo.push(State()); // External change while FakeVim disabled. break;
} else if (m_editBlockLevel > 0) { }
++m_undoState.revisions; // Document revision increased in our edit block. }
} }
m_redo.clear();
// External change while FakeVim disabled.
if (m_editBlockLevel == 0 && !m_undo.isEmpty() && !isInsertMode())
m_undo.push(State());
} }
char FakeVimHandler::Private::currentModeCode() const char FakeVimHandler::Private::currentModeCode() const
@@ -7288,34 +7273,34 @@ void FakeVimHandler::Private::undoRedo(bool undo)
QStack<State> &stack = undo ? m_undo : m_redo; QStack<State> &stack = undo ? m_undo : m_redo;
QStack<State> &stack2 = undo ? m_redo : m_undo; QStack<State> &stack2 = undo ? m_redo : m_undo;
State state = !stack.empty() ? stack.pop() : State(); State state = m_undoState.isValid() ? m_undoState
: !stack.empty() ? stack.pop() : State();
CursorPosition lastPos(m_cursor); CursorPosition lastPos(m_cursor);
const int current = revision(); if (undo ? !document()->isUndoAvailable() : !document()->isRedoAvailable()) {
const QString msg = undo ? FakeVimHandler::tr("Already at oldest change.")
: FakeVimHandler::tr("Already at newest change.");
showMessage(MessageInfo, msg);
return;
}
clearMessage();
++m_editBlockLevel; ++m_editBlockLevel;
// Do undo/redo [count] times to reach previous revision. // Do undo/redo [count] times to reach previous revision.
int count = qMax(1, m_undoState.isValid() ? m_undoState.revisions const int previousRevision = revision();
: state.revisions); if (undo) {
while (count-- > 0) { do {
if (undo)
EDITOR(undo()); EDITOR(undo());
else } while (document()->isUndoAvailable() && state.revision >= 0 && state.revision < revision());
} else {
do {
EDITOR(redo()); EDITOR(redo());
} while (document()->isRedoAvailable() && state.revision > revision());
} }
--m_editBlockLevel; --m_editBlockLevel;
if (current == revision()) {
const QString msg = undo ? FakeVimHandler::tr("Already at oldest change.")
: FakeVimHandler::tr("Already at newest change.");
showMessage(MessageInfo, msg);
stack.push(state);
return;
}
clearMessage();
if (state.isValid()) { if (state.isValid()) {
m_lastChangePosition = state.position; m_lastChangePosition = state.position;
Marks marks = m_marks; Marks marks = m_marks;
@@ -7327,6 +7312,7 @@ void FakeVimHandler::Private::undoRedo(bool undo)
setMark(QLatin1Char('`'), lastPos); setMark(QLatin1Char('`'), lastPos);
setCursorPosition(m_lastChangePosition); setCursorPosition(m_lastChangePosition);
setAnchor(); setAnchor();
state.revision = previousRevision;
} else { } else {
updateFirstVisibleLine(); updateFirstVisibleLine();
m_cursor = EDITOR(textCursor()); m_cursor = EDITOR(textCursor());