Commit d935b4cf authored by hluk's avatar hluk Committed by hjk

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

Partially reverts commit b9cc16e4.

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: default avatarhjk <hjk121@nokiamail.com>
parent a03112d2
......@@ -288,16 +288,16 @@ typedef QHashIterator<QChar, Mark> 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<State> m_undo;
QStack<State> 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<State> &stack = undo ? m_undo : m_redo;
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);
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());
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment