From 6dc7cbe1e7b56b007700346731655b8e4175e3c1 Mon Sep 17 00:00:00 2001 From: Bo Peng Date: Sun, 9 Mar 2008 06:05:22 +0000 Subject: [PATCH] Continue working on the embedding feature. An additional parameter updateFile is passed to EmbeddedFile::enable() and EmbeddedFiles::enable() to differentiate different usages. A member variable bibfiles_ is added to InsetBibtex because it is not efficient to obtain EmbeddedFileList each time from params()['bibfiles'] and params()['embed']. git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@23576 a592a061-630c-0410-9148-cb99ea01b6c8 --- src/Buffer.cpp | 4 + src/BufferView.cpp | 2 +- src/EmbeddedFiles.cpp | 36 +++-- src/EmbeddedFiles.h | 7 +- src/insets/Inset.h | 3 +- src/insets/InsetBibtex.cpp | 210 +++++++++++++---------------- src/insets/InsetBibtex.h | 17 ++- src/insets/InsetExternal.cpp | 10 +- src/insets/InsetGraphics.cpp | 16 +-- src/insets/InsetGraphicsParams.cpp | 5 - src/insets/InsetInclude.cpp | 5 +- 11 files changed, 149 insertions(+), 166 deletions(-) diff --git a/src/Buffer.cpp b/src/Buffer.cpp index a2b4d0fccb..22f5d97c46 100644 --- a/src/Buffer.cpp +++ b/src/Buffer.cpp @@ -571,6 +571,10 @@ bool Buffer::readDocument(Lexer & lex) // read main text bool const res = text().read(*this, lex, errorList, &(d->inset)); + // Enable embeded files, which will set temp path and move + // inconsistent inzip files if needed. + embeddedFiles().enable(params().embedded, *this, false); + updateMacros(); updateMacroInstances(); return res; diff --git a/src/BufferView.cpp b/src/BufferView.cpp index b13d4cebd1..eca22404b2 100644 --- a/src/BufferView.cpp +++ b/src/BufferView.cpp @@ -1249,7 +1249,7 @@ bool BufferView::dispatch(FuncRequest const & cmd) case LFUN_BUFFER_TOGGLE_EMBEDDING: { // turn embedding on/off try { - buffer_.embeddedFiles().enable(!buffer_.params().embedded, buffer_); + buffer_.embeddedFiles().enable(!buffer_.params().embedded, buffer_, true); } catch (ExceptionMessage const & message) { Alert::error(message.title_, message.details_); } diff --git a/src/EmbeddedFiles.cpp b/src/EmbeddedFiles.cpp index 9d6edc3411..f87494c821 100644 --- a/src/EmbeddedFiles.cpp +++ b/src/EmbeddedFiles.cpp @@ -110,10 +110,18 @@ void EmbeddedFile::setEmbed(bool embed) } -void EmbeddedFile::enable(bool flag, Buffer const * buf) +void EmbeddedFile::enable(bool flag, Buffer const * buf, bool updateFile) { - if (enabled() == flag) - return; + // This function will be called when + // 1. through EmbeddedFiles::enable() when a file is read. Files + // should be in place so no updateFromExternalFile or extract() + // should be called. (updateFile should be false in this case). + // 2. through menu item enable/disable. updateFile should be true. + // 3. A single embedded file is added or modified. updateFile + // can be true or false. + LYXERR(Debug::FILES, (flag ? "Enable" : "Disable") + << " " << absFilename() + << (updateFile ? " (update file)." : " (no update).")); if (flag) { temp_path_ = buf->temppath(); @@ -122,11 +130,12 @@ void EmbeddedFile::enable(bool flag, Buffer const * buf) if (embedded()) { if (inzip_name_ != calcInzipName(buf->filePath())) syncInzipFile(buf->filePath()); - updateFromExternalFile(); - } else - extract(); + if (updateFile) + updateFromExternalFile(); + } } else { - extract(); + if (embedded() && updateFile) + extract(); temp_path_ = ""; } } @@ -370,11 +379,8 @@ bool operator!=(EmbeddedFile const & lhs, EmbeddedFile const & rhs) } -void EmbeddedFileList::enable(bool flag, Buffer & buffer) +void EmbeddedFileList::enable(bool flag, Buffer & buffer, bool updateFile) { - if (buffer.embedded() == flag) - return; - // update embedded file list update(buffer); @@ -384,7 +390,7 @@ void EmbeddedFileList::enable(bool flag, Buffer & buffer) std::vector::iterator it_end = end(); // an exception may be thrown for (; it != it_end; ++it) { - it->enable(flag, &buffer); + it->enable(flag, &buffer, updateFile); if (it->embedded()) ++count_embedded; else @@ -397,7 +403,10 @@ void EmbeddedFileList::enable(bool flag, Buffer & buffer) // if the operation is successful, update insets for (it = begin(); it != it_end; ++it) it->updateInsets(); - + + if (!updateFile) + return; + // show result if (flag) { docstring const msg = bformat(_("%1$d external files are ignored.\n" @@ -414,7 +423,6 @@ void EmbeddedFileList::enable(bool flag, Buffer & buffer) void EmbeddedFileList::registerFile(EmbeddedFile const & file, Inset const * inset, Buffer const & buffer) { - BOOST_ASSERT(!buffer.embedded() || file.availableFile().exists()); BOOST_ASSERT(!buffer.embedded() || file.enabled()); // try to find this file from the list diff --git a/src/EmbeddedFiles.h b/src/EmbeddedFiles.h index 0a6e3894b8..42b02f39c7 100644 --- a/src/EmbeddedFiles.h +++ b/src/EmbeddedFiles.h @@ -141,14 +141,13 @@ public: /// embedding status of this file bool embedded() const { return embedded_; } - /// set embedding status. updateFromExternal() should be called before this - /// to copy or sync the embedded file with external one. + /// set embedding status. void setEmbed(bool embed); /// whether or not embedding is enabled in the current buffer bool enabled() const { return temp_path_ != ""; } /// enable embedding of this file - void enable(bool flag, Buffer const * buf); + void enable(bool flag, Buffer const * buf, bool updateFile); /// extract file, does not change embedding status bool extract() const; @@ -198,7 +197,7 @@ class EmbeddedFileList : public std::vector { public: /// set buffer params embedded flag. Files will be updated or extracted /// if such an operation fails, enable will fail. - void enable(bool flag, Buffer & buffer); + void enable(bool flag, Buffer & buffer, bool updateFile); /// add a file item. /* \param file Embedded file to add diff --git a/src/insets/Inset.h b/src/insets/Inset.h index a49feb1af5..1f3e911497 100644 --- a/src/insets/Inset.h +++ b/src/insets/Inset.h @@ -431,7 +431,8 @@ public: virtual void addToToc(ParConstIterator const &) const {} /// report files that can be embedded with the lyx file virtual void registerEmbeddedFiles(EmbeddedFileList &) const {} - /// use embedded or external file after the embedding status of a file is changed + /// update the properties of an embedded file of an inset + /// the name of the embedded file should not change. virtual void updateEmbeddedFile(EmbeddedFile const &) {} /// Fill keys with BibTeX information virtual void fillWithBibKeys(BiblioInfo &, InsetIterator const &) const {} diff --git a/src/insets/InsetBibtex.cpp b/src/insets/InsetBibtex.cpp index 81bdd33649..5313b1d477 100644 --- a/src/insets/InsetBibtex.cpp +++ b/src/insets/InsetBibtex.cpp @@ -48,7 +48,7 @@ namespace os = support::os; InsetBibtex::InsetBibtex(InsetCommandParams const & p) - : InsetCommand(p, "bibtex") + : InsetCommand(p, "bibtex"), bibfiles_() {} @@ -87,41 +87,10 @@ void InsetBibtex::doDispatch(Cursor & cur, FuncRequest & cmd) } // InsetCommandParams orig = params(); - // returned "embed" is composed of "true" or "false", which needs to be adjusted - string tmp; - string emb; - - string newBibfiles; - string newEmbedStatus; - - string bibfiles = to_utf8(p["bibfiles"]); - string embedStatus = to_utf8(p["embed"]); - - bibfiles = split(bibfiles, tmp, ','); - embedStatus = split(embedStatus, emb, ','); - while (!tmp.empty()) { - EmbeddedFile file(changeExtension(tmp, "bib"), buffer().filePath()); - if (!newBibfiles.empty()) - newBibfiles += ","; - newBibfiles += tmp; - if (!newEmbedStatus.empty()) - newEmbedStatus += ","; - if (emb == "true") - newEmbedStatus += file.inzipName(); - // Get next file name - bibfiles = split(bibfiles, tmp, ','); - embedStatus = split(embedStatus, emb, ','); - } - LYXERR(Debug::FILES, "Update parameters from " << p["bibfiles"] - << " " << p["embed"] << " to " << newBibfiles << " " - << newEmbedStatus); - p["bibfiles"] = from_utf8(newBibfiles); - p["embed"] = from_utf8(newEmbedStatus); - - setParams(p); try { - // test parameter and copy files - embeddedFiles(); + // returned "embed" is composed of "true" or "false", which needs to be adjusted + createBibFiles(p["bibfiles"], p["embed"], true, true); + updateParam(); } catch (ExceptionMessage const & message) { Alert::error(message.title_, message.details_); // do not set parameter if an error happens @@ -182,9 +151,8 @@ int InsetBibtex::latex(odocstream & os, OutputParams const & runparams) const // use such filenames.) // Otherwise, store the (maybe absolute) path to the original, // unmangled database name. - EmbeddedFileList const bibs = embeddedFiles(); - EmbeddedFileList::const_iterator it = bibs.begin(); - EmbeddedFileList::const_iterator it_end = bibs.end(); + EmbeddedFileList::const_iterator it = bibfiles_.begin(); + EmbeddedFileList::const_iterator it_end = bibfiles_.end(); odocstringstream dbs; for (; it != it_end; ++it) { string utf8input = removeExtension(it->availableFile().absFilename()); @@ -217,7 +185,7 @@ int InsetBibtex::latex(odocstream & os, OutputParams const & runparams) const from_utf8(database)); } - if (it != bibs.begin()) + if (it != bibfiles_.begin()) dbs << ','; // FIXME UNICODE dbs << from_utf8(latex_path(database)); @@ -328,44 +296,7 @@ int InsetBibtex::latex(odocstream & os, OutputParams const & runparams) const EmbeddedFileList InsetBibtex::embeddedFiles() const { - FileName path(buffer().filePath()); - PathChanger p(path); - - EmbeddedFileList vec; - - string tmp; - string emb; - // FIXME UNICODE - string bibfiles = to_utf8(getParam("bibfiles")); - string embedStatus = to_utf8(getParam("embed")); - bibfiles = split(bibfiles, tmp, ','); - embedStatus = split(embedStatus, emb, ','); - while (!tmp.empty()) { - if (!emb.empty()) { - EmbeddedFile file(changeExtension(tmp, "bib"), buffer().filePath()); - // If the file structure is correct, this should not fail. - file.setEmbed(true); - file.enable(buffer().embedded(), &buffer()); - vec.push_back(file); - } else { - // this includes the cases when the embed parameter is empty - FileName const file = findtexfile(changeExtension(tmp, "bib"), "bib"); - - // If we didn't find a matching file name just fail silently - if (!file.empty()) { - EmbeddedFile efile = EmbeddedFile(file.absFilename(), buffer().filePath()); - efile.setEmbed(false); - efile.enable(buffer().embedded(), &buffer()); - vec.push_back(efile); - } - } - - // Get next file name - bibfiles = split(bibfiles, tmp, ','); - embedStatus = split(embedStatus, emb, ','); - } - - return vec; + return bibfiles_; } namespace { @@ -765,36 +696,35 @@ void InsetBibtex::fillWithBibKeys(BiblioInfo & keylist, bool InsetBibtex::addDatabase(string const & db) { - // FIXME UNICODE - string bibfiles(to_utf8(getParam("bibfiles"))); - if (tokenPos(bibfiles, ',', db) == -1) { - if (!bibfiles.empty()) - bibfiles += ','; - setParam("bibfiles", from_utf8(bibfiles + db)); - return true; - } - return false; + EmbeddedFile file(changeExtension(db, "bib"), buffer().filePath()); + + // only compare filename + EmbeddedFileList::iterator it = bibfiles_.begin(); + EmbeddedFileList::iterator it_end = bibfiles_.end(); + for (; it != it_end; ++it) + if (it->absFilename() == file.absFilename()) + return false; + + bibfiles_.push_back(file); + updateParam(); + return true; } bool InsetBibtex::delDatabase(string const & db) { - // FIXME UNICODE - string bibfiles(to_utf8(getParam("bibfiles"))); - if (contains(bibfiles, db)) { - int const n = tokenPos(bibfiles, ',', db); - string bd = db; - if (n > 0) { - // this is not the first database - string tmp = ',' + bd; - setParam("bibfiles", from_utf8(subst(bibfiles, tmp, string()))); - } else if (n == 0) - // this is the first (or only) database - setParam("bibfiles", from_utf8(split(bibfiles, bd, ','))); - else - return false; - } - return true; + EmbeddedFile file(changeExtension(db, "bib"), buffer().filePath()); + + // only compare filename + EmbeddedFileList::iterator it = bibfiles_.begin(); + EmbeddedFileList::iterator it_end = bibfiles_.end(); + for (; it != it_end; ++it) + if (it->absFilename() == file.absFilename()) { + bibfiles_.erase(it); + updateParam(); + return true; + } + return false; } @@ -805,35 +735,55 @@ void InsetBibtex::validate(LaTeXFeatures & features) const } -void InsetBibtex::registerEmbeddedFiles(EmbeddedFileList & files) const +void InsetBibtex::createBibFiles(docstring const & bibParam, + docstring const & embedParam, bool boolStatus, bool updateFile) const { - EmbeddedFileList const dbs = embeddedFiles(); - for (vector::const_iterator it = dbs.begin(); - it != dbs.end(); ++it) - files.registerFile(*it, this, buffer()); + bibfiles_.clear(); + + string tmp; + string emb; + + string bibfiles = to_utf8(bibParam); + string embedStatus = to_utf8(embedParam); + + LYXERR(Debug::FILES, "Create bib files from parameters " + << bibfiles << " and " << embedStatus); + + bibfiles = split(bibfiles, tmp, ','); + embedStatus = split(embedStatus, emb, ','); + + while (!tmp.empty()) { + EmbeddedFile file(changeExtension(tmp, "bib"), buffer().filePath()); + + if (boolStatus) { + BOOST_ASSERT(emb == "true" || emb == "false"); + file.setEmbed(emb == "true"); + } else { + file.setInzipName(emb); + file.setEmbed(emb != ""); + } + file.enable(buffer().embedded(), &buffer(), updateFile); + bibfiles_.push_back(file); + // Get next file name + bibfiles = split(bibfiles, tmp, ','); + embedStatus = split(embedStatus, emb, ','); + } } -void InsetBibtex::updateEmbeddedFile(EmbeddedFile const & file) +void InsetBibtex::updateParam() { - // look for the item and update status docstring bibfiles; docstring embed; bool first = true; - EmbeddedFileList dbs = embeddedFiles(); - for (EmbeddedFileList::iterator it = dbs.begin(); - it != dbs.end(); ++it) { - // update from file - if (it->absFilename() == file.absFilename()) - it->setEmbed(file.embedded()); - // write parameter string + for (EmbeddedFileList::iterator it = bibfiles_.begin(); + it != bibfiles_.end(); ++it) { if (!first) { bibfiles += ','; embed += ','; - } else { + } else first = false; - } bibfiles += from_utf8(it->outputFilename(buffer().filePath())); if (it->embedded()) embed += from_utf8(it->inzipName()); @@ -843,4 +793,28 @@ void InsetBibtex::updateEmbeddedFile(EmbeddedFile const & file) } +void InsetBibtex::registerEmbeddedFiles(EmbeddedFileList & files) const +{ + if (bibfiles_.empty()) + createBibFiles(params()["bibfiles"], params()["embed"], false, false); + + EmbeddedFileList::const_iterator it = bibfiles_.begin(); + EmbeddedFileList::const_iterator it_end = bibfiles_.end(); + for (; it != it_end; ++it) + files.registerFile(*it, this, buffer()); +} + + +void InsetBibtex::updateEmbeddedFile(EmbeddedFile const & file) +{ + // look for the item and update status + for (EmbeddedFileList::iterator it = bibfiles_.begin(); + it != bibfiles_.end(); ++it) + if (it->absFilename() == file.absFilename()) + *it = file; + + updateParam(); +} + + } // namespace lyx diff --git a/src/insets/InsetBibtex.h b/src/insets/InsetBibtex.h index 144138e00a..ca15e131ec 100644 --- a/src/insets/InsetBibtex.h +++ b/src/insets/InsetBibtex.h @@ -15,11 +15,10 @@ #include #include "InsetCommand.h" #include "BiblioInfo.h" +#include "EmbeddedFiles.h" namespace lyx { -class EmbeddedFileList; - /** Used to insert BibTeX's information */ @@ -54,11 +53,25 @@ public: /// static bool isCompatibleCommand(std::string const & s) { return s == "bibtex"; } + /// create bibfiles_ from params bibfiles and embed + /** + \param bibfiles comma separated bib files + \param embed comma separated embed status + \param boolStatus if true, embed has values true/false, which + needs to be converted to inzip names. + \param updateFile whether or not try to update file. + */ + void createBibFiles(docstring const & bibfiles, docstring const & embed, + bool boolStatus, bool updateFile) const; + /// update bibfiles and embed from bibfiles_ + void updateParam(); private: /// void registerEmbeddedFiles(EmbeddedFileList &) const; /// void updateEmbeddedFile(EmbeddedFile const & file); + /// embedded bib files + mutable EmbeddedFileList bibfiles_; /// void doDispatch(Cursor & cur, FuncRequest & cmd); /// diff --git a/src/insets/InsetExternal.cpp b/src/insets/InsetExternal.cpp index 5237cc9aa0..d9d210107e 100644 --- a/src/insets/InsetExternal.cpp +++ b/src/insets/InsetExternal.cpp @@ -446,7 +446,7 @@ void InsetExternal::doDispatch(Cursor & cur, FuncRequest & cmd) InsetExternalMailer::string2params(to_utf8(cmd.argument()), buffer(), p); if (!p.filename.empty()) { try { - p.filename.enable(buffer().embedded(), &buffer()); + p.filename.enable(buffer().embedded(), &buffer(), true); } catch (ExceptionMessage const & message) { Alert::error(message.title_, message.details_); // do not set parameter if an error happens @@ -497,11 +497,7 @@ void InsetExternal::registerEmbeddedFiles(EmbeddedFileList & files) const void InsetExternal::updateEmbeddedFile(EmbeddedFile const & file) { - // when embedding is enabled, change of embedding status leads to actions - EmbeddedFile temp = file; - temp.enable(buffer().embedded(), &buffer()); - // this will not be set if an exception is thorwn in enable() - params_.filename = temp; + params_.filename = file; } @@ -728,7 +724,7 @@ void InsetExternal::read(Lexer & lex) InsetExternalParams params; if (params.read(buffer(), lex)) { // exception handling is not needed as long as embedded files are in place. - params.filename.enable(buffer().embedded(), &buffer()); + params.filename.enable(buffer().embedded(), &buffer(), false); setParams(params); } } diff --git a/src/insets/InsetGraphics.cpp b/src/insets/InsetGraphics.cpp index 8e592b8e3b..4fc28beb86 100644 --- a/src/insets/InsetGraphics.cpp +++ b/src/insets/InsetGraphics.cpp @@ -168,7 +168,7 @@ void InsetGraphics::doDispatch(Cursor & cur, FuncRequest & cmd) InsetGraphicsMailer::string2params(to_utf8(cmd.argument()), buffer(), p); if (!p.filename.empty()) { try { - p.filename.enable(buffer().embedded(), &buffer()); + p.filename.enable(buffer().embedded(), &buffer(), true); } catch (ExceptionMessage const & message) { Alert::error(message.title_, message.details_); // do not set parameter if an error happens @@ -220,16 +220,8 @@ void InsetGraphics::registerEmbeddedFiles(EmbeddedFileList & files) const void InsetGraphics::updateEmbeddedFile(EmbeddedFile const & file) { - // when embedding is enabled, change of embedding status leads to actions - EmbeddedFile temp = file; - temp.enable(buffer().embedded(), &buffer()); - // this will not be set if an exception is thorwn in enable() - params_.filename = temp; - - LYXERR(Debug::FILES, "Update InsetGraphic with File " - << params_.filename.toFilesystemEncoding() - << ", embedding status: " << params_.filename.embedded() - << ", enabled: " << params_.filename.enabled()); + // only properties of an embedded file can be changed here. + params_.filename = file; } @@ -273,7 +265,7 @@ void InsetGraphics::read(Lexer & lex) else LYXERR(Debug::GRAPHICS, "Not a Graphics inset!"); - params_.filename.enable(buffer().embedded(), &buffer()); + params_.filename.enable(buffer().embedded(), &buffer(), false); graphic_->update(params().as_grfxParams()); } diff --git a/src/insets/InsetGraphicsParams.cpp b/src/insets/InsetGraphicsParams.cpp index 0b044a0ec5..16130e7c6a 100644 --- a/src/insets/InsetGraphicsParams.cpp +++ b/src/insets/InsetGraphicsParams.cpp @@ -184,11 +184,6 @@ bool InsetGraphicsParams::Read(Lexer & lex, string const & token, string const & if (token == "filename") { lex.eatLine(); filename.set(lex.getString(), bufpath); - } else if (token == "inzipName") { - // this option is currently ignored because only files in - // or under current document path is embeddable, and their - // inzipName is automatically determined. - lex.eatLine(); } else if (token == "embed") { lex.next(); string const name = lex.getString(); diff --git a/src/insets/InsetInclude.cpp b/src/insets/InsetInclude.cpp index 0a63d287a8..1cdcb3ce40 100644 --- a/src/insets/InsetInclude.cpp +++ b/src/insets/InsetInclude.cpp @@ -145,7 +145,7 @@ EmbeddedFile const includedFilename(Buffer const & buffer, EmbeddedFile file(to_utf8(params["filename"]), onlyPath(parentFilename(buffer))); file.setEmbed(!params["embed"].empty()); - file.enable(buffer.embedded(), &buffer); + file.enable(buffer.embedded(), &buffer, false); return file; } @@ -252,6 +252,7 @@ void InsetInclude::doDispatch(Cursor & cur, FuncRequest & cmd) InsetCommandParams p(INCLUDE_CODE); InsetCommandMailer::string2params("include", to_utf8(cmd.argument()), p); if (!p.getCmdName().empty()) { + Buffer const & buf = cur.buffer(); if (isListings(p)){ InsetListingsParams new_params(to_utf8(p["lstparams"])); docstring const label_str = from_utf8(new_params.getParamValue("label")); @@ -272,7 +273,7 @@ void InsetInclude::doDispatch(Cursor & cur, FuncRequest & cmd) p["embed"].clear(); else p["embed"] = from_utf8(EmbeddedFile(to_utf8(p["filename"]), - onlyPath(parentFilename(cur.buffer()))).inzipName()); + onlyPath(parentFilename(buf))).inzipName()); // test parameter includedFilename(cur.buffer(), p); } catch (ExceptionMessage const & message) { -- 2.39.2