Embedding: add 'addFile' to embed arbitrary file, fix a few bugs along the way

git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@19967 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
Bo Peng 2007-09-01 04:20:34 +00:00
parent efec6dde3d
commit 7a6edab5c1
6 changed files with 104 additions and 38 deletions

View File

@ -60,6 +60,7 @@ using support::makeRelPath;
using support::changeExtension;
using support::bformat;
using support::zipFiles;
using support::prefixIs;
EmbeddedFile::EmbeddedFile(string const & file, string const & inzip_name,
@ -75,6 +76,13 @@ string EmbeddedFile::embeddedFile(Buffer const * buf) const
}
int const EmbeddedFile::parID() const
{
// some embedded file do not have a valid par iterator
return par_it_ == ParConstIterator() ? 0 : par_it_->id();
}
void EmbeddedFile::setParIter(ParConstIterator const & pit)
{
par_it_ = pit;
@ -119,23 +127,8 @@ void EmbeddedFiles::registerFile(string const & filename,
it->validate();
return;
}
// register a new one, using relative file path as inzip_name
string inzip_name = to_utf8(makeRelPath(from_utf8(abs_filename),
from_utf8(buffer_->fileName())));
// if inzip_name is an absolute path, use filename only to avoid
// leaking of filesystem information in inzip_name
if (absolutePath(inzip_name))
inzip_name = onlyFilename(inzip_name);
// if this name has been used...
// use _1_name, _2_name etc
if (!validInzipName(inzip_name)) {
size_t i = 1;
string tmp = inzip_name;
do {
inzip_name = convert<string>(i) + "_" + tmp;
} while (!validInzipName(inzip_name));
}
file_list_.push_back(EmbeddedFile(abs_filename, inzip_name, status, pit));
file_list_.push_back(EmbeddedFile(abs_filename,
getInzipName(abs_filename), status, pit));
}
@ -148,7 +141,10 @@ void EmbeddedFiles::update()
EmbeddedFileList::iterator it = file_list_.begin();
EmbeddedFileList::iterator it_end = file_list_.end();
for (; it != it_end; ++it)
it->invalidate();
// if the status of a file is EMBEDDED, it will be there
// even if it is not referred by a document.
if (it->status() != EmbeddedFile::EMBEDDED)
it->invalidate();
ParIterator pit = buffer_->par_iterator_begin();
ParIterator pit_end = buffer_->par_iterator_end();
@ -187,14 +183,25 @@ bool EmbeddedFiles::write(DocFileName const & filename)
EmbeddedFileList::iterator it_end = file_list_.end();
for (; it != it_end; ++it) {
if (it->valid() && it->embedded()) {
// use external file if possible
if (it->status() != EmbeddedFile::EMBEDDED && fs::exists(it->absFilename()))
filenames.push_back(make_pair(it->absFilename(), it->inzipName()));
// use embedded file (AUTO or EMBEDDED mode)
else if(fs::exists(it->embeddedFile(buffer_)))
filenames.push_back(make_pair(it->embeddedFile(buffer_), it->inzipName()));
else
lyxerr << "File " << it->absFilename() << " does not exist. Skip embedding it. " << endl;
string ext_file = it->absFilename();
string emb_file = it->embeddedFile(buffer_);
if (it->status() == EmbeddedFile::AUTO) {
// use external file first
if (fs::exists(ext_file))
filenames.push_back(make_pair(ext_file, it->inzipName()));
else if (fs::exists(emb_file))
filenames.push_back(make_pair(emb_file, it->inzipName()));
else
lyxerr << "File " << ext_file << " does not exist. Skip embedding it. " << endl;
} else if (it->status() == EmbeddedFile::EMBEDDED) {
// use embedded file first
if (fs::exists(emb_file))
filenames.push_back(make_pair(emb_file, it->inzipName()));
else if (fs::exists(ext_file))
filenames.push_back(make_pair(ext_file, it->inzipName()));
else
lyxerr << "File " << ext_file << " does not exist. Skip embedding it. " << endl;
}
}
}
// add filename (.lyx) and manifest to filenames
@ -221,14 +228,35 @@ bool EmbeddedFiles::write(DocFileName const & filename)
}
bool EmbeddedFiles::validInzipName(string const & name)
string const EmbeddedFiles::getInzipName(string const & abs_filename)
{
EmbeddedFileList::iterator it = file_list_.begin();
// register a new one, using relative file path as inzip_name
string inzip_name = to_utf8(makeRelPath(from_utf8(abs_filename),
from_utf8(buffer_->fileName())));
// if inzip_name is an absolute path, use filename only to avoid
// leaking of filesystem information in inzip_name
if (absolutePath(inzip_name) || prefixIs(inzip_name, ".."))
inzip_name = onlyFilename(inzip_name);
// if this name has been used...
// use _1_name, _2_name etc
string tmp = inzip_name;
EmbeddedFileList::iterator it;
EmbeddedFileList::iterator it_end = file_list_.end();
for (; it != it_end; ++it)
if (it->inzipName() == name)
return false;
return true;
bool unique_name = false;
while (!unique_name) {
unique_name = true;
size_t i = 0;
if (i > 0)
inzip_name = convert<string>(i) + "_" + tmp;
it = file_list_.begin();
for (; it != it_end; ++it)
if (it->inzipName() == inzip_name) {
unique_name = false;
++i;
break;
}
}
return inzip_name;
}

View File

@ -137,7 +137,8 @@ public:
// to generate output, and be embedded to the saved lyx file.
// Otherwise, embedded version will be used.
AUTO,
// Always use embedded version.
// Always use embedded version. The file will be embedded even
// if the file is no longer referred by the document.
EMBEDDED,
// Do not embed this file, always use external version.
EXTERNAL
@ -153,7 +154,7 @@ public:
/// paragraph id
void setParIter(ParConstIterator const & pit);
int const parID() const { return par_it_->id(); }
int const parID() const;
/// embedding status of this file
bool embedded() const { return status_ != EXTERNAL; }
@ -225,8 +226,8 @@ public:
friend std::ostream & operator<< (std::ostream & os, EmbeddedFiles const &);
private:
/// if a inzip name already exists
bool validInzipName(std::string const & name);
/// get a unique inzip name
std::string const getInzipName(std::string const & name);
/// list of embedded files
EmbeddedFileList file_list_;
///

View File

@ -18,13 +18,20 @@
#include "gettext.h"
#include "debug.h"
#include "Format.h"
#include "LyXRC.h"
#include "frontend_helpers.h"
#include "frontends/LyXView.h"
#include "support/FileFilterList.h"
#include "support/convert.h"
using std::string;
namespace lyx {
using support::FileFilterList;
namespace frontend {
ControlEmbeddedFiles::ControlEmbeddedFiles(Dialog & parent)
@ -55,8 +62,11 @@ void ControlEmbeddedFiles::dispatchParams()
void ControlEmbeddedFiles::goTo(EmbeddedFile const & item)
{
string const tmp = convert<string>(item.parID());
kernel().lyxview().dispatch(FuncRequest(LFUN_PARAGRAPH_GOTO, tmp));
int id = item.parID();
if (id != 0) {
string const tmp = convert<string>(item.parID());
kernel().lyxview().dispatch(FuncRequest(LFUN_PARAGRAPH_GOTO, tmp));
}
}
@ -65,5 +75,17 @@ void ControlEmbeddedFiles::view(EmbeddedFile const & item)
formats.view(kernel().buffer(), item, formats.getFormatFromFile(item));
}
docstring const ControlEmbeddedFiles::browseFile()
{
std::pair<docstring, docstring> dir1(_("Documents|#o#O"),
lyx::from_utf8(lyxrc.document_path));
FileFilterList const filter(_("All file (*.*)"));
return browseRelFile(docstring(), lyx::from_utf8(kernel().bufferFilepath()),
_("Select a file to embed"),
filter, false, dir1);
}
} // namespace frontend
} // namespace lyx

View File

@ -48,6 +48,8 @@ public:
void goTo(EmbeddedFile const & item);
///
void view(EmbeddedFile const & item);
///
docstring const browseFile();
protected:
// directly handle buffer embedded files

View File

@ -127,6 +127,7 @@ void GuiEmbeddedFilesDialog::on_actionPB_clicked()
// ACTION
QString action = actionCB->currentText();
if (action == "Add file") {
addFile();
} else if (action == "Extract file") {
} else if (action == "Extract all") {
} else if (action == "Embed all") {
@ -138,6 +139,16 @@ void GuiEmbeddedFilesDialog::on_actionPB_clicked()
}
void GuiEmbeddedFilesDialog::addFile()
{
docstring const file = form_->browseFile();
if (!file.empty()) {
EmbeddedFiles & files = form_->embeddedFiles();
files.registerFile(to_utf8(file), EmbeddedFile::EMBEDDED);
}
}
void GuiEmbeddedFilesDialog::on_actionCB_stateChanged(int idx)
{
// valid action, enable action button

View File

@ -43,6 +43,8 @@ public Q_SLOTS:
void on_autoRB_clicked();
void on_embeddedRB_clicked();
void on_externalRB_clicked();
///
void addFile();
private:
void set_embedding_status(EmbeddedFile::STATUS);
///