forked from qt-creator/qt-creator
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:
@@ -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());
|
||||||
|
Reference in New Issue
Block a user