]> git.lyx.org Git - lyx.git/blobdiff - src/frontends/qt/GuiCitation.cpp
Make string-widget combination more l7n friendly
[lyx.git] / src / frontends / qt / GuiCitation.cpp
index 3ef4bb77f3135a4f81c8701553881720849fa821..c5fa26631098b17c331d78b0fc71ea603b2b0c45 100644 (file)
@@ -7,7 +7,7 @@
  * \author Angus Leeming
  * \author Kalle Dalheimer
  * \author Abdelrazak Younes
- * \author Richard Heck
+ * \author Richard Kimberly Heck
  *
  * Full author contact details are available in file CREDITS.
  */
 
 #include "GuiCitation.h"
 
+#include "FancyLineEdit.h"
 #include "GuiApplication.h"
 #include "GuiSelectionManager.h"
+#include "GuiView.h"
 #include "qt_helpers.h"
 
 #include "Buffer.h"
 #include "BufferView.h"
-#include "BiblioInfo.h"
 #include "BufferParams.h"
+#include "Citation.h"
+#include "Cursor.h"
 #include "TextClass.h"
 #include "FuncRequest.h"
 
 #include <QStandardItemModel>
 #include <QVariant>
 
-#include <vector>
-#include <string>
-
 #undef KeyPress
 
-#include "support/regex.h"
-
 #include <algorithm>
+#include <regex>
 #include <string>
 #include <vector>
 
@@ -99,10 +98,7 @@ GuiCitation::GuiCitation(GuiView & lv)
 
        // 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_->setClearButton(true);
        filter_->setPlaceholderText(qt_("All avail. citations"));
 
        filterBarL->addWidget(filter_, 0);
@@ -144,6 +140,8 @@ GuiCitation::GuiCitation(GuiView & lv)
                        addPB, deletePB, upPB, downPB, &available_model_, &selected_model_, 1);
        connect(selectionManager, SIGNAL(selectionChanged()),
                this, SLOT(setCitedKeys()));
+       connect(selectionManager, SIGNAL(updateHook()),
+               this, SLOT(setCitedKeys()));
        connect(selectionManager, SIGNAL(updateHook()),
                this, SLOT(updateControls()));
        connect(selectionManager, SIGNAL(okHook()),
@@ -155,13 +153,8 @@ GuiCitation::GuiCitation(GuiView & lv)
                this, SLOT(filterChanged(QString)));
        connect(filter_, SIGNAL(returnPressed()),
                this, SLOT(filterPressed()));
-#if (QT_VERSION < 0x050000)
-       connect(filter_, SIGNAL(downPressed()),
-               availableLV, SLOT(setFocus()));
-#else
        connect(filter_, &FancyLineEdit::downPressed,
-               availableLV, [=](){ focusAndHighlight(availableLV); });
-#endif
+               availableLV, [this](){ focusAndHighlight(availableLV); });
        connect(regexp_, SIGNAL(triggered()),
                this, SLOT(regexChanged()));
        connect(casesense_, SIGNAL(triggered()),
@@ -169,11 +162,7 @@ GuiCitation::GuiCitation(GuiView & lv)
        connect(instant_, SIGNAL(triggered(bool)),
                this, SLOT(instantChanged(bool)));
 
-#if (QT_VERSION < 0x050000)
-       selectedLV->horizontalHeader()->setResizeMode(QHeaderView::Stretch);
-#else
        selectedLV->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
-#endif
 
        selectedLV->setToolTip(qt_("Ordered list of all cited references.\n"
                                   "You can reorder, add and remove references with the buttons on the left."));
@@ -199,6 +188,7 @@ void GuiCitation::applyView()
        QString const after = textAfterED->text();
 
        applyParams(choice, full, force, before, after);
+       connectToNewInset();
 }
 
 
@@ -284,12 +274,7 @@ void GuiCitation::updateFormatting(CitationStyle const & currentStyle)
 
        int const rows = selectedLV->model()->rowCount();
 
-       bool const qualified = currentStyle.hasQualifiedList
-               && (rows > 1
-                   || !params_["pretextlist"].empty()
-                   || !params_["posttextlist"].empty()
-                   || !getPreTexts().empty()
-                   || !getPostTexts().empty());
+       bool const qualified = currentStyle.hasQualifiedList && rows > 0;
 
        selectedLV->horizontalHeader()->setVisible(qualified);
        selectedLV->setColumnHidden(0, !qualified);
@@ -391,6 +376,8 @@ void GuiCitation::updateStyles(BiblioInfo const & bi)
        int curr = selectedLV->model()->rowCount() - 1;
 
        if (curr < 0 || selected_keys.empty()) {
+               last_chosen_style_ =
+                       citationStyleCO->itemData(citationStyleCO->currentIndex()).toString();
                citationStyleCO->clear();
                citationStyleCO->setEnabled(false);
                citationStyleLA->setEnabled(false);
@@ -413,7 +400,10 @@ void GuiCitation::updateStyles(BiblioInfo const & bi)
        // save old style selection
        QString const curdata =
                citationStyleCO->itemData(citationStyleCO->currentIndex()).toString();
-       QString const olddata = (curdata.isEmpty()) ? style_ : curdata;
+       QString const olddata = (curdata.isEmpty()) ?
+               (last_chosen_style_.isEmpty() ? style_ : last_chosen_style_): curdata;
+       // reset this
+       last_chosen_style_.clear();
        citationStyleCO->clear();
        BiblioInfo::CiteStringMap::const_iterator cit = sty.begin();
        BiblioInfo::CiteStringMap::const_iterator end = sty.end();
@@ -654,7 +644,7 @@ void GuiCitation::clearSelection()
 }
 
 
-void GuiCitation::setSelectedKeys(QStringList const sl)
+void GuiCitation::setSelectedKeys(QStringList const sl)
 {
        selected_model_.clear();
        selected_model_.setColumnCount(3);
@@ -692,8 +682,10 @@ QStringList GuiCitation::selectedKeys()
 }
 
 
-void GuiCitation::setPreTexts(vector<docstring> const m)
+void GuiCitation::setPreTexts(vector<docstring> const m)
 {
+       // account for multiple use of the same keys
+       QList<QModelIndex> handled;
        for (docstring const & s: m) {
                QStandardItem * si = new QStandardItem();
                docstring key;
@@ -701,11 +693,16 @@ void GuiCitation::setPreTexts(vector<docstring> const m)
                si->setData(toqstr(pre));
                si->setText(toqstr(pre));
                QModelIndexList qmil =
-                               selected_model_.match(selected_model_.index(0, 1),
-                                                    Qt::DisplayRole, toqstr(key), 1,
-                                                    Qt::MatchFlags(Qt::MatchExactly | Qt::MatchWrap));
-               if (!qmil.empty())
-                       selected_model_.setItem(qmil.front().row(), 0, si);
+                       selected_model_.match(selected_model_.index(0, 1),
+                                            Qt::DisplayRole, toqstr(key), -1,
+                                            Qt::MatchFlags(Qt::MatchExactly | Qt::MatchWrap));
+               for (auto const & idx : qmil) {
+                       if (!handled.contains(idx)) {
+                               selected_model_.setItem(idx.row(), 0, si);
+                               handled.append(idx);
+                               break;
+                       }
+               }
        }
 }
 
@@ -716,15 +713,17 @@ vector<docstring> GuiCitation::getPreTexts()
        for (int i = 0; i != selected_model_.rowCount(); ++i) {
                QStandardItem const * key = selected_model_.item(i, 1);
                QStandardItem const * pre = selected_model_.item(i, 0);
-               if (key && pre && !key->text().isEmpty() && !pre->text().isEmpty())
+               if (key && pre && !key->text().isEmpty())
                        res.push_back(qstring_to_ucs4(key->text()) + " " + qstring_to_ucs4(pre->text()));
        }
        return res;
 }
 
 
-void GuiCitation::setPostTexts(vector<docstring> const m)
+void GuiCitation::setPostTexts(vector<docstring> const m)
 {
+       // account for multiple use of the same keys
+       QList<QModelIndex> handled;
        for (docstring const & s: m) {
                QStandardItem * si = new QStandardItem();
                docstring key;
@@ -732,11 +731,16 @@ void GuiCitation::setPostTexts(vector<docstring> const m)
                si->setData(toqstr(post));
                si->setText(toqstr(post));
                QModelIndexList qmil =
-                               selected_model_.match(selected_model_.index(0, 1),
-                                                    Qt::DisplayRole, toqstr(key), 1,
-                                                    Qt::MatchFlags(Qt::MatchExactly | Qt::MatchWrap));
-               if (!qmil.empty())
-                       selected_model_.setItem(qmil.front().row(), 2, si);
+                       selected_model_.match(selected_model_.index(0, 1),
+                                            Qt::DisplayRole, toqstr(key), -1,
+                                            Qt::MatchFlags(Qt::MatchExactly | Qt::MatchWrap));
+               for (auto const & idx : qmil) {
+                       if (!handled.contains(idx)) {
+                               selected_model_.setItem(idx.row(), 2, si);
+                               handled.append(idx);
+                               break;
+                       }
+               }
        }
 }
 
@@ -747,7 +751,7 @@ vector<docstring> GuiCitation::getPostTexts()
        for (int i = 0; i != selected_model_.rowCount(); ++i) {
                QStandardItem const * key = selected_model_.item(i, 1);
                QStandardItem const * post = selected_model_.item(i, 2);
-               if (key && post && !key->text().isEmpty() && !post->text().isEmpty())
+               if (key && post && !key->text().isEmpty())
                        res.push_back(qstring_to_ucs4(key->text()) + " " + qstring_to_ucs4(post->text()));
        }
        return res;
@@ -894,17 +898,17 @@ BiblioInfo::CiteStringMap GuiCitation::citationStyles(BiblioInfo const & bi, siz
                && (selectedLV->model()->rowCount() > 1
                    || !pretexts.empty()
                    || !posttexts.empty());
-       std::map<docstring, docstring> pres;
+       vector<pair<docstring, docstring>> pres;
        for (docstring const & s: pretexts) {
                docstring key;
                docstring val = split(s, key, ' ');
-               pres[key] = val;
+               pres.push_back(make_pair(key, val));
        }
-       std::map<docstring, docstring> posts;
+       vector<pair<docstring, docstring>> posts;
        for (docstring const & s: posttexts) {
                docstring key;
                docstring val = split(s, key, ' ');
-               posts[key] = val;
+               posts.push_back(make_pair(key, val));
        }
        CiteItem ci;
        ci.textBefore = qstring_to_ucs4(textBeforeED->text());
@@ -945,7 +949,7 @@ void GuiCitation::clearParams()
 
 
 void GuiCitation::filterByEntryType(BiblioInfo const & bi,
-       vector<docstring> & keyVector, docstring entry_type)
+       vector<docstring> & keyVector, docstring const & entry_type)
 {
        if (entry_type.empty())
                return;
@@ -975,30 +979,21 @@ static docstring escape_special_chars(docstring const & expr)
 {
        // Search for all chars '.|*?+(){}[^$]\'
        // Note that '[', ']', and '\' must be escaped.
-       static const lyx::regex reg("[.|*?+(){}^$\\[\\]\\\\]");
+       static const regex reg("[.|*?+(){}^$\\[\\]\\\\]");
 
        // $& is an ECMAScript format expression that expands to all
        // of the current match
-#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
+       return from_utf8(regex_replace(to_utf8(expr), reg, string("\\$&")));
 }
 
 
 vector<docstring> GuiCitation::searchKeys(BiblioInfo const & bi,
        vector<docstring> const & keys_to_search, bool only_keys,
-       docstring const & search_expression, docstring field,
-       bool case_sensitive, bool regex)
+       docstring const & search_expression, docstring const & field,
+       bool case_sensitive, bool re)
 {
        vector<docstring> foundKeys;
 
@@ -1006,17 +1001,17 @@ vector<docstring> GuiCitation::searchKeys(BiblioInfo const & bi,
        if (expr.empty())
                return foundKeys;
 
-       if (!regex)
+       if (!re)
                // We must escape special chars in the search_expr so that
-               // it is treated as a simple string by lyx::regex.
+               // it is treated as a simple string by regex.
                expr = escape_special_chars(expr);
 
-       lyx::regex reg_exp;
+       regex reg_exp;
        try {
                reg_exp.assign(to_utf8(expr), case_sensitive ?
-                       lyx::regex_constants::ECMAScript : lyx::regex_constants::icase);
-       } catch (lyx::regex_error const & e) {
-               // lyx::regex throws an exception if the regular expression is not
+                       regex_constants::ECMAScript : regex_constants::icase);
+       } catch (regex_error const & e) {
+               // regex throws an exception if the regular expression is not
                // valid.
                LYXERR(Debug::GUI, e.what());
                return vector<docstring>();
@@ -1042,10 +1037,10 @@ vector<docstring> GuiCitation::searchKeys(BiblioInfo const & bi,
                        continue;
 
                try {
-                       if (lyx::regex_search(sdata, reg_exp))
+                       if (regex_search(sdata, reg_exp))
                                foundKeys.push_back(*it);
                }
-               catch (lyx::regex_error const & e) {
+               catch (regex_error const & e) {
                        LYXERR(Debug::GUI, e.what());
                        return vector<docstring>();
                }
@@ -1099,9 +1094,6 @@ void GuiCitation::restoreSession()
 }
 
 
-Dialog * createGuiCitation(GuiView & lv) { return new GuiCitation(lv); }
-
-
 } // namespace frontend
 } // namespace lyx