]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/QCitationDialog.cpp
Fix minor bug involving overlapping citation strings.
[lyx.git] / src / frontends / qt4 / QCitationDialog.cpp
1 /**
2  * \file QCitationDialog.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  *
11  * Full author contact details are available in file CREDITS.
12  */
13
14 #include <config.h>
15
16 #include "QCitationDialog.h"
17
18 #include "QCitation.h"
19
20 #include "frontends/controllers/frontend_helpers.h"
21 #include "frontends/controllers/ControlCitation.h"
22
23 #include "debug.h"
24 #include "gettext.h"
25
26 #include <algorithm>
27 #include <vector>
28 #include <string>
29
30 #include <QCloseEvent>
31 #include <QKeyEvent>
32
33 using std::vector;
34 using std::string;
35
36 namespace lyx {
37 namespace frontend {
38
39
40 QCitationDialog::QCitationDialog(Dialog & dialog, QCitation * form)
41         : Dialog::View(dialog, _("Citation")), form_(form)
42 {
43         setupUi(this);
44
45         setWindowTitle(toqstr("LyX: " + getTitle()));
46
47         selectedLV->setModel(form_->selected());
48         availableLV->setModel(form_->available());
49
50         connect(citationStyleCO, SIGNAL(activated(int)),
51                 this, SLOT(changed()));
52         connect(fulllistCB, SIGNAL(clicked()),
53                 this, SLOT(changed()));
54         connect(forceuppercaseCB, SIGNAL(clicked()),
55                 this, SLOT(changed()));
56         connect(textBeforeED, SIGNAL(textChanged(const QString&)),
57                 this, SLOT(changed()));
58         connect(textAfterED, SIGNAL(textChanged(const QString&)),
59                 this, SLOT(changed()));
60         connect(clearPB, SIGNAL(clicked()),
61                 findLE, SLOT(clear()));
62         connect(availableLV->selectionModel(),
63                 SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)),
64                 this, SLOT(availableChanged(const QModelIndex &, const QModelIndex &)));
65         connect(selectedLV->selectionModel(),
66                 SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)),
67                 this, SLOT(selectedChanged(const QModelIndex &, const QModelIndex &)));
68 }
69
70
71 QCitationDialog::~QCitationDialog()
72 {
73 }
74
75
76 void QCitationDialog::keyPressEvent(QKeyEvent * event)
77 {
78         if (event->key() == Qt::Key_Escape) {
79                 form_->clearSelection();
80                 form_->clearParams();
81                 event->accept();
82                 close();
83         } else
84                 event->ignore();
85 }
86
87
88 void QCitationDialog::closeEvent(QCloseEvent * e)
89 {
90         form_->clearSelection();
91         form_->clearParams();
92         e->accept();
93 }
94
95
96 void QCitationDialog::apply()
97 {
98         int  const choice = std::max(0, citationStyleCO->currentIndex());
99         style_ = choice;
100         bool const full  = fulllistCB->isChecked();
101         bool const force = forceuppercaseCB->isChecked();
102
103         QString const before = textBeforeED->text();
104         QString const after = textAfterED->text();
105
106         form_->apply(choice, full, force, before, after);
107 }
108
109
110 void QCitationDialog::hide()
111 {
112         form_->clearParams();
113         accept();
114 }
115
116
117 void QCitationDialog::show()
118 {
119         findLE->clear();
120         availableLV->setFocus();
121         QDialog::show();
122 }
123
124
125 bool QCitationDialog::isVisible() const
126 {
127         return QDialog::isVisible();
128 }
129  
130
131 void QCitationDialog::on_okPB_clicked()
132 {
133         apply();
134         form_->clearSelection();
135         hide();
136 }
137
138
139 void QCitationDialog::on_cancelPB_clicked()
140 {
141         form_->clearSelection();
142         hide();
143 }
144
145
146 void QCitationDialog::on_applyPB_clicked()
147 {
148         apply();
149 }
150
151
152 void QCitationDialog::on_restorePB_clicked()
153 {
154         form_->init();
155         update();
156 }
157
158
159 void QCitationDialog::update()
160 {
161         if (selectedLV->selectionModel()->selectedIndexes().isEmpty()) {
162                 if (availableLV->selectionModel()->selectedIndexes().isEmpty() 
163                         && availableLV->model()->rowCount() > 0)
164                                 availableLV->setCurrentIndex(availableLV->model()->index(0,0));
165                 updateInfo(availableLV->currentIndex());
166         } else
167                 updateInfo(selectedLV->currentIndex());
168
169         setButtons();
170
171         textBeforeED->setText(form_->textBefore());
172         textAfterED->setText(form_->textAfter());
173
174         fillStyles();
175         updateStyle();
176 }
177
178
179 void QCitationDialog::updateStyle()
180 {
181         biblio::CiteEngine const engine = form_->getEngine();
182         bool const natbib_engine =
183                 engine == biblio::ENGINE_NATBIB_AUTHORYEAR ||
184                 engine == biblio::ENGINE_NATBIB_NUMERICAL;
185         bool const basic_engine = engine == biblio::ENGINE_BASIC;
186
187         fulllistCB->setEnabled(natbib_engine);
188         forceuppercaseCB->setEnabled(natbib_engine);
189         textBeforeED->setEnabled(!basic_engine);
190         textBeforeLA->setEnabled(!basic_engine);
191
192         string const & command = form_->params().getCmdName();
193
194         // Find the style of the citekeys
195         vector<biblio::CiteStyle> const & styles =
196                 ControlCitation::getCiteStyles();
197         biblio::CitationStyle const cs(command);
198
199         vector<biblio::CiteStyle>::const_iterator cit =
200                 std::find(styles.begin(), styles.end(), cs.style);
201
202         // restore the latest natbib style
203         if (style_ >= 0 && style_ < citationStyleCO->count())
204                 citationStyleCO->setCurrentIndex(style_);
205         else
206                 citationStyleCO->setCurrentIndex(0);
207
208         fulllistCB->setChecked(false);
209         forceuppercaseCB->setChecked(false);
210
211         if (cit != styles.end()) {
212                 int const i = int(cit - styles.begin());
213                 citationStyleCO->setCurrentIndex(i);
214                 fulllistCB->setChecked(cs.full);
215                 forceuppercaseCB->setChecked(cs.forceUCase);
216         }
217 }
218
219
220 void QCitationDialog::fillStyles()
221 {
222         int const orig = citationStyleCO->currentIndex();
223
224         citationStyleCO->clear();
225
226         QStringList selected_keys = form_->selected()->stringList();
227         if (selected_keys.empty()) {
228                 citationStyleCO->setEnabled(false);
229                 citationStyleLA->setEnabled(false);
230                 return;
231         }
232
233         int curr = selectedLV->model()->rowCount() - 1;
234         if (curr < 0)
235                 return;
236
237         if (!selectedLV->selectionModel()->selectedIndexes().empty())
238                 curr = selectedLV->selectionModel()->selectedIndexes()[0].row();
239
240         QStringList sty = form_->citationStyles(curr);
241
242         bool const basic_engine = 
243                 (form_->getEngine() == biblio::ENGINE_BASIC);
244
245         citationStyleCO->setEnabled(!sty.isEmpty() && !basic_engine);
246         citationStyleLA->setEnabled(!sty.isEmpty() && !basic_engine);
247
248         if (sty.isEmpty() || basic_engine)
249                 return;
250
251         citationStyleCO->insertItems(0, sty);
252
253         if (orig != -1 && orig < citationStyleCO->count())
254                 citationStyleCO->setCurrentIndex(orig);
255 }
256
257
258 bool QCitationDialog::isSelected(const QModelIndex & idx)
259 {
260         QString const str = idx.data().toString();
261         return form_->selected()->stringList().contains(str);
262 }
263
264
265 void QCitationDialog::setButtons()
266 {
267         int const arows = availableLV->model()->rowCount();
268         addPB->setEnabled(arows > 0 && 
269                 availableLV->currentIndex().isValid() &&
270                 !isSelected(availableLV->currentIndex()));
271
272         int const srows = selectedLV->model()->rowCount();
273         int const sel_nr = selectedLV->currentIndex().row();
274         deletePB->setEnabled(sel_nr >= 0);
275         upPB->setEnabled(sel_nr > 0);
276         downPB->setEnabled(sel_nr >= 0 && sel_nr < srows - 1);
277         applyPB->setEnabled(srows > 0);
278         okPB->setEnabled(srows > 0);
279 }
280
281
282 void QCitationDialog::updateInfo(const QModelIndex & idx)
283 {
284         if (idx.isValid()) {
285                 QString const keytxt = form_->getKeyInfo(idx.data().toString());
286                 infoML->document()->setPlainText(keytxt);
287         } else
288                 infoML->document()->clear();
289 }
290
291
292 void QCitationDialog::on_selectedLV_clicked(const QModelIndex &)
293 {
294         availableLV->selectionModel()->reset();
295         update();
296 }
297
298
299 void QCitationDialog::selectedChanged(const QModelIndex & idx, const QModelIndex &)
300 {
301         if (!idx.isValid())
302                 return;
303
304         availableLV->selectionModel()->reset();
305         update();
306 }
307
308
309 void QCitationDialog::on_availableLV_clicked(const QModelIndex &)
310 {
311         selectedLV->selectionModel()->reset();
312         update();
313 }
314
315
316 void QCitationDialog::availableChanged(const QModelIndex & idx, const QModelIndex &)
317 {
318         if (!idx.isValid())
319                 return;
320                 
321         selectedLV->selectionModel()->reset();
322         update();
323 }
324
325
326 void QCitationDialog::on_availableLV_activated(const QModelIndex & idx)
327 {
328         if (isSelected(idx))
329                 return;
330
331         selectedLV->selectionModel()->reset();
332         on_addPB_clicked();
333         if (selectedLV->model()->rowCount() == 1)
334                 on_okPB_clicked();
335 }
336
337
338 void QCitationDialog::on_availableLV_entered(const QModelIndex &)
339 {
340 }
341
342
343 void QCitationDialog::on_addPB_clicked()
344 {
345         QModelIndex idx = selectedLV->currentIndex();
346         form_->addKey(availableLV->currentIndex());
347         if (idx.isValid())
348                 selectedLV->setCurrentIndex(idx);
349         selectedLV->selectionModel()->reset();
350         update();
351 }
352
353
354 void QCitationDialog::on_deletePB_clicked()
355 {
356         QModelIndex idx = selectedLV->currentIndex();
357         int nrows = selectedLV->model()->rowCount();
358         
359         form_->deleteKey(idx);
360
361         if (idx.row() == nrows - 1)     
362                 idx = idx.sibling(idx.row() - 1, idx.column());
363
364         if (nrows>1)
365                 selectedLV->setCurrentIndex(idx);
366
367         availableLV->selectionModel()->reset();
368         update();
369 }
370
371
372 void QCitationDialog::on_upPB_clicked()
373 {
374         QModelIndex idx = selectedLV->currentIndex();
375         form_->upKey(idx);
376         selectedLV->setCurrentIndex(idx.sibling(idx.row() - 1, idx.column()));
377         availableLV->selectionModel()->reset();
378         update();
379 }
380
381
382 void QCitationDialog::on_downPB_clicked()
383 {
384         QModelIndex idx = selectedLV->currentIndex();
385         form_->downKey(idx);
386         selectedLV->setCurrentIndex(idx.sibling(idx.row() + 1, idx.column()));
387         availableLV->selectionModel()->reset();
388         update();
389 }
390
391
392 void QCitationDialog::findText(QString const & text)
393 {
394         bool const case_sentitive = caseCB->checkState();
395         bool const reg_exp = regexCB->checkState();
396         form_->findKey(text, false, case_sentitive, reg_exp);
397         selectedLV->selectionModel()->reset();
398         update();
399 }
400
401
402 void QCitationDialog::on_findLE_textChanged(const QString & text)
403 {
404         clearPB->setDisabled(text.isEmpty());
405         if (text.isEmpty())
406                 findLE->setFocus();
407         findText(text);
408 }
409
410
411 void QCitationDialog::on_caseCB_stateChanged(int)
412 {
413         findText(findLE->text());
414 }
415
416
417 void QCitationDialog::on_regexCB_stateChanged(int)
418 {
419         findText(findLE->text());
420 }
421
422
423 void QCitationDialog::changed()
424 {
425         fillStyles();
426         setButtons();
427 }
428
429
430 } // namespace frontend
431 } // namespace lyx
432
433 #include "QCitationDialog_moc.cpp"