]> git.lyx.org Git - lyx.git/blob - src/frontends/qt/GuiSearch.cpp
GuiSearch: catch global shortcuts to find forwards/backwards (#11170)
[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 "BufferView.h"
21 #include "Buffer.h"
22 #include "Cursor.h"
23 #include "FuncRequest.h"
24 #include "KeyMap.h"
25 #include "GuiKeySymbol.h"
26 #include "GuiView.h"
27
28 #include "support/gettext.h"
29 #include "frontends/alert.h"
30
31 #include <QLineEdit>
32 #include <QShowEvent>
33
34 using namespace std;
35
36 using lyx::KeySymbol;
37
38 namespace lyx {
39 namespace frontend {
40
41 static void uniqueInsert(QComboBox * box, QString const & text)
42 {
43         for (int i = box->count(); --i >= 0; )
44                 if (box->itemText(i) == text)
45                         return;
46
47         box->insertItem(0, text);
48 }
49
50
51 GuiSearch::GuiSearch(GuiView & lv)
52         : GuiDialog(lv, "findreplace", qt_("Find and Replace"))
53 {
54         setupUi(this);
55
56         // fix height to minimum
57         setFixedHeight(sizeHint().height());
58
59         // align items in grid on top
60         mainGridLayout->setAlignment(Qt::AlignTop);
61
62         connect(buttonBox, SIGNAL(clicked(QAbstractButton *)),
63                 this, SLOT(slotButtonBox(QAbstractButton *)));
64         connect(findPB, SIGNAL(clicked()), this, SLOT(findClicked()));
65         connect(replacePB, SIGNAL(clicked()), this, SLOT(replaceClicked()));
66         connect(replaceallPB, SIGNAL(clicked()), this, SLOT(replaceallClicked()));
67         connect(findCO, SIGNAL(editTextChanged(QString)),
68                 this, SLOT(findChanged()));
69
70         setFocusProxy(findCO);
71
72         bc().setPolicy(ButtonPolicy::NoRepeatedApplyReadOnlyPolicy);
73         bc().setCancel(buttonBox->button(QDialogButtonBox::Close));
74
75         findCO->setCompleter(0);
76         replaceCO->setCompleter(0);
77
78         replacePB->setEnabled(false);
79         replaceallPB->setEnabled(false);
80 }
81
82
83 void GuiSearch::keyPressEvent(QKeyEvent * ev)
84 {
85         KeySymbol sym;
86         setKeySymbol(&sym, ev);
87
88         // we catch the key sequences for forward and backwards search
89         if (sym.isOK()) {
90                 KeyModifier mod = lyx::q_key_state(ev->modifiers());
91                 KeySequence keyseq(&theTopLevelKeymap(), &theTopLevelKeymap());
92                 FuncRequest fr = keyseq.addkey(sym, mod);
93                 if (fr == FuncRequest(LFUN_WORD_FIND_FORWARD) || fr == FuncRequest(LFUN_WORD_FIND)) {
94                         findClicked();
95                         return;
96                 }
97                 if (fr == FuncRequest(LFUN_WORD_FIND_BACKWARD)) {
98                         findClicked(true);
99                         return;
100                 }
101         }
102         QDialog::keyPressEvent(ev);
103 }
104
105
106 void GuiSearch::showEvent(QShowEvent * e)
107 {
108         findChanged();
109         findPB->setFocus();
110         findCO->lineEdit()->selectAll();
111         GuiDialog::showEvent(e);
112 }
113
114
115 void GuiSearch::findChanged()
116 {
117         findPB->setEnabled(!findCO->currentText().isEmpty());
118         bool const replace = !findCO->currentText().isEmpty() && !isBufferReadonly();
119         replacePB->setEnabled(replace);
120         replaceallPB->setEnabled(replace);
121         replaceLA->setEnabled(replace);
122         replaceCO->setEnabled(replace);
123 }
124
125
126 void GuiSearch::findClicked(bool const backwards)
127 {
128         docstring const needle = qstring_to_ucs4(findCO->currentText());
129         find(needle, caseCB->isChecked(), wordsCB->isChecked(),
130                 (!backwards && !backwardsCB->isChecked()));
131         uniqueInsert(findCO, findCO->currentText());
132         findCO->lineEdit()->selectAll();
133 }
134
135
136 void GuiSearch::replaceClicked()
137 {
138         docstring const needle = qstring_to_ucs4(findCO->currentText());
139         docstring const repl = qstring_to_ucs4(replaceCO->currentText());
140         replace(needle, repl, caseCB->isChecked(), wordsCB->isChecked(),
141                 !backwardsCB->isChecked(), false);
142         uniqueInsert(findCO, findCO->currentText());
143         uniqueInsert(replaceCO, replaceCO->currentText());
144 }
145
146
147 void GuiSearch::replaceallClicked()
148 {
149         replace(qstring_to_ucs4(findCO->currentText()),
150                 qstring_to_ucs4(replaceCO->currentText()),
151                 caseCB->isChecked(), wordsCB->isChecked(), true, true);
152         uniqueInsert(findCO, findCO->currentText());
153         uniqueInsert(replaceCO, replaceCO->currentText());
154 }
155
156
157 void GuiSearch::find(docstring const & search, bool casesensitive,
158                          bool matchword, bool forward)
159 {
160         docstring const sdata =
161                 find2string(search, casesensitive, matchword, forward);
162         dispatch(FuncRequest(LFUN_WORD_FIND, sdata));
163 }
164
165
166 void GuiSearch::replace(docstring const & search, docstring const & replace,
167                             bool casesensitive, bool matchword,
168                             bool forward, bool all)
169 {
170         docstring const sdata =
171                 replace2string(replace, search, casesensitive,
172                                      matchword, all, forward);
173         dispatch(FuncRequest(LFUN_WORD_REPLACE, sdata));
174 }
175
176
177 } // namespace frontend
178 } // namespace lyx
179
180
181 #include "moc_GuiSearch.cpp"