Improve undo of consecutive insertions/deletions

The old scheme was:
 * multiple insertions are undone by groups of 20
 * multiple deletions are undone in one big block

The new scheme is to stop merging undo elements after 2 seconds of elapsed time.

Moreover, the merging of undo elements stops when the cursor has moved. Potentially, this could allow to remove many of the finishUndo() calls.

Fixes bug #9204.
This commit is contained in:
Jean-Marc Lasgouttes 2015-03-12 14:47:39 +01:00
parent d2ab8e1b65
commit ed3d9544a3
3 changed files with 13 additions and 17 deletions

View File

@ -198,7 +198,7 @@ void mergeParagraph(BufferParams const & bparams,
Text::Text(InsetText * owner, bool use_default_layout) Text::Text(InsetText * owner, bool use_default_layout)
: owner_(owner), autoBreakRows_(false), undo_counter_(0) : owner_(owner), autoBreakRows_(false)
{ {
pars_.push_back(Paragraph()); pars_.push_back(Paragraph());
Paragraph & par = pars_.back(); Paragraph & par = pars_.back();
@ -212,7 +212,7 @@ Text::Text(InsetText * owner, bool use_default_layout)
Text::Text(InsetText * owner, Text const & text) Text::Text(InsetText * owner, Text const & text)
: owner_(owner), autoBreakRows_(text.autoBreakRows_), undo_counter_(0) : owner_(owner), autoBreakRows_(text.autoBreakRows_)
{ {
pars_ = text.pars_; pars_ = text.pars_;
ParagraphList::iterator const end = pars_.end(); ParagraphList::iterator const end = pars_.end();
@ -1081,15 +1081,6 @@ void Text::charInserted(Cursor & cur)
{ {
Paragraph & par = cur.paragraph(); Paragraph & par = cur.paragraph();
// Here we call finishUndo for every 20 characters inserted.
// This is from my experience how emacs does it. (Lgb)
if (undo_counter_ < 20) {
++undo_counter_;
} else {
cur.finishUndo();
undo_counter_ = 0;
}
// register word if a non-letter was entered // register word if a non-letter was entered
if (cur.pos() > 1 if (cur.pos() > 1
&& !par.isWordSeparator(cur.pos() - 2) && !par.isWordSeparator(cur.pos() - 2)

View File

@ -382,8 +382,6 @@ private:
bool autoBreakRows_; bool autoBreakRows_;
/// position of the text in the buffer. /// position of the text in the buffer.
DocIterator macrocontext_position_; DocIterator macrocontext_position_;
///
unsigned int undo_counter_;
}; };

View File

@ -33,6 +33,7 @@
#include "support/debug.h" #include "support/debug.h"
#include "support/gettext.h" #include "support/gettext.h"
#include "support/lassert.h" #include "support/lassert.h"
#include "support/lyxtime.h"
#include <algorithm> #include <algorithm>
#include <deque> #include <deque>
@ -72,7 +73,7 @@ struct UndoElement
bool lc, size_t gid) : bool lc, size_t gid) :
kind(kin), cur_before(cb), cell(cel), from(fro), end(en), kind(kin), cur_before(cb), cell(cel), from(fro), end(en),
pars(pl), array(ar), bparams(0), pars(pl), array(ar), bparams(0),
lyx_clean(lc), group_id(gid) lyx_clean(lc), group_id(gid), time(current_time())
{ {
} }
/// ///
@ -80,11 +81,11 @@ struct UndoElement
bool lc, size_t gid) : bool lc, size_t gid) :
kind(ATOMIC_UNDO), cur_before(cb), cell(), from(0), end(0), kind(ATOMIC_UNDO), cur_before(cb), cell(), from(0), end(0),
pars(0), array(0), bparams(new BufferParams(bp)), pars(0), array(0), bparams(new BufferParams(bp)),
lyx_clean(lc), group_id(gid) lyx_clean(lc), group_id(gid), time(current_time())
{ {
} }
/// ///
UndoElement(UndoElement const & ue) UndoElement(UndoElement const & ue) : time(current_time())
{ {
kind = ue.kind; kind = ue.kind;
cur_before = ue.cur_before; cur_before = ue.cur_before;
@ -127,6 +128,8 @@ struct UndoElement
bool lyx_clean; bool lyx_clean;
/// the element's group id /// the element's group id
size_t group_id; size_t group_id;
/// timestamp
time_t time;
private: private:
/// Protect construction /// Protect construction
UndoElement(); UndoElement();
@ -325,9 +328,13 @@ void Undo::Private::doRecordUndo(UndoKind kind,
&& samePar(stack.top().cell, cell) && samePar(stack.top().cell, cell)
&& stack.top().kind == kind && stack.top().kind == kind
&& stack.top().from == from && stack.top().from == from
&& stack.top().end == end) { && stack.top().end == end
&& stack.top().cur_after == cur_before
&& current_time() - stack.top().time <= 2) {
// reset cur_after; it will be filled correctly by endUndoGroup. // reset cur_after; it will be filled correctly by endUndoGroup.
stack.top().cur_after = CursorData(); stack.top().cur_after = CursorData();
// update the timestamp of the undo element
stack.top().time = current_time();
return; return;
} }