mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-12-22 13:18:28 +00:00
Allow LyX to find pdfs and urls of citation references and follow them from context menu.
Currently tested: - url & doi fields for bibtex. - all documented eprinttypes of biblatex - absolute paths of first entry of 'file' field for jabref and kbibtex - external script searching for author + year pdf Additional polishing will follow. https://www.mail-archive.com/lyx-devel@lists.lyx.org/msg212505.html
This commit is contained in:
parent
4bb00e99fb
commit
e648202e7e
@ -128,6 +128,7 @@ Menuset
|
||||
CiteStyles
|
||||
Separator
|
||||
Item "Settings...|S" "inset-settings"
|
||||
Item "Open Citation Content|O" "inset-edit"
|
||||
End
|
||||
|
||||
|
||||
|
@ -651,6 +651,75 @@ docstring const BibTeXInfo::getYear() const
|
||||
}
|
||||
|
||||
|
||||
void BibTeXInfo::getLocators(docstring & doi, docstring & url, docstring & file) const
|
||||
{
|
||||
if (is_bibtex_) {
|
||||
// get "doi" entry from citation record
|
||||
doi = operator[]("doi");
|
||||
if (!doi.empty() && !prefixIs(doi,from_ascii("http")))
|
||||
doi = "https://doi.org/" + doi;
|
||||
// get "url" entry from citation record
|
||||
url = operator[]("url");
|
||||
// get "file" entry from citation record
|
||||
file = operator[]("file");
|
||||
|
||||
// Jabref case, field has a format:
|
||||
// Description:Location:Filetype;Description:Location:Filetype...
|
||||
// We will grab only first pdf
|
||||
if (!file.empty()) {
|
||||
docstring ret, filedest, tmp;
|
||||
ret = split(file, tmp, ':');
|
||||
tmp = split(ret, filedest, ':');
|
||||
//TODO howto deal with relative directories?
|
||||
FileName f(to_utf8(filedest));
|
||||
if (f.exists())
|
||||
file = "file:///" + filedest;
|
||||
}
|
||||
|
||||
// kbibtex case, format:
|
||||
// file1.pdf;file2.pdf
|
||||
// We will grab only first pdf
|
||||
docstring kfile;
|
||||
if (file.empty())
|
||||
kfile = operator[]("localfile");
|
||||
if (!kfile.empty()) {
|
||||
docstring filedest, tmp;
|
||||
tmp = split(kfile, filedest, ';');
|
||||
//TODO howto deal with relative directories?
|
||||
FileName f(to_utf8(filedest));
|
||||
if (f.exists())
|
||||
file = "file:///" + filedest;
|
||||
}
|
||||
|
||||
if (!url.empty())
|
||||
return;
|
||||
|
||||
// try biblatex specific fields, see its manual
|
||||
// 3.13.7 "Electronic Publishing Informationl"
|
||||
docstring eprinttype = operator[]("eprinttype");
|
||||
docstring eprint = operator[]("eprint");
|
||||
if (eprint.empty())
|
||||
return;
|
||||
|
||||
if (eprinttype == "arxiv")
|
||||
url = "https://arxiv.org/abs/" + eprint;
|
||||
if (eprinttype == "jstor")
|
||||
url = "https://www.jstor.org/stable/" + eprint;
|
||||
if (eprinttype == "pubmed")
|
||||
url = "http://www.ncbi.nlm.nih.gov/pubmed/" + eprint;
|
||||
if (eprinttype == "hdl")
|
||||
url = "https://hdl.handle.net/" + eprint;
|
||||
if (eprinttype == "googlebooks")
|
||||
url = "http://books.google.com/books?id=" + eprint;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Here can be handled the bibliography environment. All one could do
|
||||
// here is let LyX scan the entry for URL or HRef insets.
|
||||
}
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
docstring parseOptions(docstring const & format, string & optkey,
|
||||
@ -1269,6 +1338,15 @@ docstring const BiblioInfo::getCiteNumber(docstring const & key) const
|
||||
return data.citeNumber();
|
||||
}
|
||||
|
||||
void BiblioInfo::getLocators(docstring const & key, docstring & doi, docstring & url, docstring & file) const
|
||||
{
|
||||
BiblioInfo::const_iterator it = find(key);
|
||||
if (it == end())
|
||||
return;
|
||||
BibTeXInfo const & data = it->second;
|
||||
data.getLocators(doi,url,file);
|
||||
}
|
||||
|
||||
|
||||
docstring const BiblioInfo::getYear(docstring const & key, bool use_modifier) const
|
||||
{
|
||||
|
@ -70,6 +70,8 @@ public:
|
||||
bool const allnames = false, bool const beginning = true) const;
|
||||
///
|
||||
docstring const getYear() const;
|
||||
///
|
||||
void getLocators(docstring & doi, docstring & url, docstring & file) const;
|
||||
/// \return formatted BibTeX data suitable for framing.
|
||||
/// \param vector of pointers to crossref/xdata information
|
||||
docstring const & getInfo(BibTeXInfoList const & xrefs,
|
||||
@ -213,6 +215,9 @@ public:
|
||||
/// language.
|
||||
docstring const getYear(docstring const & key, Buffer const & buf,
|
||||
bool use_modifier = false) const;
|
||||
/// get either local pdf or web location of the citation referenced by key.
|
||||
/// DOI/file are prefixed so they form proper URL for generic qt handler
|
||||
void getLocators(docstring const & key, docstring & doi, docstring & url, docstring & file) const;
|
||||
///
|
||||
docstring const getCiteNumber(docstring const & key) const;
|
||||
/// \return formatted BibTeX data associated with a given key.
|
||||
|
@ -490,6 +490,7 @@ enum FuncCode
|
||||
LFUN_MASTER_BUFFER_FORALL, // spitz 20191231
|
||||
LFUN_IF_RELATIVES, // spitz 20200102
|
||||
LFUN_WINDOW_RAISE, // forenr, 20202104
|
||||
LFUN_CITATION_OPEN, // sanda, 20200815
|
||||
LFUN_LASTACTION // end of the table
|
||||
};
|
||||
|
||||
|
@ -1239,6 +1239,18 @@ void LyXAction::init()
|
||||
* \endvar
|
||||
*/
|
||||
{ LFUN_CITATION_INSERT, "citation-insert", Noop, Edit },
|
||||
/*!
|
||||
* \var lyx::FuncCode lyx::LFUN_CITATION_OPEN
|
||||
* \li Action: Opens the corresponding pdf/url for a given citation inset.
|
||||
* \li Syntax: citation-open [EXTERNAL] TARGET
|
||||
* \li Params: <TARGET>: URL (https:,file:) of the document. \n
|
||||
<EXTERNAL>: Use external executable script for finding target \n
|
||||
and launching viewer. In this case TARGET consists of author and year \n
|
||||
and will be passed as an input argument to the script.
|
||||
* \li Origin: Sanda, 16 Aug 2020
|
||||
* \endvar
|
||||
*/
|
||||
{ LFUN_CITATION_OPEN, "citation-open", ReadOnly | NoUpdate | Argument, Edit },
|
||||
|
||||
/*!
|
||||
* \var lyx::FuncCode lyx::LFUN_CLIPBOARD_PASTE
|
||||
|
@ -2371,6 +2371,10 @@ bool GuiView::getStatus(FuncRequest const & cmd, FuncStatus & flag)
|
||||
flag.setOnOff(lyxrc.spellcheck_continuously);
|
||||
break;
|
||||
|
||||
case LFUN_CITATION_OPEN:
|
||||
enable = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@ -4620,6 +4624,10 @@ void GuiView::dispatch(FuncRequest const & cmd, DispatchResult & dr)
|
||||
dr.screenUpdate(Update::Force);
|
||||
break;
|
||||
|
||||
case LFUN_CITATION_OPEN: {
|
||||
frontend::showTarget(argument);
|
||||
}
|
||||
|
||||
default:
|
||||
// The LFUN must be for one of BufferView, Buffer or Cursor;
|
||||
// let's try that:
|
||||
|
@ -21,7 +21,10 @@
|
||||
|
||||
#include "BufferParams.h"
|
||||
#include "FloatList.h"
|
||||
#include "FuncRequest.h"
|
||||
#include "Language.h"
|
||||
#include "LyX.h"
|
||||
#include "LyXAction.h"
|
||||
#include "TextClass.h"
|
||||
|
||||
#include "support/convert.h"
|
||||
@ -293,6 +296,18 @@ void showDirectory(FileName const & directory)
|
||||
if (!QDesktopServices::openUrl(qurl))
|
||||
LYXERR0("Unable to open QUrl even though dir exists!");
|
||||
}
|
||||
|
||||
void showTarget(string const & target){
|
||||
LYXERR(Debug::INSETS, "Showtarget:" << target << "\n");
|
||||
if (prefixIs(target,"EXTERNAL ")) {
|
||||
string tmp,tar;
|
||||
tar = split(target, tmp, ' ');
|
||||
FuncRequest cmd = FuncRequest(LFUN_VC_COMMAND,"U . \"lyxpaperview " + tar + "\"");
|
||||
lyx::dispatch(cmd);
|
||||
return;
|
||||
}
|
||||
QDesktopServices::openUrl(QUrl(toqstr(target), QUrl::TolerantMode));
|
||||
}
|
||||
} // namespace frontend
|
||||
|
||||
QString const qt_(char const * str, const char *)
|
||||
|
@ -101,6 +101,9 @@ void setSectionResizeMode(QHeaderView * view,
|
||||
QHeaderView::ResizeMode mode);
|
||||
/// Shows a directory in OSs file browser
|
||||
void showDirectory(support::FileName const & directory);
|
||||
/// handle request for showing citation content - shows pdf or
|
||||
/// web page in target; external script can be used for pdf view
|
||||
void showTarget(std::string const & target);
|
||||
|
||||
} // namespace frontend
|
||||
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "FuncRequest.h"
|
||||
#include "FuncStatus.h"
|
||||
#include "LaTeXFeatures.h"
|
||||
#include "LyX.h"
|
||||
#include "output_xhtml.h"
|
||||
#include "output_docbook.h"
|
||||
#include "ParIterator.h"
|
||||
@ -133,6 +134,9 @@ CitationStyle InsetCitation::getCitationStyle(BufferParams const & bp, string co
|
||||
void InsetCitation::doDispatch(Cursor & cur, FuncRequest & cmd)
|
||||
{
|
||||
switch (cmd.action()) {
|
||||
case LFUN_INSET_EDIT:
|
||||
openCitation();
|
||||
break;
|
||||
case LFUN_INSET_MODIFY: {
|
||||
buffer().removeBiblioTempFiles();
|
||||
cache.recalculate = true;
|
||||
@ -165,6 +169,44 @@ void InsetCitation::doDispatch(Cursor & cur, FuncRequest & cmd)
|
||||
}
|
||||
|
||||
|
||||
void InsetCitation::openCitation(){
|
||||
Buffer const & buf = *buffer_;
|
||||
// Only after the buffer is loaded from file...
|
||||
if (!buf.isFullyLoaded())
|
||||
return;
|
||||
|
||||
BiblioInfo const & bi = buf.masterBibInfo();
|
||||
if (bi.empty())
|
||||
return;
|
||||
|
||||
docstring const & key = getParam("key");
|
||||
if (key.empty())
|
||||
return;
|
||||
|
||||
vector<docstring> keys = getVectorFromString(key);
|
||||
docstring year, author, doi, url, file;
|
||||
for (docstring const & kvar : keys) {
|
||||
year = bi.getYear(kvar, buffer(), false);
|
||||
author = bi.getAuthorOrEditorList(kvar, buffer());
|
||||
bi.getLocators(kvar, doi, url, file);
|
||||
LYXERR(Debug::INSETS, "Locators: doi:" << doi << " url:"
|
||||
<< url << " file:" << file << " author:" << author << " year:" << year);
|
||||
docstring locator;
|
||||
if (!file.empty()) {
|
||||
locator = file;
|
||||
} else if (!doi.empty()) {
|
||||
locator = doi;
|
||||
} else if (!url.empty()) {
|
||||
locator = url;
|
||||
} else {
|
||||
locator = "EXTERNAL " + year + " " + author;
|
||||
}
|
||||
FuncRequest cmd = FuncRequest(LFUN_CITATION_OPEN, locator);
|
||||
lyx::dispatch(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool InsetCitation::getStatus(Cursor & cur, FuncRequest const & cmd,
|
||||
FuncStatus & status) const
|
||||
{
|
||||
@ -203,6 +245,8 @@ bool InsetCitation::getStatus(Cursor & cur, FuncRequest const & cmd,
|
||||
}
|
||||
}
|
||||
return true;
|
||||
case LFUN_INSET_EDIT:
|
||||
return true;
|
||||
default:
|
||||
return InsetCommand::getStatus(cur, cmd, status);
|
||||
}
|
||||
|
@ -94,6 +94,8 @@ public:
|
||||
QualifiedList getQualifiedLists(docstring const & p) const;
|
||||
///
|
||||
static bool last_literal;
|
||||
///
|
||||
void openCitation();
|
||||
|
||||
private:
|
||||
/// tries to make a pretty label and makes a basic one if not
|
||||
|
Loading…
Reference in New Issue
Block a user