]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/GuiCitation.cpp
Fix a bunch of minor issues discovered by the cppcheck script.
[lyx.git] / src / frontends / qt4 / GuiCitation.cpp
1
2 /**
3  * \file GuiCitation.cpp
4  * This file is part of LyX, the document processor.
5  * Licence details can be found in the file COPYING.
6  *
7  * \author Angus Leeming
8  * \author Kalle Dalheimer
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 "GuiCitation.h"
18
19 #include "GuiSelectionManager.h"
20 #include "qt_helpers.h"
21
22 #include "Buffer.h"
23 #include "BufferView.h"
24 #include "BiblioInfo.h"
25 #include "BufferParams.h"
26 #include "FuncRequest.h"
27
28 #include "insets/InsetCommand.h"
29
30 #include "support/debug.h"
31 #include "support/docstring.h"
32 #include "support/gettext.h"
33 #include "support/lstrings.h"
34
35 #include <QCloseEvent>
36 #include <QSettings>
37 #include <QShowEvent>
38 #include <QVariant>
39
40 #include <vector>
41 #include <string>
42
43 #undef KeyPress
44
45 #include "support/regex.h"
46
47 #include <algorithm>
48 #include <string>
49 #include <vector>
50
51 using namespace std;
52 using namespace lyx::support;
53
54 namespace lyx {
55 namespace frontend {
56
57 // FIXME THREAD
58 // I am guessing that it would not hurt to make these private members.
59 static vector<string> citeCmds_;
60 static vector<CitationStyle> citeStyles_;
61
62
63 template<typename String>
64 static QStringList to_qstring_list(vector<String> const & v)
65 {
66         QStringList qlist;
67
68         for (size_t i = 0; i != v.size(); ++i) {
69                 if (v[i].empty())
70                         continue;
71                 qlist.append(lyx::toqstr(v[i]));
72         }
73         return qlist;
74 }
75
76
77 static vector<lyx::docstring> to_docstring_vector(QStringList const & qlist)
78 {
79         vector<lyx::docstring> v;
80         for (int i = 0; i != qlist.size(); ++i) {
81                 if (qlist[i].isEmpty())
82                         continue;
83                 v.push_back(lyx::qstring_to_ucs4(qlist[i]));
84         }
85         return v;
86 }
87
88
89 GuiCitation::GuiCitation(GuiView & lv)
90         : DialogView(lv, "citation", qt_("Citation")),
91           params_(insetCode("citation"))
92 {
93         setupUi(this);
94
95         connect(citationStyleCO, SIGNAL(activated(int)),
96                 this, SLOT(on_citationStyleCO_currentIndexChanged(int)));
97         connect(fulllistCB, SIGNAL(clicked()),
98                 this, SLOT(changed()));
99         connect(forceuppercaseCB, SIGNAL(clicked()),
100                 this, SLOT(changed()));
101         connect(textBeforeED, SIGNAL(textChanged(QString)),
102                 this, SLOT(updateStyles()));
103         connect(textAfterED, SIGNAL(textChanged(QString)),
104                 this, SLOT(updateStyles()));
105         connect(findLE, SIGNAL(returnPressed()),
106                 this, SLOT(on_searchPB_clicked()));
107         connect(textBeforeED, SIGNAL(returnPressed()),
108                 this, SLOT(on_okPB_clicked()));
109         connect(textAfterED, SIGNAL(returnPressed()),
110                 this, SLOT(on_okPB_clicked()));
111
112         selectionManager = new GuiSelectionManager(availableLV, selectedLV,
113                         addPB, deletePB, upPB, downPB, &available_model_, &selected_model_);
114         connect(selectionManager, SIGNAL(selectionChanged()),
115                 this, SLOT(setCitedKeys()));
116         connect(selectionManager, SIGNAL(updateHook()),
117                 this, SLOT(updateControls()));
118         connect(selectionManager, SIGNAL(okHook()),
119                 this, SLOT(on_okPB_clicked()));
120
121         setFocusProxy(availableLV);
122 }
123
124
125 GuiCitation::~GuiCitation()
126 {
127         delete selectionManager;
128 }
129
130
131 void GuiCitation::closeEvent(QCloseEvent * e)
132 {
133         clearSelection();
134         DialogView::closeEvent(e);
135 }
136
137
138 void GuiCitation::applyView()
139 {
140         int const choice = max(0, citationStyleCO->currentIndex());
141         style_ = choice;
142         bool const full  = fulllistCB->isChecked();
143         bool const force = forceuppercaseCB->isChecked();
144
145         QString const before = textBeforeED->text();
146         QString const after = textAfterED->text();
147
148         apply(choice, full, force, before, after);
149 }
150
151
152 void GuiCitation::showEvent(QShowEvent * e)
153 {
154         findLE->clear();
155         availableLV->setFocus();
156         DialogView::showEvent(e);
157 }
158
159
160 void GuiCitation::on_okPB_clicked()
161 {
162         applyView();
163         clearSelection();
164         hide();
165 }
166
167
168 void GuiCitation::on_cancelPB_clicked()
169 {
170         clearSelection();
171         hide();
172 }
173
174
175 void GuiCitation::on_applyPB_clicked()
176 {
177         applyView();
178 }
179
180
181 void GuiCitation::on_restorePB_clicked()
182 {
183         init();
184 }
185
186
187 void GuiCitation::updateControls()
188 {
189         BiblioInfo const & bi = bibInfo();
190         updateControls(bi);
191 }
192
193
194 // The main point of separating this out is that the fill*() methods
195 // called in update() do not need to be called for INTERNAL updates,
196 // such as when addPB is pressed, as the list of fields, entries, etc,
197 // will not have changed.
198 void GuiCitation::updateControls(BiblioInfo const & bi)
199 {
200         QModelIndex idx = selectionManager->getSelectedIndex();
201         updateInfo(bi, idx);
202         selectionManager->update();
203 }
204
205
206 void GuiCitation::updateFormatting(CitationStyle currentStyle)
207 {
208         bool const force = currentStyle.forceUpperCase;
209         bool const full = currentStyle.fullAuthorList &&
210                 documentBuffer().params().fullAuthorList();
211         bool const textbefore = currentStyle.textBefore;
212         bool const textafter = currentStyle.textAfter;
213
214         bool const haveSelection =
215                 selectedLV->model()->rowCount() > 0;
216
217         forceuppercaseCB->setEnabled(force && haveSelection);
218         fulllistCB->setEnabled(full && haveSelection);
219         textBeforeED->setEnabled(textbefore && haveSelection);
220         textBeforeLA->setEnabled(textbefore && haveSelection);
221         textAfterED->setEnabled(textafter && haveSelection);
222         textAfterLA->setEnabled(textafter && haveSelection);
223         citationStyleCO->setEnabled(haveSelection);
224         citationStyleLA->setEnabled(haveSelection);
225 }
226
227
228 // Update the styles for the style combo, citationStyleCO, and mark the
229 // settings as changed. Called upon changing the cited keys (including
230 // merely reordering the keys) or editing the text before/after fields.
231 void GuiCitation::updateStyles()
232 {
233         BiblioInfo const & bi = bibInfo();
234         updateStyles(bi);
235         changed();
236 }
237
238
239 // Update the styles for the style combo, citationStyleCO.
240 void GuiCitation::updateStyles(BiblioInfo const & bi)
241 {
242         QStringList selected_keys = selected_model_.stringList();
243         int curr = selectedLV->model()->rowCount() - 1;
244
245         if (curr < 0 || selected_keys.empty()) {
246                 citationStyleCO->clear();
247                 citationStyleCO->setEnabled(false);
248                 citationStyleLA->setEnabled(false);
249                 return;
250         }
251
252         if (!selectedLV->selectionModel()->selectedIndexes().empty())
253                 curr = selectedLV->selectionModel()->selectedIndexes()[0].row();
254
255         QStringList sty = citationStyles(bi);
256
257         if (sty.isEmpty()) {
258                 // some error
259                 citationStyleCO->setEnabled(false);
260                 citationStyleLA->setEnabled(false);
261                 citationStyleCO->clear();
262                 return;
263         }
264
265         citationStyleCO->blockSignals(true);
266
267         // save old index
268         int const oldIndex = citationStyleCO->currentIndex();
269         citationStyleCO->clear();
270         citationStyleCO->insertItems(0, sty);
271         citationStyleCO->setEnabled(true);
272         citationStyleLA->setEnabled(true);
273         // restore old index
274         if (oldIndex != -1 && oldIndex < citationStyleCO->count())
275                 citationStyleCO->setCurrentIndex(oldIndex);
276
277         citationStyleCO->blockSignals(false);
278 }
279
280
281 void GuiCitation::fillFields(BiblioInfo const & bi)
282 {
283         fieldsCO->blockSignals(true);
284         int const oldIndex = fieldsCO->currentIndex();
285         fieldsCO->clear();
286         QStringList const fields = to_qstring_list(bi.getFields());
287         fieldsCO->insertItem(0, qt_("All fields"));
288         fieldsCO->insertItem(1, qt_("Keys"));
289         fieldsCO->insertItems(2, fields);
290         if (oldIndex != -1 && oldIndex < fieldsCO->count())
291                 fieldsCO->setCurrentIndex(oldIndex);
292         fieldsCO->blockSignals(false);
293 }
294
295
296 void GuiCitation::fillEntries(BiblioInfo const & bi)
297 {
298         entriesCO->blockSignals(true);
299         int const oldIndex = entriesCO->currentIndex();
300         entriesCO->clear();
301         QStringList const entries = to_qstring_list(bi.getEntries());
302         entriesCO->insertItem(0, qt_("All entry types"));
303         entriesCO->insertItems(1, entries);
304         if (oldIndex != -1 && oldIndex < entriesCO->count())
305                 entriesCO->setCurrentIndex(oldIndex);
306         entriesCO->blockSignals(false);
307 }
308
309
310 bool GuiCitation::isSelected(QModelIndex const & idx)
311 {
312         QString const str = idx.data().toString();
313         return selected_model_.stringList().contains(str);
314 }
315
316
317 void GuiCitation::setButtons()
318 {
319         int const srows = selectedLV->model()->rowCount();
320         applyPB->setEnabled(srows > 0);
321         okPB->setEnabled(srows > 0);
322 }
323
324
325 void GuiCitation::updateInfo(BiblioInfo const & bi, QModelIndex const & idx)
326 {
327         if (!idx.isValid() || bi.empty()) {
328                 infoML->document()->clear();
329                 return;
330         }
331
332         QString const keytxt = toqstr(
333                 bi.getInfo(qstring_to_ucs4(idx.data().toString()), documentBuffer(), true));
334         infoML->document()->setHtml(keytxt);
335 }
336
337
338 void GuiCitation::findText(QString const & text, bool reset)
339 {
340         //"All Fields" and "Keys" are the first two
341         int index = fieldsCO->currentIndex() - 2;
342         BiblioInfo const & bi = bibInfo();
343         vector<docstring> const & fields = bi.getFields();
344         docstring field;
345
346         if (index <= -1 || index >= int(fields.size()))
347                 //either "All Fields" or "Keys" or an invalid value
348                 field = from_ascii("");
349         else
350                 field = fields[index];
351
352         //Was it "Keys"?
353         bool const onlyKeys = index == -1;
354
355         //"All Entry Types" is first.
356         index = entriesCO->currentIndex() - 1;
357         vector<docstring> const & entries = bi.getEntries();
358         docstring entry_type;
359         if (index < 0 || index >= int(entries.size()))
360                 entry_type = from_ascii("");
361         else
362                 entry_type = entries[index];
363
364         bool const case_sentitive = caseCB->checkState();
365         bool const reg_exp = regexCB->checkState();
366         findKey(bi, text, onlyKeys, field, entry_type,
367                        case_sentitive, reg_exp, reset);
368         //FIXME
369         //It'd be nice to save and restore the current selection in
370         //availableLV. Currently, we get an automatic reset, since the
371         //model is reset.
372
373         updateControls(bi);
374 }
375
376
377 void GuiCitation::on_fieldsCO_currentIndexChanged(int /*index*/)
378 {
379         findText(findLE->text(), true);
380 }
381
382
383 void GuiCitation::on_entriesCO_currentIndexChanged(int /*index*/)
384 {
385         findText(findLE->text(), true);
386 }
387
388
389 void GuiCitation::on_citationStyleCO_currentIndexChanged(int index)
390 {
391         if (index >= 0 && index < citationStyleCO->count()) {
392                 vector<CitationStyle> const & styles = citeStyles_;
393                 updateFormatting(styles[index]);
394                 changed();
395         }
396 }
397
398
399 void GuiCitation::on_findLE_textChanged(const QString & text)
400 {
401         bool const searchAsWeGo = (asTypeCB->checkState() == Qt::Checked);
402         searchPB->setDisabled(text.isEmpty() || searchAsWeGo);
403         if (!text.isEmpty()) {
404                 if (searchAsWeGo)
405                         findText(findLE->text());
406                 return;
407         }
408         findText(findLE->text());
409         findLE->setFocus();
410 }
411
412 void GuiCitation::on_searchPB_clicked()
413 {
414         findText(findLE->text(), true);
415 }
416
417
418 void GuiCitation::on_caseCB_stateChanged(int)
419 {
420         findText(findLE->text());
421 }
422
423
424 void GuiCitation::on_regexCB_stateChanged(int)
425 {
426         findText(findLE->text());
427 }
428
429
430 void GuiCitation::on_asTypeCB_stateChanged(int)
431 {
432         bool const searchAsWeGo = (asTypeCB->checkState() == Qt::Checked);
433         searchPB->setDisabled(findLE->text().isEmpty() || searchAsWeGo);
434         if (searchAsWeGo)
435                 findText(findLE->text(), true);
436 }
437
438
439 void GuiCitation::changed()
440 {
441         setButtons();
442 }
443
444
445 void GuiCitation::apply(int const choice, bool full, bool force,
446         QString before, QString after)
447 {
448         if (cited_keys_.isEmpty())
449                 return;
450
451         vector<CitationStyle> const & styles = citeStyles_;
452
453         CitationStyle cs = styles[choice];
454
455         if (!cs.textBefore)
456                 before.clear();
457         if (!cs.textAfter)
458                 after.clear();
459
460         cs.forceUpperCase &= force;
461         cs.fullAuthorList &= full;
462         string const command = citationStyleToString(cs);
463
464         params_.setCmdName(command);
465         params_["key"] = qstring_to_ucs4(cited_keys_.join(","));
466         params_["before"] = qstring_to_ucs4(before);
467         params_["after"] = qstring_to_ucs4(after);
468         dispatchParams();
469 }
470
471
472 void GuiCitation::clearSelection()
473 {
474         cited_keys_.clear();
475         selected_model_.setStringList(cited_keys_);
476 }
477
478
479 void GuiCitation::init()
480 {
481         // Make the list of all available bibliography keys
482         BiblioInfo const & bi = bibInfo();
483         all_keys_ = to_qstring_list(bi.getKeys());
484         available_model_.setStringList(all_keys_);
485
486         // Ditto for the keys cited in this inset
487         QString str = toqstr(params_["key"]);
488         if (str.isEmpty())
489                 cited_keys_.clear();
490         else
491                 cited_keys_ = str.split(",");
492         selected_model_.setStringList(cited_keys_);
493
494         // Initialize the drop downs
495         fillEntries(bi);
496         fillFields(bi);
497
498         // Initialize the citation formatting
499         string const & cmd = params_.getCmdName();
500         CitationStyle const cs = citationStyleFromString(cmd);
501         forceuppercaseCB->setChecked(cs.forceUpperCase);
502         fulllistCB->setChecked(cs.fullAuthorList &&
503                 documentBuffer().params().fullAuthorList());
504         textBeforeED->setText(toqstr(params_["before"]));
505         textAfterED->setText(toqstr(params_["after"]));
506
507         // Update the interface
508         updateControls(bi);
509         updateStyles(bi);
510         if (selected_model_.rowCount()) {
511                 selectedLV->blockSignals(true);
512                 selectedLV->setFocus();
513                 QModelIndex idx = selected_model_.index(0, 0);
514                 selectedLV->selectionModel()->select(idx,
515                                 QItemSelectionModel::ClearAndSelect);
516                 selectedLV->blockSignals(false);
517
518                 // Find the citation style
519                 vector<string> const & cmds = citeCmds_;
520                 vector<string>::const_iterator cit =
521                         std::find(cmds.begin(), cmds.end(), cs.cmd);
522                 int i = 0;
523                 if (cit != cmds.end())
524                         i = int(cit - cmds.begin());
525
526                 // Set the style combo appropriately
527                 citationStyleCO->blockSignals(true);
528                 citationStyleCO->setCurrentIndex(i);
529                 citationStyleCO->blockSignals(false);
530                 updateFormatting(citeStyles_[i]);
531         } else
532                 availableLV->setFocus();
533
534         applyPB->setEnabled(false);
535         okPB->setEnabled(false);
536 }
537
538
539 void GuiCitation::findKey(BiblioInfo const & bi,
540         QString const & str, bool only_keys,
541         docstring field, docstring entry_type,
542         bool case_sensitive, bool reg_exp, bool reset)
543 {
544         // FIXME THREAD
545         // Used for optimisation: store last searched string.
546         static QString last_searched_string;
547         // Used to disable the above optimisation.
548         static bool last_case_sensitive;
549         static bool last_reg_exp;
550         // Reset last_searched_string in case of changed option.
551         if (last_case_sensitive != case_sensitive
552                 || last_reg_exp != reg_exp) {
553                         LYXERR(Debug::GUI, "GuiCitation::findKey: optimisation disabled!");
554                 last_searched_string.clear();
555         }
556         // save option for next search.
557         last_case_sensitive = case_sensitive;
558         last_reg_exp = reg_exp;
559
560         Qt::CaseSensitivity qtcase = case_sensitive ?
561                         Qt::CaseSensitive: Qt::CaseInsensitive;
562         QStringList keys;
563         // If new string (str) contains the last searched one...
564         if (!reset &&
565                 !last_searched_string.isEmpty() &&
566                 str.size() > 1 &&
567                 str.contains(last_searched_string, qtcase))
568                 // ... then only search within already found list.
569                 keys = available_model_.stringList();
570         else
571                 // ... else search all keys.
572                 keys = all_keys_;
573         // save searched string for next search.
574         last_searched_string = str;
575
576         QStringList result;
577
578         // First, filter by entry_type, which will be faster than
579         // what follows, so we may get to do that on less.
580         vector<docstring> keyVector = to_docstring_vector(keys);
581         filterByEntryType(bi, keyVector, entry_type);
582
583         if (str.isEmpty())
584                 result = to_qstring_list(keyVector);
585         else
586                 result = to_qstring_list(searchKeys(bi, keyVector, only_keys,
587                         qstring_to_ucs4(str), field, case_sensitive, reg_exp));
588
589         available_model_.setStringList(result);
590 }
591
592
593 QStringList GuiCitation::citationStyles(BiblioInfo const & bi)
594 {
595         docstring const before = qstring_to_ucs4(textBeforeED->text());
596         docstring const after = qstring_to_ucs4(textAfterED->text());
597         vector<docstring> const keys = to_docstring_vector(cited_keys_);
598         vector<CitationStyle> styles = citeStyles_;
599         // FIXME: pass a dictionary instead of individual before, after, dialog, etc.
600         vector<docstring> ret = bi.getCiteStrings(keys, styles, documentBuffer(),
601                 false, before, after, from_utf8("dialog"));
602         return to_qstring_list(ret);
603 }
604
605
606 void GuiCitation::setCitedKeys()
607 {
608         cited_keys_ = selected_model_.stringList();
609         updateStyles();
610 }
611
612
613 bool GuiCitation::initialiseParams(string const & data)
614 {
615         InsetCommand::string2params(data, params_);
616         citeCmds_ = documentBuffer().params().citeCommands();
617         citeStyles_ = documentBuffer().params().citeStyles();
618         init();
619         return true;
620 }
621
622
623 void GuiCitation::clearParams()
624 {
625         params_.clear();
626 }
627
628
629 void GuiCitation::filterByEntryType(BiblioInfo const & bi,
630         vector<docstring> & keyVector, docstring entry_type)
631 {
632         if (entry_type.empty())
633                 return;
634
635         vector<docstring>::iterator it = keyVector.begin();
636         vector<docstring>::iterator end = keyVector.end();
637
638         vector<docstring> result;
639         for (; it != end; ++it) {
640                 docstring const key = *it;
641                 BiblioInfo::const_iterator cit = bi.find(key);
642                 if (cit == bi.end())
643                         continue;
644                 if (cit->second.entryType() == entry_type)
645                         result.push_back(key);
646         }
647         keyVector = result;
648 }
649
650
651 // Escape special chars.
652 // All characters are literals except: '.|*?+(){}[]^$\'
653 // These characters are literals when preceded by a "\", which is done here
654 // @todo: This function should be moved to support, and then the test in tests
655 //        should be moved there as well.
656 static docstring escape_special_chars(docstring const & expr)
657 {
658         // Search for all chars '.|*?+(){}[^$]\'
659         // Note that '[' and '\' must be escaped.
660         // This is a limitation of lyx::regex, but all other chars in BREs
661         // are assumed literal.
662         static const lyx::regex reg("[].|*?+(){}^$\\[\\\\]");
663
664         // $& is a perl-like expression that expands to all
665         // of the current match
666         // The '$' must be prefixed with the escape character '\' for
667         // boost to treat it as a literal.
668         // Thus, to prefix a matched expression with '\', we use:
669         // FIXME: UNICODE
670         return from_utf8(lyx::regex_replace(to_utf8(expr), reg, string("\\\\$&")));
671 }
672
673
674 vector<docstring> GuiCitation::searchKeys(BiblioInfo const & bi,
675         vector<docstring> const & keys_to_search, bool only_keys,
676         docstring const & search_expression, docstring field,
677         bool case_sensitive, bool regex)
678 {
679         vector<docstring> foundKeys;
680
681         docstring expr = trim(search_expression);
682         if (expr.empty())
683                 return foundKeys;
684
685         if (!regex)
686                 // We must escape special chars in the search_expr so that
687                 // it is treated as a simple string by lyx::regex.
688                 expr = escape_special_chars(expr);
689
690         lyx::regex reg_exp;
691         try {
692                 reg_exp.assign(to_utf8(expr), case_sensitive ?
693                         lyx::regex_constants::ECMAScript : lyx::regex_constants::icase);
694         } catch (lyx::regex_error const & e) {
695                 // lyx::regex throws an exception if the regular expression is not
696                 // valid.
697                 LYXERR(Debug::GUI, e.what());
698                 return vector<docstring>();
699         }
700
701         vector<docstring>::const_iterator it = keys_to_search.begin();
702         vector<docstring>::const_iterator end = keys_to_search.end();
703         for (; it != end; ++it ) {
704                 BiblioInfo::const_iterator info = bi.find(*it);
705                 if (info == bi.end())
706                         continue;
707
708                 BibTeXInfo const & kvm = info->second;
709                 string data;
710                 if (only_keys)
711                         data = to_utf8(*it);
712                 else if (field.empty())
713                         data = to_utf8(*it) + ' ' + to_utf8(kvm.allData());
714                 else
715                         data = to_utf8(kvm[field]);
716
717                 if (data.empty())
718                         continue;
719
720                 try {
721                         if (lyx::regex_search(data, reg_exp))
722                                 foundKeys.push_back(*it);
723                 }
724                 catch (lyx::regex_error const & e) {
725                         LYXERR(Debug::GUI, e.what());
726                         return vector<docstring>();
727                 }
728         }
729         return foundKeys;
730 }
731
732
733 void GuiCitation::dispatchParams()
734 {
735         std::string const lfun = InsetCommand::params2string(params_);
736         dispatch(FuncRequest(getLfun(), lfun));
737 }
738
739
740 BiblioInfo const & GuiCitation::bibInfo() const
741 {
742         Buffer const & buf = documentBuffer();
743         buf.reloadBibInfoCache();
744         return buf.masterBibInfo();
745 }
746
747
748 void GuiCitation::saveSession() const
749 {
750         Dialog::saveSession();
751         QSettings settings;
752         settings.setValue(
753                 sessionKey() + "/regex", regexCB->isChecked());
754         settings.setValue(
755                 sessionKey() + "/casesensitive", caseCB->isChecked());
756         settings.setValue(
757                 sessionKey() + "/autofind", asTypeCB->isChecked());
758 }
759
760
761 void GuiCitation::restoreSession()
762 {
763         Dialog::restoreSession();
764         QSettings settings;
765         regexCB->setChecked(
766                 settings.value(sessionKey() + "/regex").toBool());
767         caseCB->setChecked(
768                 settings.value(sessionKey() + "/casesensitive").toBool());
769         asTypeCB->setChecked(
770                 settings.value(sessionKey() + "/autofind").toBool());
771 }
772
773
774 Dialog * createGuiCitation(GuiView & lv) { return new GuiCitation(lv); }
775
776
777 } // namespace frontend
778 } // namespace lyx
779
780 #include "moc_GuiCitation.cpp"
781