]> git.lyx.org Git - features.git/blob - src/frontends/qt4/GuiCitationDialog.cpp
Merge QController into individual dialogs. Also various cleanup
[features.git] / src / frontends / qt4 / GuiCitationDialog.cpp
1 /**
2  * \file GuiCitationDialog.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Kalle Dalheimer
7  * \author John Levon
8  * \author Jürgen Spitzmüller
9  * \author Abdelrazak Younes
10  * \author Richard Heck
11  *
12  * Full author contact details are available in file CREDITS.
13  */
14
15 #include <config.h>
16
17 #include "GuiCitationDialog.h"
18
19 #include "GuiCitation.h"
20
21 #include "frontends/controllers/frontend_helpers.h"
22 #include "frontends/controllers/ControlCitation.h"
23 #include "qt_helpers.h"
24
25 #include "support/docstring.h"
26
27 #include "debug.h"
28 #include "gettext.h"
29
30 #include <algorithm>
31 #include <vector>
32 #include <string>
33
34 #include <QCloseEvent>
35 #include <QKeyEvent>
36
37 #undef KeyPress
38
39 using std::vector;
40 using std::string;
41
42 namespace lyx {
43 namespace frontend {
44
45
46 GuiCitationDialog::GuiCitationDialog(Dialog & dialog, GuiCitation * form)
47         : Dialog::View(dialog, _("Citation")), form_(form)
48 {
49         setupUi(this);
50
51         setWindowTitle(toqstr("LyX: " + getTitle()));
52
53         connect(citationStyleCO, SIGNAL(activated(int)),
54                 this, SLOT(changed()));
55         connect(fulllistCB, SIGNAL(clicked()),
56                 this, SLOT(changed()));
57         connect(forceuppercaseCB, SIGNAL(clicked()),
58                 this, SLOT(changed()));
59         connect(textBeforeED, SIGNAL(textChanged(const QString&)),
60                 this, SLOT(changed()));
61         connect(textAfterED, SIGNAL(textChanged(const QString&)),
62                 this, SLOT(changed()));
63         connect(clearPB, SIGNAL(clicked()),
64                 findLE, SLOT(clear()));
65         connect(this, SIGNAL(rejected()), this, SLOT(cleanUp()));
66
67         selectionManager = 
68                 new GuiSelectionManager(availableLV, selectedLV, 
69                                       addPB, deletePB, upPB, downPB, 
70                                       form_->available(), form_->selected());
71         connect(selectionManager, SIGNAL(selectionChanged()),
72                 this, SLOT(setCitedKeys()));
73         connect(selectionManager, SIGNAL(updateHook()),
74                 this, SLOT(updateDialog()));
75         connect(selectionManager, SIGNAL(okHook()),
76                                         this, SLOT(on_okPB_clicked()));
77
78 }
79
80
81 GuiCitationDialog::~GuiCitationDialog()
82 {}
83
84
85 void GuiCitationDialog::cleanUp() 
86 {
87         form_->clearSelection();
88         form_->clearParams();
89         close();
90 }
91
92
93 void GuiCitationDialog::closeEvent(QCloseEvent * e)
94 {
95         form_->clearSelection();
96         form_->clearParams();
97         e->accept();
98 }
99
100
101 void GuiCitationDialog::apply()
102 {
103         int  const choice = std::max(0, citationStyleCO->currentIndex());
104         style_ = choice;
105         bool const full  = fulllistCB->isChecked();
106         bool const force = forceuppercaseCB->isChecked();
107
108         QString const before = textBeforeED->text();
109         QString const after = textAfterED->text();
110
111         form_->apply(choice, full, force, before, after);
112 }
113
114
115 void GuiCitationDialog::hide()
116 {
117         form_->clearParams();
118         accept();
119 }
120
121
122 void GuiCitationDialog::show()
123 {
124         findLE->clear();
125         availableLV->setFocus();
126         QDialog::show();
127         raise();
128         activateWindow();
129 }
130
131
132 bool GuiCitationDialog::isVisible() const
133 {
134         return QDialog::isVisible();
135 }
136
137
138 void GuiCitationDialog::on_okPB_clicked()
139 {
140         apply();
141         form_->clearSelection();
142         hide();
143 }
144
145
146 void GuiCitationDialog::on_cancelPB_clicked()
147 {
148         form_->clearSelection();
149         hide();
150 }
151
152
153 void GuiCitationDialog::on_applyPB_clicked()
154 {
155         apply();
156 }
157
158
159 void GuiCitationDialog::on_restorePB_clicked()
160 {
161         form_->init();
162         update();
163 }
164
165
166 void GuiCitationDialog::update()
167 {
168         fillFields();
169         fillEntries();
170         updateDialog();
171 }
172
173
174 //The main point of separating this out is that the fill*() methods
175 //called in update() do not need to be called for INTERNAL updates,
176 //such as when addPB is pressed, as the list of fields, entries, etc,
177 //will not have changed. At the moment, however, the division between
178 //fillStyles() and updateStyles() doesn't lend itself to dividing the
179 //two methods, though they should be divisible.
180 void GuiCitationDialog::updateDialog()
181 {
182         if (selectionManager->selectedFocused()) { 
183                 if (selectedLV->selectionModel()->selectedIndexes().isEmpty())
184                         updateInfo(availableLV->currentIndex());
185                 else
186                         updateInfo(selectedLV->currentIndex());
187         } else {
188                 if (availableLV->selectionModel()->selectedIndexes().isEmpty())
189                         updateInfo(QModelIndex());
190                 else
191                         updateInfo(availableLV->currentIndex());
192         }
193         setButtons();
194
195         textBeforeED->setText(form_->textBefore());
196         textAfterED->setText(form_->textAfter());
197         fillStyles();
198         updateStyle();
199 }
200
201
202 void GuiCitationDialog::updateStyle()
203 {
204         biblio::CiteEngine const engine = form_->getEngine();
205         bool const natbib_engine =
206                 engine == biblio::ENGINE_NATBIB_AUTHORYEAR ||
207                 engine == biblio::ENGINE_NATBIB_NUMERICAL;
208         bool const basic_engine = engine == biblio::ENGINE_BASIC;
209
210         bool const haveSelection = 
211                 selectedLV->model()->rowCount() > 0;
212         fulllistCB->setEnabled(natbib_engine && haveSelection);
213         forceuppercaseCB->setEnabled(natbib_engine && haveSelection);
214         textBeforeED->setEnabled(!basic_engine && haveSelection);
215         textBeforeLA->setEnabled(!basic_engine && haveSelection);
216         textAfterED->setEnabled(haveSelection);
217         textAfterLA->setEnabled(haveSelection);
218         citationStyleCO->setEnabled(!basic_engine && haveSelection);
219         citationStyleLA->setEnabled(!basic_engine && haveSelection);
220
221         string const & command = form_->params().getCmdName();
222
223         // Find the style of the citekeys
224         vector<biblio::CiteStyle> const & styles =
225                 ControlCitation::getCiteStyles();
226         biblio::CitationStyle const cs(command);
227
228         vector<biblio::CiteStyle>::const_iterator cit =
229                 std::find(styles.begin(), styles.end(), cs.style);
230
231         // restore the latest natbib style
232         if (style_ >= 0 && style_ < citationStyleCO->count())
233                 citationStyleCO->setCurrentIndex(style_);
234         else
235                 citationStyleCO->setCurrentIndex(0);
236
237         if (cit != styles.end()) {
238                 int const i = int(cit - styles.begin());
239                 citationStyleCO->setCurrentIndex(i);
240                 fulllistCB->setChecked(cs.full);
241                 forceuppercaseCB->setChecked(cs.forceUCase);
242         } else {
243                 fulllistCB->setChecked(false);
244                 forceuppercaseCB->setChecked(false);
245         }
246 }
247
248
249 //This one needs to be called whenever citationStyleCO needs
250 //to be updated---and this would be on anything that changes the
251 //selection in selectedLV, or on a general update.
252 void GuiCitationDialog::fillStyles()
253 {
254         int const oldIndex = citationStyleCO->currentIndex();
255
256         citationStyleCO->clear();
257
258         QStringList selected_keys = form_->selected()->stringList();
259         if (selected_keys.empty()) {
260                 citationStyleCO->setEnabled(false);
261                 citationStyleLA->setEnabled(false);
262                 return;
263         }
264
265         int curr = selectedLV->model()->rowCount() - 1;
266         if (curr < 0)
267                 return;
268
269         if (!selectedLV->selectionModel()->selectedIndexes().empty())
270                 curr = selectedLV->selectionModel()->selectedIndexes()[0].row();
271
272         QStringList sty = form_->citationStyles(curr);
273
274         bool const basic_engine =
275                         (form_->getEngine() == biblio::ENGINE_BASIC);
276
277         citationStyleCO->setEnabled(!sty.isEmpty() && !basic_engine);
278         citationStyleLA->setEnabled(!sty.isEmpty() && !basic_engine);
279
280         if (sty.isEmpty() || basic_engine)
281                 return;
282
283         citationStyleCO->insertItems(0, sty);
284
285         if (oldIndex != -1 && oldIndex < citationStyleCO->count())
286                 citationStyleCO->setCurrentIndex(oldIndex);
287 }
288
289
290 void GuiCitationDialog::fillFields()
291 {
292         fieldsCO->blockSignals(true);
293         int const oldIndex = fieldsCO->currentIndex();
294         fieldsCO->clear();
295         QStringList const & fields = form_->getFieldsAsQStringList();
296         fieldsCO->insertItem(0, qt_("All Fields"));
297         fieldsCO->insertItem(1, qt_("Keys"));
298         fieldsCO->insertItems(2, fields);
299         if (oldIndex != -1 && oldIndex < fieldsCO->count())
300                 fieldsCO->setCurrentIndex(oldIndex);
301         fieldsCO->blockSignals(false);
302 }
303
304
305 void GuiCitationDialog::fillEntries()
306 {
307         entriesCO->blockSignals(true);
308         int const oldIndex = entriesCO->currentIndex();
309         entriesCO->clear();
310         QStringList const & entries = form_->getEntriesAsQStringList();
311         entriesCO->insertItem(0, qt_("All Entry Types"));
312         entriesCO->insertItems(1, entries);
313         if (oldIndex != -1 && oldIndex < entriesCO->count())
314                 entriesCO->setCurrentIndex(oldIndex);
315         entriesCO->blockSignals(false);
316 }
317
318
319 bool GuiCitationDialog::isSelected(const QModelIndex & idx)
320 {
321         QString const str = idx.data().toString();
322         return form_->selected()->stringList().contains(str);
323 }
324
325
326 void GuiCitationDialog::setButtons()
327 {
328         selectionManager->update();
329         int const srows = selectedLV->model()->rowCount();
330         applyPB->setEnabled(srows > 0);
331         okPB->setEnabled(srows > 0);
332 }
333
334
335 void GuiCitationDialog::updateInfo(QModelIndex const & idx)
336 {
337         if (idx.isValid()) {
338                 QString const keytxt = form_->getKeyInfo(idx.data().toString());
339                 infoML->document()->setPlainText(keytxt);
340         } else
341                 infoML->document()->clear();
342 }
343
344
345 void GuiCitationDialog::setCitedKeys() 
346 {
347         form_->setCitedKeys();
348 }
349
350
351 void GuiCitationDialog::findText(QString const & text, bool reset)
352 {
353         //"All Fields" and "Keys" are the first two
354         int index = fieldsCO->currentIndex() - 2; 
355         vector<docstring> const & fields = form_->availableFields();
356         docstring field;
357         
358         if (index <= -1 || index >= int(fields.size()))
359                 //either "All Fields" or "Keys" or an invalid value
360                 field = from_ascii("");
361         else
362                 field = fields[index];
363         
364         //Was it "Keys"?
365         bool const onlyKeys = index == -1;
366         
367         //"All Entry Types" is first.
368         index = entriesCO->currentIndex() - 1; 
369         vector<docstring> const & entries = form_->availableEntries();
370         docstring entryType;
371         if (index < 0 || index >= int(entries.size()))
372                 entryType = from_ascii("");
373         else 
374                 entryType = entries[index];
375         
376         bool const case_sentitive = caseCB->checkState();
377         bool const reg_exp = regexCB->checkState();
378         form_->findKey(text, onlyKeys, field, entryType, 
379                        case_sentitive, reg_exp, reset);
380         //FIXME
381         //It'd be nice to save and restore the current selection in 
382         //availableLV. Currently, we get an automatic reset, since the
383         //model is reset.
384         
385         updateDialog();
386 }
387
388
389 void GuiCitationDialog::on_fieldsCO_currentIndexChanged(int /*index*/)
390 {
391         findText(findLE->text(), true);
392 }
393
394
395 void GuiCitationDialog::on_entriesCO_currentIndexChanged(int /*index*/)
396 {
397         findText(findLE->text(), true);
398 }
399
400
401 void GuiCitationDialog::on_findLE_textChanged(const QString & text)
402 {
403         clearPB->setDisabled(text.isEmpty());
404         if (text.isEmpty())
405                 findLE->setFocus();
406         findText(text);
407 }
408
409
410 void GuiCitationDialog::on_caseCB_stateChanged(int)
411 {
412         findText(findLE->text());
413 }
414
415
416 void GuiCitationDialog::on_regexCB_stateChanged(int)
417 {
418         findText(findLE->text());
419 }
420
421
422 void GuiCitationDialog::changed()
423 {
424         fillStyles();
425         setButtons();
426 }
427
428
429 } // namespace frontend
430 } // namespace lyx
431
432 #include "GuiCitationDialog_moc.cpp"