Tommaso Cucinotta wrote:
ok, so I would disable the "master document" option if
currentMainWA()->buffer()->masterBuffer() == currentMainWA()->buffer()
or smth. like that. I'll circulate an updated patch before committing.
please, find it attached (it also checks the children of the
currentMainWA->buffer()), along with the patch of the patch, for your
convenience.
I noticed that, with this second patch, there is a "GUI Synchronization
Bug" due to the fact that the status of the "Master Document"
RadioButton (enabled/disabled) needs to be synchronized with the buffers
that are loaded/closed. Specifically, every time a document is open or
closed, one should check if the F&R dialog is open, and in such a case
update the RadioButton status accordingly (e.g., after opening or
closing the master of a buffer -- in the former example, try opening
`b.lyx', then C-S-f, then switch to "Advanced" pane, then try opening
and closing `a.lyx').
Perhaps it may be better to leave the user with the "puzzle" of whether
choosing "Current Document" or "Master Document" even if he/she has no
clue about what a "Master" is and what a document with children is,
rather than introducing further "dependencies" at the GUI level between
apparently independent GUI elements.
Comments ? (and, would you prefer me to commit the 1st or 2nd patch ?)
Thx,
T.
Index: src/lyxfind.cpp
===================================================================
--- src/lyxfind.cpp (revisione 32676)
+++ src/lyxfind.cpp (copia locale)
@@ -47,6 +47,9 @@
#include "support/lstrings.h"
#include "support/lassert.h"
+#include "frontends/Application.h"
+#include "frontends/LyXView.h"
+
#include <boost/regex.hpp>
#include <boost/next_prior.hpp>
@@ -601,7 +604,7 @@
**/
class MatchStringAdv {
public:
- MatchStringAdv(lyx::Buffer const & buf, FindAndReplaceOptions const & opt);
+ MatchStringAdv(lyx::Buffer & buf, FindAndReplaceOptions const & opt);
/** Tests if text starting at the supplied position matches with the one provided to the MatchStringAdv
** constructor as opt.search, under the opt.* options settings.
@@ -617,7 +620,9 @@
public:
/// buffer
- lyx::Buffer const & buf;
+ lyx::Buffer * p_buf;
+ /// first buffer on which search was started
+ lyx::Buffer * const p_first_buf;
/// options
FindAndReplaceOptions const & opt;
@@ -650,8 +655,8 @@
};
-MatchStringAdv::MatchStringAdv(lyx::Buffer const & buf, FindAndReplaceOptions const & opt)
- : buf(buf), opt(opt)
+MatchStringAdv::MatchStringAdv(lyx::Buffer & buf, FindAndReplaceOptions const & opt)
+ : p_buf(&buf), p_first_buf(&buf), opt(opt)
{
par_as_string = normalize(opt.search);
open_braces = 0;
@@ -889,6 +894,7 @@
return ods.str();
}
+
/** Finalize an advanced find operation, advancing the cursor to the innermost
** position that matches, plus computing the length of the matching text to
** be selected
@@ -929,8 +935,78 @@
}
+/** Switch p_buf to point to next document buffer.
+ **
+ ** Return true if restarted from master-document buffer.
+ **
+ ** @note
+ ** Not using p_buf->allRelatives() here, because I'm not sure
+ ** whether or not the returned order is independent of p_buf.
+ **/
+bool next_document_buffer(Buffer * & p_buf) {
+ Buffer *p_master = p_buf;
+ Buffer *p_old;
+ do {
+ p_old = p_master;
+ p_master = const_cast<Buffer *>(p_master->masterBuffer());
+ LYXERR(Debug::FIND, "p_old=" << p_old << ", p_master=" << p_master);
+ } while (p_master != p_old);
+ LASSERT(p_master != NULL, /**/);
+ std::vector<Buffer *> v_children;
+ /* Root master added as first buffer in the vector */
+ v_children.push_back(p_master);
+ p_master->getChildren(v_children, true);
+ LYXERR(Debug::FIND, "v_children.size()=" << v_children.size());
+ std::vector<Buffer *>::const_iterator it = std::find(v_children.begin(), v_children.end(), p_buf);
+ LASSERT(it != v_children.end(), /**/)
+ ++it;
+ if (it == v_children.end()) {
+ p_buf = *v_children.begin();
+ return true;
+ }
+ p_buf = *it;
+ return false;
+}
+
+
+/** Switch p_buf to point to previous document buffer.
+ **
+ ** Return true if restarted from last child buffer.
+ **
+ ** @note
+ ** Not using p_buf->allRelatives() here, because I'm not sure
+ ** whether or not the returned order is independent of p_buf.
+ **/
+bool prev_document_buffer(Buffer * & p_buf) {
+ Buffer *p_master = p_buf;
+ Buffer *p_old;
+ do {
+ p_old = p_master;
+ p_master = const_cast<Buffer *>(p_master->masterBuffer());
+ LYXERR(Debug::FIND, "p_old=" << p_old << ", p_master=" << p_master);
+ } while (p_master != p_old);
+ LASSERT(p_master != NULL, /**/);
+ std::vector<Buffer *> v_children;
+ /* Root master added as first buffer in the vector */
+ v_children.push_back(p_master);
+ p_master->getChildren(v_children, true);
+ LYXERR(Debug::FIND, "v_children.size()=" << v_children.size());
+ std::vector<Buffer *>::const_iterator it = std::find(v_children.begin(), v_children.end(), p_buf);
+ LASSERT(it != v_children.end(), /**/)
+ if (it == v_children.begin()) {
+ it = v_children.end();
+ --it;
+ p_buf = *it;
+ return true;
+ }
+ --it;
+ p_buf = *it;
+ return false;
+}
+
+
/// Finds forward
-int findForwardAdv(DocIterator & cur, MatchStringAdv const & match)
+int findForwardAdv(DocIterator & cur, MatchStringAdv & match)
{
if (!cur)
return 0;
@@ -947,17 +1023,29 @@
if (match(cur))
return findAdvFinalize(cur, match);
}
- if (wrap_answer != -1)
- break;
- wrap_answer = frontend::Alert::prompt(
- _("Wrap search?"),
- _("End of document reached while searching forward.\n"
- "\n"
- "Continue searching from beginning?"),
- 0, 1, _("&Yes"), _("&No"));
+ // No match has been found in current buffer
+ bool prompt = false;
+ if (match.opt.scope == FindAndReplaceOptions::S_BUFFER) {
+ prompt = true;
+ } else if (match.opt.scope == FindAndReplaceOptions::S_DOCUMENT) {
+ prompt = next_document_buffer(match.p_buf);
+ } else {
+ /* Unimplemented scope */
+ LASSERT(false, /**/);
+ }
+ if (prompt) {
+ if (wrap_answer != -1)
+ break;
+ wrap_answer = frontend::Alert::prompt(
+ _("Wrap search?"),
+ _("End of document/scope reached while searching forward.\n"
+ "\n"
+ "Continue searching from beginning?"),
+ 0, 1, _("&Yes"), _("&No"));
+ }
cur.clear();
- cur.push_back(CursorSlice(match.buf.inset()));
- } while (wrap_answer == 0);
+ cur.push_back(CursorSlice(match.p_buf->inset()));
+ } while (wrap_answer != 1);
return 0;
}
@@ -986,7 +1074,7 @@
}
/// Finds backwards
-int findBackwardsAdv(DocIterator & cur, MatchStringAdv const & match) {
+int findBackwardsAdv(DocIterator & cur, MatchStringAdv & match) {
if (! cur)
return 0;
// Backup of original position (for restoring it in case match not found)
@@ -1047,13 +1135,25 @@
cur.backwardPos();
};
}
- wrap_answer = frontend::Alert::prompt(
- _("Wrap search?"),
- _("Beginning of document reached while searching backwards\n"
- "\n"
- "Continue searching from end?"),
- 0, 1, _("&Yes"), _("&No"));
- cur = doc_iterator_end(&match.buf);
+ // No match has been found in current buffer
+ bool prompt = false;
+ if (match.opt.scope == FindAndReplaceOptions::S_BUFFER) {
+ prompt = true;
+ } else if (match.opt.scope == FindAndReplaceOptions::S_DOCUMENT) {
+ prompt = prev_document_buffer(match.p_buf);
+ } else {
+ /* Unimplemented scope */
+ LASSERT(false, /**/);
+ }
+ if (prompt) {
+ wrap_answer = frontend::Alert::prompt(
+ _("Wrap search?"),
+ _("Beginning of document/scope reached while searching backwards\n"
+ "\n"
+ "Continue searching from end?"),
+ 0, 1, _("&Yes"), _("&No"));
+ }
+ cur = doc_iterator_end(match.p_buf);
cur.backwardPos();
LYXERR(Debug::FIND, "findBackAdv5: cur: " << cur);
cur_orig2 = cur;
@@ -1062,6 +1162,7 @@
return 0;
}
+
} // anonym namespace
@@ -1077,10 +1178,11 @@
FindAndReplaceOptions::FindAndReplaceOptions(docstring const & search, bool casesensitive,
bool matchword, bool forward, bool expandmacros, bool ignoreformat,
- bool regexp, docstring const & replace, bool keep_case)
+ bool regexp, docstring const & replace, bool keep_case,
+ SearchScope scope)
: search(search), casesensitive(casesensitive), matchword(matchword),
forward(forward), expandmacros(expandmacros), ignoreformat(ignoreformat),
- regexp(regexp), replace(replace), keep_case(keep_case)
+ regexp(regexp), replace(replace), keep_case(keep_case), scope(scope)
{
}
@@ -1153,8 +1255,8 @@
// return false;
// }
+ MatchStringAdv matchAdv(bv->buffer(), opt);
try {
- MatchStringAdv const matchAdv(bv->buffer(), opt);
if (opt.forward)
match_len = findForwardAdv(cur, matchAdv);
else
@@ -1170,7 +1272,12 @@
return false;
}
- LYXERR(Debug::FIND, "Putting selection at " << cur << " with len: " << match_len);
+ LYXERR(Debug::FIND, "Putting selection at buf=" << matchAdv.p_buf
+ << "cur=" << cur << " with len: " << match_len);
+
+ theApp()->currentWindow()->selectDocumentBuffer(matchAdv.p_buf);
+ bv = theApp()->currentWindow()->documentBufferView();
+
bv->putSelectionAt(cur, match_len, ! opt.forward);
if (opt.replace == docstring(from_utf8(LYX_FR_NULL_STRING))) {
bv->message(_("Match found !"));
@@ -1248,7 +1355,8 @@
<< opt.ignoreformat << ' '
<< opt.regexp << ' '
<< to_utf8(opt.replace) << "\nEOSS\n"
- << opt.keep_case;
+ << opt.keep_case << ' '
+ << int(opt.scope);
LYXERR(Debug::FIND, "built: " << os.str());
@@ -1284,6 +1392,9 @@
getline(is, line);
}
is >> opt.keep_case;
+ int i;
+ is >> i;
+ opt.scope = FindAndReplaceOptions::SearchScope(i);
LYXERR(Debug::FIND, "parsed: " << opt.casesensitive << ' ' << opt.matchword << ' ' << opt.forward << ' '
<< opt.expandmacros << ' ' << opt.ignoreformat << ' ' << opt.regexp << ' ' << opt.keep_case);
LYXERR(Debug::FIND, "replacing with: '" << s << "'");
Index: src/Buffer.h
===================================================================
--- src/Buffer.h (revisione 32676)
+++ src/Buffer.h (copia locale)
@@ -321,6 +321,9 @@
/// return a vector with all children (and grandchildren)
std::vector<Buffer *> getChildren(bool grand_children = true) const;
+ /// Add all children (and grandchildren) to supplied vector
+ void getChildren(std::vector<Buffer *> & children, bool grand_children = true) const;
+
/// Is buffer read-only?
bool isReadonly() const;
Index: src/frontends/LyXView.h
===================================================================
--- src/frontends/LyXView.h (revisione 32676)
+++ src/frontends/LyXView.h (copia locale)
@@ -57,6 +57,10 @@
virtual BufferView const * documentBufferView() const = 0;
//@}
+ /// Find or create buffer view and WorkArea for supplied document
+ /// buffer, and make it current.
+ virtual void selectDocumentBuffer(Buffer const * p_buf) = 0;
+
/// display a message in the view
virtual void message(docstring const &) = 0;
Index: src/frontends/qt4/GuiView.h
===================================================================
--- src/frontends/qt4/GuiView.h (revisione 32676)
+++ src/frontends/qt4/GuiView.h (copia locale)
@@ -283,6 +283,10 @@
///
void disconnectDialog(std::string const & name);
+ /// Find or create buffer view and WorkArea for supplied document
+ /// buffer and make it current.
+ void selectDocumentBuffer(Buffer const * p_buf);
+
private:
///
void saveLayout() const;
Index: src/frontends/qt4/GuiView.cpp
===================================================================
--- src/frontends/qt4/GuiView.cpp (revisione 32676)
+++ src/frontends/qt4/GuiView.cpp (copia locale)
@@ -3542,6 +3542,11 @@
}
+void GuiView::selectDocumentBuffer(Buffer const * p_buf) {
+ setBuffer(const_cast<Buffer *>(p_buf));
+}
+
+
} // namespace frontend
} // namespace lyx
Index: src/frontends/qt4/FindAndReplace.cpp
===================================================================
--- src/frontends/qt4/FindAndReplace.cpp (revisione 32676)
+++ src/frontends/qt4/FindAndReplace.cpp (copia locale)
@@ -162,6 +162,13 @@
} else {
replaceString = from_utf8(LYX_FR_NULL_STRING);
}
+ FindAndReplaceOptions::SearchScope scope = FindAndReplaceOptions::S_BUFFER;
+ if (CurrentDocument->isChecked())
+ scope = FindAndReplaceOptions::S_BUFFER;
+ else if (MasterDocument->isChecked())
+ scope = FindAndReplaceOptions::S_DOCUMENT;
+ else
+ LASSERT(false, /**/);
LYXERR(Debug::FIND, "FindAndReplaceOptions: "
<< "searchstring=" << searchString
<< ", casesensitiv=" << casesensitive
@@ -171,9 +178,10 @@
<< ", ignoreformat=" << ignoreformat
<< ", regexp=" << regexp
<< ", replaceString" << replaceString
- << ", keep_case=" << keep_case);
+ << ", keep_case=" << keep_case
+ << ", scope=" << scope);
FindAndReplaceOptions opt(searchString, casesensitive, matchword, ! backwards,
- expandmacros, ignoreformat, regexp, replaceString, keep_case);
+ expandmacros, ignoreformat, regexp, replaceString, keep_case, scope);
LYXERR(Debug::FIND, "Dispatching LFUN_WORD_FINDADV");
std::ostringstream oss;
oss << opt;
@@ -268,6 +276,17 @@
find_work_area_->redraw();
find_work_area_->installEventFilter(this);
replace_work_area_->installEventFilter(this);
+
+ if (view_.currentMainWorkArea()) {
+ Buffer * p_doc_buf = &view_.currentMainWorkArea()->bufferView().buffer();
+ if (p_doc_buf->masterBuffer() == p_doc_buf && p_doc_buf->getChildren().empty()) {
+ if (MasterDocument->isChecked())
+ CurrentDocument->setChecked(true);
+ MasterDocument->setEnabled(false);
+ } else {
+ MasterDocument->setEnabled(true);
+ }
+ }
}
Index: src/lyxfind.h
===================================================================
--- src/lyxfind.h (revisione 32676)
+++ src/lyxfind.h (copia locale)
@@ -78,6 +78,12 @@
class FindAndReplaceOptions {
public:
+ typedef enum {
+ S_BUFFER,
+ S_DOCUMENT,
+ S_OPEN_BUFFERS,
+ S_ALL_MANUALS
+ } SearchScope;
FindAndReplaceOptions(
docstring const & search,
bool casesensitive,
@@ -87,7 +93,8 @@
bool ignoreformat,
bool regexp,
docstring const & replace,
- bool keep_case
+ bool keep_case,
+ SearchScope scope = S_BUFFER
);
FindAndReplaceOptions() { }
docstring search;
@@ -99,6 +106,7 @@
bool regexp;
docstring replace;
bool keep_case;
+ SearchScope scope;
};
/// Write a FindAdvOptions instance to a stringstream
Index: src/Buffer.cpp
===================================================================
--- src/Buffer.cpp (revisione 32676)
+++ src/Buffer.cpp (copia locale)
@@ -2331,9 +2331,8 @@
}
-std::vector<Buffer *> Buffer::getChildren(bool grand_children) const
+void Buffer::getChildren(std::vector<Buffer *> & clist, bool grand_children) const
{
- std::vector<Buffer *> clist;
// loop over children
Impl::BufferPositionMap::iterator it = d->children_positions.begin();
Impl::BufferPositionMap::iterator end = d->children_positions.end();
@@ -2348,10 +2347,17 @@
clist.push_back(*git);
}
}
- return clist;
}
+std::vector<Buffer *> Buffer::getChildren(bool grand_children) const
+{
+ std::vector<Buffer *> v;
+ getChildren(v, grand_children);
+ return v;
+}
+
+
template<typename M>
typename M::iterator greatest_below(M & m, typename M::key_type const & x)
{
372a373,390
> @@ -268,6 +276,17 @@
> find_work_area_->redraw();
> find_work_area_->installEventFilter(this);
> replace_work_area_->installEventFilter(this);
> +
> + if (view_.currentMainWorkArea()) {
> + Buffer * p_doc_buf = &view_.currentMainWorkArea()->bufferView().buffer();
> + if (p_doc_buf->masterBuffer() == p_doc_buf && p_doc_buf->getChildren().empty()) {
> + if (MasterDocument->isChecked())
> + CurrentDocument->setChecked(true);
> + MasterDocument->setEnabled(false);
> + } else {
> + MasterDocument->setEnabled(true);
> + }
> + }
> }
>
>