The branch, biblatex2, has been updated.

- Log -----------------------------------------------------------------

commit 84b93cf4170cd47ef6c2af345a777a4292cd70db
Merge: dcdd04a 83ac154
Author: Juergen Spitzmueller <[email protected]>
Date:   Sun Jan 1 08:08:34 2017 +0100

    Merge branch 'biblatex2' of git.lyx.org:features into biblatex2


commit dcdd04a492974bfd9e73481ebe560f25d6c3951d
Author: Juergen Spitzmueller <[email protected]>
Date:   Sat Dec 31 19:45:25 2016 +0100

    TeXFiles.py: scan for biblatex *.bbx and *.cbx files

diff --git a/lib/scripts/TeXFiles.py b/lib/scripts/TeXFiles.py
index 9e6f6b5..31b44b4 100755
--- a/lib/scripts/TeXFiles.py
+++ b/lib/scripts/TeXFiles.py
@@ -16,17 +16,20 @@
 # TeX style files      -> option sty
 # bibtex style files   -> option bst
 # bibtex database files -> option bib
+# biblatex bibstyles   -> option bbx
+# biblatex citestyles  -> option cbx
 #
 # with the help
 # of kpsewhich and creates a
-# bstFiles.lst, clsFiles.lst, styFiles.lst, bibFiles.lst
+# bstFiles.lst, clsFiles.lst, styFiles.lst, bibFiles.lst,
+# bbxFiles.lst, cbxFiles.lst
 # without any parameter all files are created.
 #
 # Herbert Voss <[email protected]>
 #
 # Updates from Jean-Marc Lasgouttes.
 #
-# bib support added by Juergen Spitzmueller (v0.3)
+# bib, bbx and cbx support added by Juergen Spitzmueller (v0.4)
 #
 # translated to python by Bo Peng, so that the script only 
 # relies on python and kpsewhich (no shell command is used).
@@ -38,6 +41,8 @@ cls_stylefile = 'clsFiles.lst'
 sty_stylefile = 'styFiles.lst'
 bst_stylefile = 'bstFiles.lst'
 bib_files = 'bibFiles.lst'
+bbx_files = 'bbxFiles.lst'
+cbx_files = 'cbxFiles.lst'
 
 def cmdOutput(cmd):
     '''utility function: run a command and get its output as a string
@@ -51,19 +56,19 @@ def cmdOutput(cmd):
 # processing command line options
 if len(sys.argv) > 1:
     if sys.argv[1] in ['--help', '-help']:
-        print '''Usage: TeXFiles.py [-version | cls | sty | bst | bib ]
+        print '''Usage: TeXFiles.py [-version | cls | sty | bst | bib | bbx| 
cbx ]
             Default is without any Parameters,
             so that all files will be created'''
         sys.exit(0)
     else:
         types = sys.argv[1:]
         for type in types:
-            if type not in ['cls', 'sty', 'bst', 'bib']:
+            if type not in ['cls', 'sty', 'bst', 'bib', 'bbx', 'cbx']:
                 print 'ERROR: unknown type', type
                 sys.exit(1)
 else:
     # if no parameter is specified, assume all
-    types = ['cls', 'sty', 'bst', 'bib']
+    types = ['cls', 'sty', 'bst', 'bib', 'bbx', 'cbx']
 
 #
 # MS-DOS and MS-Windows define $COMSPEC or $ComSpec and use `;' to separate
@@ -92,6 +97,12 @@ for type in types:
     elif type == 'bib':
         outfile = bib_files
         kpsetype = '.bib'
+    elif type == 'bbx':
+        outfile = bbx_files
+        kpsetype = '.tex'
+    elif type == 'cbx':
+        outfile = cbx_files
+        kpsetype = '.tex'
 
     dirs = cmdOutput('kpsewhich --show-path=' + kpsetype).replace('!!', 
'').strip()
     # remove excessive //

commit dc9efe3d4750bcd11f8cdb1a827de51f2fc323d5
Author: Juergen Spitzmueller <[email protected]>
Date:   Sat Dec 31 19:44:32 2016 +0100

    Add a CiteFramework tag
    
    This is to distinguish the biblatex and bibtex paradigms

diff --git a/lib/citeengines/basic.citeengine b/lib/citeengines/basic.citeengine
index 7de5e35..26d5ba3 100644
--- a/lib/citeengines/basic.citeengine
+++ b/lib/citeengines/basic.citeengine
@@ -3,12 +3,13 @@
 #   The basic citation capabilities provided by BibTeX.
 #   Mainly simple numeric styles primarily suitable for science and maths.
 # DescriptionEnd
-# Excludes: jurabib | natbib
+# Excludes: jurabib | natbib | biblatex
 
 # Author: Julien Rioux <[email protected]>
 
 Format 62
 
+CiteFramework bibtex
 CiteEngineType default
 DefaultBiblio  plain
 
diff --git a/lib/citeengines/jurabib.citeengine 
b/lib/citeengines/jurabib.citeengine
index de292bb..5c9192f 100644
--- a/lib/citeengines/jurabib.citeengine
+++ b/lib/citeengines/jurabib.citeengine
@@ -4,7 +4,7 @@
 #   and the Humanities. It includes localizations for English, German, French, 
Dutch,
 #   Spanish and Italian.
 # DescriptionEnd
-# Excludes: basic | natbib
+# Excludes: basic | natbib | biblatex
 
 # Author: Julien Rioux <[email protected]>
 
@@ -12,6 +12,7 @@ Format 62
 
 Requires jurabib
 
+CiteFramework bibtex
 CiteEngineType authoryear
 DefaultBiblio  jurabib
 
diff --git a/lib/citeengines/natbib.citeengine 
b/lib/citeengines/natbib.citeengine
index c738e51..98e5a10 100644
--- a/lib/citeengines/natbib.citeengine
+++ b/lib/citeengines/natbib.citeengine
@@ -5,7 +5,7 @@
 #   numerical citations, annotations, capitalization of the `van' part of 
 #   author names, shortened and full author lists, and more.
 # DescriptionEnd
-# Excludes: basic | jurabib
+# Excludes: basic | jurabib | biblatex
 
 # Author: Julien Rioux <[email protected]>
 
@@ -13,6 +13,7 @@ Format 62
 
 Requires natbib
 
+CiteFramework bibtex
 CiteEngineType authoryear|numerical
 DefaultBiblio  authoryear:plainnat|numerical:plainnat
 
diff --git a/lib/configure.py b/lib/configure.py
index fb5dcc6..43d3929 100644
--- a/lib/configure.py
+++ b/lib/configure.py
@@ -1511,7 +1511,7 @@ def checkCiteEnginesConfig():
 ## It has been automatically generated by configure
 ## Use "Options/Reconfigure" if you need to update it after a
 ## configuration change.
-## "CiteEngineName" "filename" "CiteEngineType" "DefaultBiblio" "Description" 
"Packages" "Requires" "Excludes"
+## "CiteEngineName" "filename" "CiteEngineType" "CiteFramework" 
"DefaultBiblio" "Description" "Packages" "Requires" "Excludes"
 ''')
 
   # build the list of available modules
@@ -1550,7 +1550,7 @@ def processCiteEngineFile(file, filename, bool_docbook):
           #Excludes: [list of excluded engines]
         The last two lines are optional.
         We expect output:
-          "CiteEngineName" "filename" "CiteEngineType" "DefaultBiblio" 
"Description" "Packages" "Requires" "Excludes"
+          "CiteEngineName" "filename" "CiteEngineType" "CiteFramework" 
"DefaultBiblio" "Description" "Packages" "Requires" "Excludes"
     '''
     remods = re.compile(r'\DeclareLyXCiteEngine\s*(?:\[([^]]*?)\])?{(.*)}')
     rereqs = re.compile(r'#+\s*Requires:\s*(.*)')
@@ -1559,8 +1559,9 @@ def processCiteEngineFile(file, filename, bool_docbook):
     redend = re.compile(r'#+\s*DescriptionEnd\s*$')
     recet = re.compile(r'\s*CiteEngineType\s*(.*)')
     redb = re.compile(r'\s*DefaultBiblio\s*(.*)')
+    resfm = re.compile(r'\s*CiteFramework\s*(.*)')
 
-    modname = desc = pkgs = req = excl = cet = db = ""
+    modname = desc = pkgs = req = excl = cet = db = cfm = ""
     readingDescription = False
     descLines = []
 
@@ -1608,6 +1609,10 @@ def processCiteEngineFile(file, filename, bool_docbook):
       if res != None:
         db = res.group(1)
         continue
+      res = resfm.search(line)
+      if res != None:
+        cfm = res.group(1)
+        continue
 
     if modname == "":
       logger.warning("Cite Engine File file without \DeclareLyXCiteEngine 
line. ")
@@ -1630,7 +1635,7 @@ def processCiteEngineFile(file, filename, bool_docbook):
             cm.write(line + '\n')
         cm.close()
 
-    return '"%s" "%s" "%s" "%s" "%s" "%s" "%s" "%s"\n' % (modname, filename, 
cet, db, desc, pkgs, req, excl)
+    return '"%s" "%s" "%s" "%s" "%s" "%s" "%s" "%s" "%s"\n' % (modname, 
filename, cet, cfm, db, desc, pkgs, req, excl)
 
 
 def checkTeXAllowSpaces():
diff --git a/src/CiteEnginesList.cpp b/src/CiteEnginesList.cpp
index 279063c..118c1b7 100644
--- a/src/CiteEnginesList.cpp
+++ b/src/CiteEnginesList.cpp
@@ -38,11 +38,12 @@ CiteEnginesList theCiteEnginesList;
 
 
 LyXCiteEngine::LyXCiteEngine(string const & n, string const & i,
-                            vector<string> const & cet, vector<string> const & 
dbs,
+                            vector<string> const & cet, string const & cfm,
+                            vector<string> const & dbs,
                             string const & d, vector<string> const & p,
                             vector<string> const & r, vector<string> const & 
e):
-       name_(n), id_(i), engine_types_(cet), default_biblios_(dbs), 
description_(d),
-       package_list_(p), required_engines_(r), excluded_engines_(e),
+       name_(n), id_(i), engine_types_(cet), cite_framework_(cfm), 
default_biblios_(dbs),
+       description_(d), package_list_(p), required_engines_(r), 
excluded_engines_(e),
        checked_(false), available_(false)
 {
        filename_ = id_ + ".citeengine";
@@ -245,6 +246,10 @@ bool CiteEnginesList::read()
                        }
                        if (!lex.next(true))
                                break;
+                       string const citeframework = lex.getString();
+                       LYXERR(Debug::TCLASS, "CiteFramework: " << 
citeframework);
+                       if (!lex.next(true))
+                               break;
                        string db = lex.getString();
                        LYXERR(Debug::TCLASS, "Default Biblio: " << db);
                        vector<string> dbs;
@@ -290,7 +295,7 @@ bool CiteEnginesList::read()
                        }
                        // This code is run when we have
                        // cename, fname, desc, pkgs, req and exc
-                       addCiteEngine(cename, fname, cets, dbs, desc, pkgs, 
req, exc);
+                       addCiteEngine(cename, fname, cets, citeframework, dbs, 
desc, pkgs, req, exc);
                } // end switch
        } //end while
 
@@ -304,11 +309,11 @@ bool CiteEnginesList::read()
 
 void CiteEnginesList::addCiteEngine(string const & cename,
        string const & filename, vector<string> const & cets,
-       vector<string> const & dbs, string const & description,
-       vector<string> const & pkgs, vector<string> const & req,
-       vector<string> const & exc)
+       string const & citeframework, vector<string> const & dbs,
+       string const & description, vector<string> const & pkgs,
+       vector<string> const & req, vector<string> const & exc)
 {
-       LyXCiteEngine ce(cename, filename, cets, dbs, description, pkgs, req, 
exc);
+       LyXCiteEngine ce(cename, filename, cets, citeframework, dbs, 
description, pkgs, req, exc);
        englist_.push_back(ce);
 }
 
diff --git a/src/CiteEnginesList.h b/src/CiteEnginesList.h
index f1fc04b..4226486 100644
--- a/src/CiteEnginesList.h
+++ b/src/CiteEnginesList.h
@@ -51,6 +51,7 @@ public:
        ///
        LyXCiteEngine(std::string const & name, std::string const & id,
                      std::vector<std::string> const & enginetypes,
+                     std::string const & cfm,
                      std::vector<std::string> const & defaultbiblios,
                      std::string const & description,
                      std::vector<std::string> const & packagelist,
@@ -67,6 +68,8 @@ public:
        ///
        std::string const & getFilename() const { return filename_; }
        ///
+       std::string const & getCiteFramework() const { return cite_framework_; }
+       ///
        std::vector<std::string> const & getEngineType() const { return 
engine_types_; }
        ///
        bool hasEngineType(CiteEngineType const &) const;
@@ -102,6 +105,8 @@ private:
        std::string filename_;
        /// the engine type(s)
        std::vector<std::string> engine_types_;
+       /// cite framework (bibtex, biblatex)
+       std::string cite_framework_;
        /// default bibliography styles
        std::vector<std::string> default_biblios_;
        /// a short description for use in the ui
@@ -160,9 +165,10 @@ public:
        void operator=(CiteEnginesList const &);
        /// add an engine to the list
        void addCiteEngine(std::string const &, std::string const &,
+               std::vector<std::string> const &, std::string const &,
+               std::vector<std::string> const &, std::string const &,
                std::vector<std::string> const &, std::vector<std::string> 
const &,
-               std::string const &, std::vector<std::string> const &,
-               std::vector<std::string> const &, std::vector<std::string> 
const &);
+               std::vector<std::string> const &);
        ///
        std::vector<LyXCiteEngine> englist_;
 };
diff --git a/src/TextClass.cpp b/src/TextClass.cpp
index 73f3cd1..b6a5ad7 100644
--- a/src/TextClass.cpp
+++ b/src/TextClass.cpp
@@ -221,6 +221,7 @@ enum TextClassTags {
        TC_CITEENGINE,
        TC_CITEENGINETYPE,
        TC_CITEFORMAT,
+       TC_CITEFRAMEWORK,
        TC_DEFAULTBIBLIO,
        TC_FULLAUTHORLIST,
        TC_OUTLINERNAME
@@ -236,6 +237,7 @@ LexerKeyword textClassTags[] = {
        { "citeengine",        TC_CITEENGINE },
        { "citeenginetype",    TC_CITEENGINETYPE },
        { "citeformat",        TC_CITEFORMAT },
+       { "citeframework",     TC_CITEFRAMEWORK },
        { "classoptions",      TC_CLASSOPTIONS },
        { "columns",           TC_COLUMNS },
        { "counter",           TC_COUNTER },
@@ -758,6 +760,11 @@ TextClass::ReturnValues TextClass::read(Lexer & lexrc, 
ReadType rt)
                        error = !readCiteFormat(lexrc);
                        break;
 
+               case TC_CITEFRAMEWORK:
+                       lexrc.next();
+                       citeframework_ = rtrim(lexrc.getString());
+                       break;
+
                case TC_DEFAULTBIBLIO:
                        if (lexrc.next()) {
                                vector<string> const dbs =
diff --git a/src/TextClass.h b/src/TextClass.h
index 3f83216..51bb417 100644
--- a/src/TextClass.h
+++ b/src/TextClass.h
@@ -258,6 +258,8 @@ protected:
        mutable std::string prerequisites_;
        /// The possible cite engine types
        std::string opt_enginetype_;
+       /// The cite framework (bibtex, biblatex)
+       std::string citeframework_;
        ///
        std::string opt_fontsize_;
        ///
@@ -421,6 +423,8 @@ public:
        ///
        std::string const & opt_enginetype() const { return opt_enginetype_; }
        ///
+       std::string const & citeFramework() const { return citeframework_; }
+       ///
        std::string const & opt_fontsize() const { return opt_fontsize_; }
        ///
        std::string const & opt_pagestyle() const { return opt_pagestyle_; }

commit c72ecbcd1b3b39c38bd9b88e9008a1182da4d64b
Author: Juergen Spitzmueller <[email protected]>
Date:   Sat Dec 31 17:38:26 2016 +0100

    Improve style.
    
    Thanks, José!

diff --git a/src/CiteEnginesList.cpp b/src/CiteEnginesList.cpp
index ee72875..279063c 100644
--- a/src/CiteEnginesList.cpp
+++ b/src/CiteEnginesList.cpp
@@ -123,10 +123,7 @@ string LyXCiteEngine::getDefaultBiblio(CiteEngineType 
const & cet) const
        string res;
        string const etp = theCiteEnginesList.getTypeAsString(cet) + ":";
        //check whether all of the required packages are available
-       vector<string>::const_iterator it  = default_biblios_.begin();
-       vector<string>::const_iterator end = default_biblios_.end();
-       for (; it != end; ++it) {
-               string const s = *it;
+       for (string const &s: default_biblios_) {
                if (prefixIs(s, etp))
                        res = split(s, ':');
                else if (!contains(s, ':') && res.empty())
@@ -139,13 +136,10 @@ string LyXCiteEngine::getDefaultBiblio(CiteEngineType 
const & cet) const
 bool LyXCiteEngine::isDefaultBiblio(string const & bf) const
 {
        string const bfs = ":" + bf;
-       vector<string>::const_iterator it  = default_biblios_.begin();
-       vector<string>::const_iterator end = default_biblios_.end();
-       for (; it != end; ++it) {
-               string const s = *it;
+       for (string const &s: default_biblios_)
                if (suffixIs(s, bfs) || bf == s)
                        return true;
-       }
+
        return false;
 }
 

commit 4cbd28e3fe656d02934af3fa197f468e02b1ed07
Author: Juergen Spitzmueller <[email protected]>
Date:   Sat Dec 31 16:01:11 2016 +0100

    Fix isDefaultBiblio() test

diff --git a/src/CiteEnginesList.cpp b/src/CiteEnginesList.cpp
index 0e3f455..ee72875 100644
--- a/src/CiteEnginesList.cpp
+++ b/src/CiteEnginesList.cpp
@@ -138,10 +138,15 @@ string LyXCiteEngine::getDefaultBiblio(CiteEngineType 
const & cet) const
 
 bool LyXCiteEngine::isDefaultBiblio(string const & bf) const
 {
-       if (find(default_biblios_.begin(), default_biblios_.end(), bf) != 
default_biblios_.end())
-               return true;
-       string const bfp = ":" + bf;
-       return find(default_biblios_.begin(), default_biblios_.end(), bfp) != 
default_biblios_.end();
+       string const bfs = ":" + bf;
+       vector<string>::const_iterator it  = default_biblios_.begin();
+       vector<string>::const_iterator end = default_biblios_.end();
+       for (; it != end; ++it) {
+               string const s = *it;
+               if (suffixIs(s, bfs) || bf == s)
+                       return true;
+       }
+       return false;
 }
 
 

commit ff93aea509686ed32ef15bd74244de067c4fbd9e
Author: Juergen Spitzmueller <[email protected]>
Date:   Sat Dec 31 14:57:09 2016 +0100

    Rework default bibliography style UI
    
    * Use a combo with all available styles
    * Correctly reset default on engine change
    * Consider that EngineTypes might have different defaults

diff --git a/lib/citeengines/natbib.citeengine 
b/lib/citeengines/natbib.citeengine
index dcd160f..c738e51 100644
--- a/lib/citeengines/natbib.citeengine
+++ b/lib/citeengines/natbib.citeengine
@@ -14,7 +14,7 @@ Format 62
 Requires natbib
 
 CiteEngineType authoryear|numerical
-DefaultBiblio  plainnat
+DefaultBiblio  authoryear:plainnat|numerical:plainnat
 
 CiteEngine authoryear
        Citet*[][]
diff --git a/lib/configure.py b/lib/configure.py
index 680e32a..fb5dcc6 100644
--- a/lib/configure.py
+++ b/lib/configure.py
@@ -1511,7 +1511,7 @@ def checkCiteEnginesConfig():
 ## It has been automatically generated by configure
 ## Use "Options/Reconfigure" if you need to update it after a
 ## configuration change.
-## "CiteEngineName" "filename" "CiteEngineType" "Description" "Packages" 
"Requires" "Excludes"
+## "CiteEngineName" "filename" "CiteEngineType" "DefaultBiblio" "Description" 
"Packages" "Requires" "Excludes"
 ''')
 
   # build the list of available modules
@@ -1550,16 +1550,17 @@ def processCiteEngineFile(file, filename, bool_docbook):
           #Excludes: [list of excluded engines]
         The last two lines are optional.
         We expect output:
-          "CiteEngineName" "filename" "CiteEngineType" "Description" 
"Packages" "Requires" "Excludes"
+          "CiteEngineName" "filename" "CiteEngineType" "DefaultBiblio" 
"Description" "Packages" "Requires" "Excludes"
     '''
     remods = re.compile(r'\DeclareLyXCiteEngine\s*(?:\[([^]]*?)\])?{(.*)}')
-    rereqs = re.compile(r'#+\s*Requires: (.*)')
-    reexcs = re.compile(r'#+\s*Excludes: (.*)')
+    rereqs = re.compile(r'#+\s*Requires:\s*(.*)')
+    reexcs = re.compile(r'#+\s*Excludes:\s*(.*)')
     redbeg = re.compile(r'#+\s*DescriptionBegin\s*$')
     redend = re.compile(r'#+\s*DescriptionEnd\s*$')
-    recet = re.compile(r'\s*CiteEngineType (.*)')
+    recet = re.compile(r'\s*CiteEngineType\s*(.*)')
+    redb = re.compile(r'\s*DefaultBiblio\s*(.*)')
 
-    modname = desc = pkgs = req = excl = cet = ""
+    modname = desc = pkgs = req = excl = cet = db = ""
     readingDescription = False
     descLines = []
 
@@ -1603,6 +1604,10 @@ def processCiteEngineFile(file, filename, bool_docbook):
       if res != None:
         cet = res.group(1)
         continue
+      res = redb.search(line)
+      if res != None:
+        db = res.group(1)
+        continue
 
     if modname == "":
       logger.warning("Cite Engine File file without \DeclareLyXCiteEngine 
line. ")
@@ -1625,7 +1630,7 @@ def processCiteEngineFile(file, filename, bool_docbook):
             cm.write(line + '\n')
         cm.close()
 
-    return '"%s" "%s" "%s" "%s" "%s" "%s" "%s"\n' % (modname, filename, cet, 
desc, pkgs, req, excl)
+    return '"%s" "%s" "%s" "%s" "%s" "%s" "%s" "%s"\n' % (modname, filename, 
cet, db, desc, pkgs, req, excl)
 
 
 def checkTeXAllowSpaces():
diff --git a/src/BufferParams.cpp b/src/BufferParams.cpp
index 1e7f772..9cab407 100644
--- a/src/BufferParams.cpp
+++ b/src/BufferParams.cpp
@@ -3240,7 +3240,8 @@ bool BufferParams::addCiteEngine(vector<string> const & 
engine)
 
 string const & BufferParams::defaultBiblioStyle() const
 {
-       return documentClass().defaultBiblioStyle();
+       map<string, string> bs = documentClass().defaultBiblioStyle();
+       return bs[documentClass().opt_enginetype()];
 }
 
 
diff --git a/src/CiteEnginesList.cpp b/src/CiteEnginesList.cpp
index 209c8bc..0e3f455 100644
--- a/src/CiteEnginesList.cpp
+++ b/src/CiteEnginesList.cpp
@@ -38,11 +38,11 @@ CiteEnginesList theCiteEnginesList;
 
 
 LyXCiteEngine::LyXCiteEngine(string const & n, string const & i,
-                            vector<string> const & cet, string const & d,
-                            vector<string> const & p,
+                            vector<string> const & cet, vector<string> const & 
dbs,
+                            string const & d, vector<string> const & p,
                             vector<string> const & r, vector<string> const & 
e):
-       name_(n), id_(i), engine_types_(cet), description_(d), package_list_(p),
-       required_engines_(r), excluded_engines_(e),
+       name_(n), id_(i), engine_types_(cet), default_biblios_(dbs), 
description_(d),
+       package_list_(p), required_engines_(r), excluded_engines_(e),
        checked_(false), available_(false)
 {
        filename_ = id_ + ".citeengine";
@@ -118,6 +118,33 @@ bool LyXCiteEngine::areCompatible(string const & eng1, 
string const & eng2)
 }
 
 
+string LyXCiteEngine::getDefaultBiblio(CiteEngineType const & cet) const
+{
+       string res;
+       string const etp = theCiteEnginesList.getTypeAsString(cet) + ":";
+       //check whether all of the required packages are available
+       vector<string>::const_iterator it  = default_biblios_.begin();
+       vector<string>::const_iterator end = default_biblios_.end();
+       for (; it != end; ++it) {
+               string const s = *it;
+               if (prefixIs(s, etp))
+                       res = split(s, ':');
+               else if (!contains(s, ':') && res.empty())
+                       res = s;
+       }
+       return res;
+}
+
+
+bool LyXCiteEngine::isDefaultBiblio(string const & bf) const
+{
+       if (find(default_biblios_.begin(), default_biblios_.end(), bf) != 
default_biblios_.end())
+               return true;
+       string const bfp = ":" + bf;
+       return find(default_biblios_.begin(), default_biblios_.end(), bfp) != 
default_biblios_.end();
+}
+
+
 // used when sorting the cite engine list.
 class EngineSorter {
 public:
@@ -219,6 +246,16 @@ bool CiteEnginesList::read()
                        }
                        if (!lex.next(true))
                                break;
+                       string db = lex.getString();
+                       LYXERR(Debug::TCLASS, "Default Biblio: " << db);
+                       vector<string> dbs;
+                       while (!db.empty()) {
+                               string p;
+                               db = split(db, p, '|');
+                               dbs.push_back(p);
+                       }
+                       if (!lex.next(true))
+                               break;
                        string const desc = lex.getString();
                        LYXERR(Debug::TCLASS, "Description: " << desc);
                        //FIXME Add packages
@@ -254,7 +291,7 @@ bool CiteEnginesList::read()
                        }
                        // This code is run when we have
                        // cename, fname, desc, pkgs, req and exc
-                       addCiteEngine(cename, fname, cets, desc, pkgs, req, 
exc);
+                       addCiteEngine(cename, fname, cets, dbs, desc, pkgs, 
req, exc);
                } // end switch
        } //end while
 
@@ -267,11 +304,12 @@ bool CiteEnginesList::read()
 
 
 void CiteEnginesList::addCiteEngine(string const & cename,
-       string const & filename, vector<string> const & cets, string const & 
description,
+       string const & filename, vector<string> const & cets,
+       vector<string> const & dbs, string const & description,
        vector<string> const & pkgs, vector<string> const & req,
        vector<string> const & exc)
 {
-       LyXCiteEngine ce(cename, filename, cets, description, pkgs, req, exc);
+       LyXCiteEngine ce(cename, filename, cets, dbs, description, pkgs, req, 
exc);
        englist_.push_back(ce);
 }
 
diff --git a/src/CiteEnginesList.h b/src/CiteEnginesList.h
index 17cfbb8..f1fc04b 100644
--- a/src/CiteEnginesList.h
+++ b/src/CiteEnginesList.h
@@ -51,6 +51,7 @@ public:
        ///
        LyXCiteEngine(std::string const & name, std::string const & id,
                      std::vector<std::string> const & enginetypes,
+                     std::vector<std::string> const & defaultbiblios,
                      std::string const & description,
                      std::vector<std::string> const & packagelist,
                      std::vector<std::string> const & requires,
@@ -70,6 +71,10 @@ public:
        ///
        bool hasEngineType(CiteEngineType const &) const;
        ///
+       std::string getDefaultBiblio(CiteEngineType const &) const;
+       ///
+       bool isDefaultBiblio(std::string const &) const;
+       ///
        std::string const & getDescription() const { return description_; }
        ///
        std::vector<std::string> const & getPackageList() const
@@ -97,6 +102,8 @@ private:
        std::string filename_;
        /// the engine type(s)
        std::vector<std::string> engine_types_;
+       /// default bibliography styles
+       std::vector<std::string> default_biblios_;
        /// a short description for use in the ui
        std::string description_;
        /// the LaTeX packages on which this depends, if any
@@ -153,7 +160,8 @@ public:
        void operator=(CiteEnginesList const &);
        /// add an engine to the list
        void addCiteEngine(std::string const &, std::string const &,
-               std::vector<std::string> const &, std::string const &, 
std::vector<std::string> const &,
+               std::vector<std::string> const &, std::vector<std::string> 
const &,
+               std::string const &, std::vector<std::string> const &,
                std::vector<std::string> const &, std::vector<std::string> 
const &);
        ///
        std::vector<LyXCiteEngine> englist_;
diff --git a/src/TextClass.cpp b/src/TextClass.cpp
index d14ef29..73f3cd1 100644
--- a/src/TextClass.cpp
+++ b/src/TextClass.cpp
@@ -759,8 +759,21 @@ TextClass::ReturnValues TextClass::read(Lexer & lexrc, 
ReadType rt)
                        break;
 
                case TC_DEFAULTBIBLIO:
-                       if (lexrc.next())
-                               cite_default_biblio_style_ = 
rtrim(lexrc.getString());
+                       if (lexrc.next()) {
+                               vector<string> const dbs =
+                                       
getVectorFromString(rtrim(lexrc.getString()), "|");
+                               vector<string>::const_iterator it  = 
dbs.begin();
+                               vector<string>::const_iterator end = dbs.end();
+                               for (; it != end; ++it) {
+                                       if (!contains(*it, ':'))
+                                               
cite_default_biblio_style_[opt_enginetype_] = *it;
+                                       else {
+                                               string eng;
+                                               string const db = split(*it, 
eng, ':');
+                                               cite_default_biblio_style_[eng] 
= db;
+                                       }
+                               }
+                       }
                        break;
 
                case TC_FULLAUTHORLIST:
diff --git a/src/TextClass.h b/src/TextClass.h
index d082e10..3f83216 100644
--- a/src/TextClass.h
+++ b/src/TextClass.h
@@ -330,7 +330,7 @@ protected:
        /// Citation macros
        std::map<CiteEngineType, std::map<std::string, std::string> > 
cite_macros_;
        /// The default BibTeX bibliography style file
-       std::string cite_default_biblio_style_;
+       std::map<std::string, std::string> cite_default_biblio_style_;
        /// Whether full author lists are supported
        bool cite_full_author_list_;
        /// The possible citation styles
@@ -487,7 +487,8 @@ public:
        ///
        std::vector<CitationStyle> const & citeStyles(CiteEngineType const &) 
const;
        ///
-       std::string const & defaultBiblioStyle() const { return 
cite_default_biblio_style_; }
+       std::map<std::string, std::string> const & defaultBiblioStyle() const
+       { return cite_default_biblio_style_; }
        ///
        bool const & fullAuthorList() const { return cite_full_author_list_; }
 protected:
diff --git a/src/frontends/qt4/GuiDocument.cpp 
b/src/frontends/qt4/GuiDocument.cpp
index d971eeb..34b2fc0 100644
--- a/src/frontends/qt4/GuiDocument.cpp
+++ b/src/frontends/qt4/GuiDocument.cpp
@@ -1130,15 +1130,23 @@ GuiDocument::GuiDocument(GuiView & lv)
        connect(biblioModule->citeEngineCO, SIGNAL(activated(int)),
                this, SLOT(citeEngineChanged(int)));
        connect(biblioModule->citeStyleCO, SIGNAL(activated(int)),
-               this, SLOT(biblioChanged()));
+               this, SLOT(citeStyleChanged()));
        connect(biblioModule->bibtopicCB, SIGNAL(clicked()),
                this, SLOT(biblioChanged()));
        connect(biblioModule->bibtexCO, SIGNAL(activated(int)),
                this, SLOT(bibtexChanged(int)));
        connect(biblioModule->bibtexOptionsLE, SIGNAL(textChanged(QString)),
                this, SLOT(biblioChanged()));
-       connect(biblioModule->bibtexStyleLE, SIGNAL(textChanged(QString)),
+       connect(biblioModule->defaultBiblioCO, SIGNAL(activated(int)),
+               this, SLOT(biblioChanged()));
+       connect(biblioModule->defaultBiblioCO, SIGNAL(editTextChanged(QString)),
                this, SLOT(biblioChanged()));
+       connect(biblioModule->defaultBiblioCO, SIGNAL(editTextChanged(QString)),
+               this, SLOT(updateResetDefaultBiblio()));
+       connect(biblioModule->rescanBibliosPB, SIGNAL(clicked()),
+               this, SLOT(rescanBibFiles()));
+       connect(biblioModule->resetDefaultBiblioPB, SIGNAL(clicked()),
+               this, SLOT(resetDefaultBibfile()));
 
        biblioModule->citeEngineCO->clear();
        for (LyXCiteEngine const & cet : theCiteEnginesList) {
@@ -1150,8 +1158,8 @@ GuiDocument::GuiDocument(GuiView & lv)
 
        biblioModule->bibtexOptionsLE->setValidator(new NoNewLineValidator(
                biblioModule->bibtexOptionsLE));
-       biblioModule->bibtexStyleLE->setValidator(new NoNewLineValidator(
-               biblioModule->bibtexStyleLE));
+       biblioModule->defaultBiblioCO->lineEdit()->setValidator(new 
NoNewLineValidator(
+               biblioModule->defaultBiblioCO->lineEdit()));
 
        // NOTE: we do not provide "custom" here for security reasons!
        biblioModule->bibtexCO->clear();
@@ -2271,41 +2279,58 @@ void GuiDocument::biblioChanged()
 }
 
 
+void GuiDocument::rescanBibFiles()
+{
+       rescanTexStyles("bst");
+}
+
+
+void GuiDocument::resetDefaultBibfile()
+{
+       QString const engine =
+               biblioModule->citeEngineCO->itemData(
+                               
biblioModule->citeEngineCO->currentIndex()).toString();
+
+       CiteEngineType const cet =
+               CiteEngineType(biblioModule->citeStyleCO->itemData(
+                                                         
biblioModule->citeStyleCO->currentIndex()).toInt());
+
+       
updateDefaultBiblio(theCiteEnginesList[fromqstr(engine)]->getDefaultBiblio(cet));
+}
+
+
 void GuiDocument::citeEngineChanged(int n)
 {
-       QString const engine = 
biblioModule->citeEngineCO->itemData(n).toString();
+       QString const engine =
+               biblioModule->citeEngineCO->itemData(n).toString();
 
        vector<string> const engs =
                theCiteEnginesList[fromqstr(engine)]->getEngineType();
 
        updateCiteStyles(engs);
+       resetDefaultBibfile();
 
        biblioChanged();
 }
 
 
-void GuiDocument::bibtexChanged(int n)
+void GuiDocument::citeStyleChanged()
 {
-       biblioModule->bibtexOptionsLE->setEnabled(
-               biblioModule->bibtexCO->itemData(n).toString() != "default");
-       biblioChanged();
-}
-
+       QString const engine =
+               biblioModule->citeEngineCO->itemData(
+                               
biblioModule->citeEngineCO->currentIndex()).toString();
+       if (theCiteEnginesList[fromqstr(engine)]->isDefaultBiblio(
+                               
fromqstr(biblioModule->defaultBiblioCO->currentText())))
+               resetDefaultBibfile();
 
-void GuiDocument::setAuthorYear(bool authoryear)
-{
-       if (authoryear)
-               biblioModule->citeStyleCO->setCurrentIndex(
-                       
biblioModule->citeStyleCO->findData(ENGINE_TYPE_AUTHORYEAR));
        biblioChanged();
 }
 
 
-void GuiDocument::setNumerical(bool numerical)
+void GuiDocument::bibtexChanged(int n)
 {
-       if (numerical)
-               biblioModule->citeStyleCO->setCurrentIndex(
-                       
biblioModule->citeStyleCO->findData(ENGINE_TYPE_NUMERICAL));
+       biblioModule->bibtexOptionsLE->setEnabled(
+               biblioModule->bibtexCO->itemData(n).toString() != "default");
        biblioChanged();
 }
 
@@ -2617,7 +2642,7 @@ void GuiDocument::applyView()
        bp_.use_bibtopic =
                biblioModule->bibtopicCB->isChecked();
 
-       bp_.biblio_style = fromqstr(biblioModule->bibtexStyleLE->text());
+       bp_.biblio_style = 
fromqstr(biblioModule->defaultBiblioCO->currentText());
 
        string const bibtex_command =
                fromqstr(biblioModule->bibtexCO->itemData(
@@ -3040,7 +3065,7 @@ void GuiDocument::paramsToDialog()
        biblioModule->bibtopicCB->setChecked(
                bp_.use_bibtopic);
 
-       biblioModule->bibtexStyleLE->setText(toqstr(bp_.biblio_style));
+       updateDefaultBiblio(bp_.defaultBiblioStyle());
 
        string command;
        string options =
@@ -3626,6 +3651,59 @@ void GuiDocument::updateIncludeonlys()
 }
 
 
+void GuiDocument::updateDefaultBiblio(string const & style)
+{
+       QString const bibstyle = toqstr(style);
+       biblioModule->defaultBiblioCO->clear();
+
+       int item_nr = -1;
+
+       QStringList str = texFileList("bstFiles.lst");
+       // test whether we have a valid list, otherwise run rescan
+       if (str.isEmpty()) {
+               rescanTexStyles("bst");
+               str = texFileList("bstFiles.lst");
+       }
+       for (int i = 0; i != str.size(); ++i)
+               str[i] = onlyFileName(str[i]);
+       // sort on filename only (no path)
+       str.sort();
+
+       for (int i = 0; i != str.count(); ++i) {
+               QString item = changeExtension(str[i], "");
+               if (item == bibstyle)
+                       item_nr = i;
+               biblioModule->defaultBiblioCO->addItem(item);
+       }
+
+       if (item_nr == -1 && !bibstyle.isEmpty()) {
+               biblioModule->defaultBiblioCO->addItem(bibstyle);
+               item_nr = biblioModule->defaultBiblioCO->count() - 1;
+       }
+
+       if (item_nr != -1)
+               biblioModule->defaultBiblioCO->setCurrentIndex(item_nr);
+       else
+               biblioModule->defaultBiblioCO->clearEditText();
+
+       updateResetDefaultBiblio();
+}
+
+
+void GuiDocument::updateResetDefaultBiblio()
+{
+       QString const engine =
+               biblioModule->citeEngineCO->itemData(
+                               
biblioModule->citeEngineCO->currentIndex()).toString();
+       CiteEngineType const cet =
+               CiteEngineType(biblioModule->citeStyleCO->itemData(
+                                                         
biblioModule->citeStyleCO->currentIndex()).toInt());
+       biblioModule->resetDefaultBiblioPB->setEnabled(
+               theCiteEnginesList[fromqstr(engine)]->getDefaultBiblio(cet)
+                       != 
fromqstr(biblioModule->defaultBiblioCO->currentText()));
+}
+
+
 void GuiDocument::updateContents()
 {
        // Nothing to do here as the document settings is not cursor dependant.
diff --git a/src/frontends/qt4/GuiDocument.h b/src/frontends/qt4/GuiDocument.h
index e5aa4fa..012a7a1 100644
--- a/src/frontends/qt4/GuiDocument.h
+++ b/src/frontends/qt4/GuiDocument.h
@@ -115,10 +115,12 @@ private Q_SLOTS:
        void classChanged_adaptor();
        void languagePackageChanged(int);
        void biblioChanged();
+       void rescanBibFiles();
+       void resetDefaultBibfile();
        void citeEngineChanged(int);
+       void citeStyleChanged();
        void bibtexChanged(int);
-       void setAuthorYear(bool);
-       void setNumerical(bool);
+       void updateResetDefaultBiblio();
        void updateModuleInfo();
        void modulesChanged();
        void changeBackgroundColor();
@@ -181,6 +183,8 @@ private:
        void updateSelectedModules();
        ///
        void updateIncludeonlys();
+       ///
+       void updateDefaultBiblio(std::string const & style);
        /// save as default template
        void saveDocDefault();
        /// reset to default params
diff --git a/src/frontends/qt4/ui/BiblioUi.ui b/src/frontends/qt4/ui/BiblioUi.ui
index 7cc821b..b6ce417 100644
--- a/src/frontends/qt4/ui/BiblioUi.ui
+++ b/src/frontends/qt4/ui/BiblioUi.ui
@@ -6,7 +6,7 @@
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>418</width>
+    <width>475</width>
     <height>394</height>
    </rect>
   </property>
@@ -46,7 +46,7 @@
            <string/>
           </property>
           <property name="text">
-           <string>Sty&amp;le Engine:</string>
+           <string>Sty&amp;le engine:</string>
           </property>
           <property name="buddy">
            <cstring>citeEngineCO</cstring>
@@ -116,36 +116,72 @@
       <bool>true</bool>
      </property>
      <layout class="QGridLayout" name="gridLayout_1">
+      <item row="1" column="0">
+       <widget class="QCheckBox" name="bibtopicCB">
+        <property name="toolTip">
+         <string>Select this if you want to split your bibliography into 
sections</string>
+        </property>
+        <property name="text">
+         <string>S&amp;ectioned bibliography</string>
+        </property>
+       </widget>
+      </item>
       <item row="0" column="0">
        <layout class="QHBoxLayout" name="horizontalLayout_1">
         <item>
          <widget class="QLabel" name="bibtexStyleLA">
           <property name="text">
-           <string>Default st&amp;yle:</string>
+           <string>Default BibTeX st&amp;yle:</string>
           </property>
           <property name="buddy">
-           <cstring>bibtexStyleLE</cstring>
+           <cstring>defaultBiblioCO</cstring>
           </property>
          </widget>
         </item>
         <item>
-         <widget class="QLineEdit" name="bibtexStyleLE">
+         <widget class="QComboBox" name="defaultBiblioCO">
           <property name="toolTip">
-           <string>Define the default BibTeX style</string>
+           <string>Here, you can define a BibTeX style that is suggested in 
the BibTeX dialog by default</string>
+          </property>
+          <property name="editable">
+           <bool>true</bool>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QPushButton" name="rescanBibliosPB">
+          <property name="toolTip">
+           <string>Rescan style files</string>
+          </property>
+          <property name="text">
+           <string>Re&amp;scan</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QPushButton" name="resetDefaultBiblioPB">
+          <property name="toolTip">
+           <string>Reset to the preset default</string>
+          </property>
+          <property name="text">
+           <string>&amp;Reset</string>
           </property>
          </widget>
         </item>
        </layout>
       </item>
-      <item row="1" column="0">
-       <widget class="QCheckBox" name="bibtopicCB">
-        <property name="toolTip">
-         <string>Select this if you want to split your bibliography into 
sections</string>
+      <item row="0" column="1">
+       <spacer name="horizontalSpacer_2">
+        <property name="orientation">
+         <enum>Qt::Horizontal</enum>
         </property>
-        <property name="text">
-         <string>S&amp;ectioned bibliography</string>
+        <property name="sizeHint" stdset="0">
+         <size>
+          <width>40</width>
+          <height>20</height>
+         </size>
         </property>
-       </widget>
+       </spacer>
       </item>
      </layout>
     </widget>
diff --git a/src/insets/InsetBibtex.cpp b/src/insets/InsetBibtex.cpp
index 13c91b0..1c4090a 100644
--- a/src/insets/InsetBibtex.cpp
+++ b/src/insets/InsetBibtex.cpp
@@ -328,7 +328,7 @@ void InsetBibtex::latex(otexstream & os, OutputParams const 
& runparams) const
        }
 
        if (style == "default")
-               style = buffer().params().biblio_style;
+               style = buffer().params().defaultBiblioStyle();
 
        if (!style.empty() && !buffer().params().use_bibtopic) {
                string base = normalizeName(buffer(), runparams, style, ".bst");

commit 59a4f263a44ca3a1f5a37a652c8df154788f72d1
Author: Juergen Spitzmueller <[email protected]>
Date:   Sat Dec 31 09:28:51 2016 +0100

    Properly support the cite engines in the GUI
    
    Instead of hardcoding 3 engines, we now support all engines which are
    defined in the *.citeengines files.

diff --git a/lib/citeengines/basic.citeengine b/lib/citeengines/basic.citeengine
index dc4941b..7de5e35 100644
--- a/lib/citeengines/basic.citeengine
+++ b/lib/citeengines/basic.citeengine
@@ -1,6 +1,7 @@
-# \DeclareLyXCiteEngine{BibTeX (basic)}
+# \DeclareLyXCiteEngine{Basic (BibTeX)}
 # DescriptionBegin
-#   Use the basic citation capabilities provided by plain LaTeX.
+#   The basic citation capabilities provided by BibTeX.
+#   Mainly simple numeric styles primarily suitable for science and maths.
 # DescriptionEnd
 # Excludes: jurabib | natbib
 
diff --git a/lib/citeengines/jurabib.citeengine 
b/lib/citeengines/jurabib.citeengine
index 13bbc6f..de292bb 100644
--- a/lib/citeengines/jurabib.citeengine
+++ b/lib/citeengines/jurabib.citeengine
@@ -1,8 +1,8 @@
-# \DeclareLyXCiteEngine[jurabib.sty]{Jurabib}
+# \DeclareLyXCiteEngine[jurabib.sty]{Jurabib (BibTeX)}
 # DescriptionBegin
-#   Loads the LaTeX package jurabib, a citation engine. Jurabib supports 
annotations,
-#   author-year style citations and hyphenation patterns for bibliography 
entries in
-#   English, German, French, Dutch, Spanish and Italian.
+#   Jurabib supports a range of author-year styles primarily suitable for law 
studies
+#   and the Humanities. It includes localizations for English, German, French, 
Dutch,
+#   Spanish and Italian.
 # DescriptionEnd
 # Excludes: basic | natbib
 
diff --git a/lib/citeengines/natbib.citeengine 
b/lib/citeengines/natbib.citeengine
index 63bf1cb..dcd160f 100644
--- a/lib/citeengines/natbib.citeengine
+++ b/lib/citeengines/natbib.citeengine
@@ -1,9 +1,9 @@
-# \DeclareLyXCiteEngine[natbib.sty]{Natbib}
+# \DeclareLyXCiteEngine[natbib.sty]{Natbib (BibTeX)}
 # DescriptionBegin
-#   Loads the LaTeX package natbib, a citation engine. Natbib supports
-#   both author-year and numerical styles for citations, automatic sorting
-#   and merging of numerical citations, annotations, capitalization of the
-#   `van' part of author names, shortened and full author lists, and more.
+#   Natbib supports a range of both author-year and numerical styles mainly
+#   aimed at the Humanities. It features automatic sorting and merging of 
+#   numerical citations, annotations, capitalization of the `van' part of 
+#   author names, shortened and full author lists, and more.
 # DescriptionEnd
 # Excludes: basic | jurabib
 
diff --git a/src/BufferParams.cpp b/src/BufferParams.cpp
index 326d487..1e7f772 100644
--- a/src/BufferParams.cpp
+++ b/src/BufferParams.cpp
@@ -23,6 +23,7 @@
 #include "Buffer.h"
 #include "buffer_funcs.h"
 #include "Bullet.h"
+#include "CiteEnginesList.h"
 #include "Color.h"
 #include "ColorSet.h"
 #include "Converter.h"
@@ -272,27 +273,6 @@ PackageTranslator const & packagetranslator()
 }
 
 
-// Cite engine
-typedef Translator<string, CiteEngineType> CiteEngineTypeTranslator;
-
-
-CiteEngineTypeTranslator const init_citeenginetypetranslator()
-{
-       CiteEngineTypeTranslator translator("authoryear", 
ENGINE_TYPE_AUTHORYEAR);
-       translator.addPair("numerical", ENGINE_TYPE_NUMERICAL);
-       translator.addPair("default", ENGINE_TYPE_DEFAULT);
-       return translator;
-}
-
-
-CiteEngineTypeTranslator const & citeenginetypetranslator()
-{
-       static CiteEngineTypeTranslator const translator =
-               init_citeenginetypetranslator();
-       return translator;
-}
-
-
 // Spacing
 typedef Translator<string, Spacing::Space> SpaceTranslator;
 
@@ -863,7 +843,7 @@ string BufferParams::readToken(Lexer & lex, string const & 
token,
        } else if (token == "\\cite_engine_type") {
                string engine_type;
                lex >> engine_type;
-               cite_engine_type_ = 
citeenginetypetranslator().find(engine_type);
+               cite_engine_type_ = theCiteEnginesList.getType(engine_type);
        } else if (token == "\\biblio_style") {
                lex.eatLine();
                biblio_style = lex.getString();
@@ -1234,7 +1214,7 @@ void BufferParams::writeFile(ostream & os, Buffer const * 
buf) const
                os << "basic";
        }
 
-       os << "\n\\cite_engine_type " << 
citeenginetypetranslator().find(cite_engine_type_)
+       os << "\n\\cite_engine_type " << 
theCiteEnginesList.getTypeAsString(cite_engine_type_)
           << "\n\\biblio_style " << biblio_style
           << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
           << "\n\\use_indices " << convert<string>(use_indices)
diff --git a/src/CiteEnginesList.cpp b/src/CiteEnginesList.cpp
index 48222cb..209c8bc 100644
--- a/src/CiteEnginesList.cpp
+++ b/src/CiteEnginesList.cpp
@@ -14,6 +14,7 @@
 
 #include "CiteEnginesList.h"
 
+#include "Citation.h"
 #include "LaTeXFeatures.h"
 #include "Lexer.h"
 
@@ -22,6 +23,7 @@
 #include "support/gettext.h"
 #include "support/filetools.h"
 #include "support/lstrings.h"
+#include "support/Translator.h"
 
 #include <algorithm>
 
@@ -76,6 +78,13 @@ bool LyXCiteEngine::isAvailable() const
 }
 
 
+bool LyXCiteEngine::hasEngineType(CiteEngineType const & et) const
+{
+       return std::find(engine_types_.begin(), engine_types_.end(),
+                        theCiteEnginesList.getTypeAsString(et)) != 
engine_types_.end();
+}
+
+
 bool LyXCiteEngine::isCompatible(string const & cename) const
 {
        // do we exclude it?
@@ -119,6 +128,43 @@ public:
 };
 
 
+// Local translators
+namespace {
+
+typedef Translator<string, CiteEngineType> CiteEngineTypeTranslator;
+
+
+CiteEngineTypeTranslator const init_citeenginetypetranslator()
+{
+       CiteEngineTypeTranslator translator("authoryear", 
ENGINE_TYPE_AUTHORYEAR);
+       translator.addPair("numerical", ENGINE_TYPE_NUMERICAL);
+       translator.addPair("default", ENGINE_TYPE_DEFAULT);
+       return translator;
+}
+
+
+CiteEngineTypeTranslator const & citeenginetypetranslator()
+{
+       static CiteEngineTypeTranslator const translator =
+               init_citeenginetypetranslator();
+       return translator;
+}
+
+} // namespace anon
+
+
+string CiteEnginesList::getTypeAsString(CiteEngineType const & et) const
+{
+       return citeenginetypetranslator().find(et);
+}
+
+
+CiteEngineType CiteEnginesList::getType(string const & et) const
+{
+       return citeenginetypetranslator().find(et);
+}
+
+
 // Much of this is borrowed from LayoutFileList::read()
 bool CiteEnginesList::read()
 {
diff --git a/src/CiteEnginesList.h b/src/CiteEnginesList.h
index 0e6d119..17cfbb8 100644
--- a/src/CiteEnginesList.h
+++ b/src/CiteEnginesList.h
@@ -13,6 +13,8 @@
 #ifndef CITEENGINESLIST_H
 #define CITEENGINESLIST_H
 
+#include "Citation.h"
+
 #include <string>
 #include <vector>
 
@@ -29,13 +31,13 @@ namespace lyx {
  *  which must begin roughly so:
  *  # \DeclareLyXCiteEngine[natbib.sty]{Natbib}
  *  # DescriptionBegin
- *  #   Loads the LaTeX package natbib, a citation engine. Natbib supports
- *  #   both author-year and numerical styles for citations, automatic sorting
- *  #   and merging of numerical citations, annotations, capitalization of the
- *  #   `van' part of author names, shortened and full author lists, and more.
+ *  #   Natbib supports a range of both author-year and numerical styles mainly
+ *  #   aimed at the Humanities. It features automatic sorting and merging of
+ *  #   numerical citations, annotations, capitalization of the `van' part of
+ *  #   author names, shortened and full author lists, and more.
  *  # DescriptionEnd
  *  # Excludes: basic | jurabib
- *  The description might be used in the gui to give information to the user. 
The
+ *  The description will be used in the gui to give information to the user. 
The
  *  Requires and Excludes lines are read by the configuration script
  *  and written to a file citeengines.lst in the user configuration directory.
  *  That file is then read on startup to populate the CiteEnginesList, below.
@@ -66,6 +68,8 @@ public:
        ///
        std::vector<std::string> const & getEngineType() const { return 
engine_types_; }
        ///
+       bool hasEngineType(CiteEngineType const &) const;
+       ///
        std::string const & getDescription() const { return description_; }
        ///
        std::vector<std::string> const & getPackageList() const
@@ -121,6 +125,10 @@ class CiteEnginesList {
 public:
        ///
        CiteEnginesList() {}
+       ///
+       std::string getTypeAsString(CiteEngineType const &) const;
+       ///
+       CiteEngineType getType(std::string const &) const;
        /// reads the engines from a file generated by configure.py
        bool read();
        ///
diff --git a/src/frontends/qt4/GuiDocument.cpp 
b/src/frontends/qt4/GuiDocument.cpp
index 6ef39dc..d971eeb 100644
--- a/src/frontends/qt4/GuiDocument.cpp
+++ b/src/frontends/qt4/GuiDocument.cpp
@@ -29,6 +29,7 @@
 #include "Buffer.h"
 #include "BufferParams.h"
 #include "BufferView.h"
+#include "CiteEnginesList.h"
 #include "Color.h"
 #include "ColorCache.h"
 #include "Converter.h"
@@ -1126,22 +1127,10 @@ GuiDocument::GuiDocument(GuiView & lv)
 
        // biblio
        biblioModule = new UiWidget<Ui::BiblioUi>;
-       connect(biblioModule->citeDefaultRB, SIGNAL(toggled(bool)),
-               this, SLOT(setNumerical(bool)));
-       connect(biblioModule->citeJurabibRB, SIGNAL(toggled(bool)),
-               this, SLOT(setAuthorYear(bool)));
-       connect(biblioModule->citeNatbibRB, SIGNAL(toggled(bool)),
-               biblioModule->citationStyleL, SLOT(setEnabled(bool)));
-       connect(biblioModule->citeNatbibRB, SIGNAL(toggled(bool)),
-               biblioModule->citeStyleCO, SLOT(setEnabled(bool)));
-       connect(biblioModule->citeDefaultRB, SIGNAL(clicked()),
-               this, SLOT(biblioChanged()));
-       connect(biblioModule->citeNatbibRB, SIGNAL(clicked()),
-               this, SLOT(biblioChanged()));
+       connect(biblioModule->citeEngineCO, SIGNAL(activated(int)),
+               this, SLOT(citeEngineChanged(int)));
        connect(biblioModule->citeStyleCO, SIGNAL(activated(int)),
                this, SLOT(biblioChanged()));
-       connect(biblioModule->citeJurabibRB, SIGNAL(clicked()),
-               this, SLOT(biblioChanged()));
        connect(biblioModule->bibtopicCB, SIGNAL(clicked()),
                this, SLOT(biblioChanged()));
        connect(biblioModule->bibtexCO, SIGNAL(activated(int)),
@@ -1151,15 +1140,19 @@ GuiDocument::GuiDocument(GuiView & lv)
        connect(biblioModule->bibtexStyleLE, SIGNAL(textChanged(QString)),
                this, SLOT(biblioChanged()));
 
+       biblioModule->citeEngineCO->clear();
+       for (LyXCiteEngine const & cet : theCiteEnginesList) {
+               biblioModule->citeEngineCO->addItem(qt_(cet.getName()), 
toqstr(cet.getID()));
+               int const i = 
biblioModule->citeEngineCO->findData(toqstr(cet.getID()));
+               biblioModule->citeEngineCO->setItemData(i, 
qt_(cet.getDescription()),
+                                                       Qt::ToolTipRole);
+       }
+
        biblioModule->bibtexOptionsLE->setValidator(new NoNewLineValidator(
                biblioModule->bibtexOptionsLE));
        biblioModule->bibtexStyleLE->setValidator(new NoNewLineValidator(
                biblioModule->bibtexStyleLE));
 
-       biblioModule->citeStyleCO->addItem(qt_("Author-year"));
-       biblioModule->citeStyleCO->addItem(qt_("Numerical"));
-       biblioModule->citeStyleCO->setCurrentIndex(0);
-
        // NOTE: we do not provide "custom" here for security reasons!
        biblioModule->bibtexCO->clear();
        biblioModule->bibtexCO->addItem(qt_("Default"), QString("default"));
@@ -2278,6 +2271,19 @@ void GuiDocument::biblioChanged()
 }
 
 
+void GuiDocument::citeEngineChanged(int n)
+{
+       QString const engine = 
biblioModule->citeEngineCO->itemData(n).toString();
+
+       vector<string> const engs =
+               theCiteEnginesList[fromqstr(engine)]->getEngineType();
+
+       updateCiteStyles(engs);
+
+       biblioChanged();
+}
+
+
 void GuiDocument::bibtexChanged(int n)
 {
        biblioModule->bibtexOptionsLE->setEnabled(
@@ -2289,7 +2295,8 @@ void GuiDocument::bibtexChanged(int n)
 void GuiDocument::setAuthorYear(bool authoryear)
 {
        if (authoryear)
-               biblioModule->citeStyleCO->setCurrentIndex(0);
+               biblioModule->citeStyleCO->setCurrentIndex(
+                       
biblioModule->citeStyleCO->findData(ENGINE_TYPE_AUTHORYEAR));
        biblioChanged();
 }
 
@@ -2297,11 +2304,39 @@ void GuiDocument::setAuthorYear(bool authoryear)
 void GuiDocument::setNumerical(bool numerical)
 {
        if (numerical)
-               biblioModule->citeStyleCO->setCurrentIndex(1);
+               biblioModule->citeStyleCO->setCurrentIndex(
+                       
biblioModule->citeStyleCO->findData(ENGINE_TYPE_NUMERICAL));
        biblioChanged();
 }
 
 
+void GuiDocument::updateCiteStyles(vector<string> const & engs, CiteEngineType 
const & sel)
+{
+       biblioModule->citeStyleCO->clear();
+
+       vector<string>::const_iterator it  = engs.begin();
+       vector<string>::const_iterator end = engs.end();
+       for (; it != end; ++it) {
+               if (*it == "default")
+                       biblioModule->citeStyleCO->addItem(qt_("Basic 
numerical"),
+                                                          ENGINE_TYPE_DEFAULT);
+               else if (*it == "authoryear")
+                       biblioModule->citeStyleCO->addItem(qt_("Author-year"),
+                                                          
ENGINE_TYPE_AUTHORYEAR);
+               else if (*it == "numerical")
+                       biblioModule->citeStyleCO->addItem(qt_("Author-number"),
+                                                          
ENGINE_TYPE_NUMERICAL);
+       }
+       int i = biblioModule->citeStyleCO->findData(sel);
+       if (biblioModule->citeStyleCO->findData(sel) == -1)
+               i = 0;
+       biblioModule->citeStyleCO->setCurrentIndex(i);
+
+       biblioModule->citationStyleL->setEnabled(engs.size() > 1);
+       biblioModule->citeStyleCO->setEnabled(engs.size() > 1);
+}
+
+
 void GuiDocument::updateEngineType(string const & items, CiteEngineType const 
& sel)
 {
        engine_types_.clear();
@@ -2314,28 +2349,7 @@ void GuiDocument::updateEngineType(string const & items, 
CiteEngineType const &
                engine_types_.push_back(style);
        }
 
-       switch (sel) {
-               case ENGINE_TYPE_AUTHORYEAR:
-                       biblioModule->citeStyleCO->setCurrentIndex(0);
-                       break;
-               case ENGINE_TYPE_NUMERICAL:
-               case ENGINE_TYPE_DEFAULT:
-                       biblioModule->citeStyleCO->setCurrentIndex(1);
-                       break;
-       }
-
-       biblioModule->citationStyleL->setEnabled(nn > 1);
-       biblioModule->citeStyleCO->setEnabled(nn > 1);
-
-       if (nn != 1)
-               return;
-
-       // If the textclass allows only one of authoryear or numerical,
-       // we have no choice but to force that engine type.
-       if (engine_types_[0] == "authoryear")
-               biblioModule->citeStyleCO->setCurrentIndex(0);
-       else
-               biblioModule->citeStyleCO->setCurrentIndex(1);
+       updateCiteStyles(engine_types_, sel);
 }
 
 
@@ -2588,19 +2602,17 @@ void GuiDocument::applyView()
        bp_.use_refstyle  = latexModule->refstyleCB->isChecked();
 
        // biblio
-       if (biblioModule->citeNatbibRB->isChecked())
-               bp_.setCiteEngine("natbib");
-       else if (biblioModule->citeJurabibRB->isChecked())
-               bp_.setCiteEngine("jurabib");
-       if (biblioModule->citeDefaultRB->isChecked()) {
-               bp_.setCiteEngine("basic");
-               bp_.setCiteEngineType(ENGINE_TYPE_DEFAULT);
-       }
-       else
-       if (biblioModule->citeStyleCO->currentIndex())
-               bp_.setCiteEngineType(ENGINE_TYPE_NUMERICAL);
+       string const engine =
+               fromqstr(biblioModule->citeEngineCO->itemData(
+                               
biblioModule->citeEngineCO->currentIndex()).toString());
+       bp_.setCiteEngine(engine);
+
+       CiteEngineType const style = 
CiteEngineType(biblioModule->citeStyleCO->itemData(
+               biblioModule->citeStyleCO->currentIndex()).toInt());
+       if (theCiteEnginesList[engine]->hasEngineType(style))
+               bp_.setCiteEngineType(style);
        else
-               bp_.setCiteEngineType(ENGINE_TYPE_AUTHORYEAR);
+               bp_.setCiteEngineType(ENGINE_TYPE_DEFAULT);
 
        bp_.use_bibtopic =
                biblioModule->bibtopicCB->isChecked();
@@ -3016,21 +3028,15 @@ void GuiDocument::paramsToDialog()
        // biblio
        string const cite_engine = bp_.citeEngine().list().front();
 
-       biblioModule->citeDefaultRB->setChecked(
-               cite_engine == "basic");
-
-       biblioModule->citeJurabibRB->setChecked(
-               cite_engine == "jurabib");
-
-       biblioModule->citeNatbibRB->setChecked(
-               cite_engine == "natbib");
-
-       biblioModule->citeStyleCO->setCurrentIndex(
-               bp_.citeEngineType() & ENGINE_TYPE_NUMERICAL);
+       biblioModule->citeEngineCO->setCurrentIndex(
+               biblioModule->citeEngineCO->findData(toqstr(cite_engine)));
 
        updateEngineType(documentClass().opt_enginetype(),
                bp_.citeEngineType());
 
+       biblioModule->citeStyleCO->setCurrentIndex(
+               biblioModule->citeStyleCO->findData(bp_.citeEngineType()));
+
        biblioModule->bibtopicCB->setChecked(
                bp_.use_bibtopic);
 
diff --git a/src/frontends/qt4/GuiDocument.h b/src/frontends/qt4/GuiDocument.h
index c055378..e5aa4fa 100644
--- a/src/frontends/qt4/GuiDocument.h
+++ b/src/frontends/qt4/GuiDocument.h
@@ -75,6 +75,8 @@ public:
        void updateFontsize(std::string const &, std::string const &);
        void updateFontlist();
        void updateDefaultFormat();
+       void updateCiteStyles(std::vector<std::string> const &,
+                             CiteEngineType const & sel = 
ENGINE_TYPE_AUTHORYEAR);
        void updateEngineType(std::string const &, CiteEngineType const &);
        void updatePagestyle(std::string const &, std::string const &);
        bool isChildIncluded(std::string const &);
@@ -113,6 +115,7 @@ private Q_SLOTS:
        void classChanged_adaptor();
        void languagePackageChanged(int);
        void biblioChanged();
+       void citeEngineChanged(int);
        void bibtexChanged(int);
        void setAuthorYear(bool);
        void setNumerical(bool);
diff --git a/src/frontends/qt4/ui/BiblioUi.ui b/src/frontends/qt4/ui/BiblioUi.ui
index f0103cf..7cc821b 100644
--- a/src/frontends/qt4/ui/BiblioUi.ui
+++ b/src/frontends/qt4/ui/BiblioUi.ui
@@ -1,7 +1,8 @@
-<ui version="4.0" >
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
  <class>BiblioUi</class>
- <widget class="QWidget" name="BiblioUi" >
-  <property name="geometry" >
+ <widget class="QWidget" name="BiblioUi">
+  <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
@@ -9,81 +10,93 @@
     <height>394</height>
    </rect>
   </property>
-  <property name="windowTitle" >
+  <property name="windowTitle">
    <string/>
   </property>
-  <layout class="QGridLayout" name="gridLayout_3" >
-   <item row="0" column="0" >
-    <widget class="QGroupBox" name="CiteStyleBG" >
-     <property name="title" >
+  <layout class="QGridLayout" name="gridLayout_3">
+   <item row="0" column="0">
+    <widget class="QGroupBox" name="CiteStyleBG">
+     <property name="title">
       <string>Citation Style</string>
      </property>
-     <property name="flat" >
+     <property name="flat">
       <bool>true</bool>
      </property>
-     <layout class="QGridLayout" name="gridLayout" >
-      <item row="0" column="0" >
-       <widget class="QRadioButton" name="citeDefaultRB" >
-        <property name="toolTip" >
-         <string>Use BibTeX's default numerical styles</string>
-        </property>
-        <property name="text" >
-         <string>&amp;Default (numerical)</string>
+     <layout class="QGridLayout" name="gridLayout">
+      <item row="0" column="0">
+       <layout class="QHBoxLayout">
+        <property name="spacing">
+         <number>6</number>
         </property>
-       </widget>
-      </item>
-      <item row="1" column="0" >
-       <widget class="QRadioButton" name="citeNatbibRB" >
-        <property name="toolTip" >
-         <string>Use the natbib styles for natural sciences and arts. Set 
additional parameters in document class options.</string>
+        <property name="leftMargin">
+         <number>0</number>
         </property>
-        <property name="text" >
-         <string>&amp;Natbib</string>
+        <property name="topMargin">
+         <number>0</number>
         </property>
-       </widget>
-      </item>
-      <item row="1" column="1" >
-       <layout class="QHBoxLayout" >
-        <property name="spacing" >
-         <number>6</number>
+        <property name="rightMargin">
+         <number>0</number>
         </property>
-        <property name="margin" >
+        <property name="bottomMargin">
          <number>0</number>
         </property>
         <item>
-         <widget class="QLabel" name="citationStyleL" >
-          <property name="enabled" >
+         <widget class="QLabel" name="citeEngineLA">
+          <property name="toolTip">
+           <string/>
+          </property>
+          <property name="text">
+           <string>Sty&amp;le Engine:</string>
+          </property>
+          <property name="buddy">
+           <cstring>citeEngineCO</cstring>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QComboBox" name="citeEngineCO">
+          <property name="toolTip">
+           <string>A selection of different style engines (such as natbib) 
that respectively provide support for specific citytion and bibliography 
styles. Expand to get more information.</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QLabel" name="citationStyleL">
+          <property name="enabled">
            <bool>false</bool>
           </property>
-          <property name="text" >
-           <string>Natbib &amp;style:</string>
+          <property name="text">
+           <string>&amp;Variant:</string>
           </property>
-          <property name="buddy" >
+          <property name="buddy">
            <cstring>citeStyleCO</cstring>
           </property>
          </widget>
         </item>
         <item>
-         <widget class="QComboBox" name="citeStyleCO" >
-          <property name="enabled" >
+         <widget class="QComboBox" name="citeStyleCO">
+          <property name="enabled">
            <bool>false</bool>
           </property>
-          <property name="sizePolicy" >
-           <sizepolicy vsizetype="Fixed" hsizetype="Fixed" >
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
             <horstretch>0</horstretch>
             <verstretch>0</verstretch>
            </sizepolicy>
           </property>
+          <property name="toolTip">
+           <string>Provides available cite style variants.</string>
+          </property>
          </widget>
         </item>
        </layout>
       </item>
-      <item row="1" column="2" >
+      <item row="0" column="1">
        <spacer>
-        <property name="orientation" >
+        <property name="orientation">
          <enum>Qt::Horizontal</enum>
         </property>
-        <property name="sizeHint" stdset="0" >
+        <property name="sizeHint" stdset="0">
          <size>
           <width>40</width>
           <height>20</height>
@@ -91,55 +104,45 @@
         </property>
        </spacer>
       </item>
-      <item row="2" column="0" >
-       <widget class="QRadioButton" name="citeJurabibRB" >
-        <property name="toolTip" >
-         <string>Use the jurabib styles for law and humanities</string>
-        </property>
-        <property name="text" >
-         <string>&amp;Jurabib</string>
-        </property>
-       </widget>
-      </item>
      </layout>
     </widget>
    </item>
-   <item row="1" column="0" >
-    <widget class="QGroupBox" name="BiblioStyleBG" >
-     <property name="title" >
+   <item row="1" column="0">
+    <widget class="QGroupBox" name="BiblioStyleBG">
+     <property name="title">
       <string>Bibliography Style</string>
      </property>
-     <property name="flat" >
+     <property name="flat">
       <bool>true</bool>
      </property>
-     <layout class="QGridLayout" name="gridLayout_1" >
-      <item row="0" column="0" >
-       <layout class="QHBoxLayout" name="horizontalLayout_1" >
+     <layout class="QGridLayout" name="gridLayout_1">
+      <item row="0" column="0">
+       <layout class="QHBoxLayout" name="horizontalLayout_1">
         <item>
-         <widget class="QLabel" name="bibtexStyleLA" >
-          <property name="text" >
+         <widget class="QLabel" name="bibtexStyleLA">
+          <property name="text">
            <string>Default st&amp;yle:</string>
           </property>
-          <property name="buddy" >
+          <property name="buddy">
            <cstring>bibtexStyleLE</cstring>
           </property>
          </widget>
         </item>
         <item>
-         <widget class="QLineEdit" name="bibtexStyleLE" >
-          <property name="toolTip" >
+         <widget class="QLineEdit" name="bibtexStyleLE">
+          <property name="toolTip">
            <string>Define the default BibTeX style</string>
           </property>
          </widget>
         </item>
        </layout>
       </item>
-      <item row="1" column="0" >
-       <widget class="QCheckBox" name="bibtopicCB" >
-        <property name="toolTip" >
+      <item row="1" column="0">
+       <widget class="QCheckBox" name="bibtopicCB">
+        <property name="toolTip">
          <string>Select this if you want to split your bibliography into 
sections</string>
         </property>
-        <property name="text" >
+        <property name="text">
          <string>S&amp;ectioned bibliography</string>
         </property>
        </widget>
@@ -147,45 +150,45 @@
      </layout>
     </widget>
    </item>
-   <item row="2" column="0" >
-    <widget class="QGroupBox" name="bibtexGB" >
-     <property name="toolTip" >
+   <item row="2" column="0">
+    <widget class="QGroupBox" name="bibtexGB">
+     <property name="toolTip">
       <string>Here you can define an alternative program to or specific 
options of BibTeX.</string>
      </property>
-     <property name="title" >
+     <property name="title">
       <string>Bibliography Generation</string>
      </property>
-     <property name="flat" >
+     <property name="flat">
       <bool>true</bool>
      </property>
-     <layout class="QGridLayout" name="gridLayout_2" >
-      <item row="0" column="0" >
-       <layout class="QHBoxLayout" name="horizontalLayout" >
+     <layout class="QGridLayout" name="gridLayout_2">
+      <item row="0" column="0">
+       <layout class="QHBoxLayout" name="horizontalLayout">
         <item>
-         <widget class="QLabel" name="bibtexLA" >
-          <property name="text" >
+         <widget class="QLabel" name="bibtexLA">
+          <property name="text">
            <string>&amp;Processor:</string>
           </property>
-          <property name="buddy" >
+          <property name="buddy">
            <cstring>bibtexCO</cstring>
           </property>
          </widget>
         </item>
         <item>
-         <widget class="QComboBox" name="bibtexCO" >
-          <property name="toolTip" >
+         <widget class="QComboBox" name="bibtexCO">
+          <property name="toolTip">
            <string>Select a processor</string>
           </property>
          </widget>
         </item>
        </layout>
       </item>
-      <item rowspan="2" row="0" column="1" >
-       <spacer name="horizontalSpacer" >
-        <property name="orientation" >
+      <item row="0" column="1" rowspan="2">
+       <spacer name="horizontalSpacer">
+        <property name="orientation">
          <enum>Qt::Horizontal</enum>
         </property>
-        <property name="sizeHint" stdset="0" >
+        <property name="sizeHint" stdset="0">
          <size>
           <width>183</width>
           <height>20</height>
@@ -193,21 +196,21 @@
         </property>
        </spacer>
       </item>
-      <item row="1" column="0" >
-       <layout class="QHBoxLayout" name="horizontalLayout_2" >
+      <item row="1" column="0">
+       <layout class="QHBoxLayout" name="horizontalLayout_2">
         <item>
-         <widget class="QLabel" name="bibtexOptionsLA" >
-          <property name="text" >
-           <string>&amp;Options:</string>
+         <widget class="QLabel" name="bibtexOptionsLA">
+          <property name="text">
+           <string>Op&amp;tions:</string>
           </property>
-          <property name="buddy" >
+          <property name="buddy">
            <cstring>bibtexOptionsLE</cstring>
           </property>
          </widget>
         </item>
         <item>
-         <widget class="QLineEdit" name="bibtexOptionsLE" >
-          <property name="toolTip" >
+         <widget class="QLineEdit" name="bibtexOptionsLE">
+          <property name="toolTip">
            <string>Define options such as --min-crossrefs (see the 
documentation of BibTeX)</string>
           </property>
          </widget>
@@ -217,15 +220,15 @@
      </layout>
     </widget>
    </item>
-   <item row="3" column="0" >
+   <item row="3" column="0">
     <spacer>
-     <property name="orientation" >
+     <property name="orientation">
       <enum>Qt::Vertical</enum>
      </property>
-     <property name="sizeType" >
+     <property name="sizeType">
       <enum>QSizePolicy::Expanding</enum>
      </property>
-     <property name="sizeHint" stdset="0" >
+     <property name="sizeHint" stdset="0">
       <size>
        <width>20</width>
        <height>20</height>
@@ -236,7 +239,7 @@
   </layout>
  </widget>
  <includes>
-  <include location="local" >qt_i18n.h</include>
+  <include location="local">qt_i18n.h</include>
  </includes>
  <resources/>
  <connections/>

commit 97aea7e5b1707d662d6d7146d53adc97045c44c9
Author: Juergen Spitzmueller <[email protected]>
Date:   Fri Dec 30 16:22:08 2016 +0100

    Disentangle CiteEngines and Modules
    
    These two are different beasts and thus should be handled differently.

diff --git a/lib/Makefile.am b/lib/Makefile.am
index ee7e2b1..36c9c0c 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -2107,7 +2107,6 @@ dist_layouts_DATA =\
        layouts/arab-article.layout \
        layouts/article.layout \
        layouts/article-beamer.layout \
-       layouts/basic.module \
        layouts/beamer.layout \
        layouts/beamerposter.layout \
        layouts/bicaption.module \
@@ -2185,7 +2184,6 @@ dist_layouts_DATA =\
        layouts/jsarticle.layout \
        layouts/jsbook.layout \
        layouts/jss.layout \
-       layouts/jurabib.module \
        layouts/kluwer.layout \
        layouts/knitr.module \
        layouts/latex8.layout \
@@ -2205,7 +2203,6 @@ dist_layouts_DATA =\
        layouts/mwart.layout \
        layouts/mwbk.layout \
        layouts/mwrep.layout \
-       layouts/natbib.module \
        layouts/natbibapa.module \
        layouts/noweb.module \
        layouts/numarticle.inc \
@@ -2302,6 +2299,12 @@ dist_layouts_DATA =\
        layouts/tufte-handout.layout \
        layouts/varwidth.module
 
+citeenginesdir = $(pkgdatadir)/citeengines
+dist_citeengines_DATA = \
+       citeengines/basic.citeengine \
+        citeengines/jurabib.citeengine \
+        citeengines/natbib.citeengine
+
 scriptsdir = $(pkgdatadir)/scripts
 dist_scripts_DATA = \
        scripts/bash_completion \
diff --git a/lib/chkconfig.ltx b/lib/chkconfig.ltx
index 140014a..9daca8f 100644
--- a/lib/chkconfig.ltx
+++ b/lib/chkconfig.ltx
@@ -492,6 +492,7 @@
 % configure script.
 \input{chklayouts}
 \input{chkmodules}
+\input{chkciteengines}
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %%%%% END ACTUAL CONFIGURATION INSPECTION CODE %%%%%%%%%%%%%%%%%%%%%%%%%%%%
diff --git a/lib/layouts/basic.module b/lib/citeengines/basic.citeengine
similarity index 93%
rename from lib/layouts/basic.module
rename to lib/citeengines/basic.citeengine
index 8e0ed1c..dc4941b 100644
--- a/lib/layouts/basic.module
+++ b/lib/citeengines/basic.citeengine
@@ -1,9 +1,8 @@
-# \DeclareLyXModule{Default (basic)}
+# \DeclareLyXCiteEngine{BibTeX (basic)}
 # DescriptionBegin
 #   Use the basic citation capabilities provided by plain LaTeX.
 # DescriptionEnd
 # Excludes: jurabib | natbib
-# Category: Citation engine
 
 # Author: Julien Rioux <[email protected]>
 
diff --git a/lib/layouts/jurabib.module b/lib/citeengines/jurabib.citeengine
similarity index 98%
rename from lib/layouts/jurabib.module
rename to lib/citeengines/jurabib.citeengine
index 63bae5a..13bbc6f 100644
--- a/lib/layouts/jurabib.module
+++ b/lib/citeengines/jurabib.citeengine
@@ -1,11 +1,10 @@
-# \DeclareLyXModule[jurabib.sty]{Jurabib}
+# \DeclareLyXCiteEngine[jurabib.sty]{Jurabib}
 # DescriptionBegin
 #   Loads the LaTeX package jurabib, a citation engine. Jurabib supports 
annotations,
 #   author-year style citations and hyphenation patterns for bibliography 
entries in
 #   English, German, French, Dutch, Spanish and Italian.
 # DescriptionEnd
 # Excludes: basic | natbib
-# Category: Citation engine
 
 # Author: Julien Rioux <[email protected]>
 
diff --git a/lib/layouts/natbib.module b/lib/citeengines/natbib.citeengine
similarity index 97%
rename from lib/layouts/natbib.module
rename to lib/citeengines/natbib.citeengine
index d4d250e..63bf1cb 100644
--- a/lib/layouts/natbib.module
+++ b/lib/citeengines/natbib.citeengine
@@ -1,4 +1,4 @@
-# \DeclareLyXModule[natbib.sty]{Natbib}
+# \DeclareLyXCiteEngine[natbib.sty]{Natbib}
 # DescriptionBegin
 #   Loads the LaTeX package natbib, a citation engine. Natbib supports
 #   both author-year and numerical styles for citations, automatic sorting
@@ -6,7 +6,6 @@
 #   `van' part of author names, shortened and full author lists, and more.
 # DescriptionEnd
 # Excludes: basic | jurabib
-# Category: Citation engine
 
 # Author: Julien Rioux <[email protected]>
 
diff --git a/lib/configure.py b/lib/configure.py
index fb1abd3..680e32a 100644
--- a/lib/configure.py
+++ b/lib/configure.py
@@ -1502,6 +1502,132 @@ def processModuleFile(file, filename, bool_docbook):
     return '"%s" "%s" "%s" "%s" "%s" "%s" "%s"\n' % (modname, filename, desc, 
pkgs, req, excl, catgy)
 
 
+def checkCiteEnginesConfig():
+  removeFiles(['lyxciteengines.lst', 'chkciteengines.tex'])
+
+  logger.info('+checking list of cite engines... ')
+  tx = open('lyxciteengines.lst', 'w')
+  tx.write('''## This file declares cite engines and their associated 
definition files.
+## It has been automatically generated by configure
+## Use "Options/Reconfigure" if you need to update it after a
+## configuration change.
+## "CiteEngineName" "filename" "CiteEngineType" "Description" "Packages" 
"Requires" "Excludes"
+''')
+
+  # build the list of available modules
+  seen = []
+  # note that this searches the local directory first, then the
+  # system directory. that way, we pick up the user's version first.
+  for file in glob.glob( os.path.join('citeengines', '*.citeengine') ) + \
+      glob.glob( os.path.join(srcdir, 'citeengines', '*.citeengine' ) ) :
+      # valid file?
+      logger.info(file)
+      if not os.path.isfile(file):
+          continue
+
+      filename = file.split(os.sep)[-1]
+      filename = filename[:-11]
+      if seen.count(filename):
+          continue
+
+      seen.append(filename)
+      retval = processCiteEngineFile(file, filename, bool_docbook)
+      if retval != "":
+          tx.write(retval)
+  tx.close()
+  logger.info('\tdone')
+
+
+def processCiteEngineFile(file, filename, bool_docbook):
+    ''' process cite engines file and get a line of result
+
+        The top of a cite engine file should look like this:
+          #\DeclareLyXCiteEngine[LaTeX Packages]{CiteEngineName}
+          #DescriptionBegin
+          #...body of description...
+          #DescriptionEnd
+          #Requires: [list of required engines]
+          #Excludes: [list of excluded engines]
+        The last two lines are optional.
+        We expect output:
+          "CiteEngineName" "filename" "CiteEngineType" "Description" 
"Packages" "Requires" "Excludes"
+    '''
+    remods = re.compile(r'\DeclareLyXCiteEngine\s*(?:\[([^]]*?)\])?{(.*)}')
+    rereqs = re.compile(r'#+\s*Requires: (.*)')
+    reexcs = re.compile(r'#+\s*Excludes: (.*)')
+    redbeg = re.compile(r'#+\s*DescriptionBegin\s*$')
+    redend = re.compile(r'#+\s*DescriptionEnd\s*$')
+    recet = re.compile(r'\s*CiteEngineType (.*)')
+
+    modname = desc = pkgs = req = excl = cet = ""
+    readingDescription = False
+    descLines = []
+
+    for line in open(file).readlines():
+      if readingDescription:
+        res = redend.search(line)
+        if res != None:
+          readingDescription = False
+          desc = " ".join(descLines)
+          # Escape quotes.
+          desc = desc.replace('"', '\\"')
+          continue
+        descLines.append(line[1:].strip())
+        continue
+      res = redbeg.search(line)
+      if res != None:
+        readingDescription = True
+        continue
+      res = remods.search(line)
+      if res != None:
+          (pkgs, modname) = res.groups()
+          if pkgs == None:
+            pkgs = ""
+          else:
+            tmp = [s.strip() for s in pkgs.split(",")]
+            pkgs = ",".join(tmp)
+          continue
+      res = rereqs.search(line)
+      if res != None:
+        req = res.group(1)
+        tmp = [s.strip() for s in req.split("|")]
+        req = "|".join(tmp)
+        continue
+      res = reexcs.search(line)
+      if res != None:
+        excl = res.group(1)
+        tmp = [s.strip() for s in excl.split("|")]
+        excl = "|".join(tmp)
+        continue
+      res = recet.search(line)
+      if res != None:
+        cet = res.group(1)
+        continue
+
+    if modname == "":
+      logger.warning("Cite Engine File file without \DeclareLyXCiteEngine 
line. ")
+      return ""
+
+    if pkgs != "":
+        # this cite engine has some latex dependencies:
+        # append the dependencies to chkciteengines.tex,
+        # which is \input'ed by chkconfig.ltx
+        testpackages = list()
+        for pkg in pkgs.split(","):
+            if "->" in pkg:
+                # this is a converter dependency: skip
+                continue
+            if pkg.endswith(".sty"):
+                pkg = pkg[:-4]
+            testpackages.append("\\TestPackage{%s}" % (pkg,))
+        cm = open('chkciteengines.tex', 'a')
+        for line in testpackages:
+            cm.write(line + '\n')
+        cm.close()
+
+    return '"%s" "%s" "%s" "%s" "%s" "%s" "%s"\n' % (modname, filename, cet, 
desc, pkgs, req, excl)
+
+
 def checkTeXAllowSpaces():
     ''' Let's check whether spaces are allowed in TeX file names '''
     tex_allows_spaces = 'false'
@@ -1543,8 +1669,8 @@ def removeTempFiles():
     # Final clean-up
     if not lyx_keep_temps:
         removeFiles(['chkconfig.vars', 'chklatex.ltx', 'chklatex.log',
-            'chklayouts.tex', 'chkmodules.tex', 'missfont.log',
-            'wrap_chkconfig.ltx', 'wrap_chkconfig.log'])
+            'chklayouts.tex', 'chkmodules.tex', 'chkciteengines.tex',
+            'missfont.log', 'wrap_chkconfig.ltx', 'wrap_chkconfig.log'])
 
 
 if __name__ == '__main__':
@@ -1623,6 +1749,7 @@ Format %i
     if lyx_kpsewhich:
         rescanTeXFiles()
     checkModulesConfig()
+    checkCiteEnginesConfig()
     # --without-latex-config can disable lyx_check_config
     ret = checkLatexConfig(lyx_check_config and LATEX != '', bool_docbook)
     removeTempFiles()
diff --git a/po/Rules-lyx b/po/Rules-lyx
index 42998f2..23d4c06 100644
--- a/po/Rules-lyx
+++ b/po/Rules-lyx
@@ -34,7 +34,7 @@ layouts_l10n.pot: $(top_srcdir)/lib/layouts/*.layout \
 # Read translatable strings from layouts and translations from the po files and
 # create the layouttranslations file containing all LaTeX relevant translations
 $(top_srcdir)/lib/layouttranslations: $(POFILES) 
$(top_srcdir)/lib/layouts/*.layout \
-                $(top_srcdir)/lib/layouts/*.inc 
$(top_srcdir)/lib/layouts/*.module
+                $(top_srcdir)/lib/layouts/*.inc 
$(top_srcdir)/lib/layouts/*.module $(top_srcdir)/lib/citeengines/*.citeengines
        $(LYX_POT) -o $@ -t layouttranslations 
${top_srcdir}/lib/layouts/*.layout ${top_srcdir}/lib/layouts/*.inc 
${top_srcdir}/lib/layouts/*.module
 
 languages_l10n.pot: $(top_srcdir)/lib/languages
diff --git a/po/lyx_pot.py b/po/lyx_pot.py
index 761e3dd..0fc7ee4 100755
--- a/po/lyx_pot.py
+++ b/po/lyx_pot.py
@@ -91,6 +91,7 @@ def layouts_l10n(input_files, output, base, 
layouttranslations):
     ListName = re.compile(r'^\s*ListName\s+(.*\S)\s*$', re.IGNORECASE)
     CategoryName = re.compile(r'^\s*Category\s+(.*\S)\s*$', re.IGNORECASE)
     NameRE = re.compile(r'^\s*#\s*\\DeclareLyXModule.*{(.*)}$', re.IGNORECASE)
+    CiteNameRE = re.compile(r'^\s*#\s*\\DeclareLyXCiteEngine.*{(.*)}$', 
re.IGNORECASE)
     InsetLayout = re.compile(r'^InsetLayout\s+\"?(.*)\"?\s*$', re.IGNORECASE)
     FlexCheck = re.compile(r'^Flex:(.*)', re.IGNORECASE)
     CaptionCheck = re.compile(r'^Caption:(.*)', re.IGNORECASE)
@@ -234,6 +235,12 @@ def layouts_l10n(input_files, output, base, 
layouttranslations):
                 if not layouttranslations:
                     writeString(out, src, base, lineno + 1, string)
                 continue
+            res = CiteNameRE.search(line)
+            if res != None:
+                string = res.group(1)
+                if not layouttranslations:
+                    writeString(out, src, base, lineno + 1, string)
+                continue
             res = Style.search(line)
             if res != None:
                 string = res.group(1)
diff --git a/src/BufferParams.cpp b/src/BufferParams.cpp
index fa0b7c3..326d487 100644
--- a/src/BufferParams.cpp
+++ b/src/BufferParams.cpp
@@ -2333,6 +2333,7 @@ void BufferParams::makeDocumentClass(bool const clone)
 
        invalidateConverterCache();
        LayoutModuleList mods;
+       LayoutModuleList ces;
        LayoutModuleList::iterator it = layout_modules_.begin();
        LayoutModuleList::iterator en = layout_modules_.end();
        for (; it != en; ++it)
@@ -2341,9 +2342,9 @@ void BufferParams::makeDocumentClass(bool const clone)
        it = cite_engine_.begin();
        en = cite_engine_.end();
        for (; it != en; ++it)
-               mods.push_back(*it);
+               ces.push_back(*it);
 
-       doc_class_ = getDocumentClass(*baseClass(), mods, clone);
+       doc_class_ = getDocumentClass(*baseClass(), mods, ces, clone);
 
        TextClass::ReturnValues success = TextClass::OK;
        if (!forced_local_layout_.empty())
diff --git a/src/CiteEnginesList.cpp b/src/CiteEnginesList.cpp
new file mode 100644
index 0000000..48222cb
--- /dev/null
+++ b/src/CiteEnginesList.cpp
@@ -0,0 +1,280 @@
+// -*- C++ -*-
+/**
+ * \file CiteEnginesList.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Richard Heck
+ * \author Jürgen Spitzmüller
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "CiteEnginesList.h"
+
+#include "LaTeXFeatures.h"
+#include "Lexer.h"
+
+#include "support/debug.h"
+#include "support/FileName.h"
+#include "support/gettext.h"
+#include "support/filetools.h"
+#include "support/lstrings.h"
+
+#include <algorithm>
+
+using namespace std;
+using namespace lyx::support;
+
+namespace lyx {
+
+
+//global variable: cite engine list
+CiteEnginesList theCiteEnginesList;
+
+
+LyXCiteEngine::LyXCiteEngine(string const & n, string const & i,
+                            vector<string> const & cet, string const & d,
+                            vector<string> const & p,
+                            vector<string> const & r, vector<string> const & 
e):
+       name_(n), id_(i), engine_types_(cet), description_(d), package_list_(p),
+       required_engines_(r), excluded_engines_(e),
+       checked_(false), available_(false)
+{
+       filename_ = id_ + ".citeengine";
+}
+
+
+vector<string> LyXCiteEngine::prerequisites() const
+{
+       if (!checked_)
+               isAvailable();
+       return prerequisites_;
+}
+
+
+bool LyXCiteEngine::isAvailable() const
+{
+       if (package_list_.empty())
+               return true;
+       if (checked_)
+               return available_;
+       checked_ = true;
+       available_ = true;
+       //check whether all of the required packages are available
+       vector<string>::const_iterator it  = package_list_.begin();
+       vector<string>::const_iterator end = package_list_.end();
+       for (; it != end; ++it) {
+               if (!LaTeXFeatures::isAvailable(*it)) {
+                       available_ = false;
+                       prerequisites_.push_back(*it);
+               }
+       }
+       return available_;
+}
+
+
+bool LyXCiteEngine::isCompatible(string const & cename) const
+{
+       // do we exclude it?
+       if (find(excluded_engines_.begin(), excluded_engines_.end(), cename) !=
+                       excluded_engines_.end())
+               return false;
+
+       LyXCiteEngine const * const lm = theCiteEnginesList[cename];
+       if (!lm)
+               return true;
+
+       // does it exclude us?
+       vector<string> const excengs = lm->getExcludedEngines();
+       if (find(excengs.begin(), excengs.end(), id_) != excengs.end())
+               return false;
+
+       return true;
+}
+
+
+bool LyXCiteEngine::areCompatible(string const & eng1, string const & eng2)
+{
+       LyXCiteEngine const * const lm1 = theCiteEnginesList[eng1];
+       if (lm1)
+               return lm1->isCompatible(eng2);
+       LyXCiteEngine const * const lm2 = theCiteEnginesList[eng2];
+       if (lm2)
+               return lm2->isCompatible(eng1);
+       // Can't check it either way.
+       return true;
+}
+
+
+// used when sorting the cite engine list.
+class EngineSorter {
+public:
+       int operator()(LyXCiteEngine const & ce1, LyXCiteEngine const & ce2) 
const
+       {
+               return _(ce1.getName()) < _(ce2.getName());
+       }
+};
+
+
+// Much of this is borrowed from LayoutFileList::read()
+bool CiteEnginesList::read()
+{
+       FileName const real_file = libFileSearch("", "lyxciteengines.lst");
+       LYXERR(Debug::TCLASS, "Reading cite engines from `" << real_file << 
'\'');
+
+       if (real_file.empty()) {
+               LYXERR0("unable to find cite engines file `citeengines.lst'.\n"
+                       << "No cite engines will be available.");
+               return false;
+       }
+
+       Lexer lex;
+       if (!lex.setFile(real_file)) {
+               LYXERR0("lyxlex was not able to set file: "
+                       << real_file << ".\nNo cite engines will be 
available.");
+               return false;
+       }
+
+       if (!lex.isOK()) {
+               LYXERR0("unable to open cite engines file  `"
+                       << to_utf8(makeDisplayPath(real_file.absFileName(), 
1000))
+                       << "'\nNo cite engines will be available.");
+               return false;
+       }
+
+       bool finished = false;
+       // Parse cite engines files
+       LYXERR(Debug::TCLASS, "Starting parsing of lyxciteengines.lst");
+       while (lex.isOK() && !finished) {
+               LYXERR(Debug::TCLASS, "\tline by line");
+               switch (lex.lex()) {
+               case Lexer::LEX_FEOF:
+                       finished = true;
+                       break;
+               default:
+                       string const cename = lex.getString();
+                       LYXERR(Debug::TCLASS, "Engine name: " << cename);
+                       if (!lex.next())
+                               break;
+                       string const fname = lex.getString();
+                       LYXERR(Debug::TCLASS, "Filename: " << fname);
+                       if (!lex.next(true))
+                               break;
+                       string cet = lex.getString();
+                       LYXERR(Debug::TCLASS, "Engine Type: " << cet);
+                       vector<string> cets;
+                       while (!cet.empty()) {
+                               string p;
+                               cet = split(cet, p, '|');
+                               cets.push_back(p);
+                       }
+                       if (!lex.next(true))
+                               break;
+                       string const desc = lex.getString();
+                       LYXERR(Debug::TCLASS, "Description: " << desc);
+                       //FIXME Add packages
+                       if (!lex.next())
+                               break;
+                       string str = lex.getString();
+                       LYXERR(Debug::TCLASS, "Packages: " << str);
+                       vector<string> pkgs;
+                       while (!str.empty()) {
+                               string p;
+                               str = split(str, p, ',');
+                               pkgs.push_back(p);
+                       }
+                       if (!lex.next())
+                               break;
+                       str = lex.getString();
+                       LYXERR(Debug::TCLASS, "Required: " << str);
+                       vector<string> req;
+                       while (!str.empty()) {
+                               string p;
+                               str = split(str, p, '|');
+                               req.push_back(p);
+                       }
+                       if (!lex.next())
+                               break;
+                       str = lex.getString();
+                       LYXERR(Debug::TCLASS, "Excluded: " << str);
+                       vector<string> exc;
+                       while (!str.empty()) {
+                               string p;
+                               str = split(str, p, '|');
+                               exc.push_back(p);
+                       }
+                       // This code is run when we have
+                       // cename, fname, desc, pkgs, req and exc
+                       addCiteEngine(cename, fname, cets, desc, pkgs, req, 
exc);
+               } // end switch
+       } //end while
+
+       LYXERR(Debug::TCLASS, "End of parsing of lyxciteengines.lst");
+
+       if (!theCiteEnginesList.empty())
+               sort(theCiteEnginesList.begin(), theCiteEnginesList.end(), 
EngineSorter());
+       return true;
+}
+
+
+void CiteEnginesList::addCiteEngine(string const & cename,
+       string const & filename, vector<string> const & cets, string const & 
description,
+       vector<string> const & pkgs, vector<string> const & req,
+       vector<string> const & exc)
+{
+       LyXCiteEngine ce(cename, filename, cets, description, pkgs, req, exc);
+       englist_.push_back(ce);
+}
+
+
+LyXCiteEnginesList::const_iterator CiteEnginesList::begin() const
+{
+       return englist_.begin();
+}
+
+
+LyXCiteEnginesList::iterator CiteEnginesList::begin()
+{
+       return englist_.begin();
+}
+
+
+LyXCiteEnginesList::const_iterator CiteEnginesList::end() const
+{
+       return englist_.end();
+}
+
+
+LyXCiteEnginesList::iterator CiteEnginesList::end()
+{
+       return englist_.end();
+}
+
+
+LyXCiteEngine const * CiteEnginesList::operator[](string const & str) const
+{
+       LyXCiteEnginesList::const_iterator it = englist_.begin();
+       for (; it != englist_.end(); ++it)
+               if (it->getID() == str) {
+                       LyXCiteEngine const & eng = *it;
+                       return &eng;
+               }
+       return 0;
+}
+
+
+LyXCiteEngine * CiteEnginesList::operator[](string const & str)
+{
+       LyXCiteEnginesList::iterator it = englist_.begin();
+       for (; it != englist_.end(); ++it)
+               if (it->getID() == str) {
+                       LyXCiteEngine & eng = *it;
+                       return &eng;
+               }
+       return 0;
+}
+
+} // namespace lyx
diff --git a/src/CiteEnginesList.h b/src/CiteEnginesList.h
new file mode 100644
index 0000000..0e6d119
--- /dev/null
+++ b/src/CiteEnginesList.h
@@ -0,0 +1,156 @@
+// -*- C++ -*-
+/**
+ * \file CiteEnginesList.h
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Richard Heck
+ * \author Jürgen Spitzmüller
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#ifndef CITEENGINESLIST_H
+#define CITEENGINESLIST_H
+
+#include <string>
+#include <vector>
+
+namespace lyx {
+
+/**
+ *  This class represents a particular LyX "cite engine", which defines the 
features
+ * of a particular citation backend such as natbib or biblatex. In that sense, 
it is more like
+ *  a LaTeX package, where a layout file corresponds to a LaTeX class.
+ *
+ *  In general, a given cite engine can be used with any document class. That 
said,
+ *  one cite engine may `require' another, or it may `exclude' some other cite 
engine.
+ *  The requires and excludes are given in comments within the cite engine 
file,
+ *  which must begin roughly so:
+ *  # \DeclareLyXCiteEngine[natbib.sty]{Natbib}
+ *  # DescriptionBegin
+ *  #   Loads the LaTeX package natbib, a citation engine. Natbib supports
+ *  #   both author-year and numerical styles for citations, automatic sorting
+ *  #   and merging of numerical citations, annotations, capitalization of the
+ *  #   `van' part of author names, shortened and full author lists, and more.
+ *  # DescriptionEnd
+ *  # Excludes: basic | jurabib
+ *  The description might be used in the gui to give information to the user. 
The
+ *  Requires and Excludes lines are read by the configuration script
+ *  and written to a file citeengines.lst in the user configuration directory.
+ *  That file is then read on startup to populate the CiteEnginesList, below.
+ *
+ *  Engines can also be "provided" or "excluded" by document classes, using
+ *  the ProvidesEngine and ExcludesEngine tags.
+ */
+
+class LyXCiteEngine {
+public:
+       ///
+       LyXCiteEngine(std::string const & name, std::string const & id,
+                     std::vector<std::string> const & enginetypes,
+                     std::string const & description,
+                     std::vector<std::string> const & packagelist,
+                     std::vector<std::string> const & requires,
+                     std::vector<std::string> const & excludes);
+       /// whether the required packages are available
+       bool isAvailable() const;
+       /// the missing prerequisites, if any
+       std::vector<std::string> prerequisites() const;
+       ///
+       std::string const & getName() const { return name_; }
+       ///
+       std::string const & getID() const { return id_; }
+       ///
+       std::string const & getFilename() const { return filename_; }
+       ///
+       std::vector<std::string> const & getEngineType() const { return 
engine_types_; }
+       ///
+       std::string const & getDescription() const { return description_; }
+       ///
+       std::vector<std::string> const & getPackageList() const
+               { return package_list_; }
+       ///
+       std::vector<std::string> const & getRequiredEngines() const
+               { return required_engines_; }
+       /// Engines this one excludes: the list should be treated disjunctively
+       std::vector<std::string> const & getExcludedEngines() const
+               { return excluded_engines_; }
+       /// \return true if the engine is compatible with this one, i.e.,
+       /// it does not exclude us and we do not exclude it.
+       /// this will also return true if cename is unknown and we do not
+       /// exclude it, since in that case we cannot check its exclusions.
+       bool isCompatible(std::string const & cename) const;
+       ///
+       static bool areCompatible(std::string const & eng1, std::string const & 
eng2);
+private:
+       /// what appears in the ui
+       std::string name_;
+       /// the engine's unique identifier
+       /// at present, this is the filename, without the extension
+       std::string id_;
+       /// the filename
+       std::string filename_;
+       /// the engine type(s)
+       std::vector<std::string> engine_types_;
+       /// a short description for use in the ui
+       std::string description_;
+       /// the LaTeX packages on which this depends, if any
+       std::vector<std::string> package_list_;
+       /// Engines this one requires: at least one
+       std::vector<std::string> required_engines_;
+       /// Engines this one excludes: none of these
+       std::vector<std::string> excluded_engines_;
+       // these are mutable because they are used to cache the results
+       // or an otherwise const operation.
+       ///
+       mutable bool checked_;
+       ///
+       mutable bool available_;
+       ///
+       mutable std::vector<std::string> prerequisites_;
+};
+
+typedef std::vector<LyXCiteEngine> LyXCiteEnginesList;
+
+/**
+ *  The CiteEnginesList represents the various LyXCiteEngine's that are 
available at
+ *  present.
+ */
+class CiteEnginesList {
+public:
+       ///
+       CiteEnginesList() {}
+       /// reads the engines from a file generated by configure.py
+       bool read();
+       ///
+       LyXCiteEnginesList::const_iterator begin() const;
+       ///
+       LyXCiteEnginesList::iterator begin();
+       ///
+       LyXCiteEnginesList::const_iterator end() const;
+       ///
+       LyXCiteEnginesList::iterator end();
+       ///
+       bool empty() const { return englist_.empty(); }
+       /// Returns a pointer to the LyXCiteEngine with filename str.
+       /// Returns a null pointer if no such engine is found.
+       LyXCiteEngine const * operator[](std::string const & str) const;
+       ///
+       LyXCiteEngine * operator[](std::string const & str);
+       private:
+       /// noncopyable
+       CiteEnginesList(CiteEnginesList const &);
+       ///
+       void operator=(CiteEnginesList const &);
+       /// add an engine to the list
+       void addCiteEngine(std::string const &, std::string const &,
+               std::vector<std::string> const &, std::string const &, 
std::vector<std::string> const &,
+               std::vector<std::string> const &, std::vector<std::string> 
const &);
+       ///
+       std::vector<LyXCiteEngine> englist_;
+};
+
+extern CiteEnginesList theCiteEnginesList;
+}
+#endif
diff --git a/src/LyX.cpp b/src/LyX.cpp
index b10b60b..2ba217c 100644
--- a/src/LyX.cpp
+++ b/src/LyX.cpp
@@ -22,6 +22,7 @@
 #include "Buffer.h"
 #include "BufferList.h"
 #include "CmdDef.h"
+#include "CiteEnginesList.h"
 #include "ColorSet.h"
 #include "ConverterCache.h"
 #include "Converter.h"
@@ -934,8 +935,10 @@ bool LyX::init()
        LYXERR(Debug::INIT, "Reading layouts...");
        // Load the layouts
        LayoutFileList::get().read();
-       //...and the modules
+       //... the modules
        theModuleList.read();
+       //... and the cite engines
+       theCiteEnginesList.read();
 
        // read keymap and ui files in batch mode as well
        // because InsetInfo needs to know these to produce
@@ -1019,7 +1022,8 @@ bool LyX::queryUserLyXDir(bool explicit_userdir)
                return configFileNeedsUpdate("lyxrc.defaults")
                        || configFileNeedsUpdate("lyxmodules.lst")
                        || configFileNeedsUpdate("textclass.lst")
-                       || configFileNeedsUpdate("packages.lst");
+                       || configFileNeedsUpdate("packages.lst")
+                       || configFileNeedsUpdate("lyxciteengines.lst");
        }
 
        first_start = !explicit_userdir;
diff --git a/src/Makefile.am b/src/Makefile.am
index f87d029..4cb38b5 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -108,6 +108,7 @@ SOURCEFILESCORE = \
        Bullet.cpp \
        Changes.cpp \
        Chktex.cpp \
+       CiteEnginesList.cpp \
        CmdDef.cpp \
        Color.cpp \
        ConverterCache.cpp \
@@ -201,6 +202,7 @@ HEADERFILESCORE = \
        BufferView.h \
        Bullet.h \
        Citation.h \
+       CiteEnginesList.h \
        Changes.h \
        Chktex.h \
        CmdDef.h \
diff --git a/src/TextClass.cpp b/src/TextClass.cpp
index 46a96e4..d14ef29 100644
--- a/src/TextClass.cpp
+++ b/src/TextClass.cpp
@@ -17,6 +17,7 @@
 #include "TextClass.h"
 
 #include "LayoutFile.h"
+#include "CiteEnginesList.h"
 #include "Color.h"
 #include "Counters.h"
 #include "Floating.h"
@@ -123,6 +124,8 @@ string translateReadType(TextClass::ReadType rt)
                return "input file";
        case TextClass::MODULE:
                return "module file";
+       case TextClass::CITE_ENGINE:
+               return "cite engine";
        case TextClass::VALIDATION:
                return "validation";
        }
@@ -1585,6 +1588,7 @@ Layout TextClass::createBasicLayout(docstring const & 
name, bool unknown) const
 
 DocumentClassPtr getDocumentClass(
                LayoutFile const & baseClass, LayoutModuleList const & modlist,
+               LayoutModuleList const & celist,
                bool const clone)
 {
        DocumentClassPtr doc_class =
@@ -1623,6 +1627,42 @@ DocumentClassPtr getDocumentClass(
                        frontend::Alert::warning(_("Read Error"), msg);
                }
        }
+
+       LayoutModuleList::const_iterator cit = celist.begin();
+       LayoutModuleList::const_iterator cen = celist.end();
+       for (; cit != cen; ++cit) {
+               string const ceName = *cit;
+               LyXCiteEngine * ce = theCiteEnginesList[ceName];
+               if (!ce) {
+                       docstring const msg =
+                                               bformat(_("The cite engine %1$s 
has been requested by\n"
+                                               "this document but has not been 
found in the list of\n"
+                                               "available engines. If you 
recently installed it, you\n"
+                                               "probably need to reconfigure 
LyX.\n"), from_utf8(ceName));
+                       if (!clone)
+                               frontend::Alert::warning(_("Cite Engine not 
available"), msg);
+                       continue;
+               }
+               if (!ce->isAvailable() && !clone) {
+                       docstring const prereqs = 
from_utf8(getStringFromVector(ce->prerequisites(), "\n\t"));
+                       docstring const msg =
+                               bformat(_("The cite engine %1$s requires a 
package that is not\n"
+                                       "available in your LaTeX installation, 
or a converter that\n"
+                                       "you have not installed. LaTeX output 
may not be possible.\n"
+                                       "Missing prerequisites:\n"
+                                               "\t%2$s\n"
+                                       "See section 3.1.2.3 (Modules) of the 
User's Guide for more information."),
+                               from_utf8(ceName), prereqs);
+                       frontend::Alert::warning(_("Package not available"), 
msg, true);
+               }
+               FileName layout_file = libFileSearch("citeengines", 
ce->getFilename());
+               if (!doc_class->read(layout_file, TextClass::CITE_ENGINE)) {
+                       docstring const msg =
+                                               bformat(_("Error reading cite 
engine %1$s\n"), from_utf8(ceName));
+                       frontend::Alert::warning(_("Read Error"), msg);
+               }
+       }
+
        return doc_class;
 }
 
diff --git a/src/TextClass.h b/src/TextClass.h
index 22d426c..d082e10 100644
--- a/src/TextClass.h
+++ b/src/TextClass.h
@@ -151,6 +151,7 @@ public:
                BASECLASS, //>This is a base class, i.e., top-level layout file
                MERGE, //>This is a file included in a layout file
                MODULE, //>This is a layout module
+               CITE_ENGINE, //>This is a cite engine
                VALIDATION //>We're just validating
        };
        /// return values for read()
@@ -498,6 +499,7 @@ private:
        /// The only way to make a DocumentClass is to call this function.
        friend DocumentClassPtr
                getDocumentClass(LayoutFile const &, LayoutModuleList const &,
+                                LayoutModuleList const &,
                                 bool const clone);
 };
 
@@ -508,6 +510,7 @@ private:
 /// on the CutStack.
 DocumentClassPtr getDocumentClass(LayoutFile const & baseClass,
                        LayoutModuleList const & modlist,
+                       LayoutModuleList const & celist,
                        bool const clone = false);
 
 /// convert page sides option to text 1 or 2
diff --git a/src/tex2lyx/Makefile.am b/src/tex2lyx/Makefile.am
index bf2d66d..a4a5fdc 100644
--- a/src/tex2lyx/Makefile.am
+++ b/src/tex2lyx/Makefile.am
@@ -83,6 +83,7 @@ updatetests: tex2lyx
 
 LINKED_FILES = \
        ../Author.cpp \
+       ../CiteEnginesList.cpp \
        ../Color.cpp \
        ../Counters.cpp \
        ../Encoding.cpp \
diff --git a/src/tex2lyx/tex2lyx.cpp b/src/tex2lyx/tex2lyx.cpp
index 7a6bbb0..3f6fe73 100644
--- a/src/tex2lyx/tex2lyx.cpp
+++ b/src/tex2lyx/tex2lyx.cpp
@@ -282,10 +282,11 @@ void initModules()
                for (; it != end; ++it) {
                        string const module = it->getID();
                        LayoutModuleList m;
+                       LayoutModuleList c;
                        vector<string> v;
                        if (!addModule(module, baseClass, m, v))
                                continue;
-                       modules[module] = getDocumentClass(baseClass, m);
+                       modules[module] = getDocumentClass(baseClass, m, c);
                }
                init = false;
        }

commit 9a9288d67dac1cdbd76372b1c0e0b7a25708cc09
Author: Guillaume Munch <[email protected]>
Date:   Sat Dec 31 15:16:15 2016 +0100

    Fix memory leak with WordLists
    
    https://www.mail-archive.com/[email protected]/msg198230.html

diff --git a/src/LyX.cpp b/src/LyX.cpp
index 047e265..b10b60b 100644
--- a/src/LyX.cpp
+++ b/src/LyX.cpp
@@ -234,7 +234,6 @@ LyX::~LyX()
 {
        delete pimpl_;
        singleton_ = 0;
-       WordList::cleanupWordLists();
 }
 
 
diff --git a/src/WordList.cpp b/src/WordList.cpp
index 8180985..9bc52ac 100644
--- a/src/WordList.cpp
+++ b/src/WordList.cpp
@@ -16,6 +16,7 @@
 #include "support/debug.h"
 #include "support/docstring.h"
 #include "support/lassert.h"
+#include "support/unique_ptr.h"
 #include "support/weighted_btree.h"
 
 #include <QThreadStorage>
@@ -27,7 +28,7 @@ using namespace std;
 namespace lyx {
 
 ///
-typedef map<string, WordList *> GlobalWordList;
+typedef map<string, unique_ptr<WordList>> GlobalWordList;
 // Each thread uses its own word list, but only the one of the GUI thread is
 // used to do real work. The others are only neded to prevent simultanous
 // write access e.g. from a cloned buffer and a true document buffer.
@@ -38,27 +39,12 @@ WordList & theWordList(string const & lang)
 {
        if (!theGlobalWordList.hasLocalData())
                theGlobalWordList.setLocalData(new GlobalWordList);
-       GlobalWordList * globalWordList = theGlobalWordList.localData();
-       GlobalWordList::iterator it = globalWordList->find(lang);
-       if (it != globalWordList->end())
+       GlobalWordList & globalWordList = *theGlobalWordList.localData();
+       GlobalWordList::iterator it = globalWordList.find(lang);
+       if (it != globalWordList.end())
                return *it->second;
-       else {
-               WordList * wl = new WordList;
-               (*globalWordList)[lang] = wl;
-               return *wl;
-       }
-}
-
-
-void WordList::cleanupWordLists()
-{
-       if (!theGlobalWordList.hasLocalData())
-               return;
-       GlobalWordList * globalWordList = theGlobalWordList.localData();
-       GlobalWordList::const_iterator it = globalWordList->begin();
-       for (; it != globalWordList->end(); ++it)
-               delete it->second;
-       globalWordList->clear();
+       else
+               return *(globalWordList[lang] = make_unique<WordList>());
 }
 
 
@@ -73,7 +59,7 @@ struct WordList::Impl {
 };
 
 
-WordList::WordList() : d(new Impl)
+WordList::WordList() : d(make_unique<Impl>())
 {
        d->c_ = 0;
 
diff --git a/src/WordList.h b/src/WordList.h
index 0c5c0a8..2afd6cb 100644
--- a/src/WordList.h
+++ b/src/WordList.h
@@ -30,8 +30,6 @@ public:
        void insert(docstring const & w);
        ///
        void remove(docstring const & w);
-       ///
-       static void cleanupWordLists();
 
 private:
        struct Impl;

commit 0eb0b8531a08a81e1b9cdde108be124edbd6dfdd
Author: Guillaume Munch <[email protected]>
Date:   Sat Dec 31 15:22:07 2016 +0100

    Convert a pointer to a reference
    
    The validity of the reference is guaranteed by QThreadLocalStorage

diff --git a/src/Paragraph.cpp b/src/Paragraph.cpp
index 6238033..ba101e4 100644
--- a/src/Paragraph.cpp
+++ b/src/Paragraph.cpp
@@ -3705,11 +3705,11 @@ void Paragraph::deregisterWords()
        Private::LangWordsMap::const_iterator itl = d->words_.begin();
        Private::LangWordsMap::const_iterator ite = d->words_.end();
        for (; itl != ite; ++itl) {
-               WordList * wl = theWordList(itl->first);
+               WordList & wl = theWordList(itl->first);
                Private::Words::const_iterator it = (itl->second).begin();
                Private::Words::const_iterator et = (itl->second).end();
                for (; it != et; ++it)
-                       wl->remove(*it);
+                       wl.remove(*it);
        }
        d->words_.clear();
 }
@@ -3785,11 +3785,11 @@ void Paragraph::registerWords()
        Private::LangWordsMap::const_iterator itl = d->words_.begin();
        Private::LangWordsMap::const_iterator ite = d->words_.end();
        for (; itl != ite; ++itl) {
-               WordList * wl = theWordList(itl->first);
+               WordList & wl = theWordList(itl->first);
                Private::Words::const_iterator it = (itl->second).begin();
                Private::Words::const_iterator et = (itl->second).end();
                for (; it != et; ++it)
-                       wl->insert(*it);
+                       wl.insert(*it);
        }
 }
 
diff --git a/src/Text.cpp b/src/Text.cpp
index deefc4b..8e0d1be 100644
--- a/src/Text.cpp
+++ b/src/Text.cpp
@@ -586,7 +586,7 @@ class TextCompletionList : public CompletionList
 {
 public:
        ///
-       TextCompletionList(Cursor const & cur, WordList const * list)
+       TextCompletionList(Cursor const & cur, WordList const & list)
                : buffer_(cur.buffer()), list_(list)
        {}
        ///
@@ -597,19 +597,19 @@ public:
        ///
        virtual size_t size() const
        {
-               return list_->size();
+               return list_.size();
        }
        ///
        virtual docstring const & data(size_t idx) const
        {
-               return list_->word(idx);
+               return list_.word(idx);
        }
 
 private:
        ///
        Buffer const * buffer_;
        ///
-       WordList const * list_;
+       WordList const & list_;
 };
 
 
@@ -2156,7 +2156,7 @@ bool Text::completionSupported(Cursor const & cur) const
 
 CompletionList const * Text::createCompletionList(Cursor const & cur) const
 {
-       WordList const * list = theWordList(cur.getFont().language()->lang());
+       WordList const & list = theWordList(cur.getFont().language()->lang());
        return new TextCompletionList(cur, list);
 }
 
diff --git a/src/WordList.cpp b/src/WordList.cpp
index d883994..8180985 100644
--- a/src/WordList.cpp
+++ b/src/WordList.cpp
@@ -34,18 +34,18 @@ typedef map<string, WordList *> GlobalWordList;
 QThreadStorage<GlobalWordList *> theGlobalWordList;
 
 
-WordList * theWordList(string const & lang)
+WordList & theWordList(string const & lang)
 {
        if (!theGlobalWordList.hasLocalData())
                theGlobalWordList.setLocalData(new GlobalWordList);
        GlobalWordList * globalWordList = theGlobalWordList.localData();
        GlobalWordList::iterator it = globalWordList->find(lang);
        if (it != globalWordList->end())
-               return it->second;
+               return *it->second;
        else {
                WordList * wl = new WordList;
                (*globalWordList)[lang] = wl;
-               return wl;
+               return *wl;
        }
 }
 
diff --git a/src/WordList.h b/src/WordList.h
index 5b0488b..0c5c0a8 100644
--- a/src/WordList.h
+++ b/src/WordList.h
@@ -38,7 +38,7 @@ private:
        std::unique_ptr<Impl> d;
 };
 
-WordList * theWordList(std::string const & lang);
+WordList & theWordList(std::string const & lang);
 
 } // namespace lyx
 

commit 832b99a3949d3efc63a7e8a95cbcb9eb994c75c1
Author: Guillaume Munch <[email protected]>
Date:   Sat Dec 31 15:16:15 2016 +0100

    Remove a redundant deletion of a QObject

diff --git a/src/frontends/qt4/GuiToc.cpp b/src/frontends/qt4/GuiToc.cpp
index 29ec85c..e124a46 100644
--- a/src/frontends/qt4/GuiToc.cpp
+++ b/src/frontends/qt4/GuiToc.cpp
@@ -33,20 +33,15 @@ namespace lyx {
 namespace frontend {
 
 GuiToc::GuiToc(GuiView & parent, Qt::DockWidgetArea area, Qt::WindowFlags 
flags)
-       : DockView(parent, "toc", qt_("Outline"), area, flags), 
is_closing_(false)
+       : DockView(parent, "toc", qt_("Outline"), area, flags),
+         widget_(new TocWidget(parent, this)),
+         is_closing_(false)
 {
-       widget_ = new TocWidget(parent, this);
        setWidget(widget_);
        setFocusProxy(widget_);
 }
 
 
-GuiToc::~GuiToc()
-{
-       delete widget_;
-}
-
-
 void GuiToc::updateView()
 {
        widget_->updateView();
diff --git a/src/frontends/qt4/GuiToc.h b/src/frontends/qt4/GuiToc.h
index 6c7db9d..d403bc9 100644
--- a/src/frontends/qt4/GuiToc.h
+++ b/src/frontends/qt4/GuiToc.h
@@ -34,8 +34,6 @@ public:
                Qt::DockWidgetArea area = Qt::LeftDockWidgetArea, ///< Position 
of the dock (and also drawer)
                Qt::WindowFlags flags = 0);
 
-       ~GuiToc();
-
        ///
        bool initialiseParams(std::string const & data);
        void updateView();

commit cde3f6b84cb965b6258cde2ab19f02a160e0d268
Author: Guillaume Munch <[email protected]>
Date:   Sat Dec 31 15:16:15 2016 +0100

    TocWidget: Remove possibly dangling BufferView pointer

diff --git a/src/frontends/qt4/TocModel.cpp b/src/frontends/qt4/TocModel.cpp
index 96711e6..e40d99c 100644
--- a/src/frontends/qt4/TocModel.cpp
+++ b/src/frontends/qt4/TocModel.cpp
@@ -248,7 +248,6 @@ int TocModel::modelDepth() const
 ///////////////////////////////////////////////////////////////////////////////
 
 TocModels::TocModels()
-       : bv_(0)
 {
        names_ = new TocTypeModel(this);
        names_sorted_ = new TocModelSortProxyModel(this);
@@ -272,7 +271,7 @@ void TocModels::clear()
 int TocModels::depth(QString const & type)
 {
        const_iterator it = models_.find(type);
-       if (!bv_ || it == models_.end())
+       if (it == models_.end())
                return 0;
        return it.value()->modelDepth();
 }
@@ -280,8 +279,6 @@ int TocModels::depth(QString const & type)
 
 QAbstractItemModel * TocModels::model(QString const & type)
 {
-       if (!bv_)
-               return 0;
        iterator it = models_.find(type);
        if (it != models_.end())
                return it.value()->model();
@@ -296,12 +293,13 @@ QAbstractItemModel * TocModels::nameModel()
 }
 
 
-QModelIndex TocModels::currentIndex(QString const & type) const
+QModelIndex TocModels::currentIndex(QString const & type,
+                                    DocIterator const & dit) const
 {
        const_iterator it = models_.find(type);
-       if (!bv_ || it == models_.end())
+       if (it == models_.end())
                return QModelIndex();
-       return it.value()->modelIndex(bv_->cursor());
+       return it.value()->modelIndex(dit);
 }
 
 
@@ -341,9 +339,8 @@ void TocModels::updateItem(QString const & type, 
DocIterator const & dit)
 
 void TocModels::reset(BufferView const * bv)
 {
-       bv_ = bv;
        clear();
-       if (!bv_) {
+       if (!bv) {
                iterator end = models_.end();
                for (iterator it = models_.begin(); it != end;  ++it)
                        it.value()->reset();
@@ -354,7 +351,7 @@ void TocModels::reset(BufferView const * bv)
        names_->blockSignals(true);
        names_->beginResetModel();
        names_->insertColumns(0, 1);
-       TocList const & tocs = 
bv_->buffer().masterBuffer()->tocBackend().tocs();
+       TocList const & tocs = bv->buffer().masterBuffer()->tocBackend().tocs();
        TocList::const_iterator it = tocs.begin();
        TocList::const_iterator toc_end = tocs.end();
        for (; it != toc_end; ++it) {
diff --git a/src/frontends/qt4/TocModel.h b/src/frontends/qt4/TocModel.h
index f7d54e8..0c3c6b0 100644
--- a/src/frontends/qt4/TocModel.h
+++ b/src/frontends/qt4/TocModel.h
@@ -121,7 +121,8 @@ public:
        ///
        QAbstractItemModel * nameModel();
        ///
-       QModelIndex currentIndex(QString const & type) const;
+       QModelIndex currentIndex(QString const & type,
+                                DocIterator const & dit) const;
        ///
        void goTo(QString const & type, QModelIndex const & index) const;
        ///
@@ -142,8 +143,6 @@ private:
        ///
        void clear();
        ///
-       BufferView const * bv_;
-       ///
        QHash<QString, TocModel *> models_;
        ///
        TocTypeModel * names_;
diff --git a/src/frontends/qt4/TocWidget.cpp b/src/frontends/qt4/TocWidget.cpp
index 8bf753a..b96a7c6 100644
--- a/src/frontends/qt4/TocWidget.cpp
+++ b/src/frontends/qt4/TocWidget.cpp
@@ -456,7 +456,11 @@ void TocWidget::finishUpdateView()
                if (!persistent_)
                        setTreeDepth(depth_);
                persistentCB->setChecked(persistent_);
-               select(gui_view_.tocModels().currentIndex(current_type_));
+               // select the item at current cursor location
+               if (gui_view_.documentBufferView()) {
+                       DocIterator const & dit = 
gui_view_.documentBufferView()->cursor();
+                       
select(gui_view_.tocModels().currentIndex(current_type_, dit));
+               }
        }
        filterContents();
 }

commit 3d6a7a1200a5efdeafda80bde80fa67427fa1a07
Author: Guillaume Munch <[email protected]>
Date:   Sat Dec 31 15:16:15 2016 +0100

    Fix dangling inset pointers after buffer reload
    
    https://www.mail-archive.com/[email protected]/msg198191.html
    
    The root of the issue is in Buffer::reload() called during "Save As".  After
    loadLyXFile() there, all the insets have been deleted, and therefore the 
Inset
    pointer GuiView::documentBufferView()->cursor().inset() is dangling. 
Immediately
    after loadLyXFile(), reload() calls updateBuffer() which causes a segfault.
    
    While debugging I got other segfaults caused by the same dangling Inset 
pointer
    in Cursor, notably: 1) a trace identical to the second one from
    <http://www.lyx.org/trac/ticket/10520>, and 2) a similar segfault in the
    critical path after emergency saving (call to inMathed()).
    
    Having to "refresh" by hand the inset pointer cache in CursorSlice is very
    unsatisfactory, but there does not appears to be a consistent strategy for
    managing these Inset pointers in CursorSlice.

diff --git a/src/frontends/qt4/GuiView.cpp b/src/frontends/qt4/GuiView.cpp
index 90b43eb..2c48124 100644
--- a/src/frontends/qt4/GuiView.cpp
+++ b/src/frontends/qt4/GuiView.cpp
@@ -1652,6 +1652,10 @@ void GuiView::updateTocItem(string const & type, 
DocIterator const & dit)
 
 void GuiView::structureChanged()
 {
+       // This is called from the Buffer, which has no way to ensure that 
cursors
+       // in BufferView remain valid.
+       if (documentBufferView())
+               documentBufferView()->cursor().sanitize();
        // FIXME: This is slightly expensive, though less than the tocBackend 
update
        // (#9880). This also resets the view in the Toc Widget (#6675).
        d.toc_models_.reset(documentBufferView());

commit 550567d8f2a8a4444e9f4893cf3ed325a429e798
Author: Guillaume Munch <[email protected]>
Date:   Sat Dec 31 15:01:12 2016 +0100

    Remove outdated comment
    
    UpdateToolbars is no longer slow

diff --git a/src/frontends/qt4/TocWidget.cpp b/src/frontends/qt4/TocWidget.cpp
index 1f172a1..8bf753a 100644
--- a/src/frontends/qt4/TocWidget.cpp
+++ b/src/frontends/qt4/TocWidget.cpp
@@ -450,10 +450,8 @@ void TocWidget::updateViewNow()
 void TocWidget::finishUpdateView()
 {
        // Profiling shows that this is the expensive stuff in the context of 
typing
-       // text and moving with arrows (still five times less than 
updateToolbars in
-       // my tests with a medium-sized document, however this grows linearly 
in the
-       // size of the document). For bigger operations, this is negligible, and
-       // outweighted by TocModels::reset() anyway.
+       // text and moving with arrows. For bigger operations, this is 
negligible,
+       // and outweighted by TocModels::reset() anyway.
        if (canNavigate()) {
                if (!persistent_)
                        setTreeDepth(depth_);

-----------------------------------------------------------------------

Summary of changes:
 src/LyX.cpp                     |    1 -
 src/Paragraph.cpp               |    8 ++++----
 src/Text.cpp                    |   10 +++++-----
 src/WordList.cpp                |   34 ++++++++++------------------------
 src/WordList.h                  |    4 +---
 src/frontends/qt4/GuiToc.cpp    |   11 +++--------
 src/frontends/qt4/GuiToc.h      |    2 --
 src/frontends/qt4/GuiView.cpp   |    4 ++++
 src/frontends/qt4/TocModel.cpp  |   17 +++++++----------
 src/frontends/qt4/TocModel.h    |    5 ++---
 src/frontends/qt4/TocWidget.cpp |   12 +++++++-----
 11 files changed, 43 insertions(+), 65 deletions(-)


hooks/post-receive
-- 
Repository for new features

Reply via email to