2 * \file FindAndReplace.cpp
3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
6 * \author Tommaso Cucinotta
8 * Full author contact details are available in file CREDITS.
13 #include "FindAndReplace.h"
15 #include "GuiApplication.h"
16 #include "qt_helpers.h"
18 #include "GuiWorkArea.h"
20 #include "buffer_funcs.h"
21 #include "BufferParams.h"
23 #include "FuncRequest.h"
25 #include "OutputParams.h"
26 #include "output_latex.h"
29 #include "support/debug.h"
30 #include "support/FileName.h"
31 #include "support/gettext.h"
32 #include "support/lassert.h"
34 #include <QCloseEvent>
40 using namespace lyx::support;
46 FindAndReplaceWidget::FindAndReplaceWidget(GuiView & view)
50 find_work_area_->setGuiView(view_);
51 find_work_area_->init();
52 setFocusProxy(find_work_area_);
53 replace_work_area_->setGuiView(view_);
54 replace_work_area_->init();
55 // We don't want two cursors blinking.
56 replace_work_area_->stopBlinkingCursor();
60 bool FindAndReplaceWidget::eventFilter(QObject *obj, QEvent *event)
62 LYXERR(Debug::FIND, "FindAndReplace::eventFilter(): obj=" << obj << ", fwa=" << find_work_area_ << ", rwa=" << replace_work_area_ << "fsa=" << find_scroll_area_ << ", rsa=" << replace_scroll_area_);
63 if (obj == find_work_area_ && event->type() == QEvent::KeyPress) {
64 QKeyEvent *e = static_cast<QKeyEvent *> (event);
65 if (e->key() == Qt::Key_Escape && e->modifiers() == Qt::NoModifier) {
68 } else if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) {
69 if (e->modifiers() == Qt::ShiftModifier) {
70 on_findPrevPB_clicked();
72 } else if (e->modifiers() == Qt::NoModifier) {
73 on_findNextPB_clicked();
76 } else if (e->key() == Qt::Key_Tab && e->modifiers() == Qt::NoModifier) {
77 LYXERR(Debug::FIND, "Focusing replace WA");
78 replace_work_area_->setFocus();
82 if (obj == replace_work_area_ && event->type() == QEvent::KeyPress) {
83 QKeyEvent *e = static_cast<QKeyEvent *> (event);
84 if (e->key() == Qt::Key_Escape && e->modifiers() == Qt::NoModifier) {
87 } else if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) {
88 if (e->modifiers() == Qt::ShiftModifier) {
89 on_replacePrevPB_clicked();
91 } else if (e->modifiers() == Qt::NoModifier) {
92 on_replaceNextPB_clicked();
95 } else if (e->key() == Qt::Key_Backtab) {
96 LYXERR(Debug::FIND, "Focusing find WA");
97 find_work_area_->setFocus();
101 // standard event processing
102 return QWidget::eventFilter(obj, event);
105 static docstring buffer_to_latex(Buffer & buffer) {
106 OutputParams runparams(&buffer.params().encoding());
108 runparams.nice = true;
109 runparams.flavor = OutputParams::LATEX;
110 runparams.linelen = 80; //lyxrc.plaintext_linelen;
111 // No side effect of file copying and image conversion
112 runparams.dryrun = true;
113 buffer.texrow().reset();
114 ParagraphList::const_iterator pit = buffer.paragraphs().begin();
115 ParagraphList::const_iterator const end = buffer.paragraphs().end();
116 for (; pit != end; ++pit) {
117 TeXOnePar(buffer, buffer.text(), pit, os, buffer.texrow(), runparams);
118 LYXERR(Debug::FIND, "searchString up to here: " << os.str());
123 void FindAndReplaceWidget::findAndReplace(
124 bool casesensitive, bool matchword, bool backwards,
125 bool expandmacros, bool ignoreformat, bool replace,
128 Buffer & buffer = find_work_area_->bufferView().buffer();
129 docstring searchString;
131 searchString = buffer_to_latex(buffer);
133 ParIterator it = buffer.par_iterator_begin();
134 ParIterator end = buffer.par_iterator_end();
135 OutputParams runparams(&buffer.params().encoding());
137 runparams.nice = true;
138 runparams.flavor = OutputParams::LATEX;
139 runparams.linelen = 100000; //lyxrc.plaintext_linelen;
140 runparams.dryrun = true;
141 for (; it != end; ++it) {
142 LYXERR(Debug::FIND, "Adding to search string: '" << it->asString(false) << "'");
143 searchString += it->stringify(pos_type(0), it->size(), AS_STR_INSETS, runparams);
146 if (to_utf8(searchString).empty()) {
147 buffer.message(_("Nothing to search"));
150 bool const regexp = to_utf8(searchString).find("\\regexp") != std::string::npos;
151 docstring replaceString;
153 Buffer & repl_buffer = replace_work_area_->bufferView().buffer();
155 repl_buffer.write(oss);
156 replaceString = from_utf8(oss.str()); //buffer_to_latex(replace_buffer);
158 replaceString = from_utf8(LYX_FR_NULL_STRING);
160 LYXERR(Debug::FIND, "FindAndReplaceOptions: "
161 << "searchstring=" << searchString
162 << ", casesensitiv=" << casesensitive
163 << ", matchword=" << matchword
164 << ", backwards=" << backwards
165 << ", expandmacros=" << expandmacros
166 << ", ignoreformat=" << ignoreformat
167 << ", regexp=" << regexp
168 << ", replaceString" << replaceString
169 << ", keep_case=" << keep_case);
170 FindAndReplaceOptions opt(searchString, casesensitive, matchword, ! backwards,
171 expandmacros, ignoreformat, regexp, replaceString, keep_case);
172 LYXERR(Debug::FIND, "Dispatching LFUN_WORD_FINDADV");
173 std::ostringstream oss;
175 LYXERR(Debug::FIND, "Dispatching LFUN_WORD_FINDADV");
176 dispatch(FuncRequest(LFUN_WORD_FINDADV, from_utf8(oss.str())));
180 void FindAndReplaceWidget::findAndReplace(bool backwards, bool replace)
182 // FIXME: create a Dialog::returnFocus() or something instead of this:
183 view_.setCurrentWorkArea(view_.currentMainWorkArea());
184 findAndReplace(caseCB->isChecked(),
185 wordsCB->isChecked(),
187 expandMacrosCB->isChecked(),
188 ignoreFormatCB->isChecked(),
190 keepCaseCB->isChecked());
191 view_.currentMainWorkArea()->redraw();
195 void FindAndReplaceWidget::on_regexpInsertCombo_currentIndexChanged(int index)
197 static char const * regexps[] = {
198 ".*", ".+", "[a-z]+", "[0-9]+"
200 LYXERR(Debug::FIND, "Index: " << index);
201 if (index >= 1 && index < 1 + int(sizeof(regexps)/sizeof(regexps[0]))) {
202 find_work_area_->setFocus();
203 Cursor & cur = find_work_area_->bufferView().cursor();
204 if (! cur.inRegexped())
205 dispatch(FuncRequest(LFUN_REGEXP_MODE));
206 dispatch(FuncRequest(LFUN_SELF_INSERT, regexps[index - 1]));
207 regexpInsertCombo->setCurrentIndex(0);
212 void FindAndReplaceWidget::on_closePB_clicked()
214 dispatch(FuncRequest(LFUN_DIALOG_TOGGLE, "findreplaceadv"));
218 void FindAndReplaceWidget::on_findNextPB_clicked() {
219 findAndReplace(false, false);
220 find_work_area_->setFocus();
224 void FindAndReplaceWidget::on_findPrevPB_clicked() {
225 findAndReplace(true, false);
226 find_work_area_->setFocus();
230 void FindAndReplaceWidget::on_replaceNextPB_clicked()
232 findAndReplace(false, true);
233 replace_work_area_->setFocus();
237 void FindAndReplaceWidget::on_replacePrevPB_clicked()
239 findAndReplace(true, true);
240 replace_work_area_->setFocus();
244 void FindAndReplaceWidget::on_replaceallPB_clicked()
246 replace_work_area_->setFocus();
250 void FindAndReplaceWidget::showEvent(QShowEvent * /* ev */)
252 replace_work_area_->redraw();
253 find_work_area_->setFocus();
254 dispatch(FuncRequest(LFUN_BUFFER_BEGIN));
255 dispatch(FuncRequest(LFUN_BUFFER_END_SELECT));
256 find_work_area_->redraw();
257 find_work_area_->installEventFilter(this);
258 replace_work_area_->installEventFilter(this);
262 void FindAndReplaceWidget::hideEvent(QHideEvent *ev)
264 replace_work_area_->removeEventFilter(this);
265 find_work_area_->removeEventFilter(this);
266 this->QWidget::hideEvent(ev);
270 bool FindAndReplaceWidget::initialiseParams(std::string const & /* params */)
272 find_work_area_->redraw();
273 replace_work_area_->redraw();
274 find_work_area_->setFocus();
275 dispatch(FuncRequest(LFUN_BUFFER_BEGIN));
276 dispatch(FuncRequest(LFUN_BUFFER_END_SELECT));
281 FindAndReplace::FindAndReplace(GuiView & parent,
282 Qt::DockWidgetArea area, Qt::WindowFlags flags)
283 : DockView(parent, "Find LyX", qt_("Find LyX Dialog"), area, flags)
285 widget_ = new FindAndReplaceWidget(parent);
287 setFocusProxy(widget_);
291 FindAndReplace::~FindAndReplace()
298 bool FindAndReplace::initialiseParams(std::string const & params)
300 return widget_->initialiseParams(params);
304 Dialog * createGuiSearchAdv(GuiView & lv)
306 return new FindAndReplace(lv, Qt::RightDockWidgetArea);
310 } // namespace frontend
314 #include "moc_FindAndReplace.cpp"