]> git.lyx.org Git - lyx.git/blobdiff - src/frontends/qt4/GuiCitation.cpp
Add ability to use refstyle's plural and capitalization features.
[lyx.git] / src / frontends / qt4 / GuiCitation.cpp
index 5a8e09dcdeabc20a63147b60e262aff0cc1be137..10c91670afbb4a6985973102aa4015c7f976e89f 100644 (file)
@@ -16,7 +16,9 @@
 
 #include "GuiCitation.h"
 
+#include "GuiApplication.h"
 #include "GuiSelectionManager.h"
+#include "LyXToolBox.h"
 #include "qt_helpers.h"
 
 #include "Buffer.h"
@@ -33,6 +35,7 @@
 #include "support/lstrings.h"
 
 #include <QCloseEvent>
+#include <QMenu>
 #include <QSettings>
 #include <QShowEvent>
 #include <QVariant>
@@ -88,10 +91,36 @@ static vector<lyx::docstring> to_docstring_vector(QStringList const & qlist)
 
 GuiCitation::GuiCitation(GuiView & lv)
        : DialogView(lv, "citation", qt_("Citation")),
-         params_(insetCode("citation"))
+         style_(0), params_(insetCode("citation"))
 {
        setupUi(this);
 
+       // The filter bar
+       filter_ = new FancyLineEdit(this);
+       filter_->setButtonPixmap(FancyLineEdit::Right, getPixmap("images/", "editclear", "svgz,png"));
+       filter_->setButtonVisible(FancyLineEdit::Right, true);
+       filter_->setButtonToolTip(FancyLineEdit::Right, qt_("Clear text"));
+       filter_->setAutoHideButton(FancyLineEdit::Right, true);
+       filter_->setPlaceholderText(qt_("All avail. citations"));
+
+       filterBarL->addWidget(filter_, 0);
+       findKeysLA->setBuddy(filter_);
+
+       // Add search options as button menu
+       regexp_ = new QAction(qt_("Regular e&xpression"), this);
+       regexp_->setCheckable(true);
+       casesense_ = new QAction(qt_("Case se&nsitive"), this);
+       casesense_->setCheckable(true);
+       instant_ = new QAction(qt_("Search as you &type"), this);
+       instant_->setCheckable(true);
+       instant_->setChecked(true);
+
+       QMenu * searchOpts = new QMenu(this);
+       searchOpts->addAction(regexp_);
+       searchOpts->addAction(casesense_);
+       searchOpts->addAction(instant_);
+       searchOptionsPB->setMenu(searchOpts);
+
        connect(citationStyleCO, SIGNAL(activated(int)),
                this, SLOT(on_citationStyleCO_currentIndexChanged(int)));
        connect(fulllistCB, SIGNAL(clicked()),
@@ -102,8 +131,6 @@ GuiCitation::GuiCitation(GuiView & lv)
                this, SLOT(updateStyles()));
        connect(textAfterED, SIGNAL(textChanged(QString)),
                this, SLOT(updateStyles()));
-       connect(findLE, SIGNAL(returnPressed()),
-               this, SLOT(on_searchPB_clicked()));
        connect(textBeforeED, SIGNAL(returnPressed()),
                this, SLOT(on_okPB_clicked()));
        connect(textAfterED, SIGNAL(returnPressed()),
@@ -118,7 +145,20 @@ GuiCitation::GuiCitation(GuiView & lv)
        connect(selectionManager, SIGNAL(okHook()),
                this, SLOT(on_okPB_clicked()));
 
-       setFocusProxy(availableLV);
+       connect(filter_, SIGNAL(rightButtonClicked()),
+               this, SLOT(resetFilter()));
+       connect(filter_, SIGNAL(textEdited(QString)),
+               this, SLOT(filterChanged(QString)));
+       connect(filter_, SIGNAL(returnPressed()),
+               this, SLOT(filterPressed()));
+       connect(regexp_, SIGNAL(triggered()),
+               this, SLOT(regexChanged()));
+       connect(casesense_, SIGNAL(triggered()),
+               this, SLOT(caseChanged()));
+       connect(instant_, SIGNAL(triggered(bool)),
+               this, SLOT(instantChanged(bool)));
+
+       setFocusProxy(filter_);
 }
 
 
@@ -151,7 +191,7 @@ void GuiCitation::applyView()
 
 void GuiCitation::showEvent(QShowEvent * e)
 {
-       findLE->clear();
+       filter_->clear();
        availableLV->setFocus();
        DialogView::showEvent(e);
 }
@@ -181,6 +221,7 @@ void GuiCitation::on_applyPB_clicked()
 void GuiCitation::on_restorePB_clicked()
 {
        init();
+       updateFilterHint();
 }
 
 
@@ -249,9 +290,6 @@ void GuiCitation::updateStyles(BiblioInfo const & bi)
                return;
        }
 
-       if (!selectedLV->selectionModel()->selectedIndexes().empty())
-               curr = selectedLV->selectionModel()->selectedIndexes()[0].row();
-
        static const size_t max_length = 80;
        QStringList sty = citationStyles(bi, max_length);
 
@@ -266,7 +304,8 @@ void GuiCitation::updateStyles(BiblioInfo const & bi)
        citationStyleCO->blockSignals(true);
 
        // save old index
-       int const oldIndex = citationStyleCO->currentIndex();
+       int const curindex = citationStyleCO->currentIndex();
+       int const oldIndex = (curindex < 0) ? style_ : curindex;
        citationStyleCO->clear();
        citationStyleCO->insertItems(0, sty);
        citationStyleCO->setEnabled(true);
@@ -327,9 +366,11 @@ void GuiCitation::updateInfo(BiblioInfo const & bi, QModelIndex const & idx)
 {
        if (!idx.isValid() || bi.empty()) {
                infoML->document()->clear();
+               infoML->setToolTip(qt_("Displays a sketchy preview if a citation is selected above"));
                return;
        }
 
+       infoML->setToolTip(qt_("Sketchy preview of the selected citation"));
        QString const keytxt = toqstr(
                bi.getInfo(qstring_to_ucs4(idx.data().toString()), documentBuffer(), true));
        infoML->document()->setHtml(keytxt);
@@ -362,8 +403,9 @@ void GuiCitation::findText(QString const & text, bool reset)
        else
                entry_type = entries[index];
 
-       bool const case_sentitive = caseCB->checkState();
-       bool const reg_exp = regexCB->checkState();
+       bool const case_sentitive = casesense_->isChecked();
+       bool const reg_exp = regexp_->isChecked();
+
        findKey(bi, text, onlyKeys, field, entry_type,
                       case_sentitive, reg_exp, reset);
        //FIXME
@@ -377,13 +419,13 @@ void GuiCitation::findText(QString const & text, bool reset)
 
 void GuiCitation::on_fieldsCO_currentIndexChanged(int /*index*/)
 {
-       findText(findLE->text(), true);
+       findText(filter_->text(), true);
 }
 
 
 void GuiCitation::on_entriesCO_currentIndexChanged(int /*index*/)
 {
-       findText(findLE->text(), true);
+       findText(filter_->text(), true);
 }
 
 
@@ -397,43 +439,58 @@ void GuiCitation::on_citationStyleCO_currentIndexChanged(int index)
 }
 
 
-void GuiCitation::on_findLE_textChanged(const QString & text)
+void GuiCitation::filterChanged(const QString & text)
 {
-       bool const searchAsWeGo = (asTypeCB->checkState() == Qt::Checked);
-       searchPB->setDisabled(text.isEmpty() || searchAsWeGo);
        if (!text.isEmpty()) {
-               if (searchAsWeGo)
-                       findText(findLE->text());
+               if (instant_->isChecked())
+                       findText(filter_->text());
                return;
        }
-       findText(findLE->text());
-       findLE->setFocus();
+       findText(filter_->text());
+       filter_->setFocus();
+}
+
+
+void GuiCitation::filterPressed()
+{
+       findText(filter_->text(), true);
 }
 
-void GuiCitation::on_searchPB_clicked()
+
+void GuiCitation::resetFilter()
+{
+       filter_->setText(QString());
+       findText(filter_->text(), true);
+}
+
+
+void GuiCitation::caseChanged()
 {
-       findText(findLE->text(), true);
+       findText(filter_->text());
 }
 
 
-void GuiCitation::on_caseCB_stateChanged(int)
+void GuiCitation::regexChanged()
 {
-       findText(findLE->text());
+       findText(filter_->text());
 }
 
 
-void GuiCitation::on_regexCB_stateChanged(int)
+void GuiCitation::updateFilterHint()
 {
-       findText(findLE->text());
+       QString const hint = instant_->isChecked() ?
+               qt_("Enter string to filter the list of available citations") :
+               qt_("Enter string to filter the list of available citations and press <Enter>");
+       filter_->setToolTip(hint);
 }
 
 
-void GuiCitation::on_asTypeCB_stateChanged(int)
+void GuiCitation::instantChanged(bool checked)
 {
-       bool const searchAsWeGo = (asTypeCB->checkState() == Qt::Checked);
-       searchPB->setDisabled(findLE->text().isEmpty() || searchAsWeGo);
-       if (searchAsWeGo)
-               findText(findLE->text(), true);
+       if (checked)
+               findText(filter_->text(), true);
+
+       updateFilterHint();
 }
 
 
@@ -543,6 +600,7 @@ void GuiCitation::findKey(BiblioInfo const & bi,
        bool case_sensitive, bool reg_exp, bool reset)
 {
        // FIXME THREAD
+       // This should be moved to a class member.
        // Used for optimisation: store last searched string.
        static QString last_searched_string;
        // Used to disable the above optimisation.
@@ -657,18 +715,24 @@ void GuiCitation::filterByEntryType(BiblioInfo const & bi,
 static docstring escape_special_chars(docstring const & expr)
 {
        // Search for all chars '.|*?+(){}[^$]\'
-       // Note that '[' and '\' must be escaped.
-       // This is a limitation of lyx::regex, but all other chars in BREs
-       // are assumed literal.
-       static const lyx::regex reg("[].|*?+(){}^$\\[\\\\]");
+       // Note that '[', ']', and '\' must be escaped.
+       static const lyx::regex reg("[.|*?+(){}^$\\[\\]\\\\]");
 
-       // $& is a perl-like expression that expands to all
+       // $& is an ECMAScript format 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:
+#ifdef LYX_USE_STD_REGEX
+       // To prefix a matched expression with a single literal backslash, we
+       // need to escape it for the C++ compiler and use:
+       // FIXME: UNICODE
+       return from_utf8(lyx::regex_replace(to_utf8(expr), reg, string("\\$&")));
+#else
+       // A backslash in the format string starts an escape sequence in boost.
+       // Thus, to prefix a matched expression with a single literal backslash,
+       // we need to give two backslashes to the regex engine, and escape both
+       // for the C++ compiler and use:
        // FIXME: UNICODE
        return from_utf8(lyx::regex_replace(to_utf8(expr), reg, string("\\\\$&")));
+#endif
 }
 
 
@@ -751,11 +815,13 @@ void GuiCitation::saveSession() const
        Dialog::saveSession();
        QSettings settings;
        settings.setValue(
-               sessionKey() + "/regex", regexCB->isChecked());
+               sessionKey() + "/regex", regexp_->isChecked());
+       settings.setValue(
+               sessionKey() + "/casesensitive", casesense_->isChecked());
        settings.setValue(
-               sessionKey() + "/casesensitive", caseCB->isChecked());
+               sessionKey() + "/autofind", instant_->isChecked());
        settings.setValue(
-               sessionKey() + "/autofind", asTypeCB->isChecked());
+               sessionKey() + "/citestyle", style_);
 }
 
 
@@ -763,12 +829,11 @@ void GuiCitation::restoreSession()
 {
        Dialog::restoreSession();
        QSettings settings;
-       regexCB->setChecked(
-               settings.value(sessionKey() + "/regex").toBool());
-       caseCB->setChecked(
-               settings.value(sessionKey() + "/casesensitive").toBool());
-       asTypeCB->setChecked(
-               settings.value(sessionKey() + "/autofind").toBool());
+       regexp_->setChecked(settings.value(sessionKey() + "/regex").toBool());
+       casesense_->setChecked(settings.value(sessionKey() + "/casesensitive").toBool());
+       instant_->setChecked(settings.value(sessionKey() + "/autofind").toBool());
+       style_ = settings.value(sessionKey() + "/citestyle").toInt();
+       updateFilterHint();
 }