]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/FindAndReplace.cpp
8c0f4ec4ada0aa99cc608a6b8fb7735ad1bbd365
[lyx.git] / src / frontends / qt4 / FindAndReplace.cpp
1 /**
2  * \file FindAndReplace.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Tommaso Cucinotta
7  *
8  * Full author contact details are available in file CREDITS.
9  */
10
11 #include <config.h>
12
13 #include "FindAndReplace.h"
14
15 #include "GuiApplication.h"
16 #include "qt_helpers.h"
17 #include "GuiView.h"
18 #include "GuiWorkArea.h"
19
20 #include "buffer_funcs.h"
21 #include "BufferParams.h"
22 #include "Cursor.h"
23 #include "FuncRequest.h"
24 #include "lyxfind.h"
25 #include "OutputParams.h"
26 #include "output_latex.h"
27 #include "TexRow.h"
28
29 #include "support/debug.h"
30 #include "support/FileName.h"
31 #include "support/gettext.h"
32 #include "support/lassert.h"
33
34 #include <QCloseEvent>
35 #include <QLineEdit>
36
37 #include <iostream>
38
39 using namespace std;
40 using namespace lyx::support;
41
42 namespace lyx {
43 namespace frontend {
44
45
46 FindAndReplaceWidget::FindAndReplaceWidget(GuiView & view)
47         :       view_(view)
48 {
49         setupUi(this);
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();
57 }
58
59
60 bool FindAndReplaceWidget::eventFilter(QObject *obj, QEvent *event)
61 {
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) {
66                         on_closePB_clicked();
67                         return true;
68                 } else if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) {
69                         if (e->modifiers() == Qt::ShiftModifier) {
70                                 on_findPrevPB_clicked();
71                                 return true;
72                         } else if (e->modifiers() == Qt::NoModifier) {
73                                 on_findNextPB_clicked();
74                                 return true;
75                         }
76                 } else if (e->key() == Qt::Key_Tab && e->modifiers() == Qt::NoModifier) {
77                         LYXERR(Debug::FIND, "Focusing replace WA");
78                         replace_work_area_->setFocus();
79                         return true;
80                 }
81         }
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) {
85                         on_closePB_clicked();
86                         return true;
87                 } else if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) {
88                         if (e->modifiers() == Qt::ShiftModifier) {
89                                 on_replacePrevPB_clicked();
90                                 return true;
91                         } else if (e->modifiers() == Qt::NoModifier) {
92                                 on_replaceNextPB_clicked();
93                                 return true;
94                         }
95                 } else if (e->key() == Qt::Key_Backtab) {
96                         LYXERR(Debug::FIND, "Focusing find WA");
97                         find_work_area_->setFocus();
98                         return true;
99                 }
100         }
101         // standard event processing
102         return QWidget::eventFilter(obj, event);
103 }
104
105 static docstring buffer_to_latex(Buffer & buffer) {
106         OutputParams runparams(&buffer.params().encoding());
107         odocstringstream os;
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());
119         }
120         return os.str();
121 }
122
123 void FindAndReplaceWidget::findAndReplace(
124         bool casesensitive, bool matchword, bool backwards,
125         bool expandmacros, bool ignoreformat, bool replace,
126         bool keep_case)
127 {
128         Buffer & buffer = find_work_area_->bufferView().buffer();
129         docstring searchString;
130         if (!ignoreformat) {
131                 searchString = buffer_to_latex(buffer);
132         } else {
133                 ParIterator it = buffer.par_iterator_begin();
134                 ParIterator end = buffer.par_iterator_end();
135                 OutputParams runparams(&buffer.params().encoding());
136                 odocstringstream os;
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);
144                 }
145         }
146         if (to_utf8(searchString).empty()) {
147                 buffer.message(_("Nothing to search"));
148                 return;
149         }
150         bool const regexp = to_utf8(searchString).find("\\regexp") != std::string::npos;
151         docstring replaceString;
152         if (replace) {
153                 Buffer & repl_buffer = replace_work_area_->bufferView().buffer();
154                 ostringstream oss;
155                 repl_buffer.write(oss);
156                 replaceString = from_utf8(oss.str()); //buffer_to_latex(replace_buffer);
157         } else {
158                 replaceString = from_utf8(LYX_FR_NULL_STRING);
159         }
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;
174         oss << opt;
175         LYXERR(Debug::FIND, "Dispatching LFUN_WORD_FINDADV");
176         dispatch(FuncRequest(LFUN_WORD_FINDADV, from_utf8(oss.str())));
177 }
178
179
180 void FindAndReplaceWidget::findAndReplace(bool backwards, bool replace)
181 {
182         // FIXME: create a Dialog::returnFocus() or something instead of this:
183         view_.setCurrentWorkArea(view_.currentMainWorkArea());
184         findAndReplace(caseCB->isChecked(),
185                 wordsCB->isChecked(),
186                 backwards,
187                 expandMacrosCB->isChecked(),
188                 ignoreFormatCB->isChecked(),
189                 replace,
190                 keepCaseCB->isChecked());
191         view_.currentMainWorkArea()->redraw();
192 }
193
194
195 void FindAndReplaceWidget::on_regexpInsertCombo_currentIndexChanged(int index)
196 {
197         static char const * regexps[] = {
198                 ".*", ".+", "[a-z]+", "[0-9]+"
199         };
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);
208         }
209 }
210
211
212 void FindAndReplaceWidget::on_closePB_clicked()
213 {
214         dispatch(FuncRequest(LFUN_DIALOG_TOGGLE, "findreplaceadv"));
215 }
216
217
218 void FindAndReplaceWidget::on_findNextPB_clicked() {
219         findAndReplace(false, false);
220         find_work_area_->setFocus();
221 }
222
223
224 void FindAndReplaceWidget::on_findPrevPB_clicked() {
225         findAndReplace(true, false);
226         find_work_area_->setFocus();
227 }
228
229
230 void FindAndReplaceWidget::on_replaceNextPB_clicked()
231 {
232         findAndReplace(false, true);
233         replace_work_area_->setFocus();
234 }
235
236
237 void FindAndReplaceWidget::on_replacePrevPB_clicked()
238 {
239         findAndReplace(true, true);
240         replace_work_area_->setFocus();
241 }
242
243
244 void FindAndReplaceWidget::on_replaceallPB_clicked()
245 {
246         replace_work_area_->setFocus();
247 }
248
249
250 void FindAndReplaceWidget::showEvent(QShowEvent * /* ev */)
251 {
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);
259 }
260
261
262 void FindAndReplaceWidget::hideEvent(QHideEvent *ev)
263 {
264         replace_work_area_->removeEventFilter(this);
265         find_work_area_->removeEventFilter(this);
266         this->QWidget::hideEvent(ev);
267 }
268
269
270 bool FindAndReplaceWidget::initialiseParams(std::string const & /* params */)
271 {
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));
277         return true;
278 }
279
280
281 FindAndReplace::FindAndReplace(GuiView & parent,
282                 Qt::DockWidgetArea area, Qt::WindowFlags flags)
283         : DockView(parent, "Find LyX", qt_("Find LyX Dialog"), area, flags)
284 {
285         widget_ = new FindAndReplaceWidget(parent);
286         setWidget(widget_);
287         setFocusProxy(widget_);
288 }
289
290
291 FindAndReplace::~FindAndReplace()
292 {
293         setFocusProxy(0);
294         delete widget_;
295 }
296
297
298 bool FindAndReplace::initialiseParams(std::string const & params)
299 {
300         return widget_->initialiseParams(params);
301 }
302
303
304 Dialog * createGuiSearchAdv(GuiView & lv)
305 {
306         return new FindAndReplace(lv, Qt::RightDockWidgetArea);
307 }
308
309
310 } // namespace frontend
311 } // namespace lyx
312
313
314 #include "moc_FindAndReplace.cpp"