Fix bug #3733: 'undo' does not revert 'changed' status for file

* src/LyXAction.cpp: add ReadOnly flag to LFUN_UNDO and LFUN_REDO, since
  we do not want the dispatch mechanism to mark buffer dirty after them.
* src/BufferView.cpp: handle "by hand" the activation of undo/redo
* src/Undo.cpp: add lyx_clean member to UndoElement and make sure to 
  maintain it with undo operations; add a new markDirty() member for UndoStack
* src/Buffer.cpp: when saving a document, mark the undo and redo stacks 
  elements as dirty.


git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@35068 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
Jean-Marc Lasgouttes 2010-08-06 23:54:04 +00:00
parent 7c54fd51e9
commit f8eda52820
5 changed files with 41 additions and 13 deletions

View File

@ -2364,6 +2364,7 @@ void Buffer::markClean() const
// if the .lyx file has been saved, we don't need an // if the .lyx file has been saved, we don't need an
// autosave // autosave
d->bak_clean = true; d->bak_clean = true;
d->undo_.markDirty();
} }

View File

@ -993,8 +993,8 @@ bool BufferView::getStatus(FuncRequest const & cmd, FuncStatus & flag)
// FIXME: This is a bit problematic because we don't check if this is // FIXME: This is a bit problematic because we don't check if this is
// a document BufferView or not for these LFUNs. We probably have to // a document BufferView or not for these LFUNs. We probably have to
// dispatch both to currentBufferView() and, if that fails, // dispatch both to currentBufferView() and, if that fails,
// to documentBufferView(); same as we do know for current Buffer and // to documentBufferView(); same as we do now for current Buffer and
// document Buffer. Ideally those LFUN should go to Buffer as they* // document Buffer. Ideally those LFUN should go to Buffer as they
// operate on the full Buffer and the cursor is only needed either for // operate on the full Buffer and the cursor is only needed either for
// an Undo record or to restore a cursor position. But we don't know // an Undo record or to restore a cursor position. But we don't know
// how to do that inside Buffer of course. // how to do that inside Buffer of course.
@ -1008,10 +1008,14 @@ bool BufferView::getStatus(FuncRequest const & cmd, FuncStatus & flag)
break; break;
case LFUN_UNDO: case LFUN_UNDO:
flag.setEnabled(buffer_.undo().hasUndoStack()); // We do not use the LyXAction flag for readonly because Undo sets the
// buffer clean/dirty status by itself.
flag.setEnabled(!buffer_.isReadonly() && buffer_.undo().hasUndoStack());
break; break;
case LFUN_REDO: case LFUN_REDO:
flag.setEnabled(buffer_.undo().hasRedoStack()); // We do not use the LyXAction flag for readonly because Redo sets the
// buffer clean/dirty status by itself.
flag.setEnabled(!buffer_.isReadonly() && buffer_.undo().hasRedoStack());
break; break;
case LFUN_FILE_INSERT: case LFUN_FILE_INSERT:
case LFUN_FILE_INSERT_PLAINTEXT_PARA: case LFUN_FILE_INSERT_PLAINTEXT_PARA:

View File

@ -1222,14 +1222,14 @@ void LyXAction::init()
* \li Syntax: undo * \li Syntax: undo
* \endvar * \endvar
*/ */
{ LFUN_UNDO, "undo", Noop, Edit }, { LFUN_UNDO, "undo", ReadOnly, Edit },
/*! /*!
* \var lyx::FuncCode lyx::LFUN_REDO * \var lyx::FuncCode lyx::LFUN_REDO
* \li Action: Redoes the last thing undone. * \li Action: Redoes the last thing undone.
* \li Syntax: redo * \li Syntax: redo
* \endvar * \endvar
*/ */
{ LFUN_REDO, "redo", Noop, Edit }, { LFUN_REDO, "redo", ReadOnly, Edit },
/*! /*!
* \var lyx::FuncCode lyx::LFUN_REPEAT * \var lyx::FuncCode lyx::LFUN_REPEAT
* \li Action: Repeat the given command. * \li Action: Repeat the given command.

View File

@ -71,9 +71,9 @@ struct UndoElement
StableDocIterator const & cel, StableDocIterator const & cel,
pit_type fro, pit_type en, ParagraphList * pl, pit_type fro, pit_type en, ParagraphList * pl,
MathData * ar, BufferParams const & bp, MathData * ar, BufferParams const & bp,
bool ifb, size_t gid) : bool ifb, bool lc, size_t gid) :
kind(kin), cursor(cur), cell(cel), from(fro), end(en), kind(kin), cursor(cur), cell(cel), from(fro), end(en),
pars(pl), array(ar), bparams(0), isFullBuffer(ifb), group_id(gid) pars(pl), array(ar), bparams(0), isFullBuffer(ifb), lyx_clean(lc), group_id(gid)
{ {
if (isFullBuffer) if (isFullBuffer)
bparams = new BufferParams(bp); bparams = new BufferParams(bp);
@ -91,6 +91,7 @@ struct UndoElement
bparams = ue.isFullBuffer bparams = ue.isFullBuffer
? new BufferParams(*ue.bparams) : ue.bparams; ? new BufferParams(*ue.bparams) : ue.bparams;
isFullBuffer = ue.isFullBuffer; isFullBuffer = ue.isFullBuffer;
lyx_clean = ue.lyx_clean;
group_id = ue.group_id; group_id = ue.group_id;
} }
/// ///
@ -117,6 +118,8 @@ struct UndoElement
BufferParams const * bparams; BufferParams const * bparams;
/// Only used in case of full backups /// Only used in case of full backups
bool isFullBuffer; bool isFullBuffer;
/// Was the buffer clean at this point?
bool lyx_clean;
/// the element's group id /// the element's group id
size_t group_id; size_t group_id;
private: private:
@ -163,6 +166,12 @@ public:
} }
} }
/// Mark all the elements of the stack as dirty
void markDirty() {
for (size_t i = 0; i != c_.size(); ++i)
c_[i].lyx_clean = false;
}
private: private:
/// Internal contents. /// Internal contents.
std::deque<UndoElement> c_; std::deque<UndoElement> c_;
@ -242,11 +251,10 @@ bool Undo::hasRedoStack() const
} }
static bool samePar(StableDocIterator const & i1, StableDocIterator const & i2) void Undo::markDirty()
{ {
StableDocIterator tmpi2 = i2; d->undostack_.markDirty();
tmpi2.pos() = i1.pos(); d->redostack_.markDirty();
return i1 == tmpi2;
} }
@ -256,6 +264,14 @@ static bool samePar(StableDocIterator const & i1, StableDocIterator const & i2)
// //
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
static bool samePar(StableDocIterator const & i1, StableDocIterator const & i2)
{
StableDocIterator tmpi2 = i2;
tmpi2.pos() = i1.pos();
return i1 == tmpi2;
}
void Undo::Private::doRecordUndo(UndoKind kind, void Undo::Private::doRecordUndo(UndoKind kind,
DocIterator const & cell, DocIterator const & cell,
pit_type first_pit, pit_type last_pit, pit_type first_pit, pit_type last_pit,
@ -291,7 +307,7 @@ void Undo::Private::doRecordUndo(UndoKind kind,
LYXERR(Debug::UNDO, "Create undo element of group " << group_id); LYXERR(Debug::UNDO, "Create undo element of group " << group_id);
// create the position information of the Undo entry // create the position information of the Undo entry
UndoElement undo(kind, cur, cell, from, end, 0, 0, UndoElement undo(kind, cur, cell, from, end, 0, 0,
buffer_.params(), isFullBuffer, group_id); buffer_.params(), isFullBuffer, buffer_.isClean(), group_id);
// fill in the real data to be saved // fill in the real data to be saved
if (cell.inMathed()) { if (cell.inMathed()) {
@ -406,6 +422,10 @@ void Undo::Private::doTextUndoOrRedo(DocIterator & cur, UndoElementStack & stack
LASSERT(undo.array == 0, /**/); LASSERT(undo.array == 0, /**/);
cur = undo.cursor.asDocIterator(&buffer_); cur = undo.cursor.asDocIterator(&buffer_);
if (undo.lyx_clean)
buffer_.markClean();
else
buffer_.markDirty();
// Now that we're done with undo, we pop it off the stack. // Now that we're done with undo, we pop it off the stack.
stack.pop(); stack.pop();
} }

View File

@ -67,6 +67,9 @@ public:
/// ///
bool hasRedoStack() const; bool hasRedoStack() const;
/// Mark all the elements of the undo and redo stacks as dirty
void markDirty();
/// open a new group of undo operations. /// open a new group of undo operations.
/** /**
* Groups can be nested. Such a nested group e.g. { {} {} } is undone in * Groups can be nested. Such a nested group e.g. { {} {} } is undone in