]> git.lyx.org Git - lyx.git/blobdiff - src/frontends/qt4/GuiCitation.cpp
header cleanup
[lyx.git] / src / frontends / qt4 / GuiCitation.cpp
index 94ce98800117a0bfd69881370fb1fa1776aab96f..1135d54aa4f5e14f102836cb082cff725c76daf4 100644 (file)
 
 #include "GuiCitation.h"
 
-#include "debug.h"
-#include "gettext.h"
-#include "frontend_helpers.h"
+#include "support/debug.h"
+#include "support/gettext.h"
 #include "qt_helpers.h"
+#include "Buffer.h"
+#include "BufferParams.h"
 
 #include "support/lstrings.h"
 #include "support/docstring.h"
 
+#include "insets/InsetCommand.h"
+
 #include <vector>
 #include <string>
 
 #include <QCloseEvent>
+#include <QShowEvent>
 
 #undef KeyPress
 
+#include <boost/regex.hpp>
+
 #include <algorithm>
 #include <string>
 #include <vector>
 
-using std::vector;
-using std::string;
+using namespace std;
+using namespace lyx::support;
+
+namespace lyx {
+namespace frontend {
+
+static vector<biblio::CiteStyle> citeStyles_;
 
 
 template<typename String>
@@ -64,74 +75,57 @@ static vector<lyx::docstring> to_docstring_vector(QStringList const & qlist)
 }
 
 
-namespace lyx {
-namespace frontend {
-
-///////////////////////////////////////////////////////////////////////
-//
-// GuiCitationDialog
-//
-///////////////////////////////////////////////////////////////////////
-
-
-GuiCitationDialog::GuiCitationDialog(Dialog & dialog, GuiCitation * form)
-       : Dialog::View(dialog, _("Citation")), form_(form)
+GuiCitation::GuiCitation(GuiView & lv)
+       : GuiCommand(lv, "citation", qt_("Citation"))
 {
        setupUi(this);
 
-       setWindowTitle(toqstr("LyX: " + getTitle()));
-
        connect(citationStyleCO, SIGNAL(activated(int)),
-               this, SLOT(changed()));
+               this, SLOT(on_citationStyleCO_currentIndexChanged(int)));
        connect(fulllistCB, SIGNAL(clicked()),
                this, SLOT(changed()));
        connect(forceuppercaseCB, SIGNAL(clicked()),
                this, SLOT(changed()));
-       connect(textBeforeED, SIGNAL(textChanged(const QString&)),
+       connect(textBeforeED, SIGNAL(textChanged(QString)),
                this, SLOT(changed()));
-       connect(textAfterED, SIGNAL(textChanged(const QString&)),
+       connect(textAfterED, SIGNAL(textChanged(QString)),
                this, SLOT(changed()));
        connect(clearPB, SIGNAL(clicked()),
                findLE, SLOT(clear()));
        connect(this, SIGNAL(rejected()), this, SLOT(cleanUp()));
 
-       selectionManager = 
-               new GuiSelectionManager(availableLV, selectedLV, 
-                                     addPB, deletePB, upPB, downPB, 
-                                     form_->available(), form_->selected());
+       selectionManager = new GuiSelectionManager(availableLV, selectedLV, 
+                       addPB, deletePB, upPB, downPB, available(), selected());
        connect(selectionManager, SIGNAL(selectionChanged()),
                this, SLOT(setCitedKeys()));
        connect(selectionManager, SIGNAL(updateHook()),
                this, SLOT(updateDialog()));
        connect(selectionManager, SIGNAL(okHook()),
-                                       this, SLOT(on_okPB_clicked()));
+               this, SLOT(on_okPB_clicked()));
 
+       bc().setPolicy(ButtonPolicy::NoRepeatedApplyReadOnlyPolicy);
 }
 
 
-GuiCitationDialog::~GuiCitationDialog()
-{}
-
-
-void GuiCitationDialog::cleanUp() 
+void GuiCitation::cleanUp() 
 {
-       form_->clearSelection();
-       form_->clearParams();
+       clearSelection();
+       clearParams();
        close();
 }
 
 
-void GuiCitationDialog::closeEvent(QCloseEvent * e)
+void GuiCitation::closeEvent(QCloseEvent * e)
 {
-       form_->clearSelection();
-       form_->clearParams();
+       clearSelection();
+       clearParams();
        e->accept();
 }
 
 
-void GuiCitationDialog::apply()
+void GuiCitation::applyView()
 {
-       int  const choice = std::max(0, citationStyleCO->currentIndex());
+       int  const choice = max(0, citationStyleCO->currentIndex());
        style_ = choice;
        bool const full  = fulllistCB->isChecked();
        bool const force = forceuppercaseCB->isChecked();
@@ -139,76 +133,63 @@ void GuiCitationDialog::apply()
        QString const before = textBeforeED->text();
        QString const after = textAfterED->text();
 
-       form_->apply(choice, full, force, before, after);
+       apply(choice, full, force, before, after);
 }
 
 
-void GuiCitationDialog::hide()
-{
-       form_->clearParams();
-       accept();
-}
-
-
-void GuiCitationDialog::show()
+void GuiCitation::showEvent(QShowEvent * e)
 {
+       init();
        findLE->clear();
        availableLV->setFocus();
-       QDialog::show();
-       raise();
-       activateWindow();
-}
-
-
-bool GuiCitationDialog::isVisible() const
-{
-       return QDialog::isVisible();
+       GuiDialog::showEvent(e);
 }
 
 
-void GuiCitationDialog::on_okPB_clicked()
+void GuiCitation::on_okPB_clicked()
 {
-       apply();
-       form_->clearSelection();
+       applyView();
+       clearSelection();
        hide();
 }
 
 
-void GuiCitationDialog::on_cancelPB_clicked()
+void GuiCitation::on_cancelPB_clicked()
 {
-       form_->clearSelection();
+       clearSelection();
        hide();
 }
 
 
-void GuiCitationDialog::on_applyPB_clicked()
+void GuiCitation::on_applyPB_clicked()
 {
-       apply();
+       applyView();
 }
 
 
-void GuiCitationDialog::on_restorePB_clicked()
+void GuiCitation::on_restorePB_clicked()
 {
-       form_->init();
-       update();
+       init();
+       updateView();
 }
 
 
-void GuiCitationDialog::update()
+void GuiCitation::updateView()
 {
+       init();
        fillFields();
        fillEntries();
        updateDialog();
 }
 
 
-//The main point of separating this out is that the fill*() methods
-//called in update() do not need to be called for INTERNAL updates,
-//such as when addPB is pressed, as the list of fields, entries, etc,
-//will not have changed. At the moment, however, the division between
-//fillStyles() and updateStyles() doesn't lend itself to dividing the
-//two methods, though they should be divisible.
-void GuiCitationDialog::updateDialog()
+// The main point of separating this out is that the fill*() methods
+// called in update() do not need to be called for INTERNAL updates,
+// such as when addPB is pressed, as the list of fields, entries, etc,
+// will not have changed. At the moment, however, the division between
+// fillStyles() and updateStyle() doesn't lend itself to dividing the
+// two methods, though they should be divisible.
+void GuiCitation::updateDialog()
 {
        if (selectionManager->selectedFocused()) { 
                if (selectedLV->selectionModel()->selectedIndexes().isEmpty())
@@ -223,16 +204,16 @@ void GuiCitationDialog::updateDialog()
        }
        setButtons();
 
-       textBeforeED->setText(form_->textBefore());
-       textAfterED->setText(form_->textAfter());
+       textBeforeED->setText(textBefore());
+       textAfterED->setText(textAfter());
        fillStyles();
        updateStyle();
 }
 
 
-void GuiCitationDialog::updateStyle()
+void GuiCitation::updateFormatting(biblio::CiteStyle currentStyle)
 {
-       biblio::CiteEngine const engine = form_->getEngine();
+       biblio::CiteEngine const engine = getEngine();
        bool const natbib_engine =
                engine == biblio::ENGINE_NATBIB_AUTHORYEAR ||
                engine == biblio::ENGINE_NATBIB_NUMERICAL;
@@ -240,20 +221,26 @@ void GuiCitationDialog::updateStyle()
 
        bool const haveSelection = 
                selectedLV->model()->rowCount() > 0;
-       fulllistCB->setEnabled(natbib_engine && haveSelection);
-       forceuppercaseCB->setEnabled(natbib_engine && haveSelection);
-       textBeforeED->setEnabled(!basic_engine && haveSelection);
-       textBeforeLA->setEnabled(!basic_engine && haveSelection);
-       textAfterED->setEnabled(haveSelection);
-       textAfterLA->setEnabled(haveSelection);
-       citationStyleCO->setEnabled(!basic_engine && haveSelection);
-       citationStyleLA->setEnabled(!basic_engine && haveSelection);
 
-       string const & command = form_->params().getCmdName();
+       bool const isNocite = currentStyle == biblio::NOCITE;
+
+       fulllistCB->setEnabled(natbib_engine && haveSelection && !isNocite);
+       forceuppercaseCB->setEnabled(natbib_engine && haveSelection && !isNocite);
+       textBeforeED->setEnabled(!basic_engine && haveSelection && !isNocite);
+       textBeforeLA->setEnabled(!basic_engine && haveSelection && !isNocite);
+       textAfterED->setEnabled(haveSelection && !isNocite);
+       textAfterLA->setEnabled(haveSelection && !isNocite);
+       citationStyleCO->setEnabled(haveSelection);
+       citationStyleLA->setEnabled(haveSelection);
+}
+
+
+void GuiCitation::updateStyle()
+{
+       string const & command = params_.getCmdName();
 
        // Find the style of the citekeys
-       vector<biblio::CiteStyle> const & styles =
-               ControlCitation::getCiteStyles();
+       vector<biblio::CiteStyle> const & styles = citeStyles_;
        biblio::CitationStyle const cs(command);
 
        vector<biblio::CiteStyle>::const_iterator cit =
@@ -274,19 +261,19 @@ void GuiCitationDialog::updateStyle()
                fulllistCB->setChecked(false);
                forceuppercaseCB->setChecked(false);
        }
+       updateFormatting(cs.style);
 }
 
-
 //This one needs to be called whenever citationStyleCO needs
 //to be updated---and this would be on anything that changes the
 //selection in selectedLV, or on a general update.
-void GuiCitationDialog::fillStyles()
+void GuiCitation::fillStyles()
 {
        int const oldIndex = citationStyleCO->currentIndex();
 
        citationStyleCO->clear();
 
-       QStringList selected_keys = form_->selected()->stringList();
+       QStringList selected_keys = selected()->stringList();
        if (selected_keys.empty()) {
                citationStyleCO->setEnabled(false);
                citationStyleLA->setEnabled(false);
@@ -300,15 +287,12 @@ void GuiCitationDialog::fillStyles()
        if (!selectedLV->selectionModel()->selectedIndexes().empty())
                curr = selectedLV->selectionModel()->selectedIndexes()[0].row();
 
-       QStringList sty = form_->citationStyles(curr);
-
-       bool const basic_engine =
-                       (form_->getEngine() == biblio::ENGINE_BASIC);
+       QStringList sty = citationStyles(curr);
 
-       citationStyleCO->setEnabled(!sty.isEmpty() && !basic_engine);
-       citationStyleLA->setEnabled(!sty.isEmpty() && !basic_engine);
+       citationStyleCO->setEnabled(!sty.isEmpty());
+       citationStyleLA->setEnabled(!sty.isEmpty());
 
-       if (sty.isEmpty() || basic_engine)
+       if (sty.isEmpty())
                return;
 
        citationStyleCO->insertItems(0, sty);
@@ -318,12 +302,12 @@ void GuiCitationDialog::fillStyles()
 }
 
 
-void GuiCitationDialog::fillFields()
+void GuiCitation::fillFields()
 {
        fieldsCO->blockSignals(true);
        int const oldIndex = fieldsCO->currentIndex();
        fieldsCO->clear();
-       QStringList const & fields = form_->getFieldsAsQStringList();
+       QStringList const & fields = getFieldsAsQStringList();
        fieldsCO->insertItem(0, qt_("All Fields"));
        fieldsCO->insertItem(1, qt_("Keys"));
        fieldsCO->insertItems(2, fields);
@@ -333,12 +317,12 @@ void GuiCitationDialog::fillFields()
 }
 
 
-void GuiCitationDialog::fillEntries()
+void GuiCitation::fillEntries()
 {
        entriesCO->blockSignals(true);
        int const oldIndex = entriesCO->currentIndex();
        entriesCO->clear();
-       QStringList const & entries = form_->getEntriesAsQStringList();
+       QStringList const & entries = getEntriesAsQStringList();
        entriesCO->insertItem(0, qt_("All Entry Types"));
        entriesCO->insertItems(1, entries);
        if (oldIndex != -1 && oldIndex < entriesCO->count())
@@ -347,14 +331,14 @@ void GuiCitationDialog::fillEntries()
 }
 
 
-bool GuiCitationDialog::isSelected(const QModelIndex & idx)
+bool GuiCitation::isSelected(const QModelIndex & idx)
 {
        QString const str = idx.data().toString();
-       return form_->selected()->stringList().contains(str);
+       return selected()->stringList().contains(str);
 }
 
 
-void GuiCitationDialog::setButtons()
+void GuiCitation::setButtons()
 {
        selectionManager->update();
        int const srows = selectedLV->model()->rowCount();
@@ -363,27 +347,21 @@ void GuiCitationDialog::setButtons()
 }
 
 
-void GuiCitationDialog::updateInfo(QModelIndex const & idx)
+void GuiCitation::updateInfo(QModelIndex const & idx)
 {
        if (idx.isValid()) {
-               QString const keytxt = form_->getKeyInfo(idx.data().toString());
+               QString const keytxt = getKeyInfo(idx.data().toString());
                infoML->document()->setPlainText(keytxt);
        } else
                infoML->document()->clear();
 }
 
 
-void GuiCitationDialog::setCitedKeys() 
-{
-       form_->setCitedKeys();
-}
-
-
-void GuiCitationDialog::findText(QString const & text, bool reset)
+void GuiCitation::findText(QString const & text, bool reset)
 {
        //"All Fields" and "Keys" are the first two
        int index = fieldsCO->currentIndex() - 2; 
-       vector<docstring> const & fields = form_->availableFields();
+       vector<docstring> const & fields = availableFields();
        docstring field;
        
        if (index <= -1 || index >= int(fields.size()))
@@ -397,16 +375,16 @@ void GuiCitationDialog::findText(QString const & text, bool reset)
        
        //"All Entry Types" is first.
        index = entriesCO->currentIndex() - 1; 
-       vector<docstring> const & entries = form_->availableEntries();
-       docstring entryType;
+       vector<docstring> const & entries = availableEntries();
+       docstring entry_type;
        if (index < 0 || index >= int(entries.size()))
-               entryType = from_ascii("");
+               entry_type = from_ascii("");
        else 
-               entryType = entries[index];
+               entry_type = entries[index];
        
        bool const case_sentitive = caseCB->checkState();
        bool const reg_exp = regexCB->checkState();
-       form_->findKey(text, onlyKeys, field, entryType, 
+       findKey(text, onlyKeys, field, entry_type, 
                       case_sentitive, reg_exp, reset);
        //FIXME
        //It'd be nice to save and restore the current selection in 
@@ -417,19 +395,28 @@ void GuiCitationDialog::findText(QString const & text, bool reset)
 }
 
 
-void GuiCitationDialog::on_fieldsCO_currentIndexChanged(int /*index*/)
+void GuiCitation::on_fieldsCO_currentIndexChanged(int /*index*/)
 {
        findText(findLE->text(), true);
 }
 
 
-void GuiCitationDialog::on_entriesCO_currentIndexChanged(int /*index*/)
+void GuiCitation::on_entriesCO_currentIndexChanged(int /*index*/)
 {
        findText(findLE->text(), true);
 }
 
 
-void GuiCitationDialog::on_findLE_textChanged(const QString & text)
+void GuiCitation::on_citationStyleCO_currentIndexChanged(int index)
+{
+       if (index >= 0 && index < citationStyleCO->count()) {
+               vector<biblio::CiteStyle> const & styles = citeStyles_;
+               updateFormatting(styles[index]);
+       }
+}
+
+
+void GuiCitation::on_findLE_textChanged(const QString & text)
 {
        clearPB->setDisabled(text.isEmpty());
        if (text.isEmpty())
@@ -438,53 +425,46 @@ void GuiCitationDialog::on_findLE_textChanged(const QString & text)
 }
 
 
-void GuiCitationDialog::on_caseCB_stateChanged(int)
+void GuiCitation::on_caseCB_stateChanged(int)
 {
        findText(findLE->text());
 }
 
 
-void GuiCitationDialog::on_regexCB_stateChanged(int)
+void GuiCitation::on_regexCB_stateChanged(int)
 {
        findText(findLE->text());
 }
 
 
-void GuiCitationDialog::changed()
+void GuiCitation::changed()
 {
-       fillStyles();
        setButtons();
 }
 
-///////////////////////////////////////////////////////////////////////
-//
-// GuiCitation
-//
-///////////////////////////////////////////////////////////////////////
-
-GuiCitation::GuiCitation(GuiDialog & parent)
-       : ControlCitation(parent)
-{
-}
-
 
-void GuiCitation::apply(int const choice, bool const full, bool const force,
-                     QString before, QString after)
+void GuiCitation::apply(int const choice, bool full, bool force,
+       QString before, QString after)
 {
        if (cited_keys_.isEmpty())
                return;
 
-       vector<biblio::CiteStyle> const & styles =
-               ControlCitation::getCiteStyles();
-
+       vector<biblio::CiteStyle> const & styles = citeStyles_;
+       if (styles[choice] == biblio::NOCITE) {
+               full = false;
+               force = false;
+               before.clear();
+               after.clear();
+       }
+       
        string const command =
                biblio::CitationStyle(styles[choice], full, force)
                .asLatexStr();
 
-       params().setCmdName(command);
-       params()["key"] = qstring_to_ucs4(cited_keys_.join(","));
-       params()["before"] = qstring_to_ucs4(before);
-       params()["after"] = qstring_to_ucs4(after);
+       params_.setCmdName(command);
+       params_["key"] = qstring_to_ucs4(cited_keys_.join(","));
+       params_["before"] = qstring_to_ucs4(before);
+       params_["after"] = qstring_to_ucs4(after);
        dispatchParams();
 }
 
@@ -498,22 +478,13 @@ void GuiCitation::clearSelection()
 
 QString GuiCitation::textBefore()
 {
-       return toqstr(params()["before"]);
+       return toqstr(params_["before"]);
 }
 
 
 QString GuiCitation::textAfter()
 {
-       return toqstr(params()["after"]);
-}
-
-
-bool GuiCitation::initialiseParams(std::string const & data)
-{
-       if (!ControlCitation::initialiseParams(data))
-               return false;
-       init();
-       return true;
+       return toqstr(params_["after"]);
 }
 
 
@@ -524,7 +495,7 @@ void GuiCitation::init()
        available_model_.setStringList(all_keys_);
 
        // Ditto for the keys cited in this inset
-       QString str = toqstr(params()["key"]);
+       QString str = toqstr(params_["key"]);
        if (str.isEmpty())
                cited_keys_.clear();
        else
@@ -534,7 +505,7 @@ void GuiCitation::init()
 
 
 void GuiCitation::findKey(QString const & str, bool only_keys,
-       docstring field, docstring entryType,
+       docstring field, docstring entry_type,
        bool case_sensitive, bool reg_exp, bool reset)
 {
        // Used for optimisation: store last searched string.
@@ -545,7 +516,7 @@ void GuiCitation::findKey(QString const & str, bool only_keys,
        // Reset last_searched_string in case of changed option.
        if (last_case_sensitive != case_sensitive
                || last_reg_exp != reg_exp) {
-                       LYXERR(Debug::GUI) << "GuiCitation::findKey: optimisation disabled!" << std::endl;
+                       LYXERR(Debug::GUI, "GuiCitation::findKey: optimisation disabled!");
                last_searched_string.clear();
        }
        // save option for next search.
@@ -570,10 +541,10 @@ void GuiCitation::findKey(QString const & str, bool only_keys,
 
        QStringList result;
        
-       // First, filter by entryType, which will be faster than 
+       // First, filter by entry_type, which will be faster than 
        // what follows, so we may get to do that on less.
        vector<docstring> keyVector = to_docstring_vector(keys);
-       filterByEntryType(keyVector, entryType);
+       filterByEntryType(keyVector, entry_type);
        
        if (str.isEmpty())
                result = to_qstring_list(keyVector);
@@ -600,7 +571,7 @@ QStringList GuiCitation::getEntriesAsQStringList()
 QStringList GuiCitation::citationStyles(int sel)
 {
        docstring const key = qstring_to_ucs4(cited_keys_[sel]);
-       return to_qstring_list(getCiteStrings(key));
+       return to_qstring_list(bibkeysInfo_.getCiteStrings(key, buffer()));
 }
 
 
@@ -609,11 +580,174 @@ QString GuiCitation::getKeyInfo(QString const & sel)
        return toqstr(getInfo(qstring_to_ucs4(sel)));
 }
 
+
 void GuiCitation::setCitedKeys() 
 {
        cited_keys_ = selected_model_.stringList();
 }
 
+
+bool GuiCitation::initialiseParams(string const & data)
+{
+       InsetCommandMailer::string2params(lfun_name_, data, params_);
+
+       biblio::CiteEngine const engine = buffer().params().getEngine();
+
+       bibkeysInfo_.fillWithBibKeys(&buffer());
+       
+       citeStyles_ = biblio::getCiteStyles(engine);
+
+       return true;
+}
+
+
+void GuiCitation::clearParams()
+{
+       params_.clear();
+       bibkeysInfo_.clear();
+}
+
+
+vector<docstring> const GuiCitation::availableKeys() const
+{
+       return bibkeysInfo_.getKeys();
+}
+
+
+vector<docstring> const GuiCitation::availableFields() const
+{
+       return bibkeysInfo_.getFields();
+}
+
+
+vector<docstring> const GuiCitation::availableEntries() const
+{
+       return bibkeysInfo_.getEntries();
+}
+
+
+void GuiCitation::filterByEntryType(
+       vector<docstring> & keyVector, docstring entry_type) 
+{
+       if (entry_type.empty())
+               return;
+       
+       vector<docstring>::iterator it = keyVector.begin();
+       vector<docstring>::iterator end = keyVector.end();
+       
+       vector<docstring> result;
+       for (; it != end; ++it) {
+               docstring const key = *it;
+               BiblioInfo::const_iterator cit = bibkeysInfo_.find(key);
+               if (cit == bibkeysInfo_.end())
+                       continue;
+               if (cit->second.entryType() == entry_type)
+                       result.push_back(key);
+       }
+       keyVector = result;
+}
+
+
+biblio::CiteEngine GuiCitation::getEngine() const
+{
+       return buffer().params().getEngine();
+}
+
+
+docstring GuiCitation::getInfo(docstring const & key) const
+{
+       if (bibkeysInfo_.empty())
+               return docstring();
+
+       return bibkeysInfo_.getInfo(key);
+}
+
+
+// Escape special chars.
+// All characters are literals except: '.|*?+(){}[]^$\'
+// These characters are literals when preceded by a "\", which is done here
+// @todo: This function should be moved to support, and then the test in tests
+//        should be moved there as well.
+static docstring escape_special_chars(docstring const & expr)
+{
+       // Search for all chars '.|*?+(){}[^$]\'
+       // Note that '[' and '\' must be escaped.
+       // This is a limitation of boost::regex, but all other chars in BREs
+       // are assumed literal.
+       static const boost::regex reg("[].|*?+(){}^$\\[\\\\]");
+
+       // $& is a perl-like expression that expands to all
+       // of the current match
+       // The '$' must be prefixed with the escape character '\' for
+       // boost to treat it as a literal.
+       // Thus, to prefix a matched expression with '\', we use:
+       // FIXME: UNICODE
+       return from_utf8(boost::regex_replace(to_utf8(expr), reg, "\\\\$&"));
+}
+
+
+vector<docstring> GuiCitation::searchKeys(
+       vector<docstring> const & keys_to_search, bool only_keys,
+       docstring const & search_expression, docstring field,
+       bool case_sensitive, bool regex)
+{
+       vector<docstring> foundKeys;
+
+       docstring expr = trim(search_expression);
+       if (expr.empty())
+               return foundKeys;
+
+       if (!regex)
+               // We must escape special chars in the search_expr so that
+               // it is treated as a simple string by boost::regex.
+               expr = escape_special_chars(expr);
+
+       boost::regex reg_exp;
+       try {
+               reg_exp.assign(to_utf8(expr), case_sensitive ?
+                       boost::regex_constants::normal : boost::regex_constants::icase);
+       } catch (boost::regex_error & e) {
+               // boost::regex throws an exception if the regular expression is not
+               // valid.
+               LYXERR(Debug::GUI, e.what());
+               return vector<docstring>();
+       }
+
+       vector<docstring>::const_iterator it = keys_to_search.begin();
+       vector<docstring>::const_iterator end = keys_to_search.end();
+       for (; it != end; ++it ) {
+               BiblioInfo::const_iterator info = bibkeysInfo_.find(*it);
+               if (info == bibkeysInfo_.end())
+                       continue;
+               
+               BibTeXInfo const & kvm = info->second;
+               string data;
+               if (only_keys)
+                       data = to_utf8(*it);
+               else if (field.empty())
+                       data = to_utf8(*it) + ' ' + to_utf8(kvm.allData());
+               else if (kvm.hasField(field))
+                       data = to_utf8(kvm.getValueForField(field));
+               
+               if (data.empty())
+                       continue;
+
+               try {
+                       if (boost::regex_search(data, reg_exp))
+                               foundKeys.push_back(*it);
+               }
+               catch (boost::regex_error & e) {
+                       LYXERR(Debug::GUI, e.what());
+                       return vector<docstring>();
+               }
+       }
+       return foundKeys;
+}
+
+
+Dialog * createGuiCitation(GuiView & lv) { return new GuiCitation(lv); }
+
+
 } // namespace frontend
 } // namespace lyx