From d935b4cfc62890b41fb0b343197e62214244c65d Mon Sep 17 00:00:00 2001 From: hluk Date: Sat, 20 Jul 2013 08:36:05 +0200 Subject: [PATCH] FakeVim: Use QTextDocument::availableUndoSteps() for undo/redo Partially reverts commit b9cc16e405378a927cf013ef0b89c964532aa03a. 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 --- src/plugins/fakevim/fakevimhandler.cpp | 94 +++++++++++--------------- 1 file changed, 40 insertions(+), 54 deletions(-) diff --git a/src/plugins/fakevim/fakevimhandler.cpp b/src/plugins/fakevim/fakevimhandler.cpp index 28563eefb15..1fe2e0795c2 100644 --- a/src/plugins/fakevim/fakevimhandler.cpp +++ b/src/plugins/fakevim/fakevimhandler.cpp @@ -288,16 +288,16 @@ typedef QHashIterator MarksIterator; struct State { - State() : revisions(0), position(), marks(), lastVisualMode(NoVisualMode), + State() : revision(-1), position(), marks(), lastVisualMode(NoVisualMode), lastVisualModeInverted(false) {} - State(const CursorPosition &position, const Marks &marks, - VisualMode lastVisualMode, bool lastVisualModeInverted) : revisions(0), + State(int revision, const CursorPosition &position, const Marks &marks, + VisualMode lastVisualMode, bool lastVisualModeInverted) : revision(revision), position(position), marks(marks), lastVisualMode(lastVisualMode), lastVisualModeInverted(lastVisualModeInverted) {} bool isValid() const { return position.isValid(); } - int revisions; + int revision; CursorPosition position; Marks marks; VisualMode lastVisualMode; @@ -1837,7 +1837,7 @@ public: bool passEventToEditor(QEvent &event); // Pass event to editor widget without filtering. Returns true if event was processed. // undo handling - int revision() const { return document()->revision(); } + int revision() const { return document()->availableUndoSteps(); } void undoRedo(bool undo); void undo(); void redo(); @@ -1846,7 +1846,7 @@ public: QStack m_undo; QStack m_redo; State m_undoState; - int m_lastUndoSteps; + int m_lastRevision; // extra data for '.' 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)), SLOT(onContentsChanged(int,int,int))); connect(EDITOR(document()), SIGNAL(undoCommandAdded()), SLOT(onUndoCommandAdded())); - m_lastUndoSteps = document()->availableUndoSteps(); + m_lastRevision = revision(); } //new Highlighter(document(), &pythonRules); init(); @@ -2809,7 +2809,7 @@ void FakeVimHandler::Private::pushUndoState(bool overwrite) 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); } @@ -7179,7 +7179,7 @@ void FakeVimHandler::Private::endEditBlock() QTC_ASSERT(m_editBlockLevel > 0, qDebug() << "beginEditBlock() not called before endEditBlock()!"; return); --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_undoState = State(); } @@ -7230,40 +7230,25 @@ void FakeVimHandler::Private::onContentsChanged(int position, int charsRemoved, 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() { - m_redo.clear(); - // Remember chage so it can be correctly undone/redone with undo/redo commands. - if (m_editBlockLevel == 0 && !m_undo.isEmpty()) { - if (isInsertMode()) - ++m_undo.top().revisions; // External change in insert mode (auto-completion etc.) - else - m_undo.push(State()); // External change while FakeVim disabled. - } else if (m_editBlockLevel > 0) { - ++m_undoState.revisions; // Document revision increased in our edit block. + // Undo commands removed? + if (m_lastRevision >= revision()) { + const int removed = m_lastRevision - revision(); + for (int i = m_undo.size() - 1; i >= 0; --i) { + if ((m_undo[i].revision -= removed) < 0) { + m_undo.remove(0, i + 1); + break; + } + } } + + 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 @@ -7288,34 +7273,34 @@ void FakeVimHandler::Private::undoRedo(bool undo) QStack &stack = undo ? m_undo : m_redo; QStack &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); - 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; // Do undo/redo [count] times to reach previous revision. - int count = qMax(1, m_undoState.isValid() ? m_undoState.revisions - : state.revisions); - while (count-- > 0) { - if (undo) + const int previousRevision = revision(); + if (undo) { + do { EDITOR(undo()); - else + } while (document()->isUndoAvailable() && state.revision >= 0 && state.revision < revision()); + } else { + do { EDITOR(redo()); + } while (document()->isRedoAvailable() && state.revision > revision()); } --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()) { m_lastChangePosition = state.position; Marks marks = m_marks; @@ -7327,6 +7312,7 @@ void FakeVimHandler::Private::undoRedo(bool undo) setMark(QLatin1Char('`'), lastPos); setCursorPosition(m_lastChangePosition); setAnchor(); + state.revision = previousRevision; } else { updateFirstVisibleLine(); m_cursor = EDITOR(textCursor());