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>&amp;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>&amp;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>&amp;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>&amp;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&amp;ly</string>
+       </property>
+       <property name="autoDefault">
+        <bool>false</bool>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QPushButton" name="cancelPB">
+       <property name="text">
+        <string>&amp;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&amp;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 &amp;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&amp;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&amp;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&amp;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&amp;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 &amp;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&amp;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&amp;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&amp;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>&amp;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>&amp;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&amp;ly</string>
-       </property>
-       <property name="autoDefault">
-        <bool>false</bool>
-       </property>
-      </widget>
-     </item>
-     <item>
-      <widget class="QPushButton" name="cancelPB">
-       <property name="text">
-        <string>&amp;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

Reply via email to