The attached patch resolved the following tickets: #6486 Citation not selected by default. #6487 Add "file" and "url" links to Citation Dialog.
This means that if you are reading you see something like "As proved by [ABC09] 1+1=3" you can double click the ABC09 and immediately get the citation info (#6486). If the document has a DOI or a Jabref url field you can click the URL button to load the website of the citation and check whether ABC09 really does prove that 1+1=3; if there is a JabRef file field, you can also click the "File" button to open your local copy of the file (#6487). I find this makes checking my citations much easier than with the existing LyX behavior. Would you like me to split this into two patches (on for #6486 and one for #6487?). Is the following OK? I note we have existing code for opening files, but that code seems to be for opening files exported from a Buffer. If so it should perhaps be merged with similar code in backtrace-helper +// Tells OS to open a File or URL +// Formats::view does not seem appropriate as it wants a Buffer +static void system_viewer (string url) { + string open_cmd; + #ifdef _WIN32 + open_cmd = "start"; + #elif defined(USE_MACOSX_PACKAGING) + open_cmd = "open"; + #else + open_cmd = "xdg-open"; + #endif + string cmd = open_cmd + " \"" + url + "\" &"; + int result = system(cmd.c_str()); + if (result) { + Alert::warning(_("Could not open file"), bformat(_("Command \n$1%s\n Exited with Error#$2%d"), from_local8bit(cmd), result)); + } +} John C. McCabe-Dansted
Index: BiblioInfo.cpp =================================================================== --- BiblioInfo.cpp (revision 33816) +++ BiblioInfo.cpp (working copy) @@ -248,6 +248,43 @@ } +docstring const BibTeXInfo::getFile() const +{ + if (is_bibtex_) + return operator[]("file"); + return docstring(); +} + + +docstring const BibTeXInfo::getURL() const +{ + if (is_bibtex_) { + if (operator[]("url").empty()) { + docstring doi = operator[]("doi"); + if (doi.empty()) { + // We could also try falling back to something like + // http://www.google.com.au/search?ie=UTF-8&q=... + return docstring(); + } else { + if (prefixIs(doi, from_ascii("http:"))) { + return doi; + } + if (prefixIs(lowercase(doi), from_ascii("doi:"))) { + doi = doi.substr(4); + doi = ltrim(doi); + } + + return "http://dx.doi.org/" + doi; + } + } else { + return operator[]("url"); + } + } + return docstring(); +} + + + docstring const BibTeXInfo::getYear() const { if (is_bibtex_) @@ -441,6 +478,28 @@ } +docstring const BiblioInfo::getFile(docstring const & key) const +{ + BiblioInfo::const_iterator it = find(key); + if (it == end()) + return docstring(); + BibTeXInfo const & data = it->second; + docstring file = data.getFile(); + return file; +} + + +docstring const BiblioInfo::getURL(docstring const & key) const +{ + BiblioInfo::const_iterator it = find(key); + if (it == end()) + return docstring(); + BibTeXInfo const & data = it->second; + docstring url = data.getURL(); + return url; +} + + docstring const BiblioInfo::getYear(docstring const & key, bool use_modifier) const { BiblioInfo::const_iterator it = find(key); Index: BiblioInfo.h =================================================================== --- BiblioInfo.h (revision 33816) +++ BiblioInfo.h (working copy) @@ -56,7 +56,9 @@ /// \return the short form of an authorlist docstring const getAbbreviatedAuthor() const; /// - docstring const getYear() const; + docstring const getFile() const; + docstring const getURL() const; + docstring const getYear() const; /// docstring const getXRef() const; /// \return formatted BibTeX data suitable for framing. @@ -143,7 +145,9 @@ std::vector<docstring> const getEntries() const; /// \return the short form of an authorlist docstring const getAbbreviatedAuthor(docstring const & key) const; - /// \return the year from the bibtex data record for \param key + docstring const getFile(docstring const & key) const; + docstring const getURL(docstring const & key) const; + /// \return the year from the bibtex data record for \param key /// if \param use_modifier is true, then we will also append any /// modifier for this entry (e.g., 1998b). /// Note that this will get the year from the crossref if it's Index: frontends/qt4/ui/CitationUi.ui =================================================================== --- frontends/qt4/ui/CitationUi.ui (revision 33816) +++ frontends/qt4/ui/CitationUi.ui (working copy) @@ -1,3 +1,4 @@ +<?xml version="1.0" encoding="UTF-8"?> <ui version="4.0"> <class>CitationUi</class> <widget class="QDialog" name="CitationUi"> @@ -19,7 +20,7 @@ <item row="0" column="0" colspan="3"> <layout class="QHBoxLayout"> <property name="spacing"> - <number>6</number> + <number>8</number> </property> <property name="margin"> <number>0</number> @@ -59,7 +60,7 @@ </item> </layout> </item> - <item row="1" column="0" rowspan="5"> + <item row="1" column="0" rowspan="7"> <widget class="QListView" name="availableLV"> <property name="editTriggers"> <set>QAbstractItemView::NoEditTriggers</set> @@ -79,7 +80,7 @@ </property> </widget> </item> - <item row="1" column="2" rowspan="5"> + <item row="1" column="2" rowspan="7"> <widget class="QListView" name="selectedLV"> <property name="editTriggers"> <set>QAbstractItemView::NoEditTriggers</set> @@ -107,12 +108,66 @@ <property name="sizeHint" stdset="0"> <size> <width>77</width> - <height>71</height> + <height>41</height> </size> </property> </spacer> </item> <item row="4" column="1"> + <widget class="QPushButton" name="filePB"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="toolTip"> + <string>Open Local Copy of this Cited Work</string> + </property> + <property name="text"> + <string>&File</string> + </property> + <property name="icon"> + <iconset> + <normaloff/> + </iconset> + </property> + <property name="autoDefault"> + <bool>false</bool> + </property> + </widget> + </item> + <item row="5" column="1"> + <widget class="QPushButton" name="urlPB"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="toolTip"> + <string>Open Webpage of Citation</string> + </property> + <property name="text"> + <string>&URL</string> + </property> + <property name="icon"> + <iconset> + <normaloff/> + </iconset> + </property> + <property name="autoDefault"> + <bool>false</bool> + </property> + </widget> + </item> + <item row="6" column="1"> <widget class="QPushButton" name="upPB"> <property name="sizePolicy"> <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> @@ -136,7 +191,7 @@ </property> </widget> </item> - <item row="5" column="1"> + <item row="7" column="1"> <widget class="QPushButton" name="downPB"> <property name="sizePolicy"> <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> @@ -160,7 +215,73 @@ </property> </widget> </item> - <item row="6" column="0" colspan="3"> + <item row="11" column="0" colspan="3"> + <layout class="QHBoxLayout"> + <property name="spacing"> + <number>6</number> + </property> + <property name="margin"> + <number>0</number> + </property> + <item> + <widget class="QPushButton" name="restorePB"> + <property name="text"> + <string>&Restore</string> + </property> + <property name="autoDefault"> + <bool>false</bool> + </property> + </widget> + </item> + <item> + <spacer> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="okPB"> + <property name="text"> + <string>&OK</string> + </property> + <property name="autoDefault"> + <bool>false</bool> + </property> + <property name="default"> + <bool>false</bool> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="applyPB"> + <property name="text"> + <string>App&ly</string> + </property> + <property name="autoDefault"> + <bool>false</bool> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="cancelPB"> + <property name="text"> + <string>&Cancel</string> + </property> + <property name="autoDefault"> + <bool>false</bool> + </property> + </widget> + </item> + </layout> + </item> + <item row="8" column="0" colspan="3"> <widget class="QTextEdit" name="infoML"> <property name="acceptDrops"> <bool>false</bool> @@ -170,7 +291,113 @@ </property> </widget> </item> - <item row="7" column="0" colspan="3"> + <item row="10" column="0" colspan="3"> + <widget class="QGroupBox" name="styleGB"> + <property name="title"> + <string>Formatting</string> + </property> + <property name="flat"> + <bool>true</bool> + </property> + <layout class="QGridLayout"> + <item row="0" column="0"> + <widget class="QLabel" name="citationStyleLA"> + <property name="text"> + <string>Citation st&yle:</string> + </property> + <property name="buddy"> + <cstring>citationStyleCO</cstring> + </property> + </widget> + </item> + <item row="0" column="1" colspan="3"> + <widget class="QComboBox" name="citationStyleCO"> + <property name="toolTip"> + <string>Natbib citation style to use</string> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="textBeforeLA"> + <property name="text"> + <string>Text &before:</string> + </property> + <property name="buddy"> + <cstring>textBeforeED</cstring> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QLineEdit" name="textBeforeED"> + <property name="toolTip"> + <string>Text to place before citation</string> + </property> + </widget> + </item> + <item row="1" column="2"> + <widget class="QLabel" name="textAfterLA"> + <property name="text"> + <string>Text a&fter:</string> + </property> + <property name="buddy"> + <cstring>textAfterED</cstring> + </property> + </widget> + </item> + <item row="1" column="3"> + <widget class="QLineEdit" name="textAfterED"> + <property name="toolTip"> + <string>Text to place after citation</string> + </property> + </widget> + </item> + <item row="2" column="0" colspan="4"> + <layout class="QHBoxLayout"> + <property name="spacing"> + <number>6</number> + </property> + <property name="margin"> + <number>0</number> + </property> + <item> + <spacer> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>21</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QCheckBox" name="fulllistCB"> + <property name="toolTip"> + <string>List all authors</string> + </property> + <property name="text"> + <string>Full aut&hor list</string> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="forceuppercaseCB"> + <property name="toolTip"> + <string>Force upper case in citation</string> + </property> + <property name="text"> + <string>Force u&pper case</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + </item> + <item row="9" column="0" colspan="3"> <widget class="QGroupBox" name="groupBox"> <property name="title"> <string>Search Citation</string> @@ -327,179 +554,15 @@ </layout> </widget> </item> - <item row="8" column="0" colspan="3"> - <widget class="QGroupBox" name="styleGB"> - <property name="title"> - <string>Formatting</string> - </property> - <property name="flat"> - <bool>true</bool> - </property> - <layout class="QGridLayout"> - <item row="0" column="0"> - <widget class="QLabel" name="citationStyleLA"> - <property name="text"> - <string>Citation st&yle:</string> - </property> - <property name="buddy"> - <cstring>citationStyleCO</cstring> - </property> - </widget> - </item> - <item row="0" column="1" colspan="3"> - <widget class="QComboBox" name="citationStyleCO"> - <property name="toolTip"> - <string>Natbib citation style to use</string> - </property> - </widget> - </item> - <item row="1" column="0"> - <widget class="QLabel" name="textBeforeLA"> - <property name="text"> - <string>Text &before:</string> - </property> - <property name="buddy"> - <cstring>textBeforeED</cstring> - </property> - </widget> - </item> - <item row="1" column="1"> - <widget class="QLineEdit" name="textBeforeED"> - <property name="toolTip"> - <string>Text to place before citation</string> - </property> - </widget> - </item> - <item row="1" column="2"> - <widget class="QLabel" name="textAfterLA"> - <property name="text"> - <string>Text a&fter:</string> - </property> - <property name="buddy"> - <cstring>textAfterED</cstring> - </property> - </widget> - </item> - <item row="1" column="3"> - <widget class="QLineEdit" name="textAfterED"> - <property name="toolTip"> - <string>Text to place after citation</string> - </property> - </widget> - </item> - <item row="2" column="0" colspan="4"> - <layout class="QHBoxLayout"> - <property name="spacing"> - <number>6</number> - </property> - <property name="margin"> - <number>0</number> - </property> - <item> - <spacer> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>21</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QCheckBox" name="fulllistCB"> - <property name="toolTip"> - <string>List all authors</string> - </property> - <property name="text"> - <string>Full aut&hor list</string> - </property> - </widget> - </item> - <item> - <widget class="QCheckBox" name="forceuppercaseCB"> - <property name="toolTip"> - <string>Force upper case in citation</string> - </property> - <property name="text"> - <string>Force u&pper case</string> - </property> - </widget> - </item> - </layout> - </item> - </layout> - </widget> - </item> - <item row="9" column="0" colspan="3"> - <layout class="QHBoxLayout"> - <property name="spacing"> - <number>6</number> - </property> - <property name="margin"> - <number>0</number> - </property> - <item> - <widget class="QPushButton" name="restorePB"> - <property name="text"> - <string>&Restore</string> - </property> - <property name="autoDefault"> - <bool>false</bool> - </property> - </widget> - </item> - <item> - <spacer> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>40</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QPushButton" name="okPB"> - <property name="text"> - <string>&OK</string> - </property> - <property name="autoDefault"> - <bool>false</bool> - </property> - <property name="default"> - <bool>false</bool> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="applyPB"> - <property name="text"> - <string>App&ly</string> - </property> - <property name="autoDefault"> - <bool>false</bool> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="cancelPB"> - <property name="text"> - <string>&Cancel</string> - </property> - <property name="autoDefault"> - <bool>false</bool> - </property> - </widget> - </item> - </layout> - </item> </layout> + <zorder>availableLV</zorder> + <zorder>addPB</zorder> + <zorder>selectedLV</zorder> + <zorder>deletePB</zorder> + <zorder>filePB</zorder> + <zorder>urlPB</zorder> + <zorder>upPB</zorder> + <zorder>downPB</zorder> <zorder>infoML</zorder> <zorder>styleGB</zorder> <zorder>groupBox</zorder> Index: frontends/qt4/GuiCitation.cpp =================================================================== --- frontends/qt4/GuiCitation.cpp (revision 33816) +++ frontends/qt4/GuiCitation.cpp (working copy) @@ -18,7 +18,9 @@ #include "GuiSelectionManager.h" #include "qt_helpers.h" +#include "alert.h" + #include "Buffer.h" #include "BiblioInfo.h" #include "BufferParams.h" @@ -56,6 +58,24 @@ static vector<CiteStyle> citeStyles_; +// Tells OS to open a File or URL +// Formats::view does not seem appropriate as it wants a Buffer +static void system_viewer (string url) { + string open_cmd; + #ifdef _WIN32 + open_cmd = "start"; + #elif defined(USE_MACOSX_PACKAGING) + open_cmd = "open"; + #else + open_cmd = "xdg-open"; + #endif + string cmd = open_cmd + " \"" + url + "\" &"; + int result = system(cmd.c_str()); + if (result) { + Alert::warning(_("Could not open file"), bformat(_("Command \n$1%s\n Exited with Error#$2%d"), from_local8bit(cmd), result)); + } +} + template<typename String> static QStringList to_qstring_list(vector<String> const & v) { @@ -100,6 +120,10 @@ this, SLOT(changed())); connect(findLE, SIGNAL(returnPressed()), this, SLOT(on_searchPB_clicked())); + connect(urlPB, SIGNAL(clicked()), + this, SLOT(on_urlPB_clicked())); + connect(filePB, SIGNAL(clicked()), + this, SLOT(on_filePB_clicked())); connect(textBeforeED, SIGNAL(returnPressed()), this, SLOT(on_okPB_clicked())); connect(textAfterED, SIGNAL(returnPressed()), @@ -114,8 +138,14 @@ connect(selectionManager, SIGNAL(okHook()), this, SLOT(on_okPB_clicked())); - setFocusProxy(availableLV); + if (selected_model_.rowCount()) { + setFocusProxy(availableLV); + } else { + setFocusProxy(selectedLV); + //updateControls(); + } + // FIXME: the sizeHint() for this is _way_ too high infoML->setFixedHeight(60); } @@ -156,6 +186,29 @@ } +void GuiCitation::on_urlPB_clicked() +{ + system_viewer(to_filesystem8bit(citationURL_)); +} + + +void GuiCitation::on_filePB_clicked() +{ + string filename = to_filesystem8bit(citationFile_); + //docstring filename = citationFile_; + size_t pos = filename.find(":"); + if (pos != string::npos) { + filename = filename.substr(pos + 1); + } else { + lyxerr << "file entry \"" << filename + << "\" does not contain ':' (missing JabRef filetype; " + << "but we don't need it anyway)\n"; + } + + system_viewer(filename); +} + + void GuiCitation::on_okPB_clicked() { applyView(); @@ -198,11 +251,13 @@ // two methods, though they should be divisible. void GuiCitation::updateControls(BiblioInfo const & bi) { + //if (selectionManager->selectedFocused()) { if (selectionManager->selectedFocused()) { - if (selectedLV->selectionModel()->selectedIndexes().isEmpty()) + if (!selectedLV->currentIndex().isValid()) { updateInfo(bi, availableLV->currentIndex()); - else + } else { updateInfo(bi, selectedLV->currentIndex()); + } } else { if (availableLV->selectionModel()->selectedIndexes().isEmpty()) updateInfo(bi, QModelIndex()); @@ -211,6 +266,8 @@ } setButtons(); + //updateInfo(bi, selectedLV->currentIndex()); + textBeforeED->setText(toqstr(params_["before"])); textAfterED->setText(toqstr(params_["after"])); fillStyles(bi); @@ -367,8 +424,16 @@ return; } - QString const keytxt = toqstr( - bi.getInfo(qstring_to_ucs4(idx.data().toString()))); + docstring key = qstring_to_ucs4(idx.data().toString()); + + QString const keytxt = toqstr(bi.getInfo(key)); + citationURL_ = bi.getURL(key); + citationFile_ = bi.getFile(key); + urlPB->setEnabled(!citationURL_.empty()); + filePB->setEnabled(!citationFile_.empty()); + infoML->document()->setPlainText(keytxt); } Index: frontends/qt4/GuiCitation.h =================================================================== --- frontends/qt4/GuiCitation.h (revision 33816) +++ frontends/qt4/GuiCitation.h (working copy) @@ -44,6 +44,8 @@ ~GuiCitation(); private Q_SLOTS: + void on_urlPB_clicked(); + void on_filePB_clicked(); void on_okPB_clicked(); void on_cancelPB_clicked(); void on_restorePB_clicked(); @@ -166,6 +168,10 @@ QStringList cited_keys_; /// InsetCommandParams params_; + /// File containing paper being cited by last clicked entry + docstring citationFile_; + /// URL of paper being cited by last clicked entry + docstring citationURL_; }; } // namespace frontend