]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/FindAndReplace.cpp
a0ac3cd5563964e0abd9a64d545fe4a00cca27c9
[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
16 #include "GuiWorkArea.h"
17 #include "GuiView.h"
18 #include "qt_helpers.h"
19
20 #include "Application.h"
21 #include "BufferList.h"
22 #include "buffer_funcs.h"
23 #include "BufferParams.h"
24 #include "Cursor.h"
25 #include "FuncRequest.h"
26 #include "lyxfind.h"
27 #include "OutputParams.h"
28 #include "output_latex.h"
29 #include "TexRow.h"
30
31 #include "support/FileName.h"
32 #include "support/convert.h"
33 #include "support/debug.h"
34 #include "support/gettext.h"
35 #include "support/lassert.h"
36
37 #include <QLineEdit>
38 #include <QCloseEvent>
39
40 #include <iostream>
41
42 using namespace std;
43 using namespace lyx::support;
44
45 namespace lyx {
46 namespace frontend {
47
48
49 FindAndReplace::FindAndReplace(GuiView & parent)
50         : DockView(parent, "Find LyX", "Find LyX Dialog", Qt::RightDockWidgetArea),
51         parent_view_(parent),
52         delayedFocusTimer_(this)
53 {
54         searchBuffer_ = theBufferList().newBuffer(
55                 support::FileName::tempName().absFilename() + "_searchadv.internal");
56         LASSERT(searchBuffer_ != 0, /* */);
57         searchBufferView_ = new BufferView(*searchBuffer_);
58         searchBuffer_->setUnnamed(true);
59         searchBuffer_->setFullyLoaded(true);
60
61         setupUi(this);
62         find_work_area_->setGuiView(parent_view_);
63         find_work_area_->setBuffer(*searchBuffer_);
64         find_work_area_->setUpdatesEnabled(false);
65         find_work_area_->setDialogMode(true);
66 }
67
68
69 FindAndReplace::~FindAndReplace()
70 {
71         // No need to destroy buffer and bufferview here, because it is done
72         // in theBuffeerList() destruction loop at application exit
73         LYXERR(Debug::DEBUG, "FindAndReplace::~FindAndReplace()");
74 }
75
76
77 bool FindAndReplace::eventFilter(QObject *obj, QEvent *event)
78 {
79         LYXERR(Debug::DEBUG, "FindAndReplace::eventFilter()" << std::endl);
80         if (obj == find_work_area_ && event->type() == QEvent::KeyPress) {
81                 QKeyEvent *e = static_cast<QKeyEvent *> (event);
82                 if (e->key() == Qt::Key_Escape && e->modifiers() == Qt::NoModifier) {
83                         on_closePB_clicked();
84                         return true;
85                 } else if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) {
86                         if (e->modifiers() == Qt::ShiftModifier) {
87                                 on_findPrevPB_clicked();
88                                 return true;
89                         } else if (e->modifiers() == Qt::NoModifier) {
90                                 on_findNextPB_clicked();
91                                 return true;
92                         }
93                 }
94         }
95
96         // standard event processing
97         return QObject::eventFilter(obj, event);
98 }
99
100
101 void FindAndReplace::closeEvent(QCloseEvent * close_event)
102 {
103         LYXERR(Debug::DEBUG, "FindAndReplace::closeEvent()");
104         find_work_area_->removeEventFilter(this);
105         disableSearchWorkArea();
106
107         DockView::closeEvent(close_event);
108 }
109
110
111 void FindAndReplace::selectAll()
112 {
113         dispatch(FuncRequest(LFUN_BUFFER_BEGIN));
114         dispatch(FuncRequest(LFUN_BUFFER_END_SELECT));
115         find_work_area_->redraw();
116 }
117
118
119 void FindAndReplace::findAdv(bool casesensitive,
120                 bool matchword, bool backwards,
121                 bool expandmacros, bool ignoreformat)
122 {
123         docstring searchString;
124         if (! ignoreformat) {
125                 OutputParams runparams(&searchBuffer_->params().encoding());
126                 odocstringstream os;
127                 runparams.nice = true;
128                 runparams.flavor = OutputParams::LATEX;
129                 runparams.linelen = 80; //lyxrc.plaintext_linelen;
130                 // No side effect of file copying and image conversion
131                 runparams.dryrun = true;
132                 searchBuffer_->texrow().reset();
133 //              latexParagraphs(searchBuffer_, searchBuffer_.paragraphs(), os, searchBuffer_.texrow(), runparams);
134                 for (ParagraphList::const_iterator pit = searchBuffer_->paragraphs().begin(); pit != searchBuffer_->paragraphs().end(); ++pit) {
135                         TeXOnePar(*searchBuffer_, searchBuffer_->text(), pit, os, searchBuffer_->texrow(), runparams);
136                         lyxerr << "searchString up to here: " << to_utf8(os.str()) << std::endl;
137                 }
138                 searchString = os.str();
139         } else {
140                 for (ParIterator it = searchBuffer_->par_iterator_begin(); it != searchBuffer_->par_iterator_end(); ++it) {
141                         lyxerr << "Adding to search string: '" << to_utf8(it->asString(false)) << "'" << std::endl;
142                         searchString += it->asString(AS_STR_INSETS);
143                 }
144         }
145 //      lyxerr << "Searching for '" << to_utf8(searchString) << "'" << std::endl;
146         if (to_utf8(searchString).empty()) {
147                 searchBufferView_->message(_("Nothing to search"));
148                 return;
149         }
150         bool regexp = (to_utf8(searchString).find("\\regexp") != std::string::npos);
151         FindAdvOptions opt(searchString, casesensitive, matchword, ! backwards, expandmacros, ignoreformat, regexp);
152         std::cerr << "Dispatching LFUN_WORD_FINDADV" << std::endl;
153         std::ostringstream oss;
154         oss << opt;
155         std::cerr << "Dispatching LFUN_WORD_FINDADV" << std::endl;
156         dispatch(FuncRequest(LFUN_WORD_FINDADV, from_utf8(oss.str())));
157
158         //      findAdv(&theApp()->currentView()->currentWorkArea()->bufferView(),
159         //                      searchString, len, casesensitive, matchword, ! backwards, expandmacros);
160 }
161
162
163 void FindAndReplace::onDelayedFocus()
164 {
165         LYXERR(Debug::DEBUG, "Delayed Focus");
166         parent_view_.setCurrentWorkArea(find_work_area_);
167         find_work_area_->setFocus();
168 }
169
170
171 void FindAndReplace::showEvent(QShowEvent *ev)
172 {
173         LYXERR(Debug::DEBUG, "FindAndReplace::showEvent");
174         parent_view_.setCurrentWorkArea(find_work_area_);
175         selectAll();
176         find_work_area_->redraw();
177         find_work_area_->setFocus();
178         find_work_area_->installEventFilter(this);
179         connect(&delayedFocusTimer_, SIGNAL(timeout()), this, SLOT(onDelayedFocus()));
180         delayedFocusTimer_.setSingleShot(true);
181         delayedFocusTimer_.start(100);
182
183         this->QWidget::showEvent(ev);
184 }
185
186
187 void FindAndReplace::disableSearchWorkArea()
188 {
189         LYXERR(Debug::DEBUG, "FindAndReplace::disableSearchWorkArea()");
190         // Ok, closing the window before 100ms may be impossible, however...
191         delayedFocusTimer_.stop();
192         if (parent_view_.currentWorkArea() == find_work_area_) {
193                 LASSERT(parent_view_.currentMainWorkArea(), /* */);
194                 parent_view_.setCurrentWorkArea(parent_view_.currentMainWorkArea());
195         }
196         find_work_area_->stopBlinkingCursor();
197 }
198
199
200 void FindAndReplace::hideEvent(QHideEvent *ev)
201 {
202         LYXERR(Debug::DEBUG, "FindAndReplace::hideEvent");
203         find_work_area_->removeEventFilter(this);
204         disableSearchWorkArea();
205         this->QWidget::hideEvent(ev);
206 }
207
208
209 void FindAndReplace::find(bool backwards)
210 {
211         parent_view_.setCurrentWorkArea(parent_view_.currentMainWorkArea());
212         findAdv(caseCB->isChecked(),
213                         wordsCB->isChecked(),
214                         backwards,
215                         expandMacrosCB->isChecked(),
216                         ignoreFormatCB->isChecked());
217         parent_view_.currentMainWorkArea()->redraw();
218         parent_view_.setCurrentWorkArea(find_work_area_);
219         find_work_area_->setFocus();
220 }
221
222
223 void FindAndReplace::on_regexpInsertCombo_currentIndexChanged(int index)
224 {
225         static char const * regexps[] = {
226                 ".*", ".+", "[a-z]+", "[0-9]+"
227         };
228         //lyxerr << "Index: " << index << std::endl;
229         if (index >= 1 && index < 1 + int(sizeof(regexps)/sizeof(regexps[0]))) {
230                 find_work_area_->setFocus();
231                 Cursor & cur = find_work_area_->bufferView().cursor();
232                 if (! cur.inRegexped())
233                         dispatch(FuncRequest(LFUN_REGEXP_MODE));
234                 dispatch(FuncRequest(LFUN_SELF_INSERT, regexps[index - 1]));
235                 regexpInsertCombo->setCurrentIndex(0);
236         }
237 }
238
239
240 void FindAndReplace::on_closePB_clicked() {
241         disableSearchWorkArea();
242         LYXERR(Debug::DEBUG, "Dispatching dialog-hide findreplaceadv" << std::endl);
243         parent_view_.dispatch(FuncRequest(LFUN_DIALOG_TOGGLE, "findreplaceadv"));
244 }
245
246
247 void FindAndReplace::on_findNextPB_clicked() {
248         find(false);
249 }
250
251
252 void FindAndReplace::on_findPrevPB_clicked() {
253         find(true);
254 }
255
256
257 void FindAndReplace::on_replacePB_clicked()
258 {
259 }
260
261
262 void FindAndReplace::on_replaceallPB_clicked()
263 {
264 }
265
266 Dialog * createGuiSearchAdv(GuiView & lv)
267 {
268         return new FindAndReplace(lv);
269 }
270
271
272 } // namespace frontend
273 } // namespace lyx
274
275
276 #include "moc_FindAndReplace.cpp"