# math: the toolbar is visible only when in math
# mathmacrotemplate: the toolbar is visible only when in a macro definition
# table: the toolbar is visible only when in a table
-# review: the toolbar is visible only when inside a tracked change
+# review: the toolbar is visible only when tracked changes are present or
+# change tracking is enabled
# ipa: the toolbar is only visible when inside an ipa inset
#
# top: the toolbar should be at the top of the window
+ (with_blanks ? blank_count_ : 0);
}
+ // does the buffer contains tracked changes? (if so, we automatically
+ // display the review toolbar)
+ mutable bool tracked_changes_present_;
+
private:
/// So we can force access via the accessors.
mutable Buffer const * parent_buffer;
preview_file_ = cloned_buffer_->d->preview_file_;
preview_format_ = cloned_buffer_->d->preview_format_;
preview_error_ = cloned_buffer_->d->preview_error_;
+ tracked_changes_present_ = cloned_buffer_->d->tracked_changes_present_;
}
if (params().save_transient_properties)
undo().recordUndoBufferParams(CursorData());
params().track_changes = !params().track_changes;
+ if (!params().track_changes)
+ dr.forceChangesUpdate();
break;
case LFUN_CHANGES_OUTPUT:
// update all caches
clearReferenceCache();
updateMacros();
+ setChangesPresent(false);
Buffer & cbuf = const_cast<Buffer &>(*this);
// set the counter for this paragraph
d->setLabel(parit, utype);
+ // update change-tracking flag
+ parit->addChangesToBuffer(*this);
+
// now the insets
InsetList::const_iterator iit = parit->insetList().begin();
InsetList::const_iterator end = parit->insetList().end();
from_utf8(filePath())));
}
+
+void Buffer::setChangesPresent(bool b) const
+{
+ d->tracked_changes_present_ = b;
+}
+
+
+bool Buffer::areChangesPresent() const
+{
+ return d->tracked_changes_present_;
+}
+
+
+void Buffer::updateChangesPresent() const
+{
+ LYXERR(Debug::CHANGES, "Buffer::updateChangesPresent");
+ setChangesPresent(false);
+ ParConstIterator it = par_iterator_begin();
+ ParConstIterator const end = par_iterator_end();
+ for (; !areChangesPresent() && it != end; ++it)
+ it->addChangesToBuffer(*this);
+}
+
+
+
} // namespace lyx
int wordCount() const;
int charCount(bool with_blanks) const;
+ // this is const because it does not modify the buffer's real contents,
+ // only the mutable flag.
+ void setChangesPresent(bool) const;
+ bool areChangesPresent() const;
+ void updateChangesPresent() const;
+
private:
friend class MarkAsExporting;
/// mark the buffer as busy exporting something, or not
}
+bool Changes::isChanged() const
+{
+ ChangeTable::const_iterator it = table_.begin();
+ ChangeTable::const_iterator const itend = table_.end();
+ for (; it != itend; ++it) {
+ if (it->change.changed())
+ return true;
+ }
+ return false;
+}
+
+
void Changes::merge()
{
+ bool merged = false;
ChangeTable::iterator it = table_.begin();
while (it != table_.end()) {
<< it->range.start);
table_.erase(it);
+ merged = true;
// start again
it = table_.begin();
continue;
(it + 1)->change.changetime = max(it->change.changetime,
(it + 1)->change.changetime);
table_.erase(it);
+ merged = true;
// start again
it = table_.begin();
continue;
++it;
}
+ if (merged && !isChanged())
+ is_update_required_ = true;
}
}
}
+
+void Changes::updateBuffer(Buffer const & buf)
+{
+ is_update_required_ = false;
+ if (!buf.areChangesPresent() && isChanged())
+ buf.setChangesPresent(true);
+}
+
+
+
+
} // namespace lyx
class Changes {
public:
+ Changes() : is_update_required_(false) {}
+
/// set the pos to the given change
void set(Change const & change, pos_type pos);
/// set the range (excluding end) to the given change
/// return true if there is a change in the given range (excluding end)
bool isChanged(pos_type start, pos_type end) const;
+ ///
+ bool isChanged() const;
/// return true if the whole range is deleted
bool isDeleted(pos_type start, pos_type end) const;
void addToToc(DocIterator const & cdit, Buffer const & buffer,
bool output_active) const;
+ ///
+ void updateBuffer(Buffer const & buf);
+ ///
+ bool isUpdateRequired() const { return is_update_required_; }
+
private:
class Range {
public:
/// table of changes, every row a change and range descriptor
ChangeTable table_;
+
+ /// signals that the buffer's flag tracked_changes_present_ needs to be
+ /// recalculated
+ bool is_update_required_;
};
// In case the master has no gui associated with it,
// the TocItem is not updated (part of bug 5699).
buffer()->tocBackend().updateItem(*this);
+
+ // If the last tracked change of the paragraph has just been
+ // deleted, then we need to recompute the buffer flag
+ // tracked_changes_present_.
+ if (inTexted() && paragraph().isChangeUpdateRequired())
+ disp_.forceChangesUpdate();
}
error_(false),
update_(Update::None),
need_buf_update_(false),
- need_msg_update_(true)
+ need_msg_update_(true),
+ need_changes_update_(false)
{}
///
DispatchResult(bool dispatched, Update::flags f) :
error_(false),
update_(f),
need_buf_update_(false),
- need_msg_update_(true)
+ need_msg_update_(true),
+ need_changes_update_(false)
{}
///
bool dispatched() const { return dispatched_; }
Update::flags screenUpdate() const { return update_; }
///
void screenUpdate(Update::flags f) { update_ = f; }
+
/// Does the buffer need updating?
bool needBufferUpdate() const { return need_buf_update_; }
/// Force the buffer to be updated
void forceBufferUpdate() { need_buf_update_ = true; }
/// Clear the flag indicating we need an update
void clearBufferUpdate() { need_buf_update_ = false; }
+
/// Do we need to display a message in the status bar?
bool needMessageUpdate() const { return need_msg_update_; }
/// Force the message to be displayed
/// Clear the flag indicating we need to display the message
void clearMessageUpdate() { need_msg_update_ = false; }
+ /// Do we need to update the change tracking presence flag?
+ bool needChangesUpdate() { return need_changes_update_; }
+ /// Force the change tracking presence flag to be updated
+ void forceChangesUpdate() { need_changes_update_ = true; }
+ /// Clear the flag indicating that we need to update the change tracking
+ /// presence flag
+ void clearChangesUpdate() { need_changes_update_ = false; }
+
private:
/// was the event fully dispatched?
bool dispatched_;
bool need_buf_update_;
///
bool need_msg_update_;
+ ///
+ bool need_changes_update_;
};
}
+void Paragraph::addChangesToBuffer(Buffer const & buf) const
+{
+ d->changes_.updateBuffer(buf);
+}
+
+
+bool Paragraph::isChangeUpdateRequired() const
+{
+ return d->changes_.isUpdateRequired();
+}
+
+
bool Paragraph::isDeleted(pos_type start, pos_type end) const
{
LASSERT(start >= 0 && start <= size(), return false);
///
void addChangesToToc(DocIterator const & cdit, Buffer const & buf,
bool output_active) const;
+ /// set the buffer flag if there are changes in the paragraph
+ void addChangesToBuffer(Buffer const & buf) const;
+ ///
+ bool isChangeUpdateRequired() const;
///
Language const * getParLanguage(BufferParams const &) const;
///
if (dr.needBufferUpdate()) {
bv->cursor().clearBufferUpdate();
bv->buffer().updateBuffer();
+ } else if (dr.needChangesUpdate()) {
+ // updateBuffer() already updates the change-tracking presence flag
+ bv->buffer().updateChangesPresent();
}
// BufferView::update() updates the ViewMetricsInfo and
// also initializes the position cache for all insets in
context |= Toolbars::MATH;
if (lyx::getStatus(FuncRequest(LFUN_LAYOUT_TABULAR)).enabled())
context |= Toolbars::TABLE;
- if (lyx::getStatus(FuncRequest(LFUN_CHANGES_TRACK)).enabled()
- && lyx::getStatus(FuncRequest(LFUN_CHANGES_TRACK)).onOff(true))
+ if (currentBufferView()->buffer().areChangesPresent()
+ || (lyx::getStatus(FuncRequest(LFUN_CHANGES_TRACK)).enabled()
+ && lyx::getStatus(FuncRequest(LFUN_CHANGES_TRACK)).onOff(true)))
context |= Toolbars::REVIEW;
if (lyx::getStatus(FuncRequest(LFUN_IN_MATHMACROTEMPLATE)).enabled())
context |= Toolbars::MATHMACROTEMPLATE;