Support for "qualified citation lists"

These are biblatex-specific multicite commands that allow for multiple
pre- and postnotes, as in:

\cites(pre)(post)[pre1][post1]{key1}[pre2][post2]{key2}...

with an optional general pre- and postnote, which applies to the whole
list (like [][] in normal cite commands) and an optional pre- and
postnotes for each item, so that pagination can actually be specified in
multi-cite references, as in:
(cf. Miller 2015, 2; furthermore Smith 2013, 23-23; Jenkins 2012, 103,
also refer to chapter 6 in this book)

See the biblatex manual, sec. 3.8.3., for details.

File format change.
This commit is contained in:
Juergen Spitzmueller 2017-01-21 14:25:17 +01:00
parent 633ad2032e
commit 68ab4023cc
19 changed files with 715 additions and 94 deletions

View File

@ -7,6 +7,13 @@ changes happened in particular if possible. A good example would be
-----------------------
2017-01-21 Jürgen Spitzmüller <spitz@lyx.org>
* Format incremented to 531: Support for qualified citation lists.
\begin_inset CommandInset citation
New params: pretextlist, posttextlist
A tab-separated list consisting of a cite key, a space and the the
pre- or postnote associated with that specific key.
2017-01-13 Jürgen Spitzmüller <spitz@lyx.org>
* Format incremented to 530: Support natbib & jurabib package options.

View File

@ -68,6 +68,8 @@ MaxCiteNames 3
# dropping the '!' from the prefix (see below), e.g.:
# _stardesc Starred command label
# _stardesctooltip Tooltip for the starred command checkbox.
# * A trailing $ indicates that a command features "qualified citation
# lists" (a specific Biblatex feature)
#
# CITE COMMAND DEFINITIONS for either engine type
@ -84,8 +86,8 @@ CiteEngine authoryear
citeyearpar[][]
citeyear=cite*
citebyear[][]=citeyear
Footcite[][]=smartcite
Autocite[][]
Footcite$[][]=smartcite
Autocite$[][]
citetitle*<!_citetitlestar!_citetitlestartooltip>[][]
fullcite[][]
footfullcite[][]
@ -97,8 +99,8 @@ CiteEngine numerical
Citep|citealp,citealt*[][]
Citet|textcite*[][]
supercite
Footcite[][]=smartcite
Autocite[][]
Footcite$[][]=smartcite
Autocite$[][]
Citeauthor[][]*
citeyearpar[][]
citeyear|citebyear[][]
@ -177,6 +179,10 @@ CiteFormat default
!textbefore {%textbefore%[[%textbefore% ]]}
# ", postnote"
!textafter {%textafter%[[, %textafter%]]}
# "prenote " (for qualified lists)
!ctextbefore {%curpretext%[[%curpretext% ]]}
# ", postnote" (for qualified lists)
!ctextafter {%curposttext%[[, %curposttext%]]}
# Add a year if it exists (else "??") and possibly a modifier (as in 2017a)
!makeyear {%year%[[%year%]][[??]]}{%modifier%[[%modifier%]]}
# Add a year if it exists (else "??") and indicate a possible modifier (as in 2017[a])
@ -239,6 +245,8 @@ CiteFormat authoryear
!sep ;
!close )
# "cf. Author et. al Year..."
!makecite %!ctextbefore%%!startlink%%!abbrvciteauthor% %!makeyear%%!endlink%%!ctextafter%%!nextcite%
# "Author et al. (cf. Year..."
!makecitet %!startlink%%!makeauthor%%!endlink% %!open%%!textbefore%%!makeyear%%!nextcitet%
# "cf. Author et al. Year..."
@ -246,6 +254,8 @@ CiteFormat authoryear
# "Author et al., Year..."
!makecitealp %!startlink%%!makeauthor%, %!makeyear%%!endlink%%!nextcitealp%
# "...; Nextauthor Year..."
!nextcite {%next%[[%!sep% %!makecite%]]}
# "...), [and] Nextauthor (Year..."
!nextcitet {%next%[[%!close%%!smartsep%%!startlink%%!makeauthor%%!endlink% %!open%%!makeyear%%!nextcitet%]]}
# "...; NextAuthor et al. Year..."
@ -268,9 +278,9 @@ CiteFormat authoryear
# "cf. Author Year; NextAuthor Year, p. xx" [NB: textbefore position differs from real natbib!]
citealt %!makecitealt%%!textafter%
# "Footnote: cf. Author A Year; Author B Year, p. xx."
footcite {%dialog%[[%_footnote%]][[%_foot%]]}: %!textbefore%%!makecitealp%%!textafter%.
footcite {%dialog%[[%_footnote%]][[%_foot%]]}: %!textbefore%%!makecite%%!textafter%.
# "Auto: (cf. Author A Year; Author B Year, p. xx)"
autocite {%dialog%[[%_autocite%]][[%_auto%]]}: %!open%%!textbefore%%!makecitealp%%!textafter%%!close%
autocite {%dialog%[[%_autocite%]][[%_auto%]]}: %!open%%!textbefore%%!makecite%%!textafter%%!close%
# Fallback style: "Author A (cf. Year),[ and] Author B (Year, p. xx)"
cite %!makecitet%%!textafter%%!close%
@ -298,6 +308,8 @@ CiteFormat numerical
!makecitealt {%dialog%[[#ID]][[%!startlink%{%numericallabel%[[%numericallabel%]][[#%key%]]}%!endlink%]]}%!nextcitealt%
# "ID..."
!hashkey {%dialog%[[#ID]][[%!startlink%{%numericallabel%[[%numericallabel%]][[#%key%]]}%!endlink%%!nexthashkey%]]}
# "ID"
!makekey %!ctextbefore%{%dialog%[[#ID]][[%!startlink%{%numericallabel%[[%numericallabel%]][[#%key%]]}%!endlink%]]}%!ctextafter%%!nextkey%
# "...], [and] NextAuthor [ID..."
!nextcitet {%next%[[%!close%%!smartsep%%!makeauthor% %!open%%!textbefore%{%dialog%[[#ID]][[%!startlink%{%numericallabel%[[%numericallabel%]][[#%key%]]}%!endlink%]]}%!nextcitet%]]}
@ -309,6 +321,8 @@ CiteFormat numerical
!nexthashkey {%next%[[%!sep% %!startlink%{%numericallabel%[[%numericallabel%]][[#%key%]]}%!endlink%%!nexthashkey%]]}
# "...); Nextauthor [ID..."
!nextcitet {%next%[[%!close%%!smartsep%%!makeauthor% %!open%{%dialog%[[#ID]][[%!startlink%{%numericallabel%[[%numericallabel%]][[#%key%]]}%!endlink%]]}%!nextcitet%]]}
# "..., NextID..."
!nextkey {%next%[[%!sep% %!ctextbefore%{%dialog%[[#ID]][[%!startlink%{%numericallabel%[[%numericallabel%]][[#%key%]]}%!endlink%]]}%!ctextafter%%!nextkey%]]}
#
# ACTUAL STYLE DEFINITIONS

View File

@ -64,20 +64,22 @@ MaxCiteNames 3
# the '!' from the prefix (see below), e.g.:
# _stardesc Starred command label
# _stardesctooltip Tooltip for the starred command checkbox.
# * A trailing $ indicates that a command features "qualified citation
# lists" (a specific Biblatex feature)
#
# CITE COMMAND DEFINITIONS for either engine type
#
CiteEngine authoryear
Cite|citealt,citealp[][]
Citet[][]=textcite
Citep[][]=parencite
Cite$|citealt,citealp[][]
Citet$[][]=textcite
Citep$[][]=parencite
Citeauthor*<!_citeauthorstar!_citeauthorstartooltip>[][]
citeyearpar[][]=parencite*
citeyear[][]=cite*
citebyear[][]=citeyear
Footcite[][]=smartcite
Autocite[][]
Footcite$[][]=smartcite
Autocite$[][]
citetitle*<!_citetitlestar!_citetitlestartooltip>[][]
fullcite[][]
footfullcite[][]
@ -86,11 +88,11 @@ CiteEngine authoryear
End
CiteEngine numerical
cite|parencite,citep,citealt,citealp[][]
Citet[][]=textcite
cite$|parencite,citep,citealt,citealp[][]
Citet$[][]=textcite
supercite
Footcite[][]=smartcite
Autocite[][]
Footcite$[][]=smartcite
Autocite$[][]
Citeauthor*<!_citeauthorstar!_citeauthorstartooltip>[][]
citeyear|parencite*,citebyear[][]=citeyear*
citetitle*<!_citetitlestar!_citetitlestartooltip>[][]
@ -182,6 +184,10 @@ CiteFormat default
!textbefore {%textbefore%[[%textbefore% ]]}
# ", postnote"
!textafter {%textafter%[[, %textafter%]]}
# "prenote " (for qualified lists)
!ctextbefore {%curpretext%[[%curpretext% ]]}
# ", postnote" (for qualified lists)
!ctextafter {%curposttext%[[, %curposttext%]]}
# Add a year if it exists (else "??") and possibly a modifier (as in 2017a)
!year {%year%[[%year%]][[??]]}{%modifier%[[%modifier%]]}
# Add a year if it exists (else "??") and indicate a possible modifier (as in 2017[a])
@ -228,14 +234,14 @@ CiteFormat authoryear
!close )
# "cf. Author et. al Year..."
!makecite %!startlink%%!abbrvciteauthor% %!year%%!endlink%%!nextcite%
!makecite %!ctextbefore%%!startlink%%!abbrvciteauthor% %!year%%!endlink%%!ctextafter%%!nextcite%
# Author et al. (cf. Year...
!maketextcite %!startlink%%!abbrvciteauthor%%!endlink% %!open%%!textbefore%%!year%%!nexttextcite%
!maketextcite {%ifqualified%[[%!textbefore%]]}%!startlink%%!abbrvciteauthor%%!endlink% %!open%{%ifqualified%[[%!ctextbefore%]][[%!textbefore%]]}%!year%%!ctextafter%%!nexttextcite%
# "...; Nextauthor Year..."
!nextcite {%next%[[%!sep% %!makecite%]]}
# "...); Nextauthor (Year..."
!nexttextcite {%next%[[%!close%%!smartsep%%!startlink%%!abbrvciteauthor%%!endlink% %!open%%!year%%!nexttextcite%]]}
!nexttextcite {%next%[[%!close%%!smartsep%%!startlink%%!abbrvciteauthor%%!endlink% %!open%%!ctextbefore%%!year%%!ctextafter%%!nexttextcite%]]}
# Add a year if it exists (else title, else "??") and possibly a modifier (as in 2017a)
!yeartitle {%year%[[%year%{%modifier%[[%modifier%]][[{%export%[[]][[%!dummymod%]]}]]}]][[{%title%[[%title%]][[??]]}]]}
@ -283,12 +289,12 @@ CiteFormat numerical
# "Author [cf. ID..."
!maketextcite %!abbrvciteauthor% %!open%%!textbefore%{%dialog%[[#ID]][[%!startlink%{%numericallabel%[[%numericallabel%]][[#%key%]]}%!endlink%]]}%!nexttextcite%
# "ID"
!makekey {%dialog%[[#ID]][[%!startlink%{%numericallabel%[[%numericallabel%]][[#%key%]]}%!endlink%%!nextkey%]]}
!makekey %!ctextbefore%{%dialog%[[#ID]][[%!startlink%{%numericallabel%[[%numericallabel%]][[#%key%]]}%!endlink%]]}%!ctextafter%%!nextkey%
# "...); Nextauthor [ID..."
!nexttextcite {%next%[[%!close%%!smartsep%%!abbrvciteauthor% %!open%{%dialog%[[#ID]][[%!startlink%{%numericallabel%[[%numericallabel%]][[#%key%]]}%!endlink%]]}%!nexttextcite%]]}
!nexttextcite {%next%[[%!close%%!smartsep%%!abbrvciteauthor% %!open%%!ctextbefore%{%dialog%[[#ID]][[%!startlink%{%numericallabel%[[%numericallabel%]][[#%key%]]}%!endlink%]]}%!nexttextcite%]]}
# "..., NextID..."
!nextkey {%next%[[%!sep% %!startlink%{%numericallabel%[[%numericallabel%]][[#%key%]]}%!endlink%%!nextkey%]]}
!nextkey {%next%[[%!sep% %!ctextbefore%{%dialog%[[#ID]][[%!startlink%{%numericallabel%[[%numericallabel%]][[#%key%]]}%!endlink%]]}%!ctextafter%%!nextkey%]]}
#
# ACTUAL STYLE DEFINITIONS

View File

@ -1,5 +1,5 @@
#LyX 2.3 created this file. For more info see http://www.lyx.org/
\lyxformat 528
\lyxformat 530
\begin_document
\begin_header
\save_transient_properties true
@ -21598,8 +21598,8 @@ The full syntax is:
\begin_layout LyX-Code
\change_inserted -712698321 1483870927
LyXName|alias*<!_stardesc!_stardesctooltip>[][]=latexcmd
\change_inserted -712698321 1484997816
LyXName|alias$*<!_stardesc!_stardesctooltip>[][]=latexcmd
\end_layout
\begin_layout Itemize
@ -22048,11 +22048,50 @@ _stardesc Sta&rred command label
\begin_layout LyX-Code
\change_inserted -712698321 1483872184
\change_inserted -712698321 1484997832
_stardesctooltip Tooltip for the starred command checkbox.
\end_layout
\end_deeper
\begin_layout Itemize
\change_inserted -712698321 1484997948
A dollar sign
\begin_inset Flex Code
status collapsed
\begin_layout Plain Layout
\change_inserted -712698321 1484997871
$
\change_unchanged
\end_layout
\end_inset
indicates that this command features
\begin_inset Quotes eld
\end_inset
qualified citation lists
\begin_inset Quotes erd
\end_inset
.
This is a
\family sans
Biblatex
\family default
-specific feature for multi-reference citations where an individual pre-
and postnote can be given to each reference in the list.
Please refer to the
\family sans
Biblatex
\family default
manual for details.
\end_layout
\begin_layout Subsection
\begin_inset CommandInset label
LatexCommand label
@ -22670,7 +22709,7 @@ status collapsed
\begin_layout Itemize
\change_inserted -712698321 1483978548
\change_inserted -712698321 1484997600
\begin_inset Flex Code
status collapsed
@ -22704,6 +22743,36 @@ status collapsed
\end_inset
)
\end_layout
\begin_layout Itemize
\change_inserted -712698321 1484997681
\begin_inset Flex Code
status collapsed
\begin_layout Plain Layout
\change_inserted -712698321 1484997608
{%ifqualified%[[true]][[false]]}
\end_layout
\end_inset
: process the
\begin_inset Quotes eld
\end_inset
true
\begin_inset Quotes erd
\end_inset
part if the current citation is a qualified citation list (a specific
\family sans
Biblatex
\family default
format for multi-reference citations), the false part if this is not the
case.
\change_unchanged
\end_layout

View File

@ -30040,7 +30040,7 @@ key "latexcompanion"
\begin_layout Standard
\change_inserted -712698321 1483891777
\change_inserted -712698321 1484998090
All styles except for
\family sans
Basic
@ -30056,6 +30056,99 @@ cf.
).
This text is then also included in the parentheses, if the style requires
this.
\end_layout
\begin_layout Standard
\change_inserted -712698321 1484998495
Note that these pre- and postnotes apply to the whole citation.
That is to say, if you refer to multiple references at one, the prenote
will precede the first citation in the list, the postnote will follow the
last.
Some
\family sans
Biblatex
\family default
styles allow for adding pre- and postnotes to any individual reference
in a multi-citation (so-called
\begin_inset Quotes eld
\end_inset
qualified citation lists
\begin_inset Quotes erd
\end_inset
).
\SpecialChar LyX
supports this.
If you use such a style, and if the current reference includes multiple
items, the
\begin_inset Quotes eld
\end_inset
Selected Citations
\begin_inset Quotes erd
\end_inset
window will display three columns:
\begin_inset Quotes eld
\end_inset
Text before
\begin_inset Quotes erd
\end_inset
,
\begin_inset Quotes eld
\end_inset
Cite key
\begin_inset Quotes erd
\end_inset
, and
\begin_inset Quotes eld
\end_inset
Text after
\begin_inset Quotes erd
\end_inset
.
If you double-click on an item's
\begin_inset Quotes eld
\end_inset
Text before
\begin_inset Quotes erd
\end_inset
or
\begin_inset Quotes eld
\end_inset
Text after
\begin_inset Quotes erd
\end_inset
field, you can add such individual pre- and postnotes.
In the
\begin_inset Quotes eld
\end_inset
General text before
\begin_inset Quotes erd
\end_inset
and
\begin_inset Quotes eld
\end_inset
General text after
\begin_inset Quotes erd
\end_inset
input widgets, you can add pre- and postnotes that apply to the whole list.
\change_unchanged
\end_layout

View File

@ -1331,10 +1331,10 @@ def revert_biblatex(document):
res = "\\" + new_citations[cmd]
if pre:
res += "[" + pre + "]"
elif post:
res += "[]"
if post:
res += "[" + post + "]"
elif pre:
res += "[]"
res += "{" + key + "}"
document.body[i:j+1] = put_cmd_in_ert([res])
elif cmd not in old_citations:
@ -1450,6 +1450,103 @@ def revert_bibpackopts(document):
]
def revert_qualicites(document):
" Revert qualified citation list commands to ERT "
# Citation insets that support qualified lists, with their LaTeX code
ql_citations = {
"cite" : "cites",
"Cite" : "Cites",
"citet" : "textcites",
"Citet" : "Textcites",
"citep" : "parencites",
"Citep" : "Parencites",
"Footcite" : "Smartcites",
"footcite" : "smartcites",
"Autocite" : "Autocites",
"autocite" : "autocites",
}
# Get cite engine
engine = "basic"
i = find_token(document.header, "\\cite_engine", 0)
if i == -1:
document.warning("Malformed document! Missing \\cite_engine")
else:
engine = get_value(document.header, "\\cite_engine", i)
biblatex = engine in ["biblatex", "biblatex-natbib"]
i = 0
while (True):
i = find_token(document.body, "\\begin_inset CommandInset citation", i)
if i == -1:
break
j = find_end_of_inset(document.body, i)
if j == -1:
document.warning("Can't find end of citation inset at line %d!!" %(i))
i += 1
continue
pres = find_token(document.body, "pretextlist", i, j)
posts = find_token(document.body, "posttextlist", i, j)
if pres == -1 and posts == -1:
# nothing to do.
i = j + 1
continue
pretexts = get_quoted_value(document.body, "pretextlist", pres)
posttexts = get_quoted_value(document.body, "posttextlist", posts)
k = find_token(document.body, "LatexCommand", i, j)
if k == -1:
document.warning("Can't find LatexCommand for citation inset at line %d!" %(i))
i = j + 1
continue
cmd = get_value(document.body, "LatexCommand", k)
if biblatex and cmd in list(ql_citations.keys()):
pre = get_quoted_value(document.body, "before", i, j)
post = get_quoted_value(document.body, "after", i, j)
key = get_quoted_value(document.body, "key", i, j)
if not key:
document.warning("Citation inset at line %d does not have a key!" %(i))
key = "???"
keys = key.split(",")
prelist = pretexts.split("\t")
premap = dict()
for pp in prelist:
ppp = pp.split(" ", 1)
premap[ppp[0]] = ppp[1]
postlist = posttexts.split("\t")
postmap = dict()
for pp in postlist:
ppp = pp.split(" ", 1)
postmap[ppp[0]] = ppp[1]
# Replace known new commands with ERT
if "(" in pre or ")" in pre:
pre = "{" + pre + "}"
if "(" in post or ")" in post:
post = "{" + post + "}"
res = "\\" + ql_citations[cmd]
if pre:
res += "(" + pre + ")"
if post:
res += "(" + post + ")"
elif pre:
res += "()"
for kk in keys:
if premap.get(kk, "") != "":
res += "[" + premap[kk] + "]"
if postmap.get(kk, "") != "":
res += "[" + postmap[kk] + "]"
elif premap.get(kk, "") != "":
res += "[]"
res += "{" + kk + "}"
document.body[i:j+1] = put_cmd_in_ert([res])
else:
# just remove the params
del document.body[posttexts]
del document.body[pretexts]
i += 1
##
# Conversion hub
#
@ -1477,10 +1574,12 @@ convert = [
[527, []],
[528, []],
[529, []],
[530, []]
[530, []],
[531, []]
]
revert = [
[530, [revert_qualicites]],
[529, [revert_bibpackopts]],
[528, [revert_citekeyonly]],
[527, [revert_biblatex]],

View File

@ -36,6 +36,7 @@
#include "support/regex.h"
#include "support/textutils.h"
#include <map>
#include <set>
using namespace std;
@ -812,6 +813,8 @@ docstring BibTeXInfo::getValueForKey(string const & oldkey, Buffer const & buf,
ret = from_ascii("x"); // any non-empty string will do
else if (key == "ifstar" && ci.Starred)
ret = from_ascii("x"); // any non-empty string will do
else if (key == "ifqualified" && ci.isQualified)
ret = from_ascii("x"); // any non-empty string will do
else if (key == "entrytype")
ret = entry_type_;
else if (prefixIs(key, "ifentrytype:")
@ -908,6 +911,10 @@ docstring BibTeXInfo::getValueForKey(string const & oldkey, Buffer const & buf,
ret = ci.textBefore;
else if (key == "textafter")
ret = ci.textAfter;
else if (key == "curpretext")
ret = ci.getPretexts()[bib_key_];
else if (key == "curposttext")
ret = ci.getPosttexts()[bib_key_];
else if (key == "year")
ret = getYear();
}

View File

@ -13,6 +13,7 @@
#define CITATION_H
#include "support/docstring.h"
#include <map>
#include <string>
namespace lyx {
@ -32,7 +33,8 @@ class CitationStyle
public:
///
CitationStyle() : name("cite"), cmd("cite"), forceUpperCase(false),
hasStarredVersion(false), textAfter(false), textBefore(false) {}
hasStarredVersion(false), hasQualifiedList(false),
textAfter(false), textBefore(false) {}
/// the LyX name
std::string name;
@ -46,6 +48,8 @@ public:
bool forceUpperCase;
/// starred version (full author list by default)
bool hasStarredVersion;
/// allows for qualified citation lists (a Biblatex feature)
bool hasQualifiedList;
/// supports text after the citation
bool textAfter;
/// supports text before the citation
@ -67,7 +71,7 @@ public:
Export
};
///
CiteItem() : forceUpperCase(false), Starred(false),
CiteItem() : forceUpperCase(false), Starred(false), isQualified(false),
context(CiteItem::Everywhere), textAfter(docstring()),
textBefore(docstring()), max_size(128), max_key_size(128),
richtext(false) {}
@ -75,12 +79,22 @@ public:
bool forceUpperCase;
/// is starred version (full author list by default)
bool Starred;
/// is a real qualified list
bool isQualified;
/// where this to be displayed?
CiteItem::CiteContext context;
/// text after the citation
docstring textAfter;
/// text before the citation
docstring textBefore;
/// Qualified lists's pre texts
std::map<docstring, docstring> pretexts;
///
std::map<docstring, docstring> getPretexts() const { return pretexts; }
/// Qualified lists's post texts
std::map<docstring, docstring> posttexts;
///
std::map<docstring, docstring> getPosttexts() const { return posttexts; }
/// the maximum display size as a label
size_t max_size;
/// the maximum size of the processed keys

View File

@ -1097,6 +1097,8 @@ bool TextClass::readCiteEngine(Lexer & lexrc)
latex_cmd += ichar;
else if (mode == StarDesc)
stardesc += ichar;
else if (ichar == '$')
cs.hasQualifiedList = true;
else if (ichar == '*')
cs.hasStarredVersion = true;
else if (ichar == '[' && cs.textAfter)

View File

@ -39,6 +39,7 @@
#include <QMenu>
#include <QSettings>
#include <QShowEvent>
#include <QStandardItemModel>
#include <QVariant>
#include <vector>
@ -138,7 +139,7 @@ GuiCitation::GuiCitation(GuiView & lv)
this, SLOT(on_okPB_clicked()));
selectionManager = new GuiSelectionManager(availableLV, selectedLV,
addPB, deletePB, upPB, downPB, &available_model_, &selected_model_);
addPB, deletePB, upPB, downPB, &available_model_, &selected_model_, 1);
connect(selectionManager, SIGNAL(selectionChanged()),
this, SLOT(setCitedKeys()));
connect(selectionManager, SIGNAL(updateHook()),
@ -159,6 +160,12 @@ GuiCitation::GuiCitation(GuiView & lv)
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
setFocusProxy(filter_);
}
@ -239,7 +246,7 @@ void GuiCitation::updateControls()
// will not have changed.
void GuiCitation::updateControls(BiblioInfo const & bi)
{
QModelIndex idx = selectionManager->getSelectedIndex();
QModelIndex idx = selectionManager->getSelectedIndex(1);
updateInfo(bi, idx);
selectionManager->update();
}
@ -254,8 +261,31 @@ void GuiCitation::updateFormatting(CitationStyle currentStyle)
bool const textbefore = currentStyle.textBefore;
bool const textafter = currentStyle.textAfter;
bool const haveSelection =
selectedLV->model()->rowCount() > 0;
int const rows = selectedLV->model()->rowCount();
bool const qualified = currentStyle.hasQualifiedList
&& (rows > 1
|| !params_["pretextlist"].empty()
|| !params_["posttextlist"].empty());
selectedLV->horizontalHeader()->setVisible(qualified);
selectedLV->setColumnHidden(0, !qualified);
selectedLV->setColumnHidden(2, !qualified);
if (qualified) {
textBeforeLA->setText(qt_("General text befo&re:"));
textAfterLA->setText(qt_("General &text after:"));
textBeforeED->setToolTip(qt_("Text that precedes the whole reference list. "
"For text that precedes individual items, double-click on the respective entry above."));
textAfterLA->setToolTip(qt_("General &text after:"));
textAfterED->setToolTip(qt_("Text that follows the whole reference list. "
"For text that follows individual items, double-click on the respective entry above."));
} else {
textBeforeLA->setText(qt_("Text befo&re:"));
textBeforeED->setToolTip(qt_("Text that precedes the reference (e.g., \"cf.\")"));
textAfterLA->setText(qt_("&Text after:"));
textAfterED->setToolTip(qt_("Text that follows the reference (e.g., pages)"));
}
bool const haveSelection = rows > 0;
forceuppercaseCB->setEnabled(force && haveSelection);
starredCB->setEnabled(full && haveSelection);
@ -306,7 +336,7 @@ void GuiCitation::updateStyles()
// Update the styles for the style combo, citationStyleCO.
void GuiCitation::updateStyles(BiblioInfo const & bi)
{
QStringList selected_keys = selected_model_.stringList();
QStringList selected_keys = selectedKeys();
int curr = selectedLV->model()->rowCount() - 1;
if (curr < 0 || selected_keys.empty()) {
@ -376,7 +406,7 @@ void GuiCitation::fillEntries(BiblioInfo const & bi)
bool GuiCitation::isSelected(QModelIndex const & idx)
{
QString const str = idx.data().toString();
return selected_model_.stringList().contains(str);
return selectedKeys().contains(str);
}
@ -551,6 +581,10 @@ void GuiCitation::applyParams(int const choice, bool full, bool force,
params_["key"] = qstring_to_ucs4(cited_keys_.join(","));
params_["before"] = qstring_to_ucs4(before);
params_["after"] = qstring_to_ucs4(after);
if (cs.hasQualifiedList) {
params_["pretextlist"] = getStringFromVector(getPreTexts(), from_ascii("\t"));
params_["posttextlist"] = getStringFromVector(getPostTexts(), from_ascii("\t"));
}
dispatchParams();
}
@ -558,7 +592,107 @@ void GuiCitation::applyParams(int const choice, bool full, bool force,
void GuiCitation::clearSelection()
{
cited_keys_.clear();
selected_model_.setStringList(cited_keys_);
setSelectedKeys(cited_keys_);
}
void GuiCitation::setSelectedKeys(QStringList const sl)
{
selected_model_.clear();
selected_model_.setColumnCount(3);
QStringList headers;
headers << qt_("Text before")
<< qt_("Cite key")
<< qt_("Text after");
selected_model_.setHorizontalHeaderLabels(headers);
selectedLV->setColumnHidden(0, true);
selectedLV->setColumnHidden(2, true);
selectedLV->verticalHeader()->setVisible(false);
selectedLV->horizontalHeader()->setVisible(false);
QStringList::const_iterator it = sl.begin();
QStringList::const_iterator end = sl.end();
for (int i = 0; it != end; ++it, ++i) {
QStandardItem * si = new QStandardItem();
si->setData(*it);
si->setText(*it);
si->setToolTip(*it);
si->setEditable(false);
selected_model_.setItem(i, 1, si);
}
}
QStringList GuiCitation::selectedKeys()
{
QStringList res;
for (int i = 0; i != selected_model_.rowCount(); ++i) {
QStandardItem const * item = selected_model_.item(i, 1);
if (item)
res.append(item->text());
}
return res;
}
void GuiCitation::setPreTexts(vector<docstring> const m)
{
for (docstring const & s: m) {
QStandardItem * si = new QStandardItem();
docstring key;
docstring pre = split(s, 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);
}
}
vector<docstring> GuiCitation::getPreTexts()
{
vector<docstring> res;
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())
res.push_back(qstring_to_ucs4(key->text()) + " " + qstring_to_ucs4(pre->text()));
}
return res;
}
void GuiCitation::setPostTexts(vector<docstring> const m)
{
for (docstring const & s: m) {
QStandardItem * si = new QStandardItem();
docstring key;
docstring post = split(s, 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);
}
}
vector<docstring> GuiCitation::getPostTexts()
{
vector<docstring> res;
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)
res.push_back(qstring_to_ucs4(key->text()) + " " + qstring_to_ucs4(post->text()));
}
return res;
}
@ -567,6 +701,7 @@ void GuiCitation::init()
// Make the list of all available bibliography keys
BiblioInfo const & bi = bibInfo();
all_keys_ = to_qstring_list(bi.getKeys());
available_model_.setStringList(all_keys_);
// Ditto for the keys cited in this inset
@ -575,7 +710,7 @@ void GuiCitation::init()
cited_keys_.clear();
else
cited_keys_ = str.split(",");
selected_model_.setStringList(cited_keys_);
setSelectedKeys(cited_keys_);
// Initialize the drop downs
fillEntries(bi);
@ -585,21 +720,23 @@ void GuiCitation::init()
string const & cmd = params_.getCmdName();
CitationStyle const cs =
citationStyleFromString(cmd, documentBuffer().params());
forceuppercaseCB->setChecked(cs.forceUpperCase);
starredCB->setChecked(cs.hasStarredVersion &&
documentBuffer().params().fullAuthorList());
textBeforeED->setText(toqstr(params_["before"]));
textAfterED->setText(toqstr(params_["after"]));
setPreTexts(getVectorFromString(params_["pretextlist"], from_ascii("\t")));
setPostTexts(getVectorFromString(params_["posttextlist"], from_ascii("\t")));
// Update the interface
updateControls(bi);
updateStyles(bi);
if (selected_model_.rowCount()) {
selectedLV->blockSignals(true);
selectedLV->setFocus();
QModelIndex idx = selected_model_.index(0, 0);
selectedLV->selectionModel()->select(idx,
QItemSelectionModel::ClearAndSelect);
selectedLV->selectRow(0);
selectedLV->blockSignals(false);
// Find the citation style
@ -682,6 +819,28 @@ QStringList GuiCitation::citationStyles(BiblioInfo const & bi, size_t max_size)
{
vector<docstring> const keys = to_docstring_vector(cited_keys_);
vector<CitationStyle> styles = citeStyles_;
int ind = citationStyleCO->currentIndex();
if (ind == -1)
ind = 0;
CitationStyle cs = styles[ind];
vector<docstring> pretexts = getPreTexts();
vector<docstring> posttexts = getPostTexts();
bool const qualified = cs.hasQualifiedList
&& (selectedLV->model()->rowCount() > 1
|| !pretexts.empty()
|| !posttexts.empty());
std::map<docstring, docstring> pres;
for (docstring const & s: pretexts) {
docstring key;
docstring val = split(s, key, ' ');
pres[key] = val;
}
std::map<docstring, docstring> posts;
for (docstring const & s: posttexts) {
docstring key;
docstring val = split(s, key, ' ');
posts[key] = val;
}
CiteItem ci;
ci.textBefore = qstring_to_ucs4(textBeforeED->text());
ci.textAfter = qstring_to_ucs4(textAfterED->text());
@ -689,6 +848,9 @@ QStringList GuiCitation::citationStyles(BiblioInfo const & bi, size_t max_size)
ci.Starred = starredCB->isChecked();
ci.context = CiteItem::Dialog;
ci.max_size = max_size;
ci.isQualified = qualified;
ci.pretexts = pres;
ci.posttexts = posts;
vector<docstring> ret = bi.getCiteStrings(keys, styles, documentBuffer(), ci);
return to_qstring_list(ret);
}
@ -696,7 +858,7 @@ QStringList GuiCitation::citationStyles(BiblioInfo const & bi, size_t max_size)
void GuiCitation::setCitedKeys()
{
cited_keys_ = selected_model_.stringList();
cited_keys_ = selectedKeys();
updateStyles();
}

View File

@ -23,6 +23,8 @@
#include "Citation.h"
#include <QAbstractListModel>
#include <QStandardItemModel>
#include <QStringList>
#include <QStringListModel>
@ -34,6 +36,7 @@ namespace frontend {
class GuiSelectionManager;
class GuiCitation : public DialogView, public Ui::CitationUi
{
Q_OBJECT
@ -114,6 +117,19 @@ private:
/// Clear selected keys
void clearSelection();
/// Set selected keys
void setSelectedKeys(QStringList const);
/// Get selected keys
QStringList selectedKeys();
/// Set pre texts of qualified lists
void setPreTexts(std::vector<docstring> const m);
/// Get pre texts of qualified lists
std::vector<docstring> getPreTexts();
/// Set post texts of qualified lists
void setPostTexts(std::vector<docstring> const m);
/// Get post texts of qualified lists
std::vector<docstring> getPostTexts();
/// Find keys containing a string.
void findKey(
BiblioInfo const & bi, //< optimize by passing this
@ -171,7 +187,7 @@ private:
/// available keys.
QStringListModel available_model_;
/// selected keys.
QStringListModel selected_model_;
QStandardItemModel selected_model_;
/// All keys.
QStringList all_keys_;
/// Cited keys.

View File

@ -18,6 +18,7 @@
#include "support/debug.h"
#include <QAbstractItemModel>
#include <QAbstractListModel>
#include <QItemSelection>
#include <QListView>
@ -42,21 +43,24 @@ namespace frontend {
GuiSelectionManager::GuiSelectionManager(
QAbstractItemView * avail,
QListView * sel,
QAbstractItemView * sel,
QPushButton * add,
QPushButton * del,
QPushButton * up,
QPushButton * down,
QAbstractListModel * amod,
QAbstractListModel * smod)
QAbstractItemModel * smod,
int const main_sel_col)
: availableLV(avail), selectedLV(sel), addPB(add), deletePB(del),
upPB(up), downPB(down), availableModel(amod), selectedModel(smod),
selectedHasFocus_(false)
selectedHasFocus_(false), main_sel_col_(main_sel_col)
{
selectedLV->setModel(smod);
availableLV->setModel(amod);
selectedLV->setSelectionBehavior(QAbstractItemView::SelectRows);
selectedLV->setSelectionMode(QAbstractItemView::SingleSelection);
connect(availableLV->selectionModel(),
SIGNAL(currentChanged(QModelIndex, QModelIndex)),
this, SLOT(availableChanged(QModelIndex, QModelIndex)));
@ -69,6 +73,8 @@ GuiSelectionManager::GuiSelectionManager(
connect(selectedLV->selectionModel(),
SIGNAL(selectionChanged(QItemSelection, QItemSelection)),
this, SLOT(selectedChanged(QItemSelection, QItemSelection)));
connect(selectedLV->itemDelegate(), SIGNAL(commitData(QWidget*)),
this, SLOT(selectedEdited()));
connect(addPB, SIGNAL(clicked()),
this, SLOT(addPB_clicked()));
connect(deletePB, SIGNAL(clicked()),
@ -94,10 +100,10 @@ void GuiSelectionManager::update()
}
QModelIndex GuiSelectionManager::getSelectedIndex() const
QModelIndex GuiSelectionManager::getSelectedIndex(int const c) const
{
QModelIndexList avail = availableLV->selectionModel()->selectedIndexes();
QModelIndexList sel = selectedLV->selectionModel()->selectedIndexes();
QModelIndexList sel = selectedLV->selectionModel()->selectedRows(c);
bool const have_avl = !avail.isEmpty();
bool const have_sel = !sel.isEmpty();
@ -137,7 +143,7 @@ void GuiSelectionManager::updateDelPB()
}
QModelIndexList const selSels =
selectedLV->selectionModel()->selectedIndexes();
int const sel_nr = selSels.empty() ? -1 : selSels.first().row();
int const sel_nr = selSels.empty() ? -1 : selSels.first().row();
deletePB->setEnabled(sel_nr >= 0);
}
@ -151,7 +157,7 @@ void GuiSelectionManager::updateUpPB()
}
QModelIndexList const selSels =
selectedLV->selectionModel()->selectedIndexes();
int const sel_nr = selSels.empty() ? -1 : selSels.first().row();
int const sel_nr = selSels.empty() ? -1 : selSels.first().row();
upPB->setEnabled(sel_nr > 0);
}
@ -165,7 +171,7 @@ void GuiSelectionManager::updateDownPB()
}
QModelIndexList const selSels =
selectedLV->selectionModel()->selectedIndexes();
int const sel_nr = selSels.empty() ? -1 : selSels.first().row();
int const sel_nr = selSels.empty() ? -1 : selSels.first().row();
downPB->setEnabled(sel_nr >= 0 && sel_nr < srows - 1);
}
@ -176,7 +182,7 @@ bool GuiSelectionManager::isSelected(const QModelIndex & idx)
return false;
QVariant const & str = availableModel->data(idx, Qt::DisplayRole);
QModelIndexList qmil =
selectedModel->match(selectedModel->index(0),
selectedModel->match(selectedModel->index(0, main_sel_col_),
Qt::DisplayRole, str, 1,
Qt::MatchFlags(Qt::MatchExactly | Qt::MatchWrap));
return !qmil.empty();
@ -221,6 +227,12 @@ void GuiSelectionManager::selectedChanged(const QModelIndex & idx, const QModelI
}
void GuiSelectionManager::selectedEdited()
{
selectionChanged();
}
bool GuiSelectionManager::insertRowToSelected(int i,
QMap<int, QVariant> const & itemData)
{
@ -230,7 +242,23 @@ bool GuiSelectionManager::insertRowToSelected(int i,
i = selectedModel->rowCount();
if (!selectedModel->insertRow(i))
return false;
return selectedModel->setItemData(selectedModel->index(i), itemData);
return selectedModel->setItemData(selectedModel->index(i, main_sel_col_), itemData);
}
bool GuiSelectionManager::insertRowToSelected(int i, QMap<int, QMap<int, QVariant>> & qms)
{
if (i <= -1)
i = 0;
if (i > selectedModel->rowCount())
i = selectedModel->rowCount();
if (!selectedModel->insertRow(i))
return false;
bool res = true;
QMap<int, QMap<int, QVariant>>::const_iterator it = qms.constBegin();
for (; it != qms.constEnd(); ++it)
res &= selectedModel->setItemData(selectedModel->index(i, it.key()), it.value());
return res;
}
@ -291,11 +319,14 @@ void GuiSelectionManager::upPB_clicked()
int const pos = idx.row();
if (pos <= 0)
return;
QMap<int, QVariant> qm = selectedModel->itemData(idx);
QMap<int, QMap<int, QVariant>> qms;
QList<QModelIndex>::const_iterator it = selIdx.constBegin();
for (; it != selIdx.constEnd(); ++it)
qms[it->column()] = selectedModel->itemData(*it);
selectedModel->removeRow(pos);
insertRowToSelected(pos - 1, qm);
insertRowToSelected(pos - 1, qms);
selectionChanged(); //signal
@ -317,10 +348,13 @@ void GuiSelectionManager::downPB_clicked()
if (pos >= selectedModel->rowCount() - 1)
return;
QMap<int, QVariant> qm = selectedModel->itemData(idx);
QMap<int, QMap<int, QVariant>> qms;
QList<QModelIndex>::const_iterator it = selIdx.constBegin();
for (; it != selIdx.constEnd(); ++it)
qms[it->column()] = selectedModel->itemData(*it);
selectedModel->removeRow(pos);
insertRowToSelected(pos + 1, qm);
insertRowToSelected(pos + 1, qms);
selectionChanged(); //signal

View File

@ -14,6 +14,7 @@
#include <QObject>
class QAbstractItemModel;
class QAbstractListModel;
class QModelIndex;
class QListView;
@ -42,13 +43,14 @@ public:
///
GuiSelectionManager(
QAbstractItemView * availableLV,
QListView * selectedLV,
QAbstractItemView * selectedLV,
QPushButton * addPB,
QPushButton * delPB,
QPushButton * upPB,
QPushButton * downPB,
QAbstractListModel * availableModel,
QAbstractListModel * selectedModel);
QAbstractItemModel * selectedModel,
int const main_sel_col = 0);
/// Sets the state of the various push buttons, depending upon the
/// state of the widgets. (E.g., "delete" is enabled only if the
/// selection is non-empty.)
@ -64,7 +66,7 @@ public:
bool selectedFocused() const { return selectedHasFocus_; }
/// Returns the selected index. Note that this will depend upon
/// selectedFocused().
QModelIndex getSelectedIndex() const;
QModelIndex getSelectedIndex(int const c = 0) const;
Q_SIGNALS:
/// Emitted when the list of selected items has changed.
@ -87,11 +89,13 @@ protected:
/// been selected (i.e., is also in selectedLV).
bool isSelected(const QModelIndex & idx);
///
bool insertRowToSelected(int i, QMap<int, QVariant> const & itemData);
bool insertRowToSelected(int i, QMap<int, QVariant> const & itemData);
///
bool insertRowToSelected(int i, QMap<int, QMap<int, QVariant>> &);
///
QAbstractItemView * availableLV;
///
QListView * selectedLV;
QAbstractItemView * selectedLV;
///
QPushButton * addPB;
///
@ -103,7 +107,7 @@ protected:
///
QAbstractListModel * availableModel;
///
QAbstractListModel * selectedModel;
QAbstractItemModel * selectedModel;
protected Q_SLOTS:
///
@ -115,6 +119,8 @@ protected Q_SLOTS:
///
void selectedChanged(QItemSelection const & qis, QItemSelection const &);
///
void selectedEdited();
///
virtual void addPB_clicked();
///
virtual void deletePB_clicked();
@ -138,6 +144,8 @@ private:
virtual void updateUpPB();
///
bool selectedHasFocus_;
///
int main_sel_col_;
};
} // namespace frontend

View File

@ -1540,7 +1540,7 @@ void MenuDefinition::expandCiteStyles(BufferView const * bv)
static_cast<InsetCitation const *>(inset);
Buffer const * buf = &bv->buffer();
BufferParams const & bp = buf->params();
BufferParams const & bp = buf->masterParams();
string const cmd = citinset->params().getCmdName();
docstring const & key = citinset->getParam("key");
@ -1557,7 +1557,18 @@ void MenuDefinition::expandCiteStyles(BufferView const * bv)
vector<docstring> const keys = getVectorFromString(key);
vector<CitationStyle> const citeStyleList = buf->params().citeStyles();
vector<CitationStyle> const citeStyleList = bp.citeStyles();
CitationStyle cs = citinset->getCitationStyle(bp, cmd, citeStyleList);
bool const qualified = cs.hasQualifiedList
&& (keys.size() > 1
|| !citinset->getParam("pretextlist").empty()
|| !citinset->getParam("posttextlist").empty());
std::map<docstring, docstring> pres =
citinset->getQualifiedLists(citinset->getParam("pretextlist"));
std::map<docstring, docstring> posts =
citinset->getQualifiedLists(citinset->getParam("posttextlist"));
CiteItem ci;
ci.textBefore = citinset->getParam("before");
ci.textAfter = citinset->getParam("after");
@ -1565,6 +1576,9 @@ void MenuDefinition::expandCiteStyles(BufferView const * bv)
ci.Starred = star;
ci.context = CiteItem::Dialog;
ci.max_size = 40;
ci.isQualified = qualified;
ci.pretexts = pres;
ci.posttexts = posts;
vector<docstring> citeStrings =
buf->masterBibInfo().getCiteStrings(keys, citeStyleList, bv->buffer(), ci);
@ -1581,9 +1595,6 @@ void MenuDefinition::expandCiteStyles(BufferView const * bv)
"changetype " + from_utf8(citationStyleToString(cs)))));
}
// Extra features of the citation styles
CitationStyle cs = citinset->getCitationStyle(bp, cmd, citeStyleList);
if (cs.hasStarredVersion) {
docstring starred = _("All authors|h");
// Check if we have a custom string/tooltip for the starred version

View File

@ -234,11 +234,7 @@
</widget>
</item>
<item>
<widget class="QListView" name="selectedLV">
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
</widget>
<widget class="QTableView" name="selectedLV"/>
</item>
</layout>
</item>
@ -290,7 +286,7 @@
<item>
<widget class="QLabel" name="textBeforeLA">
<property name="text">
<string>Text &amp;before:</string>
<string>Text befo&amp;re:</string>
</property>
<property name="buddy">
<cstring>textBeforeED</cstring>
@ -483,7 +479,6 @@
<tabstop>entriesCO</tabstop>
<tabstop>searchOptionsPB</tabstop>
<tabstop>availableLV</tabstop>
<tabstop>selectedLV</tabstop>
<tabstop>addPB</tabstop>
<tabstop>deletePB</tabstop>
<tabstop>upPB</tabstop>

View File

@ -69,6 +69,8 @@ ParamInfo const & InsetCitation::findInfo(string const & /* cmdName */)
param_info_.add("after", ParamInfo::LATEX_OPTIONAL);
param_info_.add("before", ParamInfo::LATEX_OPTIONAL);
param_info_.add("key", ParamInfo::LATEX_REQUIRED);
param_info_.add("pretextlist", ParamInfo::LATEX_OPTIONAL);
param_info_.add("posttextlist", ParamInfo::LATEX_OPTIONAL);
}
return param_info_;
}
@ -312,6 +314,20 @@ inline docstring wrapCitation(docstring const & key,
} // anonymous namespace
map<docstring, docstring> InsetCitation::getQualifiedLists(docstring const p) const
{
vector<docstring> ps =
getVectorFromString(p, from_ascii("\t"));
std::map<docstring, docstring> res;
for (docstring const & s: ps) {
docstring key;
docstring val = split(s, key, ' ');
res[key] = val;
}
return res;
}
docstring InsetCitation::generateLabel(bool for_xhtml) const
{
docstring label;
@ -360,12 +376,24 @@ docstring InsetCitation::complexLabel(bool for_xhtml) const
*/
docstring label;
vector<docstring> keys = getVectorFromString(key);
CitationStyle cs = getCitationStyle(buffer().masterParams(),
cite_type, buffer().masterParams().citeStyles());
bool const qualified = cs.hasQualifiedList
&& (keys.size() > 1
|| !getParam("pretextlist").empty()
|| !getParam("posttextlist").empty());
map<docstring, docstring> pres = getQualifiedLists(getParam("pretextlist"));
map<docstring, docstring> posts = getQualifiedLists(getParam("posttextlist"));
CiteItem ci;
ci.textBefore = getParam("before");
ci.textAfter = getParam("after");
ci.forceUpperCase = uppercase;
ci.Starred = starred;
ci.max_size = UINT_MAX;
ci.isQualified = qualified;
ci.pretexts = pres;
ci.posttexts = posts;
if (for_xhtml) {
ci.max_key_size = UINT_MAX;
ci.context = CiteItem::Export;
@ -509,13 +537,15 @@ void InsetCitation::forOutliner(docstring & os, size_t const, bool const) const
void InsetCitation::latex(otexstream & os, OutputParams const & runparams) const
{
BiblioInfo const & bi = buffer().masterBibInfo();
docstring const key = getParam("key");
// "keyonly" command: output the plain key and stop.
if (getCmdName() == "keyonly") {
// Special command to only return the key
if (!bi.isBibtex(getParam("key")))
// escape chars with bibitems
os << escape(cleanupWhitespace(getParam("key")));
os << escape(cleanupWhitespace(key));
else
os << cleanupWhitespace(getParam("key"));
os << cleanupWhitespace(key);
return;
}
vector<CitationStyle> citation_styles = buffer().masterParams().citeStyles();
@ -524,23 +554,62 @@ void InsetCitation::latex(otexstream & os, OutputParams const & runparams) const
// FIXME UNICODE
docstring const cite_str = from_utf8(citationStyleToString(cs, true));
// check if we have to do a qualified list
vector<docstring> keys = getVectorFromString(cleanupWhitespace(key));
bool const qualified = cs.hasQualifiedList
&& (!getParam("pretextlist").empty()
|| !getParam("posttextlist").empty());
if (runparams.inulemcmd > 0)
os << "\\mbox{";
os << "\\" << cite_str;
docstring const & before = getParam("before");
docstring const & after = getParam("after");
if (!before.empty() && cs.textBefore)
os << '[' << before << "][" << after << ']';
else if (!after.empty() && cs.textAfter)
os << '[' << after << ']';
if (qualified)
os << "s";
if (!bi.isBibtex(getParam("key")))
docstring before = getParam("before");
docstring after = getParam("after");
if (!before.empty() && cs.textBefore) {
if (qualified) {
if (contains(before, '(') || contains(before, ')'))
// protect parens
before = '{' + before + '}';
if (contains(after, '(') || contains(after, ')'))
// protect parens
after = '{' + after + '}';
os << '(' << before << ")(" << after << ')';
} else
os << '[' << before << "][" << after << ']';
} else if (!after.empty() && cs.textAfter) {
if (qualified) {
if (contains(after, '(') || contains(after, ')'))
// protect parens
after = '{' + after + '}';
os << '(' << after << ')';
} else
os << '[' << after << ']';
}
if (!bi.isBibtex(key))
// escape chars with bibitems
os << '{' << escape(cleanupWhitespace(getParam("key"))) << '}';
else
os << '{' << cleanupWhitespace(getParam("key")) << '}';
os << '{' << escape(cleanupWhitespace(key)) << '}';
else {
if (qualified) {
map<docstring, docstring> pres = getQualifiedLists(getParam("pretextlist"));
map<docstring, docstring> posts = getQualifiedLists(getParam("posttextlist"));
for (docstring const & k: keys) {
docstring const bef = pres[k];
docstring const aft = posts[k];
if (!bef.empty())
os << '[' << bef << "][" << aft << ']';
else if (!aft.empty())
os << '[' << aft << ']';
os << '{' << k << '}';
}
} else
os << '{' << cleanupWhitespace(key) << '}';
}
if (runparams.inulemcmd)
os << "}";

View File

@ -86,6 +86,8 @@ public:
///
CitationStyle getCitationStyle(BufferParams const & bp, std::string const & input,
std::vector<CitationStyle> const & valid_styles) const;
///
std::map<docstring, docstring> getQualifiedLists(docstring const p) const;
private:
/// tries to make a pretty label and makes a basic one if not

View File

@ -134,7 +134,20 @@ Format LaTeX feature LyX feature
\citecite[*] LatexCmd citecite[*]
\fullcite LatexCmd fullcite
\footfullcite LatexCmd footfullcite
\supercite LatexCmd supercite
\supercite LatexCmd supercite
531 Biblatex "qualified citation lists"
\cites(pre)(post)[pre1][post1]{key1}[pre2][post2]{key2}...
\begin_inset CommandInset citation
LatexCmd cite
after "post"
before "pre"
key "key1,key2..."
pretextlist "key1 pre1\tab key2 pre2..."
posttextlist "key1 post1\tab key2 post2..."
Same for:
\Cites, \textcites, \Textcites, \parencites, \Parencites, \smartcites, \Smartcites, \autocites, Autocites
General

View File

@ -32,8 +32,8 @@ extern char const * const lyx_version_info;
// Do not remove the comment below, so we get merge conflict in
// independent branches. Instead add your own.
#define LYX_FORMAT_LYX 530 // spitz: natbib/jurabib package options
#define LYX_FORMAT_TEX2LYX 530
#define LYX_FORMAT_LYX 531 // spitz: qualified citation lists
#define LYX_FORMAT_TEX2LYX 531
#if LYX_FORMAT_TEX2LYX != LYX_FORMAT_LYX
#ifndef _MSC_VER