GuiSearch: Add auto-wrap option

This commit is contained in:
Juergen Spitzmueller 2021-02-15 11:30:03 +01:00
parent 6212d939b4
commit f59b8cb657
9 changed files with 79 additions and 48 deletions

View File

@ -458,7 +458,8 @@ void BufferView::setSearchRequestCache(docstring const & text)
bool casesensitive; bool casesensitive;
bool matchword; bool matchword;
bool forward; bool forward;
docstring const search = string2find(text, casesensitive, matchword, forward); bool wrap;
docstring const search = string2find(text, casesensitive, matchword, forward, wrap);
theClipboard().setFindBuffer(search); theClipboard().setFindBuffer(search);
} }
@ -1644,7 +1645,7 @@ void BufferView::dispatch(FuncRequest const & cmd, DispatchResult & dr)
break; break;
docstring const data = docstring const data =
find2string(searched_string, false, false, act == LFUN_WORD_FIND_FORWARD); find2string(searched_string, false, false, act == LFUN_WORD_FIND_FORWARD, false);
bool found = lyxfind(this, FuncRequest(LFUN_WORD_FIND, data)); bool found = lyxfind(this, FuncRequest(LFUN_WORD_FIND, data));
if (found) if (found)
dr.screenUpdate(Update::Force | Update::FitCursor); dr.screenUpdate(Update::Force | Update::FitCursor);

View File

@ -189,7 +189,7 @@ void GuiSearchWidget::findClicked(bool const backwards)
{ {
docstring const needle = qstring_to_ucs4(findCO->currentText()); docstring const needle = qstring_to_ucs4(findCO->currentText());
find(needle, caseCB->isChecked(), wordsCB->isChecked(), !backwards, find(needle, caseCB->isChecked(), wordsCB->isChecked(), !backwards,
instantSearchCB->isChecked()); instantSearchCB->isChecked(), wrapCB->isChecked());
uniqueInsert(findCO, findCO->currentText()); uniqueInsert(findCO, findCO->currentText());
if (!instantSearchCB->isChecked()) if (!instantSearchCB->isChecked())
findCO->lineEdit()->selectAll(); findCO->lineEdit()->selectAll();
@ -207,7 +207,7 @@ void GuiSearchWidget::replaceClicked(bool const backwards)
docstring const needle = qstring_to_ucs4(findCO->currentText()); docstring const needle = qstring_to_ucs4(findCO->currentText());
docstring const repl = qstring_to_ucs4(replaceCO->currentText()); docstring const repl = qstring_to_ucs4(replaceCO->currentText());
replace(needle, repl, caseCB->isChecked(), wordsCB->isChecked(), replace(needle, repl, caseCB->isChecked(), wordsCB->isChecked(),
!backwards, false); !backwards, false, wrapCB->isChecked());
uniqueInsert(findCO, findCO->currentText()); uniqueInsert(findCO, findCO->currentText());
uniqueInsert(replaceCO, replaceCO->currentText()); uniqueInsert(replaceCO, replaceCO->currentText());
} }
@ -223,17 +223,17 @@ void GuiSearchWidget::replaceallClicked()
{ {
replace(qstring_to_ucs4(findCO->currentText()), replace(qstring_to_ucs4(findCO->currentText()),
qstring_to_ucs4(replaceCO->currentText()), qstring_to_ucs4(replaceCO->currentText()),
caseCB->isChecked(), wordsCB->isChecked(), true, true); caseCB->isChecked(), wordsCB->isChecked(), true, true, true);
uniqueInsert(findCO, findCO->currentText()); uniqueInsert(findCO, findCO->currentText());
uniqueInsert(replaceCO, replaceCO->currentText()); uniqueInsert(replaceCO, replaceCO->currentText());
} }
void GuiSearchWidget::find(docstring const & search, bool casesensitive, void GuiSearchWidget::find(docstring const & search, bool casesensitive,
bool matchword, bool forward, bool instant) bool matchword, bool forward, bool instant, bool wrap)
{ {
docstring const sdata = docstring const sdata =
find2string(search, casesensitive, matchword, forward); find2string(search, casesensitive, matchword, forward, wrap);
if (instant) if (instant)
// re-query current match // re-query current match
dispatch(FuncRequest(LFUN_WORD_BACKWARD)); dispatch(FuncRequest(LFUN_WORD_BACKWARD));
@ -244,11 +244,11 @@ void GuiSearchWidget::find(docstring const & search, bool casesensitive,
void GuiSearchWidget::replace(docstring const & search, docstring const & replace, void GuiSearchWidget::replace(docstring const & search, docstring const & replace,
bool casesensitive, bool matchword, bool casesensitive, bool matchword,
bool forward, bool all) bool forward, bool all, bool wrap)
{ {
docstring const sdata = docstring const sdata =
replace2string(replace, search, casesensitive, replace2string(replace, search, casesensitive,
matchword, all, forward); matchword, all, forward, wrap);
dispatch(FuncRequest(LFUN_WORD_REPLACE, sdata)); dispatch(FuncRequest(LFUN_WORD_REPLACE, sdata));
} }
@ -257,6 +257,7 @@ void GuiSearchWidget::saveSession(QSettings & settings, QString const & session_
settings.setValue(session_key + "/casesensitive", caseCB->isChecked()); settings.setValue(session_key + "/casesensitive", caseCB->isChecked());
settings.setValue(session_key + "/words", wordsCB->isChecked()); settings.setValue(session_key + "/words", wordsCB->isChecked());
settings.setValue(session_key + "/instant", instantSearchCB->isChecked()); settings.setValue(session_key + "/instant", instantSearchCB->isChecked());
settings.setValue(session_key + "/wrap", wrapCB->isChecked());
settings.setValue(session_key + "/minimized", minimized_); settings.setValue(session_key + "/minimized", minimized_);
} }
@ -267,6 +268,7 @@ void GuiSearchWidget::restoreSession(QString const & session_key)
caseCB->setChecked(settings.value(session_key + "/casesensitive", false).toBool()); caseCB->setChecked(settings.value(session_key + "/casesensitive", false).toBool());
wordsCB->setChecked(settings.value(session_key + "/words", false).toBool()); wordsCB->setChecked(settings.value(session_key + "/words", false).toBool());
instantSearchCB->setChecked(settings.value(session_key + "/instant", false).toBool()); instantSearchCB->setChecked(settings.value(session_key + "/instant", false).toBool());
wrapCB->setChecked(settings.value(session_key + "/wrap", false).toBool());
minimized_ = settings.value(session_key + "/minimized", false).toBool(); minimized_ = settings.value(session_key + "/minimized", false).toBool();
// initialize hidings // initialize hidings
minimizeClicked(false); minimizeClicked(false);

View File

@ -61,11 +61,11 @@ private:
/// Searches occurrence of string /// Searches occurrence of string
void find(docstring const & search, void find(docstring const & search,
bool casesensitive, bool matchword, bool casesensitive, bool matchword,
bool forward, bool instant); bool forward, bool instant, bool wrap);
/// Replaces occurrence of string /// Replaces occurrence of string
void replace(docstring const & search, docstring const & replace, void replace(docstring const & search, docstring const & replace,
bool casesensitive, bool matchword, bool casesensitive, bool matchword,
bool forward, bool all); bool forward, bool all, bool wrap);
/// ///
BufferView const * bv_ = nullptr; BufferView const * bv_ = nullptr;
/// ///

View File

@ -467,7 +467,7 @@ void SpellcheckerWidget::on_findNextPB_clicked()
return; return;
docstring const textfield = qstring_to_ucs4(d->ui.wordED->text()); docstring const textfield = qstring_to_ucs4(d->ui.wordED->text());
docstring const datastring = find2string(textfield, docstring const datastring = find2string(textfield,
true, true, true); true, true, true, false);
LYXERR(Debug::GUI, "Spellchecker: find next (" << textfield << ")"); LYXERR(Debug::GUI, "Spellchecker: find next (" << textfield << ")");
dispatch(FuncRequest(LFUN_WORD_FIND, datastring)); dispatch(FuncRequest(LFUN_WORD_FIND, datastring));
d->canCheck(); d->canCheck();
@ -486,7 +486,8 @@ void SpellcheckerWidget::on_replacePB_clicked()
true, // match word true, // match word
false, // all words false, // all words
true, // forward true, // forward
false); // find next false, // find next
false); // auto-wrap
LYXERR(Debug::GUI, "Replace (" << replacement << ")"); LYXERR(Debug::GUI, "Replace (" << replacement << ")");
dispatch(FuncRequest(LFUN_WORD_REPLACE, datastring)); dispatch(FuncRequest(LFUN_WORD_REPLACE, datastring));
@ -508,7 +509,8 @@ void SpellcheckerWidget::on_replaceAllPB_clicked()
true, // match word true, // match word
true, // all words true, // all words
true, // forward true, // forward
false); // find next false, // find next
false); // auto-wrap
LYXERR(Debug::GUI, "Replace all (" << replacement << ")"); LYXERR(Debug::GUI, "Replace all (" << replacement << ")");
dispatch(FuncRequest(LFUN_WORD_REPLACE, datastring)); dispatch(FuncRequest(LFUN_WORD_REPLACE, datastring));

View File

@ -266,7 +266,8 @@ void GuiThesaurus::replace(docstring const & newstr)
true, // case sensitive true, // case sensitive
true, // match word true, // match word
false, // all words false, // all words
true); // forward true, // forward
false);// auto-wrap
dispatch(FuncRequest(LFUN_WORD_REPLACE, sdata)); dispatch(FuncRequest(LFUN_WORD_REPLACE, sdata));
} }

View File

@ -847,7 +847,8 @@ void MenuDefinition::expandSpellingSuggestions(BufferView const * bv)
true, // match word true, // match word
false, // all words false, // all words
true, // forward true, // forward
false))); // find next false, // find next
false))); // auto-wrap
if (i < m) if (i < m)
add(w); add(w);
else else

View File

@ -208,7 +208,7 @@
<item> <item>
<widget class="QCheckBox" name="wordsCB"> <widget class="QCheckBox" name="wordsCB">
<property name="text"> <property name="text">
<string>&amp;Whole words</string> <string>Wh&amp;ole words</string>
</property> </property>
</widget> </widget>
</item> </item>
@ -222,6 +222,16 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QCheckBox" name="wrapCB">
<property name="toolTip">
<string>If the beggining/start of the document is reached, automatically wrap around</string>
</property>
<property name="text">
<string>&amp;Wrap</string>
</property>
</widget>
</item>
<item> <item>
<spacer name="horizontalSpacer"> <spacer name="horizontalSpacer">
<property name="orientation"> <property name="orientation">

View File

@ -267,7 +267,7 @@ bool searchAllowed(docstring const & str)
bool findOne(BufferView * bv, docstring const & searchstr, bool findOne(BufferView * bv, docstring const & searchstr,
bool case_sens, bool whole, bool forward, bool case_sens, bool whole, bool forward,
bool find_del, bool check_wrap) bool find_del, bool check_wrap, bool auto_wrap)
{ {
if (!searchAllowed(searchstr)) if (!searchAllowed(searchstr))
return false; return false;
@ -286,6 +286,7 @@ bool findOne(BufferView * bv, docstring const & searchstr,
bv->putSelectionAt(cur, match_len, !forward); bv->putSelectionAt(cur, match_len, !forward);
else if (check_wrap) { else if (check_wrap) {
DocIterator cur_orig(bv->cursor()); DocIterator cur_orig(bv->cursor());
if (!auto_wrap) {
docstring q; docstring q;
if (forward) if (forward)
q = _("End of file reached while searching forward.\n" q = _("End of file reached while searching forward.\n"
@ -295,7 +296,9 @@ bool findOne(BufferView * bv, docstring const & searchstr,
"Continue searching from the end?"); "Continue searching from the end?");
int wrap_answer = frontend::Alert::prompt(_("Wrap search?"), int wrap_answer = frontend::Alert::prompt(_("Wrap search?"),
q, 0, 1, _("&Yes"), _("&No")); q, 0, 1, _("&Yes"), _("&No"));
if (wrap_answer == 0) { auto_wrap = wrap_answer == 0;
}
if (auto_wrap) {
if (forward) { if (forward) {
bv->cursor().clear(); bv->cursor().clear();
bv->cursor().push_back(CursorSlice(bv->buffer().inset())); bv->cursor().push_back(CursorSlice(bv->buffer().inset()));
@ -304,7 +307,7 @@ bool findOne(BufferView * bv, docstring const & searchstr,
bv->cursor().backwardPos(); bv->cursor().backwardPos();
} }
bv->clearSelection(); bv->clearSelection();
if (findOne(bv, searchstr, case_sens, whole, forward, find_del, false)) if (findOne(bv, searchstr, case_sens, whole, forward, find_del, false, false))
return true; return true;
} }
bv->cursor().setCursor(cur_orig); bv->cursor().setCursor(cur_orig);
@ -381,13 +384,13 @@ int replaceAll(BufferView * bv,
// whether anything at all was done. // whether anything at all was done.
pair<bool, int> replaceOne(BufferView * bv, docstring searchstr, pair<bool, int> replaceOne(BufferView * bv, docstring searchstr,
docstring const & replacestr, bool case_sens, docstring const & replacestr, bool case_sens,
bool whole, bool forward, bool findnext) bool whole, bool forward, bool findnext, bool wrap)
{ {
Cursor & cur = bv->cursor(); Cursor & cur = bv->cursor();
if (!cur.selection()) { if (!cur.selection()) {
// no selection, non-empty search string: find it // no selection, non-empty search string: find it
if (!searchstr.empty()) { if (!searchstr.empty()) {
bool const found = findOne(bv, searchstr, case_sens, whole, forward, true, findnext); bool const found = findOne(bv, searchstr, case_sens, whole, forward, true, findnext, wrap);
return make_pair(found, 0); return make_pair(found, 0);
} }
// empty search string // empty search string
@ -416,7 +419,7 @@ pair<bool, int> replaceOne(BufferView * bv, docstring searchstr,
// no selection or current selection is not search word: // no selection or current selection is not search word:
// just find the search word // just find the search word
if (!have_selection || !match) { if (!have_selection || !match) {
bool const found = findOne(bv, searchstr, case_sens, whole, forward, true, findnext); bool const found = findOne(bv, searchstr, case_sens, whole, forward, true, findnext, wrap);
return make_pair(found, 0); return make_pair(found, 0);
} }
@ -432,7 +435,7 @@ pair<bool, int> replaceOne(BufferView * bv, docstring searchstr,
cur.pos() = cur.lastpos()); cur.pos() = cur.lastpos());
} }
if (findnext) if (findnext)
findOne(bv, searchstr, case_sens, whole, forward, false, findnext); findOne(bv, searchstr, case_sens, whole, forward, false, findnext, wrap);
return make_pair(true, 1); return make_pair(true, 1);
} }
@ -441,13 +444,15 @@ pair<bool, int> replaceOne(BufferView * bv, docstring searchstr,
docstring const find2string(docstring const & search, docstring const find2string(docstring const & search,
bool casesensitive, bool matchword, bool forward) bool casesensitive, bool matchword,
bool forward, bool wrap)
{ {
odocstringstream ss; odocstringstream ss;
ss << search << '\n' ss << search << '\n'
<< int(casesensitive) << ' ' << int(casesensitive) << ' '
<< int(matchword) << ' ' << int(matchword) << ' '
<< int(forward); << int(forward) << ' '
<< int(wrap);
return ss.str(); return ss.str();
} }
@ -455,7 +460,7 @@ docstring const find2string(docstring const & search,
docstring const replace2string(docstring const & replace, docstring const replace2string(docstring const & replace,
docstring const & search, docstring const & search,
bool casesensitive, bool matchword, bool casesensitive, bool matchword,
bool all, bool forward, bool findnext) bool all, bool forward, bool findnext, bool wrap)
{ {
odocstringstream ss; odocstringstream ss;
ss << replace << '\n' ss << replace << '\n'
@ -464,7 +469,8 @@ docstring const replace2string(docstring const & replace,
<< int(matchword) << ' ' << int(matchword) << ' '
<< int(all) << ' ' << int(all) << ' '
<< int(forward) << ' ' << int(forward) << ' '
<< int(findnext); << int(findnext) << ' '
<< int(wrap);
return ss.str(); return ss.str();
} }
@ -472,17 +478,19 @@ docstring const replace2string(docstring const & replace,
docstring const string2find(docstring const & argument, docstring const string2find(docstring const & argument,
bool &casesensitive, bool &casesensitive,
bool &matchword, bool &matchword,
bool &forward) bool &forward,
bool &wrap)
{ {
// data is of the form // data is of the form
// "<search> // "<search>
// <casesensitive> <matchword> <forward>" // <casesensitive> <matchword> <forward> <wrap>"
docstring search; docstring search;
docstring howto = split(argument, search, '\n'); docstring howto = split(argument, search, '\n');
casesensitive = parse_bool(howto); casesensitive = parse_bool(howto);
matchword = parse_bool(howto); matchword = parse_bool(howto);
forward = parse_bool(howto, true); forward = parse_bool(howto, true);
wrap = parse_bool(howto, true);
return search; return search;
} }
@ -497,9 +505,10 @@ bool lyxfind(BufferView * bv, FuncRequest const & ev)
bool casesensitive; bool casesensitive;
bool matchword; bool matchword;
bool forward; bool forward;
docstring search = string2find(ev.argument(), casesensitive, matchword, forward); bool wrap;
docstring search = string2find(ev.argument(), casesensitive, matchword, forward, wrap);
return findOne(bv, search, casesensitive, matchword, forward, false, true); return findOne(bv, search, casesensitive, matchword, forward, false, true, wrap);
} }
@ -511,7 +520,7 @@ bool lyxreplace(BufferView * bv, FuncRequest const & ev)
// data is of the form // data is of the form
// "<search> // "<search>
// <replace> // <replace>
// <casesensitive> <matchword> <all> <forward> <findnext>" // <casesensitive> <matchword> <all> <forward> <findnext> <wrap>"
docstring search; docstring search;
docstring rplc; docstring rplc;
docstring howto = split(ev.argument(), rplc, '\n'); docstring howto = split(ev.argument(), rplc, '\n');
@ -521,7 +530,8 @@ bool lyxreplace(BufferView * bv, FuncRequest const & ev)
bool matchword = parse_bool(howto); bool matchword = parse_bool(howto);
bool all = parse_bool(howto); bool all = parse_bool(howto);
bool forward = parse_bool(howto, true); bool forward = parse_bool(howto, true);
bool findnext = howto.empty() ? true : parse_bool(howto); bool findnext = parse_bool(howto, true);
bool wrap = parse_bool(howto);
bool update = false; bool update = false;
@ -531,7 +541,7 @@ bool lyxreplace(BufferView * bv, FuncRequest const & ev)
update = replace_count > 0; update = replace_count > 0;
} else { } else {
pair<bool, int> rv = pair<bool, int> rv =
replaceOne(bv, search, rplc, casesensitive, matchword, forward, findnext); replaceOne(bv, search, rplc, casesensitive, matchword, forward, findnext, wrap);
update = rv.first; update = rv.first;
replace_count = rv.second; replace_count = rv.second;
} }

View File

@ -34,7 +34,8 @@ class FuncRequest;
docstring const string2find(docstring const & argument, docstring const string2find(docstring const & argument,
bool &casesensitive, bool &casesensitive,
bool &matchword, bool &matchword,
bool &forward); bool &forward,
bool &wrap);
/** Encode the parameters needed to find \c search as a string /** Encode the parameters needed to find \c search as a string
* that can be dispatched to the LyX core in a FuncRequest wrapper. * that can be dispatched to the LyX core in a FuncRequest wrapper.
@ -42,7 +43,8 @@ docstring const string2find(docstring const & argument,
docstring const find2string(docstring const & search, docstring const find2string(docstring const & search,
bool casesensitive, bool casesensitive,
bool matchword, bool matchword,
bool forward); bool forward,
bool wrap);
/** Encode the parameters needed to replace \c search with \c replace /** Encode the parameters needed to replace \c search with \c replace
* as a string that can be dispatched to the LyX core in a FuncRequest * as a string that can be dispatched to the LyX core in a FuncRequest
@ -54,7 +56,8 @@ docstring const replace2string(docstring const & replace,
bool matchword, bool matchword,
bool all, bool all,
bool forward, bool forward,
bool findnext = true); bool findnext = true,
bool wrap = true);
/** Parse the string encoding of the find request that is found in /** Parse the string encoding of the find request that is found in
* \c ev.argument and act on it. * \c ev.argument and act on it.
@ -65,7 +68,8 @@ bool lyxfind(BufferView * bv, FuncRequest const & ev);
bool findOne(BufferView * bv, docstring const & searchstr, bool findOne(BufferView * bv, docstring const & searchstr,
bool case_sens, bool whole, bool forward, bool case_sens, bool whole, bool forward,
bool find_del = true, bool check_wrap = false); bool find_del = true, bool check_wrap = false,
bool auto_wrap = false);
/** Parse the string encoding of the replace request that is found in /** Parse the string encoding of the replace request that is found in
* \c ev.argument and act on it. * \c ev.argument and act on it.