EmbeddedFile::EmbeddedFile(string const & file, string const & inzip_name,
- STATUS status, ParConstIterator const & pit)
- : DocFileName(file, true), inzip_name_(inzip_name), status_(status),
+ bool embed, ParConstIterator const & pit)
+ : DocFileName(file, true), inzip_name_(inzip_name), embedded_(embed),
valid_(true), par_it_(pit)
{}
string EmbeddedFile::availableFile(Buffer const * buf) const
{
- string ext_file = absFilename();
- string emb_file = embeddedFile(buf);
- if (status_ == AUTO) {
- // use external file first
- if (fs::exists(ext_file))
- return ext_file;
- else if (fs::exists(emb_file))
- return emb_file;
- else
- return string();
- } else if (status_ == EMBEDDED) {
- // use embedded file first
- if (fs::exists(emb_file))
- return emb_file;
- else if (fs::exists(ext_file))
- return ext_file;
- else
- return string();
- } else
- return string();
+ if (embedded_)
+ return embeddedFile(buf);
+ else
+ return absFilename();
}
bool EmbeddedFile::extract(Buffer const * buf) const
{
+ if (!embedded_)
+ return true;
+
string ext_file = absFilename();
string emb_file = embeddedFile(buf);
bool copyFile = false;
- // both files exist, are different, and in EMBEDDED status
- if (fs::exists(ext_file) && fs::exists(emb_file) && status_ == EMBEDDED
+ // both files exist, are different
+ if (fs::exists(ext_file) && fs::exists(emb_file)
&& sum(*this) != sum(FileName(emb_file))) {
int const ret = Alert::prompt(
_("Overwrite external file?"),
return false;
}
-
+
+bool EmbeddedFile::embed(Buffer const * buf)
+{
+ string ext_file = absFilename();
+ string emb_file = embeddedFile(buf);
+ bool copyFile = false;
+ // both files exist, are different
+ if (fs::exists(ext_file) && fs::exists(emb_file)
+ && sum(*this) != sum(FileName(emb_file))) {
+ int const ret = Alert::prompt(
+ _("Update embedded file?"),
+ bformat(_("Embeddedl file %1$s already exists, do you want to overwrite it"),
+ from_utf8(ext_file)), 1, 1, _("&Overwrite"), _("&Cancel"));
+ copyFile = ret == 0;
+ }
+ // copy file in the previous case, and a new case
+ if (copyFile || (fs::exists(ext_file) && !fs::exists(emb_file))) {
+ try {
+ // need to make directory?
+ string path = onlyPath(emb_file);
+ if (!fs::is_directory(path))
+ makedir(const_cast<char*>(path.c_str()), 0755);
+ fs::copy_file(ext_file, emb_file, false);
+ embedded_ = true;
+ } catch (fs::filesystem_error const & fe) {
+ Alert::error(_("Copy file failure"),
+ bformat(_("Cannot copy file %1$s to %2$s.\n"
+ "Please check whether the directory exists and is writeable."),
+ from_utf8(ext_file), from_utf8(emb_file)));
+ LYXERR(Debug::DEBUG) << "Fs error: " << fe.what() << endl;
+ embedded_ = false;
+ }
+ }
+ return embedded_;
+}
+
+
bool EmbeddedFiles::enabled() const
{
return buffer_->params().embedded;
void EmbeddedFiles::registerFile(string const & filename,
- EmbeddedFile::STATUS status, ParConstIterator const & pit)
+ bool embed, ParConstIterator const & pit)
{
string abs_filename = makeAbsPath(filename, buffer_->filePath()).absFilename();
// try to find this file from the list
// find this filename
if (it != file_list_.end()) {
it->setParIter(pit);
- it->setStatus(status);
+ it->embed(buffer_);
it->validate();
return;
}
file_list_.push_back(EmbeddedFile(abs_filename,
- getInzipName(abs_filename), status, pit));
+ getInzipName(abs_filename), embed, pit));
}
EmbeddedFileList::iterator it = file_list_.begin();
EmbeddedFileList::iterator it_end = file_list_.end();
for (; it != it_end; ++it)
- // Only AUTO files will be updated. If the status of a file is EMBEDDED,
- // it will be embedded even if it is not referred by a document.
- if (it->status() == EmbeddedFile::AUTO)
- it->invalidate();
+ it->invalidate();
ParIterator pit = buffer_->par_iterator_begin();
ParIterator pit_end = buffer_->par_iterator_end();
// 'do not overwrite' this file, and cancel for 'cancel extract all files'.
// I am not sure how to do this now.
for (; it != it_end; ++it)
- if (it->valid() && it->status() != EmbeddedFile::EXTERNAL)
+ if (it->valid() && it->embedded())
it->extract(buffer_);
return true;
}
getline(is, inzip_name);
getline(is, tmp);
istringstream itmp(tmp);
- int status;
- itmp >> status;
+ int embed;
+ itmp >> embed;
getline(is, tmp);
if (tmp != "</file>") {
break;
}
- files.registerFile(fname, static_cast<EmbeddedFile::STATUS>(status));
+ files.registerFile(fname, embed);
};
// the last line must be </manifest>
if (tmp != "</manifest>") {
<< to_utf8(makeRelPath(from_utf8(it->absFilename()),
from_utf8(files.buffer_->filePath()))) << '\n'
<< it->inzipName() << '\n'
- << it->status() << '\n'
+ << it->embedded() << '\n'
<< "</file>\n";
}
os << "</manifest>\n";
1. With embedding enabled (disabled by default), .lyx file can embed graphics,
listings, bib file etc.
-2. Embedding of certain files are automatic (graphics, bib etc), and
-other files can be embedded manually.
-
-3. Embedded file.lyx file is a zip file, with file.lyx, manifest.txt
+2. Embedded file.lyx file is a zip file, with file.lyx, manifest.txt
and embedded files.
-4. Embedded files can be "EMBEDDED", "EXTERNAL", or "AUTO". In the
-"AUTO" mode, external files will be used if available; otherwise the
-embedded version will be used. In this way, users can work as usual by
-modifying external listings, graphics, and do not have to worry about
-embedding. "EMBEDDED" and "EXTERNAL" modes ignore or use external files
-respectively.
-
-5. An embedding dialog is provided to change embedding status (buffer
+3. An embedding dialog is provided to change embedding status (buffer
level or individual embedded files), manually embed, extract, view
or edit files.
b. The embedded way. Figures etc are inserted to .lyx file and will
be embedded. These embedded files can be viewed or edited through
the embedding dialog. This file can be shared with others more
-easily. The advantage of lyx' embedding approach is that external files
-will be automatically used and embedded if the file is in "AUTO" mode.
+easily.
+Format a anb b can be converted easily, by enable/disable embedding. Diabling
+embedding is also called unpacking because all embedded files will be copied
+to their original locations.
Implementation:
======================
b. inzip filename. It is the relative path name if the embedded file is
in or under the document directory, or file name otherwise. Name aliasing
is used if two external files share the same name.
- c. embedding mode.
+ c. embedding status.
It also provides functions to
a. manipulate manifest
b. scan a buffer for embeddable files
- c. look up inzipname from external filename
- d. look up external filename from inzipname
+ c. determine which file to use according to embedding status
2. When a file is saved, it is scanned for embedded files. (c.f.
EmbeddedFiles::update(), Inset::registerEmbeddedFiles()).
From this dialog, a user can disable embedding, change embedding status,
or embed other files, extract, view, edit files.
-6. When a lyx file is loaded, Embedded files can have
- a. both external and internal copy
- b. only external copy (filename())
- c. only embedded copy (temppath()/inzipname)
-And each can have "AUTO", "EXTERNAL", "EMBEDDED" status. Proper
-handling of each case is required.
-
-7. If embedding of a .lyx file with embedded files is disabled, all its
+6. If embedding of a .lyx file with embedded files is disabled, all its
embedded files are copied to their respective external filenames. This
is why external filename will exist even if a file is at "EMBEDDED" status.
-8. Individual embeddable insets should find ways to handle embedded files.
+7. Individual embeddable insets should find ways to handle embedded files.
InsetGraphics replace params().filename with its temppath()/inzipname version
when the inset is created. The filename appears as /tmp/..../inzipname
when lyx runs. When params().filename is saved, lyx checks if this is an
class EmbeddedFile : public support::DocFileName
{
public:
- /**
- Embedding status of this DocFileName.
- */
- enum STATUS {
- // uninitialized/invalid status
- NONE,
- // If the external version of the file is available, it will be used
- // to generate output, and be embedded to the saved lyx file.
- // Otherwise, embedded version will be used.
- AUTO,
- // 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
- };
-
EmbeddedFile(std::string const & file, std::string const & inzip_name,
- STATUS status, ParConstIterator const & pit);
+ bool embedded, ParConstIterator const & pit);
/// filename in the zip file, usually the relative path
std::string inzipName() const { return inzip_name_; }
/// embedded file, equals to temppath()/inzipName()
std::string embeddedFile(Buffer const * buf) const;
- /// embeddedFile() or absFilename() depending on status_ and
- /// file availability
+ /// embeddedFile() or absFilename() depending on embedding status
std::string availableFile(Buffer const * buf) const;
/// paragraph id
int const parID() const;
/// embedding status of this file
- bool embedded() const { return status_ != EXTERNAL; }
- STATUS status() const { return status_; }
- void setStatus(STATUS status) { status_ = status; }
+ bool embedded() const { return embedded_; }
// A flag indicating whether or not this filename is valid.
// When lyx runs, InsetGraphics etc may be added or removed so filename
void invalidate() { valid_ = false; }
///
bool extract(Buffer const * buf) const;
+ ///
+ bool embed(Buffer const * buf);
private:
/// filename in zip file
std::string inzip_name_;
/// the status of this docfile
- STATUS status_;
+ bool embedded_;
///
bool valid_;
/// Current position of the item, used to locate the files
void enable(bool flag);
/// add a file item
- void registerFile(std::string const & filename,
- EmbeddedFile::STATUS status = EmbeddedFile::AUTO,
+ void registerFile(std::string const & filename, bool embed = false,
ParConstIterator const & pit = ParConstIterator());
/// scan the buffer and get a list of EmbeddedFile
namespace frontend {
static QString const INVALID_COLOR = "gray";
-static QString const AUTO_COLOR = "green";
static QString const EMBEDDED_COLOR = "black";
static QString const EXTERNAL_COLOR = "blue";
controller().goTo(files[idx]);
}
- EmbeddedFile::STATUS mode = EmbeddedFile::NONE;
+ bool mode = false;
for (; it != it_end; ++it) {
int idx = filesLW->row(*it);
- if (mode == EmbeddedFile::NONE) {
- mode = files[idx].status();
+ if (mode) {
+ mode = true;
continue;
}
- if (mode != files[idx].status()) {
- mode = EmbeddedFile::NONE;
- break;
- }
}
- autoRB->setChecked(mode == EmbeddedFile::AUTO);
- embeddedRB->setChecked(mode == EmbeddedFile::EMBEDDED);
- externalRB->setChecked(mode == EmbeddedFile::EXTERNAL);
}
QListWidgetItem * item = new QListWidgetItem(toqstr(it->inzipName()));
if (!it->valid())
item->setTextColor(INVALID_COLOR);
- else if(it->status() == EmbeddedFile::AUTO)
- item->setTextColor(AUTO_COLOR);
- else if(it->status() == EmbeddedFile::EMBEDDED)
+ else if(it->embedded())
item->setTextColor(EMBEDDED_COLOR);
else
item->setTextColor(EXTERNAL_COLOR);
docstring const file = controller().browseFile();
if (!file.empty()) {
EmbeddedFiles & files = controller().embeddedFiles();
- files.registerFile(to_utf8(file), EmbeddedFile::EMBEDDED);
+ files.registerFile(to_utf8(file), true);
}
}
}
-void GuiEmbeddedFilesDialog::set_embedding_status(EmbeddedFile::STATUS status)
+void GuiEmbeddedFilesDialog::set_embedding_status(bool embed)
{
EmbeddedFiles & files = controller().embeddedFiles();
QList<QListWidgetItem *> selection = filesLW->selectedItems();
it != selection.end(); ++it) {
int row = filesLW->row(*it);
// FIXME: mark buffer dirty
- if (status != files[row].status())
- files[row].setStatus(status);
- if(status == EmbeddedFile::AUTO)
- (*it)->setTextColor(AUTO_COLOR);
- else if(status == EmbeddedFile::EMBEDDED)
+ if(embed)
(*it)->setTextColor(EMBEDDED_COLOR);
else
(*it)->setTextColor(EXTERNAL_COLOR);
}
- if (status == EmbeddedFile::AUTO)
- controller().setMessage("Switch to auto embedding");
- else if (status == EmbeddedFile::EMBEDDED)
- controller().setMessage("Switch to always embedding");
+ if (embed)
+ controller().setMessage("Embed file");
else
- controller().setMessage("Switch to never embedding");
- autoRB->setChecked(status == EmbeddedFile::AUTO);
- embeddedRB->setChecked(status == EmbeddedFile::EMBEDDED);
- externalRB->setChecked(status == EmbeddedFile::EXTERNAL);
+ controller().setMessage("Extract file");
// update bufferView
controller().dispatchParams();
}
-void GuiEmbeddedFilesDialog::on_autoRB_clicked()
-{
- set_embedding_status(EmbeddedFile::AUTO);
-}
-
-
void GuiEmbeddedFilesDialog::on_embeddedRB_clicked()
{
- set_embedding_status(EmbeddedFile::EMBEDDED);
+ set_embedding_status(true);
}
void GuiEmbeddedFilesDialog::on_externalRB_clicked()
{
- set_embedding_status(EmbeddedFile::EXTERNAL);
+ set_embedding_status(false);
}
///
void on_enableCB_toggled(bool enable);
///
- void on_autoRB_clicked();
void on_embeddedRB_clicked();
void on_externalRB_clicked();
///
private:
ControlEmbeddedFiles & controller() const;
- void set_embedding_status(EmbeddedFile::STATUS);
+ void set_embedding_status(bool embed);
};
} // namespace frontend
void InsetExternal::registerEmbeddedFiles(Buffer const &,
EmbeddedFiles & files, ParConstIterator const & pit) const
{
- files.registerFile(params_.filename.absFilename(), EmbeddedFile::AUTO, pit);
+ files.registerFile(params_.filename.absFilename(), false, pit);
}
EmbeddedFiles & files, ParConstIterator const & pit) const
{
files.registerFile(params().filename.absFilename(),
- EmbeddedFile::AUTO, pit);
+ false, pit);
}
// include and input are temprarily not considered.
if (isVerbatim(params_) || isListings(params_))
files.registerFile(includedFilename(buffer, params_).absFilename(),
- EmbeddedFile::AUTO, pit);
+ false, pit);
}