Check the attached. It's more or less an inverse of what you had before.
In place of updateParams(), we have updateBibFiles(). There are still
some rough edges, though. But this will work, I think, without
undermining the InsetCommand structures.
Your patch is huge and many of them seem unnecessary.
It's less huge that it seems. Some of it---e.g., the stuff in
GuiBibtex---has to be done anyway, and I'm in the process of committing
all of that. The rest we can work out.
By the way, there seem to be some larger docstring vs string issues here
that need sorting out.
If you agree
that params can not be separated from EmbeddedFileList, why cannot we
start from my simple meta_ patch? Your Data structure makes the
problem worse by adding yet another representation of the same data.
The way I see it, the point is that we are continuing to use the same
interface as before. That's what I meant, I think, about how the
parameters are being represented. It doesn't matter what the underlying
representation is. What matters is how we access it. So, to me, it
matters that we should do this:
setParams(p);
because, well, that's how you set params. And then I can do this:
InsetBibtex::setParams(p)
{
InsetCommand::setParams(p);
updateBibFiles();
}
at which point updateBibFiles() is called transparently. (Compare
InsetInclude.) But there would still be more to do to handle the other
cases, and there are really too many ways to set parameters now; that
needs fixing independently. In the end, as I said, what really needs to
happen is probably:
class InsetBibtexParams : public InsetCommandParams; ...
at which point the Data structure gets hidden inside there. I don't
intend to do that now. But the patch I've proposed makes this possible,
because, as I said, it uses the exiting interface to the parameters.
What's attached is what's left, but not quite in final form, as there
are some other simplifications that can be made.
Richard
Index: src/insets/InsetBibtex.h
===================================================================
--- src/insets/InsetBibtex.h (revision 24043)
+++ src/insets/InsetBibtex.h (working copy)
@@ -16,11 +16,13 @@
#include "EmbeddedFiles.h"
#include "InsetCommand.h"
-#include <map>
+#include "support/docstring.h"
+#include "support/FileName.h"
+#include <vector>
+
namespace lyx {
-
/** Used to insert BibTeX's information
*/
class InsetBibtex : public InsetCommand {
@@ -56,15 +58,31 @@
///
static bool isCompatibleCommand(std::string const & s)
{ return s == "bibtex"; }
- /// update bibfiles and embed from bibfiles_
- void updateParam();
/// look up the path to the file using TeX
static support::FileName
getBibTeXPath(docstring const & filename, Buffer const & buf);
private:
- ///
- void createBibFiles() const;
+ /// This method updates bibfiles_ from the parameter information and
+ /// MUST be called whenever the parameters may have been changed, in
+ /// particular, whenever a .bib file may have been added or deleted,
+ /// or the embedding information may have changed.
+ void updateBibFiles() const;
///
+ struct Data {
+ docstring bibfile;
+ docstring embfile;
+ Data(docstring const & b, docstring const & e)
+ : bibfile(b), embfile(e) {}
+ };
+ ///
+ typedef std::vector<Data> ParamData;
+ typedef ParamData::const_iterator ParamDataCit;
+ typedef ParamData::iterator ParamDataIt;
+ ///
+ ParamData makeParamStruct() const;
+ ///
+ void writeParamStruct(ParamData const & data);
+ ///
void registerEmbeddedFiles(EmbeddedFileList &) const;
///
void updateEmbeddedFile(EmbeddedFile const & file);
Index: src/insets/InsetBibtex.cpp
===================================================================
--- src/insets/InsetBibtex.cpp (revision 24043)
+++ src/insets/InsetBibtex.cpp (working copy)
@@ -48,7 +48,7 @@
InsetBibtex::InsetBibtex(InsetCommandParams const & p)
- : InsetCommand(p, "bibtex"), bibfiles_()
+ : InsetCommand(p, "bibtex")
{}
@@ -105,10 +105,9 @@
throw message;
break;
}
- //
- createBibFiles();
- updateParam();
- setParam("options", p["options"]);
+
+ setParams(p);
+ updateBibFiles();
buffer().updateBibfilesCache();
break;
}
@@ -163,15 +162,21 @@
// use such filenames.)
// Otherwise, store the (maybe absolute) path to the original,
// unmangled database name.
- EmbeddedFileList::const_iterator it = bibfiles_.begin();
- EmbeddedFileList::const_iterator it_end = bibfiles_.end();
+
+ ParamData data = makeParamStruct();
+ ParamDataCit it = data.begin();
+ ParamDataCit en = data.end();
odocstringstream dbs;
- for (; it != it_end; ++it) {
- string utf8input = removeExtension(it->availableFile().absFilename());
+ for (; it != en; ++it) {
+ bool embedded =
+ !runparams.dryrun && buffer().embedded() && !it->embfile.empty();
+ docstring const input =
+ trim(embedded ? it->embfile : it->bibfile);
+ // FIXME UNICODE
+ string utf8input(to_utf8(input));
string database =
normalizeName(buffer(), runparams, utf8input, ".bib");
- FileName const try_in_file =
- makeAbsPath(database + ".bib", buffer().filePath());
+ FileName const try_in_file(makeAbsPath(database + ".bib", buffer().filePath()));
bool const not_from_texmf = try_in_file.isReadableFile();
if (!runparams.inComment && !runparams.dryrun && !runparams.nice &&
@@ -197,9 +202,11 @@
from_utf8(database));
}
- if (it != bibfiles_.begin())
+ if (it != data.begin())
dbs << ',';
// FIXME UNICODE
+ // FIXME This is wrong for exporting when the file is embedded. But
+ // the solution is not obvious at this point.
dbs << from_utf8(latex_path(database));
}
docstring const db_out = dbs.str();
@@ -571,12 +578,12 @@
// We don't restrict keys to ASCII in LyX, since our own
// InsetBibitem can generate non-ASCII keys, and nonstandard
// 8bit clean bibtex forks exist.
- EmbeddedFileList const & files = getBibFiles();
+ EmbeddedFileList const files = getBibFiles();
EmbeddedFileList::const_iterator it = files.begin();
EmbeddedFileList::const_iterator en = files.end();
for (; it != en; ++ it) {
idocfstream ifs(it->availableFile().toFilesystemEncoding().c_str(),
- ios_base::in, buffer().params().encoding().iconvName());
+ std::ios_base::in, buffer().params().encoding().iconvName());
char_type ch;
VarMap strings;
@@ -716,34 +723,95 @@
return file;
}
+InsetBibtex::ParamData InsetBibtex::makeParamStruct() const
+{
+ docstring bibfiles = getParam("bibfiles");
+ docstring embfiles = getParam("embed");
+ docstring bibfile;
+ docstring embfile;
+ ParamData retval;
+ char_type comma(',');
+ bibfiles = split(bibfiles, bibfile, comma);
+ embfiles = split(embfiles, embfile, comma);
+ while (!bibfile.empty()) {
+ retval.push_back(Data(bibfile, embfile));
+ bibfiles = split(bibfiles, bibfile, comma);
+ embfiles = split(embfiles, embfile, comma);
+ }
+ return retval;
+}
+
+
+void InsetBibtex::writeParamStruct(InsetBibtex::ParamData const & data)
+{
+ docstring newbibfiles;
+ docstring newembfiles;
+ bool first = true;
+ char_type comma(',');
+
+ ParamDataCit it = data.begin();
+ ParamDataCit en = data.end();
+ for (; it != en; ++it) {
+ if (!first) {
+ newbibfiles = newbibfiles + comma;
+ newembfiles = newembfiles + comma;
+ } else
+ first = false;
+ newbibfiles = newbibfiles + it->bibfile;
+ newembfiles = newembfiles + it->embfile;
+ }
+ setParam("bibfiles", newbibfiles);
+ setParam("embed", newembfiles);
+}
+
+
bool InsetBibtex::addDatabase(docstring const & db)
{
+ // look for the item and update status
+ ParamData data = makeParamStruct();
+
+ ParamDataCit it = data.begin();
+ ParamDataCit en = data.end();
+ for (; it != en; ++it)
+ if (db == it->bibfile)
+ return false;
+
FileName const texPath = getBibTeXPath(db, buffer());
- EmbeddedFileList::const_iterator efp =
- bibfiles_.findFile(texPath.absFilename());
- if (efp != bibfiles_.end())
- //already have it
- return false;
+ string const inzipName =
+ EmbeddedFile::calcInzipName(texPath.absFilename(), buffer().filePath());
+ data.push_back(Data(db, from_utf8(inzipName)));
- EmbeddedFile file(texPath.absFilename(), buffer().filePath());
- bibfiles_.push_back(file);
- updateParam();
+ writeParamStruct(data);
+ updateBibFiles();
+ buffer().updateBibfilesCache();
return true;
}
bool InsetBibtex::delDatabase(docstring const & db)
{
- FileName const texPath = getBibTeXPath(db, buffer());
- EmbeddedFileList::iterator efp =
- bibfiles_.findFile(texPath.absFilename());
- if (efp == bibfiles_.end())
- // don't have it
+ // look for the item and update status
+ ParamData data = makeParamStruct();
+
+ bool found = false;
+
+ ParamDataIt it = data.begin();
+ ParamDataIt en = data.end();
+ for (; it != en; ++it) {
+ if (db == it->bibfile) {
+ data.erase(it);
+ found = true;
+ break;
+ }
+ }
+
+ if (!found)
return false;
-
- bibfiles_.erase(efp);
- updateParam();
+
+ writeParamStruct(data);
+ updateBibFiles();
+ buffer().updateBibfilesCache();
return true;
}
@@ -755,29 +823,23 @@
}
-void InsetBibtex::createBibFiles() const
+void InsetBibtex::updateBibFiles() const
{
// need to do this to keep old info while also not
// copying over any files that have been deleted.
EmbeddedFileList oldlist = bibfiles_;
bibfiles_.clear();
-
- docstring bibfile;
- docstring embfile;
-
- docstring bibfiles = getParam("bibfiles");
- docstring embfiles = getParam("embed");
-
- bibfiles = split(bibfiles, bibfile, ',');
- embfiles = split(embfiles, embfile, ',');
-
- while (!bibfile.empty()) {
- FileName bib = getBibTeXPath(bibfile, buffer());
+
+ ParamData data = makeParamStruct();
+ ParamDataIt it = data.begin();
+ ParamDataIt en = data.end();
+ for (; it != en; ++it) {
+ FileName bib = getBibTeXPath(it->bibfile, buffer());
EmbeddedFileList::iterator efp = oldlist.findFile(bib.absFilename());
if (efp != oldlist.end()) {
// already have this one
- efp->setInzipName(to_utf8(embfile));
- efp->setEmbed(!embfile.empty());
+ efp->setInzipName(to_utf8(it->embfile));
+ efp->setEmbed(!it->embfile.empty());
try {
efp->enable(buffer().embedded(), &buffer(), false);
} catch (ExceptionMessage const & message) {
@@ -788,8 +850,8 @@
bibfiles_.push_back(*efp);
} else {
EmbeddedFile file(bib.absFilename(), buffer().filePath());
- file.setInzipName(to_utf8(embfile));
- file.setEmbed(!embfile.empty());
+ file.setInzipName(to_utf8(it->embfile));
+ file.setEmbed(!it->embfile.empty());
try {
file.enable(buffer().embedded(), &buffer(), true);
} catch (ExceptionMessage const & message) {
@@ -799,42 +861,12 @@
}
bibfiles_.push_back(file);
}
- // Get next file name
- bibfiles = split(bibfiles, bibfile, ',');
- embfiles = split(embfiles, embfile, ',');
}
}
-void InsetBibtex::updateParam()
-{
- docstring bibfiles;
- docstring embed;
-
- bool first = true;
-
- EmbeddedFileList::iterator it = bibfiles_.begin();
- EmbeddedFileList::iterator en = bibfiles_.end();
- for (; it != en; ++it) {
- if (!first) {
- bibfiles += ',';
- embed += ',';
- } else
- first = false;
- bibfiles += from_utf8(it->outputFilename(buffer().filePath()));
- if (it->embedded())
- embed += from_utf8(it->inzipName());
- }
- setParam("bibfiles", bibfiles);
- setParam("embed", embed);
-}
-
-
void InsetBibtex::registerEmbeddedFiles(EmbeddedFileList & files) const
{
- if (bibfiles_.empty())
- createBibFiles();
-
EmbeddedFileList::const_iterator it = bibfiles_.begin();
EmbeddedFileList::const_iterator en = bibfiles_.end();
for (; it != en; ++it)
@@ -850,7 +882,32 @@
if (it == bibfiles_.end())
return;
*it = file;
- updateParam();
+
+ bool first = true;
+ bool found = false;
+ docstring newembfiles;
+ char_type comma(',');
+
+ // now we need to update the relevant parameter
+ ParamData data = makeParamStruct();
+ ParamDataCit it = data.begin();
+ ParamDataCit en = data.end();
+ for (; it != en; ++it) {
+ if (!first)
+ newembfiles = newembfiles + comma;
+ else
+ first = false;
+ string pathToBib(getBibTeXPath(it->bibfile, buffer()).absFilename());
+ if (!found && pathToBib == filename) {
+ //found it, we'll suppose
+ newembfiles = newembfiles + from_utf8(file.inzipName());
+ found = true;
+ } else // just copy the old value
+ newembfiles = newembfiles + it->embfile;
+ }
+
+ BOOST_ASSERT(found); // otherwise there's some nasty inconsistency
+ setParam("embed", newembfiles);
}