* \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>
// 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);
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()),
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()),
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."));
QString const after = textAfterED->text();
applyParams(choice, full, force, before, after);
+ connectToNewInset();
}
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);
availableLV->setToolTip(qt_("All references available for citing.\n"
"To add the selected one, hit Add, press Enter or double-click.\n"
"Hit Ctrl-Enter to add and close the dialog."));
+ // With qualified citation lists, it makes sense to add the same key multiple times
+ selectionManager->allowMultiSelection(currentStyle.hasQualifiedList);
}
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);
// 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();
}
-void GuiCitation::setSelectedKeys(QStringList const sl)
+void GuiCitation::setSelectedKeys(QStringList const & sl)
{
selected_model_.clear();
selected_model_.setColumnCount(3);
}
-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;
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;
+ }
+ }
}
}
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;
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;
+ }
+ }
}
}
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;
&& (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());
void GuiCitation::filterByEntryType(BiblioInfo const & bi,
- vector<docstring> & keyVector, docstring entry_type)
+ vector<docstring> & keyVector, docstring const & entry_type)
{
if (entry_type.empty())
return;
{
// 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;
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>();
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>();
}
}
-Dialog * createGuiCitation(GuiView & lv) { return new GuiCitation(lv); }
-
-
} // namespace frontend
} // namespace lyx