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);
> +		}
> +	}
>  }
>  
>  

Reply via email to