]> git.lyx.org Git - lyx.git/blob - src/frontends/qt/GuiSearch.cpp
Remove resolved FIXME
[lyx.git] / src / frontends / qt / GuiSearch.cpp
1 /**
2  * \file GuiSearch.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author John Levon
7  * \author Edwin Leuven
8  * \author Angus Leeming
9  *
10  * Full author contact details are available in file CREDITS.
11  */
12
13 #include <config.h>
14
15 #include "GuiSearch.h"
16
17 #include "lyxfind.h"
18 #include "qt_helpers.h"
19 #include "FuncRequest.h"
20 #include "LyX.h"
21 #include "BufferView.h"
22 #include "Buffer.h"
23 #include "Cursor.h"
24 #include "FuncRequest.h"
25 #include "KeyMap.h"
26 #include "GuiKeySymbol.h"
27 #include "GuiView.h"
28
29 #include "support/debug.h"
30 #include "support/gettext.h"
31 #include "frontends/alert.h"
32
33 #include <QLineEdit>
34 #include <QSettings>
35 #include <QShowEvent>
36 #include "QSizePolicy"
37
38 using namespace std;
39
40 using lyx::KeySymbol;
41
42 namespace lyx {
43 namespace frontend {
44
45 static void uniqueInsert(QComboBox * box, QString const & text)
46 {
47         for (int i = box->count(); --i >= 0; )
48                 if (box->itemText(i) == text)
49                         return;
50
51         box->insertItem(0, text);
52 }
53
54
55 GuiSearchWidget::GuiSearchWidget(QWidget * parent)
56         :       QWidget(parent)
57 {
58         setupUi(this);
59
60         // fix height to minimum
61         setFixedHeight(sizeHint().height());
62
63         // align items in grid on top
64         gridLayout->setAlignment(Qt::AlignTop);
65
66         connect(findPB, SIGNAL(clicked()), this, SLOT(findClicked()));
67         connect(findPrevPB, SIGNAL(clicked()), this, SLOT(findPrevClicked()));
68         connect(minimizePB, SIGNAL(clicked()), this, SLOT(minimizeClicked()));
69         connect(replacePB, SIGNAL(clicked()), this, SLOT(replaceClicked()));
70         connect(replacePrevPB, SIGNAL(clicked()), this, SLOT(replacePrevClicked()));
71         connect(replaceallPB, SIGNAL(clicked()), this, SLOT(replaceallClicked()));
72         connect(findCO, SIGNAL(editTextChanged(QString)),
73                 this, SLOT(findChanged()));
74
75         setFocusProxy(findCO);
76
77         findCO->setCompleter(nullptr);
78         replaceCO->setCompleter(nullptr);
79
80         replacePB->setEnabled(false);
81         replacePrevPB->setEnabled(false);
82         replaceallPB->setEnabled(false);
83 }
84
85
86 void GuiSearchWidget::keyPressEvent(QKeyEvent * ev)
87 {
88         KeySymbol sym;
89         setKeySymbol(&sym, ev);
90
91         // catch Return and Shift-Return
92         if (ev->key() == Qt::Key_Return) {
93                 findClicked(ev->modifiers() == Qt::ShiftModifier);
94                 return;
95         }
96
97         // we catch the key sequences for forward and backwards search
98         if (sym.isOK()) {
99                 KeyModifier mod = lyx::q_key_state(ev->modifiers());
100                 KeySequence keyseq(&theTopLevelKeymap(), &theTopLevelKeymap());
101                 FuncRequest fr = keyseq.addkey(sym, mod);
102                 if (fr == FuncRequest(LFUN_WORD_FIND_FORWARD) || fr == FuncRequest(LFUN_WORD_FIND)) {
103                         findClicked();
104                         return;
105                 }
106                 if (fr == FuncRequest(LFUN_WORD_FIND_BACKWARD)) {
107                         findClicked(true);
108                         return;
109                 }
110                 if (fr == FuncRequest(LFUN_DIALOG_TOGGLE, "findreplace")) {
111                         dispatch(fr);
112                         return;
113                 }
114         }
115         QWidget::keyPressEvent(ev);
116 }
117
118
119 void GuiSearchWidget::minimizeClicked(bool const toggle)
120 {
121         if (toggle)
122                 minimized_ = !minimized_;
123
124         replaceLA->setHidden(minimized_);
125         replaceCO->setHidden(minimized_);
126         replacePB->setHidden(minimized_);
127         replacePrevPB->setHidden(minimized_);
128         replaceallPB->setHidden(minimized_);
129         CBFrame->setHidden(minimized_);
130         if (minimized_) {
131                 minimizePB->setText(qt_("Ex&pand"));
132                 minimizePB->setToolTip("Show replace and option widgets");
133         } else {
134                 minimizePB->setText(qt_("&Minimize"));
135                 minimizePB->setToolTip("Hide replace and option widgets");
136         }
137
138         Q_EMIT needSizeUpdate();
139         Q_EMIT needTitleBarUpdate();
140 }
141
142
143 void GuiSearchWidget::showEvent(QShowEvent * e)
144 {
145         findChanged();
146         findPB->setFocus();
147         findCO->lineEdit()->selectAll();
148         QWidget::showEvent(e);
149 }
150
151
152 void GuiSearchWidget::findChanged()
153 {
154         findPB->setEnabled(!findCO->currentText().isEmpty());
155         findPrevPB->setEnabled(!findCO->currentText().isEmpty());
156         bool const replace = !findCO->currentText().isEmpty()
157                         && bv_ && !bv_->buffer().isReadonly();
158         replacePB->setEnabled(replace);
159         replacePrevPB->setEnabled(replace);
160         replaceallPB->setEnabled(replace);
161         replaceLA->setEnabled(replace);
162         replaceCO->setEnabled(replace);
163 }
164
165
166 void GuiSearchWidget::findClicked(bool const backwards)
167 {
168         docstring const needle = qstring_to_ucs4(findCO->currentText());
169         find(needle, caseCB->isChecked(), wordsCB->isChecked(), !backwards);
170         uniqueInsert(findCO, findCO->currentText());
171         findCO->lineEdit()->selectAll();
172 }
173
174
175 void GuiSearchWidget::findPrevClicked()
176 {
177         findClicked(true);
178 }
179
180
181 void GuiSearchWidget::replaceClicked(bool const backwards)
182 {
183         docstring const needle = qstring_to_ucs4(findCO->currentText());
184         docstring const repl = qstring_to_ucs4(replaceCO->currentText());
185         replace(needle, repl, caseCB->isChecked(), wordsCB->isChecked(),
186                 !backwards, false);
187         uniqueInsert(findCO, findCO->currentText());
188         uniqueInsert(replaceCO, replaceCO->currentText());
189 }
190
191
192 void GuiSearchWidget::replacePrevClicked()
193 {
194         replaceClicked(true);
195 }
196
197
198 void GuiSearchWidget::replaceallClicked()
199 {
200         replace(qstring_to_ucs4(findCO->currentText()),
201                 qstring_to_ucs4(replaceCO->currentText()),
202                 caseCB->isChecked(), wordsCB->isChecked(), true, true);
203         uniqueInsert(findCO, findCO->currentText());
204         uniqueInsert(replaceCO, replaceCO->currentText());
205 }
206
207
208 void GuiSearchWidget::find(docstring const & search, bool casesensitive,
209                          bool matchword, bool forward)
210 {
211         docstring const sdata =
212                 find2string(search, casesensitive, matchword, forward);
213         dispatch(FuncRequest(LFUN_WORD_FIND, sdata));
214 }
215
216
217 void GuiSearchWidget::replace(docstring const & search, docstring const & replace,
218                             bool casesensitive, bool matchword,
219                             bool forward, bool all)
220 {
221         docstring const sdata =
222                 replace2string(replace, search, casesensitive,
223                                      matchword, all, forward);
224         dispatch(FuncRequest(LFUN_WORD_REPLACE, sdata));
225 }
226
227 void GuiSearchWidget::saveSession(QSettings & settings, QString const & session_key) const
228 {
229         settings.setValue(session_key + "/casesensitive", caseCB->isChecked());
230         settings.setValue(session_key + "/words", wordsCB->isChecked());
231         settings.setValue(session_key + "/minimized", minimized_);
232 }
233
234
235 void GuiSearchWidget::restoreSession(QString const & session_key)
236 {
237         QSettings settings;
238         caseCB->setChecked(settings.value(session_key + "/casesensitive", false).toBool());
239         wordsCB->setChecked(settings.value(session_key + "/words", false).toBool());
240         minimized_ = settings.value(session_key + "/minimized", false).toBool();
241         // initialize hidings
242         minimizeClicked(false);
243 }
244
245
246 GuiSearch::GuiSearch(GuiView & parent, Qt::DockWidgetArea area, Qt::WindowFlags flags)
247         : DockView(parent, "findreplace", qt_("Search and Replace"), area, flags),
248           widget_(new GuiSearchWidget(this))
249 {
250         setWidget(widget_);
251         widget_->setBufferView(bufferview());
252         setFocusProxy(widget_->findCO);
253
254         connect(widget_, SIGNAL(needTitleBarUpdate()), this, SLOT(updateTitle()));
255         connect(widget_, SIGNAL(needSizeUpdate()), this, SLOT(updateSize()));
256 }
257
258 void GuiSearch::onBufferViewChanged()
259 {
260         widget_->setEnabled((bool)bufferview());
261         widget_->setBufferView(bufferview());
262 }
263
264
265 void GuiSearch::updateView()
266 {
267         updateTitle();
268         updateSize();
269 }
270
271
272 void GuiSearch::saveSession(QSettings & settings) const
273 {
274         Dialog::saveSession(settings);
275         widget_->saveSession(settings, sessionKey());
276 }
277
278
279 void GuiSearch::restoreSession()
280 {
281         DockView::restoreSession();
282         widget_->restoreSession(sessionKey());
283 }
284
285
286 void GuiSearch::updateTitle()
287 {
288         if (widget_->isMinimized()) {
289                 // remove title bar
290                 setTitleBarWidget(new QWidget());
291                 titleBarWidget()->hide();
292         } else
293                 // restore title bar
294                 setTitleBarWidget(nullptr);
295 }
296
297
298 void GuiSearch::updateSize()
299 {
300         widget_->setFixedHeight(widget_->sizeHint().height());
301         if (widget_->isMinimized())
302                 setFixedHeight(widget_->sizeHint().height());
303         else {
304                 // undo setFixedHeight
305                 setMaximumHeight(QWIDGETSIZE_MAX);
306                 setMinimumHeight(0);
307         }
308         update();
309 }
310
311
312 } // namespace frontend
313 } // namespace lyx
314
315
316 #include "moc_GuiSearch.cpp"