]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/GuiThesaurus.cpp
Support for command argument placement after the workarea argument
[lyx.git] / src / frontends / qt4 / GuiThesaurus.cpp
1 /**
2  * \file GuiThesaurus.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 Jürgen Spitzmüller
8  *
9  * Full author contact details are available in file CREDITS.
10  */
11
12 #include <config.h>
13
14 #include "GuiThesaurus.h"
15 #include "GuiApplication.h"
16
17 #include "qt_helpers.h"
18
19 #include "Buffer.h"
20 #include "BufferParams.h"
21 #include "BufferView.h"
22 #include "FuncRequest.h"
23 #include "Language.h"
24 #include "lyxfind.h"
25 #include "WordLangTuple.h"
26
27 #include "support/debug.h"
28 #include "support/gettext.h"
29 #include "support/lstrings.h"
30
31 #include <QAbstractItemModel>
32 #include <QCompleter>
33 #include <QHeaderView>
34 #include <QLineEdit>
35 #include <QPushButton>
36 #include <QTreeWidget>
37 #include <QTreeWidgetItem>
38
39
40 using namespace lyx::support;
41 using namespace std;
42
43 namespace lyx {
44 namespace frontend {
45
46 GuiThesaurus::GuiThesaurus(GuiView & lv)
47         : GuiDialog(lv, "thesaurus", qt_("Thesaurus"))
48 {
49         setupUi(this);
50
51         meaningsTV->setColumnCount(1);
52         meaningsTV->header()->hide();
53
54         connect(closePB, SIGNAL(clicked()),
55                 this, SLOT(slotClose()));
56         connect(replaceED, SIGNAL(returnPressed()),
57                 this, SLOT(replaceClicked()));
58         connect(replaceED, SIGNAL(textChanged(QString)),
59                 this, SLOT(change_adaptor()));
60         connect(entryCO, SIGNAL(editTextChanged(const QString &)),
61                 this, SLOT(entryChanged()));
62         connect(entryCO, SIGNAL(activated(int)),
63                 this, SLOT(entryChanged()));
64         connect(lookupPB, SIGNAL(clicked()),
65                 this, SLOT(entryChanged()));
66         connect(replacePB, SIGNAL(clicked()),
67                 this, SLOT(replaceClicked()));
68         connect(languageCO, SIGNAL(activated(int)),
69                 this, SLOT(entryChanged()));
70         connect(meaningsTV, SIGNAL(itemClicked(QTreeWidgetItem *, int)),
71                 this, SLOT(itemClicked(QTreeWidgetItem *, int)));
72         connect(meaningsTV, SIGNAL(itemSelectionChanged()),
73                 this, SLOT(selectionChanged()));
74         connect(meaningsTV, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)),
75                 this, SLOT(selectionClicked(QTreeWidgetItem *, int)));
76
77         // language
78         QAbstractItemModel * language_model = guiApp->languageModel();
79         // FIXME: it would be nice if sorting was enabled/disabled via a checkbox.
80         language_model->sort(0);
81         languageCO->setModel(language_model);
82         languageCO->setModelColumn(2);
83
84         //bug #8138
85         if (entryCO->completer())
86                 entryCO->completer()->setCompletionMode(QCompleter::PopupCompletion);
87
88         bc().setCancel(closePB);
89         bc().setApply(replacePB);
90         bc().addReadOnly(replaceED);
91         bc().addReadOnly(replacePB);
92         bc().setPolicy(ButtonPolicy::OkApplyCancelReadOnlyPolicy);
93 }
94
95 void GuiThesaurus::checkStatus()
96 {
97         if (!isBufferAvailable()) {
98                 // deactivate the thesaurus if we have no buffer
99                 enableView(false);
100                 return;
101         }
102         updateView();
103 }
104         
105 void GuiThesaurus::change_adaptor()
106 {
107         changed();
108 }
109
110
111 void GuiThesaurus::entryChanged()
112 {
113         updateLists();
114 }
115
116
117 void GuiThesaurus::selectionChanged()
118 {
119         int const col = meaningsTV->currentColumn();
120         if (col < 0 || isBufferReadonly())
121                 return;
122
123         QString item = meaningsTV->currentItem()->text(col);
124         // cut out the classification in brackets:
125         // "hominid (generic term)" -> "hominid"
126         QRegExp re("^([^\\(\\)]+)\\b\\(?.*\\)?.*$");
127         // This is for items with classifications at the beginning:
128         // "(noun) man" -> "man"; "(noun) male (generic term)" -> "male"
129         QRegExp rex("^(\\(.+\\))\\s*([^\\(\\)]+)\\s*\\(?.*\\)?.*$");
130         int pos = re.indexIn(item);
131         if (pos > -1)
132                 item = re.cap(1).trimmed();
133         pos = rex.indexIn(item);
134         if (pos > -1)
135                 item = rex.cap(2).trimmed();
136         replaceED->setText(item);
137         replacePB->setEnabled(!isBufferReadonly());
138         changed();
139 }
140
141
142 void GuiThesaurus::itemClicked(QTreeWidgetItem * /*item*/, int /*col*/)
143 {
144         selectionChanged();
145 }
146
147
148 void GuiThesaurus::selectionClicked(QTreeWidgetItem * item, int col)
149 {
150         QString str = item->text(col);
151         // cut out the classification in brackets:
152         // "hominid (generic term)" -> "hominid"
153         QRegExp re("^([^\\(\\)]+)\\b\\(?.*\\)?.*$");
154         // This is for items with classifications at the beginning:
155         // "(noun) man" -> "man"; "(noun) male (generic term)" -> "male"
156         QRegExp rex("^(\\(.+\\))\\s*([^\\(\\)]+)\\s*\\(?.*\\)?.*$");
157         int pos = re.indexIn(str);
158         if (pos > -1)
159                 str = re.cap(1).trimmed();
160         pos = rex.indexIn(str);
161         if (pos > -1)
162                 str = rex.cap(2).trimmed();
163         entryCO->insertItem(0, str);
164         entryCO->setCurrentIndex(0);
165
166         selectionChanged();
167         updateLists();
168 }
169
170
171 void GuiThesaurus::updateLists()
172 {
173         meaningsTV->clear();
174
175         if (entryCO->currentText().isEmpty())
176                 return;
177
178         meaningsTV->setUpdatesEnabled(false);
179
180         QString const lang = languageCO->itemData(
181                 languageCO->currentIndex()).toString();
182         Language * language = const_cast<Language*>(lyx::languages.getLanguage(fromqstr(lang)));
183         docstring const lang_code = from_ascii(language->code());
184
185         Thesaurus::Meanings meanings =
186                 getMeanings(WordLangTuple(qstring_to_ucs4(entryCO->currentText()), language));
187
188         for (Thesaurus::Meanings::const_iterator cit = meanings.begin();
189                 cit != meanings.end(); ++cit) {
190                 QTreeWidgetItem * i = new QTreeWidgetItem(meaningsTV);
191                 i->setText(0, toqstr(cit->first));
192                 meaningsTV->expandItem(i);
193                 for (vector<docstring>::const_iterator cit2 = cit->second.begin();
194                         cit2 != cit->second.end(); ++cit2) {
195                                 QTreeWidgetItem * i2 = new QTreeWidgetItem(i);
196                                 i2->setText(0, toqstr(*cit2));
197                         }
198                 meaningsTV->setEnabled(true);
199                 lookupPB->setEnabled(true);
200                 bool const readonly = isBufferReadonly();
201                 replaceED->setEnabled(!readonly);
202                 replacePB->setEnabled(!readonly);
203         }
204
205         if (meanings.empty()) {
206                 if (!thesaurus.thesaurusAvailable(lang_code)) {
207                         QTreeWidgetItem * i = new QTreeWidgetItem(meaningsTV);
208                         i->setText(0, qt_("No thesaurus available for this language!"));
209                         meaningsTV->setEnabled(false);
210                         lookupPB->setEnabled(false);
211                         replaceED->setEnabled(false);
212                         replacePB->setEnabled(false);
213                 }
214         }
215
216         meaningsTV->setUpdatesEnabled(true);
217         meaningsTV->update();
218 }
219
220
221 void GuiThesaurus::updateContents()
222 {
223         entryCO->clear();
224         entryCO->addItem(toqstr(text_));
225         entryCO->setCurrentIndex(0);
226         replaceED->setText("");
227         int const pos = languageCO->findData(toqstr(lang_));
228         if (pos != -1)
229                 languageCO->setCurrentIndex(pos);
230         updateLists();
231 }
232
233
234 void GuiThesaurus::replaceClicked()
235 {
236         replace(qstring_to_ucs4(replaceED->text()));
237 }
238
239
240 bool GuiThesaurus::initialiseParams(string const & data)
241 {
242         string arg;
243         string const lang = rsplit(data, arg, ' ');
244         if (prefixIs(lang, "lang=")) {
245                 lang_ = from_utf8(split(lang, '='));
246                 text_ = from_utf8(arg);
247         } else {
248                 text_ = from_utf8(data);
249                 if (bufferview())
250                         lang_ = from_ascii(
251                                 bufferview()->buffer().params().language->lang());
252         }
253         return true;
254 }
255
256
257 void GuiThesaurus::clearParams()
258 {
259         text_.erase();
260         lang_.erase();
261 }
262
263
264 void GuiThesaurus::replace(docstring const & newstr)
265 {
266         /* FIXME: this is not suitable ! We need to have a "lock"
267          * on a particular charpos in a paragraph that is broken on
268          * deletion/change !
269          */
270         docstring const data =
271                 replace2string(newstr, text_,
272                                      true,  // case sensitive
273                                      true,  // match word
274                                      false, // all words
275                                      true); // forward
276         dispatch(FuncRequest(LFUN_WORD_REPLACE, data));
277 }
278
279
280 Thesaurus::Meanings const & GuiThesaurus::getMeanings(WordLangTuple const & wl)
281 {
282         if (wl.word() != laststr_)
283                 meanings_ = thesaurus.lookup(wl);
284         return meanings_;
285 }
286
287
288 Dialog * createGuiThesaurus(GuiView & lv) { return new GuiThesaurus(lv); }
289
290
291 } // namespace frontend
292 } // namespace lyx
293
294
295 #include "moc_GuiThesaurus.cpp"