X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Ffrontends%2Fqt4%2FGuiBibtex.cpp;h=ff0a03e272222dfcb0b7d2c6eb41d12d9fea0154;hb=425d092204118ea6c24c28e85fdf03fcf2bb51a4;hp=a39de142a4e965ea94ee33f96bac144b056436fc;hpb=34492a9d033aef3d4369d4d758b01f3969ef3af0;p=lyx.git diff --git a/src/frontends/qt4/GuiBibtex.cpp b/src/frontends/qt4/GuiBibtex.cpp index a39de142a4..ff0a03e272 100644 --- a/src/frontends/qt4/GuiBibtex.cpp +++ b/src/frontends/qt4/GuiBibtex.cpp @@ -4,8 +4,9 @@ * Licence details can be found in the file COPYING. * * \author John Levon - * \author Herbert Voß - * \author Jürgen Spitzmüller + * \author Herbert Voß + * \author Angus Leeming + * \author Jürgen Spitzmüller * * Full author contact details are available in file CREDITS. */ @@ -14,47 +15,46 @@ #include "GuiBibtex.h" -#include "ui_BibtexAddUi.h" +#include "Buffer.h" +#include "BufferParams.h" +#include "FuncRequest.h" +#include "LyXRC.h" #include "qt_helpers.h" #include "Validator.h" -#include "LyXRC.h" -#include "ControlBibtex.h" +#include "ui_BibtexAddUi.h" + #include "ButtonPolicy.h" +#include "frontends/alert.h" + +#include "insets/InsetBibtex.h" + +#include "support/debug.h" +#include "support/ExceptionMessage.h" +#include "support/FileName.h" #include "support/filetools.h" // changeExtension +#include "support/gettext.h" #include "support/lstrings.h" #include #include #include -#include #include -#include "debug.h" -#include "support/filetools.h" -#include "support/lstrings.h" - -using std::vector; -using std::string; - +using namespace std; +using namespace lyx::support; namespace lyx { namespace frontend { -using support::changeExtension; -using support::split; -using support::trim; - -GuiBibtexDialog::GuiBibtexDialog(LyXView & lv) - : GuiDialog(lv, "bibtex") +GuiBibtex::GuiBibtex(GuiView & lv) + : GuiDialog(lv, "bibtex", qt_("BibTeX Bibliography")), + params_(insetCode("bibtex")) { setupUi(this); - setViewTitle( _("BibTeX Bibliography")); - setController(new ControlBibtex(*this)); - QDialog::setModal(true); connect(okPB, SIGNAL(clicked()), @@ -65,9 +65,13 @@ GuiBibtexDialog::GuiBibtexDialog(LyXView & lv) this, SLOT(browsePressed())); connect(deletePB, SIGNAL(clicked()), this, SLOT(deletePressed())); - connect(styleCB, SIGNAL(editTextChanged(const QString &)), + connect(upPB, SIGNAL(clicked()), + this, SLOT(upPressed())); + connect(downPB, SIGNAL(clicked()), + this, SLOT(downPressed())); + connect(styleCB, SIGNAL(editTextChanged(QString)), this, SLOT(change_adaptor())); - connect(databaseLW, SIGNAL(itemSelectionChanged()), + connect(databaseLW, SIGNAL(currentItemChanged(QListWidgetItem *, QListWidgetItem *)), this, SLOT(databaseChanged())); connect(bibtocCB, SIGNAL(clicked()), this, SLOT(change_adaptor())); @@ -75,6 +79,8 @@ GuiBibtexDialog::GuiBibtexDialog(LyXView & lv) this, SLOT(change_adaptor())); connect(addBibPB, SIGNAL(clicked()), this, SLOT(addPressed())); + connect(rescanPB, SIGNAL(clicked()), + this, SLOT(rescanClicked())); add_ = new GuiBibtexAddDialog(this); add_bc_.setPolicy(ButtonPolicy::OkCancelPolicy); @@ -82,17 +88,19 @@ GuiBibtexDialog::GuiBibtexDialog(LyXView & lv) add_bc_.setCancel(add_->closePB); add_bc_.addCheckedLineEdit(add_->bibED, 0); - connect(add_->bibED, SIGNAL(textChanged(const QString &)), + connect(add_->bibED, SIGNAL(textChanged(QString)), this, SLOT(bibEDChanged())); connect(add_->addPB, SIGNAL(clicked()), this, SLOT(addDatabase())); connect(add_->addPB, SIGNAL(clicked()), add_, SLOT(accept())); + connect(add_->rescanPB, SIGNAL(clicked()), + this, SLOT(rescanClicked())); connect(add_->bibLW, SIGNAL(itemActivated(QListWidgetItem *)), this, SLOT(addDatabase())); connect(add_->bibLW, SIGNAL(itemActivated(QListWidgetItem *)), add_, SLOT(accept())); - connect(add_->bibLW, SIGNAL(itemSelectionChanged()), + connect(add_->bibLW, SIGNAL(currentItemChanged(QListWidgetItem *, QListWidgetItem *)), this, SLOT(availableChanged())); connect(add_->browsePB, SIGNAL(clicked()), this, SLOT(browseBibPressed())); @@ -107,17 +115,15 @@ GuiBibtexDialog::GuiBibtexDialog(LyXView & lv) bc().addReadOnly(styleCB); bc().addReadOnly(bibtocCB); bc().addReadOnly(addBibPB); - bc().addReadOnly(deletePB); -} + // Delete/Up/Down are handled with more conditions in + // databaseChanged(). - -ControlBibtex & GuiBibtexDialog::controller() const -{ - return static_cast(GuiDialog::controller()); + // Make sure the delete/up/down buttons are disabled if necessary. + databaseChanged(); } -void GuiBibtexDialog::bibEDChanged() +void GuiBibtex::bibEDChanged() { // Indicate to the button controller that the contents have // changed. The actual test of validity is carried out by @@ -126,75 +132,75 @@ void GuiBibtexDialog::bibEDChanged() } -void GuiBibtexDialog::change_adaptor() +void GuiBibtex::change_adaptor() { changed(); } -void GuiBibtexDialog::browsePressed() +void GuiBibtex::browsePressed() { - docstring const file = controller().browseBst(docstring()); - - if (!file.empty()) { - // FIXME UNICODE - docstring const filen = from_utf8(changeExtension(to_utf8(file), "")); - bool present = false; - unsigned int pres = 0; - - for (int i = 0; i != styleCB->count(); ++i) { - if (qstring_to_ucs4(styleCB->itemText(i)) == filen) { - present = true; - pres = i; - } - } + QString const file = browseBst(QString()); - if (!present) - styleCB->insertItem(0, toqstr(filen)); + if (file.isEmpty()) + return; - styleCB->setCurrentIndex(pres); - changed(); + QString const filen = changeExtension(file, ""); + bool present = false; + unsigned int pres = 0; + + for (int i = 0; i != styleCB->count(); ++i) { + if (styleCB->itemText(i) == filen) { + present = true; + pres = i; + } } + + if (!present) + styleCB->insertItem(0, filen); + + styleCB->setCurrentIndex(pres); + changed(); } -void GuiBibtexDialog::browseBibPressed() +void GuiBibtex::browseBibPressed() { - docstring const file = trim(controller().browseBib(docstring())); + QString const file = browseBib(QString()).trimmed(); - if (!file.empty()) { - // FIXME UNICODE - QString const f = toqstr(changeExtension(to_utf8(file), "")); - bool present = false; + if (file.isEmpty()) + return; - for (int i = 0; i < add_->bibLW->count(); ++i) { - if (add_->bibLW->item(i)->text() == f) - present = true; - } + QString const f = changeExtension(file, ""); + bool present = false; - if (!present) { - add_->bibLW->addItem(f); - changed(); - } + for (int i = 0; i < add_->bibLW->count(); ++i) { + if (add_->bibLW->item(i)->text() == f) + present = true; + } - add_->bibED->setText(f); + if (!present) { + add_->bibLW->addItem(f); + changed(); } + + add_->bibED->setText(f); } -void GuiBibtexDialog::addPressed() +void GuiBibtex::addPressed() { add_bc_.setValid(false); add_->exec(); } -void GuiBibtexDialog::addDatabase() +void GuiBibtex::addDatabase() { int const sel = add_->bibLW->currentRow(); - docstring const file = trim(qstring_to_ucs4(add_->bibED->text())); + QString const file = add_->bibED->text().trimmed(); - if (sel < 0 && file.empty()) + if (sel < 0 && file.isEmpty()) return; // Add the selected browser_bib keys to browser_database @@ -205,108 +211,146 @@ void GuiBibtexDialog::addDatabase() add_->bibLW->setItemSelected(item, false); QList matches = databaseLW->findItems(item->text(), Qt::MatchExactly); - if (matches.empty()) - databaseLW->addItem(item->text()); + if (matches.empty()) { + QString label = item->text(); + QListWidgetItem * db = new QListWidgetItem(label); + db->setFlags(db->flags() | Qt::ItemIsSelectable); + databaseLW->addItem(db); + } } } - if (!file.empty()) { + if (!file.isEmpty()) { add_->bibED->clear(); - QString const f = toqstr(from_utf8(changeExtension(to_utf8(file), ""))); + QString const f = changeExtension(file, ""); QList matches = databaseLW->findItems(f, Qt::MatchExactly); - if (matches.empty()) - databaseLW->addItem(f); + if (matches.empty()) { + QListWidgetItem * db = new QListWidgetItem(f); + db->setFlags(db->flags() | Qt::ItemIsSelectable); + databaseLW->addItem(db); + } } + databaseChanged(); changed(); } -void GuiBibtexDialog::deletePressed() +void GuiBibtex::deletePressed() { - databaseLW->takeItem(databaseLW->currentRow()); + QListWidgetItem *cur = databaseLW->takeItem(databaseLW->currentRow()); + if (cur) { + delete cur; + databaseChanged(); + changed(); + } +} + + +void GuiBibtex::upPressed() +{ + int row = databaseLW->currentRow(); + QListWidgetItem *cur = databaseLW->takeItem(row); + databaseLW->insertItem(row - 1, cur); + databaseLW->setCurrentItem(cur); changed(); } +void GuiBibtex::downPressed() +{ + int row = databaseLW->currentRow(); + QListWidgetItem *cur = databaseLW->takeItem(row); + databaseLW->insertItem(row + 1, cur); + databaseLW->setCurrentItem(cur); + changed(); +} + -void GuiBibtexDialog::databaseChanged() +void GuiBibtex::rescanClicked() { - deletePB->setEnabled(!readOnly() && databaseLW->currentRow() != -1); + rescanBibStyles(); + updateContents(); } -void GuiBibtexDialog::availableChanged() +void GuiBibtex::databaseChanged() { - add_bc_.setValid(true); + bool readOnly = isBufferReadonly(); + int count = databaseLW->count(); + int row = databaseLW->currentRow(); + deletePB->setEnabled(!readOnly && row != -1); + upPB->setEnabled(!readOnly && count > 1 && row > 0); + downPB->setEnabled(!readOnly && count > 1 && row < count - 1); } -void GuiBibtexDialog::closeEvent(QCloseEvent *e) +void GuiBibtex::availableChanged() { - slotClose(); - e->accept(); + add_bc_.setValid(true); } -void GuiBibtexDialog::update_contents() +void GuiBibtex::updateContents() { - bool bibtopic = controller().usingBibtopic(); + bool bibtopic = usingBibtopic(); databaseLW->clear(); - docstring bibs(controller().params()["bibfiles"]); + docstring bibs = params_["bibfiles"]; docstring bib; while (!bibs.empty()) { bibs = split(bibs, bib, ','); bib = trim(bib); - if (!bib.empty()) - databaseLW->addItem(toqstr(bib)); + if (!bib.empty()) { + QListWidgetItem * db = new QListWidgetItem(toqstr(bib)); + db->setFlags(db->flags() | Qt::ItemIsSelectable); + databaseLW->addItem(db); + } } add_->bibLW->clear(); - vector bib_str; - controller().getBibFiles(bib_str); - for (vector::const_iterator it = bib_str.begin(); - it != bib_str.end(); ++it) { - string bibItem(changeExtension(*it, "")); - add_->bibLW->addItem(toqstr(bibItem)); - } + QStringList bibfiles = bibFiles(); + for (int i = 0; i != bibfiles.count(); ++i) + add_->bibLW->addItem(changeExtension(bibfiles[i], "")); - string bibstyle(controller().getStylefile()); + QString bibstyle = styleFile(); - bibtocCB->setChecked(controller().bibtotoc() && !bibtopic); + bibtocCB->setChecked(bibtotoc() && !bibtopic); bibtocCB->setEnabled(!bibtopic); - docstring btprint(controller().params()["btprint"]); + if (!bibtopic && btPrintCO->count() == 3) + btPrintCO->removeItem(1); + else if (bibtopic && btPrintCO->count() < 3) + btPrintCO->insertItem(1, qt_("all uncited references", 0)); + + docstring btprint = params_["btprint"]; int btp = 0; - if (btprint == "btPrintNotCited") + if ((bibtopic && btprint == "btPrintNotCited") || + (!bibtopic && btprint == "btPrintAll")) btp = 1; - else if (btprint == "btPrintAll") + else if (bibtopic && btprint == "btPrintAll") btp = 2; btPrintCO->setCurrentIndex(btp); - btPrintCO->setEnabled(bibtopic); styleCB->clear(); - int item_nr(-1); + int item_nr = -1; - vector str; - controller().getBibStyles(str); - for (vector::const_iterator it = str.begin(); - it != str.end(); ++it) { - string item(changeExtension(*it, "")); + QStringList str = bibStyles(); + for (int i = 0; i != str.count(); ++i) { + QString item = changeExtension(str[i], ""); if (item == bibstyle) - item_nr = int(it - str.begin()); - styleCB->addItem(toqstr(item)); + item_nr = i; + styleCB->addItem(item); } - if (item_nr == -1 && !bibstyle.empty()) { - styleCB->addItem(toqstr(bibstyle)); + if (item_nr == -1 && !bibstyle.isEmpty()) { + styleCB->addItem(bibstyle); item_nr = styleCB->count() - 1; } @@ -317,63 +361,209 @@ void GuiBibtexDialog::update_contents() } -void GuiBibtexDialog::applyView() +void GuiBibtex::applyView() { - docstring dbs = qstring_to_ucs4(databaseLW->item(0)->text()); + docstring dbs; unsigned int maxCount = databaseLW->count(); - for (unsigned int i = 1; i < maxCount; i++) { - dbs += ','; - dbs += qstring_to_ucs4(databaseLW->item(i)->text()); + for (unsigned int i = 0; i < maxCount; i++) { + if (i != 0) + dbs += ','; + QString item = databaseLW->item(i)->text(); + docstring bibfile = qstring_to_ucs4(item); + dbs += bibfile; } - controller().params()["bibfiles"] = dbs; + params_["bibfiles"] = dbs; - docstring const bibstyle(qstring_to_ucs4(styleCB->currentText())); - bool const bibtotoc(bibtocCB->isChecked()); + docstring const bibstyle = qstring_to_ucs4(styleCB->currentText()); + bool const bibtotoc = bibtocCB->isChecked(); - if (bibtotoc && (!bibstyle.empty())) { + if (bibtotoc && !bibstyle.empty()) { // both bibtotoc and style - controller().params()["options"] = "bibtotoc," + bibstyle; + params_["options"] = "bibtotoc," + bibstyle; } else if (bibtotoc) { // bibtotoc and no style - controller().params()["options"] = from_ascii("bibtotoc"); + params_["options"] = from_ascii("bibtotoc"); } else { // only style. An empty one is valid, because some // documentclasses have an own \bibliographystyle{} // command! - controller().params()["options"] = bibstyle; + params_["options"] = bibstyle; } - // bibtopic allows three kinds of sections: - // 1. sections that include all cited references of the database(s) - // 2. sections that include all uncited references of the database(s) - // 3. sections that include all references of the database(s), cited or not int btp = btPrintCO->currentIndex(); - switch (btp) { - case 0: - controller().params()["btprint"] = from_ascii("btPrintCited"); + if (usingBibtopic()) { + // bibtopic allows three kinds of sections: + // 1. sections that include all cited references of the database(s) + // 2. sections that include all uncited references of the database(s) + // 3. sections that include all references of the database(s), cited or not + switch (btp) { + case 0: + params_["btprint"] = from_ascii("btPrintCited"); + break; + case 1: + params_["btprint"] = from_ascii("btPrintNotCited"); + break; + case 2: + params_["btprint"] = from_ascii("btPrintAll"); + break; + } + } else { + switch (btp) { + case 0: + params_["btprint"] = docstring(); + break; + case 1: + // use \nocite{*} + params_["btprint"] = from_ascii("btPrintAll"); + break; + } + } +} + + +bool GuiBibtex::isValid() +{ + return databaseLW->count() != 0; +} + + +QString GuiBibtex::browseBib(QString const & in_name) const +{ + QString const label1 = qt_("Documents|#o#O"); + QString const dir1 = toqstr(lyxrc.document_path); + QStringList const filter(qt_("BibTeX Databases (*.bib)")); + return browseRelFile(in_name, bufferFilepath(), + qt_("Select a BibTeX database to add"), filter, false, label1, dir1); +} + + +QString GuiBibtex::browseBst(QString const & in_name) const +{ + QString const label1 = qt_("Documents|#o#O"); + QString const dir1 = toqstr(lyxrc.document_path); + QStringList const filter(qt_("BibTeX Styles (*.bst)")); + return browseRelFile(in_name, bufferFilepath(), + qt_("Select a BibTeX style"), filter, false, label1, dir1); +} + + +QStringList GuiBibtex::bibStyles() const +{ + QStringList data = texFileList("bstFiles.lst"); + // test whether we have a valid list, otherwise run rescan + if (data.isEmpty()) { + rescanBibStyles(); + data = texFileList("bstFiles.lst"); + } + for (int i = 0; i != data.size(); ++i) + data[i] = onlyFilename(data[i]); + // sort on filename only (no path) + data.sort(); + return data; +} + + +QStringList GuiBibtex::bibFiles() const +{ + QStringList data = texFileList("bibFiles.lst"); + // test whether we have a valid list, otherwise run rescan + if (data.isEmpty()) { + rescanBibStyles(); + data = texFileList("bibFiles.lst"); + } + for (int i = 0; i != data.size(); ++i) + data[i] = onlyFilename(data[i]); + // sort on filename only (no path) + data.sort(); + return data; +} + + +void GuiBibtex::rescanBibStyles() const +{ + rescanTexStyles(); +} + + +bool GuiBibtex::usingBibtopic() const +{ + return buffer().params().use_bibtopic; +} + + +bool GuiBibtex::bibtotoc() const +{ + return prefixIs(to_utf8(params_["options"]), "bibtotoc"); +} + + +QString GuiBibtex::styleFile() const +{ + // the different bibtex packages have (and need) their + // own "plain" stylefiles + CiteEngine const engine = buffer().params().citeEngine(); + QString defaultstyle; + switch (engine) { + case ENGINE_BASIC: + defaultstyle = "plain"; + break; + case ENGINE_NATBIB_AUTHORYEAR: + defaultstyle = "plainnat"; break; - case 1: - controller().params()["btprint"] = from_ascii("btPrintNotCited"); + case ENGINE_NATBIB_NUMERICAL: + defaultstyle = "plainnat"; break; - case 2: - controller().params()["btprint"] = from_ascii("btPrintAll"); + case ENGINE_JURABIB: + defaultstyle = "jurabib"; break; } - if (!controller().usingBibtopic()) - controller().params()["btprint"] = docstring(); + QString bst = toqstr(params_["options"]); + if (bibtotoc()){ + // bibstyle exists? + int pos = bst.indexOf(','); + if (pos != -1) { + // FIXME: check + // docstring bibtotoc = from_ascii("bibtotoc"); + // bst = split(bst, bibtotoc, ','); + bst = bst.mid(pos + 1); + } else { + bst.clear(); + } + } + + // propose default style file for new insets + // existing insets might have (legally) no bst files + // (if the class already provides a style) + if (bst.isEmpty() && params_["bibfiles"].empty()) + bst = defaultstyle; + + return bst; } -bool GuiBibtexDialog::isValid() +bool GuiBibtex::initialiseParams(std::string const & data) { - return databaseLW->count() != 0; + InsetCommand::string2params("bibtex", data, params_); + return true; +} + + +void GuiBibtex::dispatchParams() +{ + std::string const lfun = InsetCommand::params2string("bibtex", params_); + dispatch(FuncRequest(getLfun(), lfun)); } + + +Dialog * createGuiBibtex(GuiView & lv) { return new GuiBibtex(lv); } + + } // namespace frontend } // namespace lyx -#include "GuiBibtex_moc.cpp" +#include "moc_GuiBibtex.cpp"