commit 68ab4023ccdf26022a053adc1bfaecef9fef58f4
Author: Juergen Spitzmueller <[email protected]>
Date: Sat Jan 21 14:25:17 2017 +0100
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.
---
development/FORMAT | 7 +
lib/citeengines/biblatex-natbib.citeengine | 26 +++-
lib/citeengines/biblatex.citeengine | 36 +++---
lib/doc/Customization.lyx | 79 +++++++++++-
lib/doc/UserGuide.lyx | 95 ++++++++++++++-
lib/lyx2lyx/lyx_2_3.py | 105 +++++++++++++++-
src/BiblioInfo.cpp | 7 +
src/Citation.h | 18 +++-
src/TextClass.cpp | 2 +
src/frontends/qt4/GuiCitation.cpp | 186 ++++++++++++++++++++++++++--
src/frontends/qt4/GuiCitation.h | 18 +++-
src/frontends/qt4/GuiSelectionManager.cpp | 66 ++++++++---
src/frontends/qt4/GuiSelectionManager.h | 20 ++-
src/frontends/qt4/Menus.cpp | 21 +++-
src/frontends/qt4/ui/CitationUi.ui | 9 +-
src/insets/InsetCitation.cpp | 93 ++++++++++++--
src/insets/InsetCitation.h | 2 +
src/tex2lyx/TODO.txt | 15 ++-
src/version.h | 4 +-
19 files changed, 715 insertions(+), 94 deletions(-)
diff --git a/development/FORMAT b/development/FORMAT
index 3c4f115..3c464f3 100644
--- a/development/FORMAT
+++ b/development/FORMAT
@@ -7,6 +7,13 @@ changes happened in particular if possible. A good example
would be
-----------------------
+2017-01-21 Jürgen Spitzmüller <[email protected]>
+ * 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 <[email protected]>
* Format incremented to 530: Support natbib & jurabib package options.
diff --git a/lib/citeengines/biblatex-natbib.citeengine
b/lib/citeengines/biblatex-natbib.citeengine
index ffcd9e6..25b76f6 100644
--- a/lib/citeengines/biblatex-natbib.citeengine
+++ b/lib/citeengines/biblatex-natbib.citeengine
@@ -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
diff --git a/lib/citeengines/biblatex.citeengine
b/lib/citeengines/biblatex.citeengine
index 657547e..c58e2be 100644
--- a/lib/citeengines/biblatex.citeengine
+++ b/lib/citeengines/biblatex.citeengine
@@ -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
diff --git a/lib/doc/Customization.lyx b/lib/doc/Customization.lyx
index 3ecd1ee..a9a23de 100644
--- a/lib/doc/Customization.lyx
+++ b/lib/doc/Customization.lyx
@@ -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
diff --git a/lib/doc/UserGuide.lyx b/lib/doc/UserGuide.lyx
index d1fd4e8..518db5d 100644
--- a/lib/doc/UserGuide.lyx
+++ b/lib/doc/UserGuide.lyx
@@ -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
diff --git a/lib/lyx2lyx/lyx_2_3.py b/lib/lyx2lyx/lyx_2_3.py
index 5b647db..044bc75 100644
--- a/lib/lyx2lyx/lyx_2_3.py
+++ b/lib/lyx2lyx/lyx_2_3.py
@@ -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]],
diff --git a/src/BiblioInfo.cpp b/src/BiblioInfo.cpp
index ab06f37..4220fe0 100644
--- a/src/BiblioInfo.cpp
+++ b/src/BiblioInfo.cpp
@@ -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();
}
diff --git a/src/Citation.h b/src/Citation.h
index c48e3c4..600ba6c 100644
--- a/src/Citation.h
+++ b/src/Citation.h
@@ -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
diff --git a/src/TextClass.cpp b/src/TextClass.cpp
index 9b25a67..34b55fa 100644
--- a/src/TextClass.cpp
+++ b/src/TextClass.cpp
@@ -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)
diff --git a/src/frontends/qt4/GuiCitation.cpp
b/src/frontends/qt4/GuiCitation.cpp
index d73f3d3..2178dd1 100644
--- a/src/frontends/qt4/GuiCitation.cpp
+++ b/src/frontends/qt4/GuiCitation.cpp
@@ -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();
}
diff --git a/src/frontends/qt4/GuiCitation.h b/src/frontends/qt4/GuiCitation.h
index 035b2d2..2fa4369 100644
--- a/src/frontends/qt4/GuiCitation.h
+++ b/src/frontends/qt4/GuiCitation.h
@@ -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.
diff --git a/src/frontends/qt4/GuiSelectionManager.cpp
b/src/frontends/qt4/GuiSelectionManager.cpp
index d3d2b01..b90d0ea 100644
--- a/src/frontends/qt4/GuiSelectionManager.cpp
+++ b/src/frontends/qt4/GuiSelectionManager.cpp
@@ -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
diff --git a/src/frontends/qt4/GuiSelectionManager.h
b/src/frontends/qt4/GuiSelectionManager.h
index 4b83e23..dae3f90 100644
--- a/src/frontends/qt4/GuiSelectionManager.h
+++ b/src/frontends/qt4/GuiSelectionManager.h
@@ -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
diff --git a/src/frontends/qt4/Menus.cpp b/src/frontends/qt4/Menus.cpp
index c8682bb..535ee31 100644
--- a/src/frontends/qt4/Menus.cpp
+++ b/src/frontends/qt4/Menus.cpp
@@ -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
diff --git a/src/frontends/qt4/ui/CitationUi.ui
b/src/frontends/qt4/ui/CitationUi.ui
index a824212..6b43968 100644
--- a/src/frontends/qt4/ui/CitationUi.ui
+++ b/src/frontends/qt4/ui/CitationUi.ui
@@ -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 &before:</string>
+ <string>Text befo&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>
diff --git a/src/insets/InsetCitation.cpp b/src/insets/InsetCitation.cpp
index 0a5da5b..9004c98 100644
--- a/src/insets/InsetCitation.cpp
+++ b/src/insets/InsetCitation.cpp
@@ -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";
+
+ 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(getParam("key")))
+ 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 << "}";
diff --git a/src/insets/InsetCitation.h b/src/insets/InsetCitation.h
index 38624ed..57b0b3d 100644
--- a/src/insets/InsetCitation.h
+++ b/src/insets/InsetCitation.h
@@ -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
diff --git a/src/tex2lyx/TODO.txt b/src/tex2lyx/TODO.txt
index c6866ed..d7178d3 100644
--- a/src/tex2lyx/TODO.txt
+++ b/src/tex2lyx/TODO.txt
@@ -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
diff --git a/src/version.h b/src/version.h
index a0b5c97..a0a611d 100644
--- a/src/version.h
+++ b/src/version.h
@@ -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