From 52cd35cd5ff366614a1d668a7ede6afa6fa03f5e Mon Sep 17 00:00:00 2001 From: Bo Peng Date: Tue, 8 Jan 2008 17:02:09 +0000 Subject: [PATCH] Embedding: add embedding support for InsetBibtex. (params["embed"] is added, use EmbeddedFileList instead of FileNameList for bibtex handling, use checkable items in GuiBibtex) git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@22443 a592a061-630c-0410-9148-cb99ea01b6c8 --- src/Buffer.cpp | 8 +-- src/Buffer.h | 4 +- src/frontends/qt4/GuiBibtex.cpp | 39 +++++++++++--- src/frontends/qt4/ui/BibtexUi.ui | 2 +- src/insets/InsetBibtex.cpp | 90 +++++++++++++++++++++++++++----- src/insets/InsetBibtex.h | 9 +++- src/insets/InsetCitation.cpp | 4 +- src/insets/InsetInclude.cpp | 6 +-- src/insets/InsetInclude.h | 4 +- src/support/FileNameList.h | 5 ++ 10 files changed, 136 insertions(+), 35 deletions(-) diff --git a/src/Buffer.cpp b/src/Buffer.cpp index 2779f7700f..1757a4af91 100644 --- a/src/Buffer.cpp +++ b/src/Buffer.cpp @@ -207,7 +207,7 @@ public: /// A cache for the bibfiles (including bibfiles of loaded child /// documents), needed for appropriate update of natbib labels. - mutable FileNameList bibfilesCache_; + mutable EmbeddedFileList bibfilesCache_; }; /// Creates the per buffer temporary directory @@ -1384,7 +1384,7 @@ void Buffer::updateBibfilesCache() const if (it->lyxCode() == BIBTEX_CODE) { InsetBibtex const & inset = static_cast(*it); - FileNameList const bibfiles = inset.getFiles(*this); + EmbeddedFileList const bibfiles = inset.getFiles(*this); d->bibfilesCache_.insert(d->bibfilesCache_.end(), bibfiles.begin(), bibfiles.end()); @@ -1392,7 +1392,7 @@ void Buffer::updateBibfilesCache() const InsetInclude & inset = static_cast(*it); inset.updateBibfilesCache(*this); - FileNameList const & bibfiles = + EmbeddedFileList const & bibfiles = inset.getBibfilesCache(*this); d->bibfilesCache_.insert(d->bibfilesCache_.end(), bibfiles.begin(), @@ -1402,7 +1402,7 @@ void Buffer::updateBibfilesCache() const } -FileNameList const & Buffer::getBibfilesCache() const +EmbeddedFileList const & Buffer::getBibfilesCache() const { // if this is a child document and the parent is already loaded // use the parent's cache instead diff --git a/src/Buffer.h b/src/Buffer.h index 9dd0fc38a4..25791be1f6 100644 --- a/src/Buffer.h +++ b/src/Buffer.h @@ -57,7 +57,7 @@ class WorkAreaManager; namespace support { class FileName; -class FileNameList; +class EmbeddedFileList; } /** The buffer object. @@ -304,7 +304,7 @@ public: void updateBibfilesCache() const; /// Return the cache with all bibfiles in use (including bibfiles /// of loaded child documents). - support::FileNameList const & getBibfilesCache() const; + support::EmbeddedFileList const & getBibfilesCache() const; /// void getLabelList(std::vector &) const; diff --git a/src/frontends/qt4/GuiBibtex.cpp b/src/frontends/qt4/GuiBibtex.cpp index c27abde77b..e7620194d1 100644 --- a/src/frontends/qt4/GuiBibtex.cpp +++ b/src/frontends/qt4/GuiBibtex.cpp @@ -194,8 +194,14 @@ void GuiBibtex::addDatabase() add_->bibLW->setItemSelected(item, false); QList matches = databaseLW->findItems(item->text(), Qt::MatchExactly); - if (matches.empty()) - databaseLW->addItem(item->text()); + if (matches.empty()) { + QString label = item->text(); + QListWidgetItem * db = new QListWidgetItem(label); + db->setFlags(db->flags() | Qt::ItemIsSelectable + | Qt::ItemIsUserCheckable); + db->setCheckState(Qt::Checked); + databaseLW->addItem(db); + } } } @@ -204,8 +210,13 @@ void GuiBibtex::addDatabase() QString const f = toqstr(from_utf8(changeExtension(to_utf8(file), ""))); QList matches = databaseLW->findItems(f, Qt::MatchExactly); - if (matches.empty()) + if (matches.empty()) { + QListWidgetItem * db = new QListWidgetItem(f); + db->setFlags(db->flags() | Qt::ItemIsSelectable + | Qt::ItemIsUserCheckable); + db->setCheckState(Qt::Checked); databaseLW->addItem(f); + } } changed(); @@ -246,13 +257,21 @@ void GuiBibtex::updateContents() databaseLW->clear(); docstring bibs = params_["bibfiles"]; + docstring embs = params_["embed"]; docstring bib; + docstring emb; while (!bibs.empty()) { bibs = split(bibs, bib, ','); + embs = split(embs, emb, ','); bib = trim(bib); - if (!bib.empty()) - databaseLW->addItem(toqstr(bib)); + if (!bib.empty()) { + QListWidgetItem * db = new QListWidgetItem(toqstr(bib)); + db->setFlags(db->flags() | Qt::ItemIsSelectable + | Qt::ItemIsUserCheckable); + db->setCheckState(emb == _("true") ? Qt::Checked : Qt::Unchecked); + databaseLW->addItem(db); + } } add_->bibLW->clear(); @@ -262,7 +281,11 @@ void GuiBibtex::updateContents() for (vector::const_iterator it = bib_str.begin(); it != bib_str.end(); ++it) { string bibItem(changeExtension(*it, "")); - add_->bibLW->addItem(toqstr(bibItem)); + QListWidgetItem * db = new QListWidgetItem(toqstr(bibItem)); + db->setFlags(db->flags() & ~Qt::ItemIsSelectable + | Qt::ItemIsUserCheckable); + db->setCheckState(Qt::Unchecked); + add_->bibLW->addItem(db); } string bibstyle = getStylefile(); @@ -314,14 +337,18 @@ void GuiBibtex::updateContents() void GuiBibtex::applyView() { docstring dbs = qstring_to_ucs4(databaseLW->item(0)->text()); + docstring emb = databaseLW->item(0)->checkState() == Qt::Checked ? _("true") : _("false"); unsigned int maxCount = databaseLW->count(); for (unsigned int i = 1; i < maxCount; i++) { dbs += ','; dbs += qstring_to_ucs4(databaseLW->item(i)->text()); + emb += ','; + emb += databaseLW->item(i)->checkState() == Qt::Checked ? _("true") : _("false"); } params_["bibfiles"] = dbs; + params_["embed"] = emb; docstring const bibstyle = qstring_to_ucs4(styleCB->currentText()); bool const bibtotoc = bibtocCB->isChecked(); diff --git a/src/frontends/qt4/ui/BibtexUi.ui b/src/frontends/qt4/ui/BibtexUi.ui index 1879c47258..84b09ade22 100644 --- a/src/frontends/qt4/ui/BibtexUi.ui +++ b/src/frontends/qt4/ui/BibtexUi.ui @@ -176,7 +176,7 @@ BibTeX database to use - Databa&ses + Databa&ses (select to embed when saved in bundled format) Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop diff --git a/src/insets/InsetBibtex.cpp b/src/insets/InsetBibtex.cpp index 4a9e22a13b..06d4fed587 100644 --- a/src/insets/InsetBibtex.cpp +++ b/src/insets/InsetBibtex.cpp @@ -55,9 +55,9 @@ InsetBibtex::InsetBibtex(InsetCommandParams const & p) CommandInfo const * InsetBibtex::findInfo(string const & /* cmdName */) { static const char * const paramnames[] = - {"options", "btprint", "bibfiles", ""}; - static const bool isoptional[] = {true, true, false}; - static const CommandInfo info = {3, paramnames, isoptional}; + {"options", "btprint", "bibfiles", "embed", ""}; + static const bool isoptional[] = {true, true, false, false}; + static const CommandInfo info = {4, paramnames, isoptional}; return &info; } @@ -88,7 +88,19 @@ void InsetBibtex::doDispatch(Cursor & cur, FuncRequest & cmd) throw message; break; } + // + InsetCommandParams orig = params(); setParams(p); + // test parameter and copy files + try { + // enable() in getFiles will try to copy files + getFiles(cur.buffer()); + } catch (ExceptionMessage const & message) { + Alert::error(message.title_, message.details_); + // do not set parameter if an error happens + setParams(orig); + break; + } cur.buffer().updateBibfilesCache(); break; } @@ -310,27 +322,43 @@ int InsetBibtex::latex(Buffer const & buffer, odocstream & os, } -FileNameList const InsetBibtex::getFiles(Buffer const & buffer) const +EmbeddedFileList const InsetBibtex::getFiles(Buffer const & buffer) const { FileName path(buffer.filePath()); PathChanger p(path); - FileNameList vec; + 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()) { - FileName const file = findtexfile(changeExtension(tmp, "bib"), "bib"); - LYXERR(Debug::LATEX, "Bibfile: " << file); - - // If we didn't find a matching file name just fail silently - if (!file.empty()) + if (emb == "true") { + EmbeddedFile file(changeExtension(tmp, "bib"), buffer.filePath()); + // If the file structure is correct, this should not fail. + file.setEmbed(true); + file.enable(buffer.embeddedFiles().enabled(), &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.embeddedFiles().enabled(), &buffer); + vec.push_back(efile); + } + } // Get next file name bibfiles = split(bibfiles, tmp, ','); + embedStatus = split(embedStatus, emb, ','); } return vec; @@ -578,8 +606,8 @@ namespace { void InsetBibtex::fillWithBibKeys(Buffer const & buffer, BiblioInfo & keylist, InsetIterator const & /*di*/) const { - FileNameList const files = getFiles(buffer); - for (vector::const_iterator it = files.begin(); + EmbeddedFileList const files = getFiles(buffer); + for (vector::const_iterator it = files.begin(); it != files.end(); ++ it) { // This bibtex parser is a first step to parse bibtex files // more precisely. @@ -600,7 +628,7 @@ void InsetBibtex::fillWithBibKeys(Buffer const & buffer, // InsetBibitem can generate non-ASCII keys, and nonstandard // 8bit clean bibtex forks exist. - idocfstream ifs(it->toFilesystemEncoding().c_str(), + idocfstream ifs(it->availableFile().toFilesystemEncoding().c_str(), ios_base::in, buffer.params().encoding().iconvName()); @@ -777,4 +805,40 @@ void InsetBibtex::validate(LaTeXFeatures & features) const } +void InsetBibtex::registerEmbeddedFiles(Buffer const & buffer, EmbeddedFiles & files) const +{ + EmbeddedFileList const dbs = getFiles(buffer); + for (vector::const_iterator it = dbs.begin(); + it != dbs.end(); ++ it) + files.registerFile(*it, this); +} + + +void InsetBibtex::updateEmbeddedFile(Buffer const & buf, EmbeddedFile const & file) +{ + // look for the item and update status + docstring bibfiles; + docstring embed; + + bool first = true; + EmbeddedFileList dbs = getFiles(buf); + for (vector::iterator it = dbs.begin(); + it != dbs.end(); ++ it) { + // update from file + if (it->absFilename() == file.absFilename()) + it->setEmbed(file.embedded()); + // write parameter string + if (!first) { + bibfiles += ','; + embed += ','; + first = false; + } + bibfiles += from_utf8(it->outputFilename(buf.filePath())); + embed += it->embedded() ? _("true") : _("false"); + } + setParam("bibfiles", bibfiles); + setParam("embed", embed); +} + + } // namespace lyx diff --git a/src/insets/InsetBibtex.h b/src/insets/InsetBibtex.h index 25ce300c9b..c9c7fe5a49 100644 --- a/src/insets/InsetBibtex.h +++ b/src/insets/InsetBibtex.h @@ -19,7 +19,7 @@ namespace lyx { namespace support { -class FileNameList; +class EmbeddedFileList; } @@ -43,7 +43,7 @@ public: virtual void fillWithBibKeys(Buffer const &, BiblioInfo &, InsetIterator const &) const; /// - support::FileNameList const getFiles(Buffer const &) const; + support::EmbeddedFileList const getFiles(Buffer const &) const; /// bool addDatabase(std::string const &); /// @@ -57,6 +57,11 @@ public: /// static bool isCompatibleCommand(std::string const & s) { return s == "bibtex"; } + /// + void registerEmbeddedFiles(Buffer const &, EmbeddedFiles &) const; + /// + void updateEmbeddedFile(Buffer const & buf, EmbeddedFile const & file); + protected: virtual void doDispatch(Cursor & cur, FuncRequest & cmd); private: diff --git a/src/insets/InsetCitation.cpp b/src/insets/InsetCitation.cpp index dcc4fad43a..de8af5727b 100644 --- a/src/insets/InsetCitation.cpp +++ b/src/insets/InsetCitation.cpp @@ -144,10 +144,10 @@ docstring const getComplexLabel(Buffer const & buffer, BiblioInfo biblist; - FileNameList const & bibfilesCache = buffer.getBibfilesCache(); + support::EmbeddedFileList const & bibfilesCache = buffer.getBibfilesCache(); // compare the cached timestamps with the actual ones. bool changed = false; - for (FileNameList::const_iterator it = bibfilesCache.begin(); + for (support::EmbeddedFileList::const_iterator it = bibfilesCache.begin(); it != bibfilesCache.end(); ++ it) { FileName const f = *it; time_t lastw = f.lastModified(); diff --git a/src/insets/InsetInclude.cpp b/src/insets/InsetInclude.cpp index c917a3d7d1..c9045b1e7a 100644 --- a/src/insets/InsetInclude.cpp +++ b/src/insets/InsetInclude.cpp @@ -713,17 +713,17 @@ void InsetInclude::updateBibfilesCache(Buffer const & buffer) } -FileNameList const & +EmbeddedFileList const & InsetInclude::getBibfilesCache(Buffer const & buffer) const { Buffer * const tmp = getChildBuffer(buffer, params()); if (tmp) { tmp->setParent(0); - FileNameList const & cache = tmp->getBibfilesCache(); + EmbeddedFileList const & cache = tmp->getBibfilesCache(); tmp->setParent(&buffer); return cache; } - static FileNameList const empty; + static EmbeddedFileList const empty; return empty; } diff --git a/src/insets/InsetInclude.h b/src/insets/InsetInclude.h index cdb819f612..6dc5142618 100644 --- a/src/insets/InsetInclude.h +++ b/src/insets/InsetInclude.h @@ -31,7 +31,7 @@ class LaTeXFeatures; class RenderMonitoredPreview; namespace support { -class FileNameList; +class EmbeddedFileList; } /// for including tex/lyx files @@ -74,7 +74,7 @@ public: * Return an empty vector if the child doc is not loaded. * \param buffer the Buffer containing this inset. */ - support::FileNameList const & + support::EmbeddedFileList const & getBibfilesCache(Buffer const & buffer) const; /// EDITABLE editable() const { return IS_EDITABLE; } diff --git a/src/support/FileNameList.h b/src/support/FileNameList.h index 20b6a85af7..6cf61abc5c 100644 --- a/src/support/FileNameList.h +++ b/src/support/FileNameList.h @@ -13,6 +13,7 @@ #define FILENAMELIST_H #include "support/FileName.h" +#include "EmbeddedFiles.h" #include @@ -28,6 +29,10 @@ class FileNameList: public std::vector { }; +class EmbeddedFileList: public std::vector +{ +}; + } // namespace support } // namespace lyx -- 2.39.2