Update paths of included files when saving to a different folder.

Fixes #9528 and #5115.
This commit is contained in:
Enrico Forestieri 2015-05-04 03:11:30 +02:00
parent 8e68c2eea1
commit 4543bf288d
9 changed files with 77 additions and 16 deletions

View File

@ -237,6 +237,9 @@ public:
/// map from children inclusion positions to their scope and their buffer
PositionScopeBufferMap position_to_children;
/// Keeps track of old buffer filePath() for save-as operations
string old_position;
/// Container for all sort of Buffer dependant errors.
map<string, ErrorList> errorLists;
@ -4866,6 +4869,8 @@ bool Buffer::saveAs(FileName const & fn)
FileName const old_name = fileName();
FileName const old_auto = getAutosaveFileName();
bool const old_unnamed = isUnnamed();
bool success = true;
d->old_position = filePath();
setFileName(fn);
markDirty();
@ -4883,22 +4888,19 @@ bool Buffer::saveAs(FileName const & fn)
// are still valid.
checkChildBuffers();
checkMasterBuffer();
return true;
} else {
// save failed
// reset the old filename and unnamed state
setFileName(old_name);
setUnnamed(old_unnamed);
return false;
success = false;
}
d->old_position.clear();
return success;
}
// FIXME We could do better here, but it is complicated. What would be
// nice is to offer either (a) to save the child buffer to an appropriate
// location, so that it would "move with the master", or else (b) to update
// the InsetInclude so that it pointed to the same file. But (a) is a bit
// complicated, because the code for this lives in GuiView.
void Buffer::checkChildBuffers()
{
Impl::BufferPositionMap::iterator it = d->children_positions.begin();
@ -4918,11 +4920,6 @@ void Buffer::checkChildBuffers()
if (oldloc == newloc)
continue;
// the location of the child file is incorrect.
Alert::warning(_("Included File Invalid"),
bformat(_("Saving this document to a new location has made the file:\n"
" %1$s\n"
"inaccessible. You will need to update the included filename."),
from_utf8(oldloc)));
cbuf->setParent(0);
inset_inc->setChildBuffer(0);
}
@ -4952,4 +4949,18 @@ void Buffer::checkMasterBuffer()
setParent(0);
}
string Buffer::includedFilePath(string const & name) const
{
if (d->old_position.empty() || d->old_position == filePath())
return name;
if (FileName::isAbsolute(name))
return to_utf8(makeRelPath(from_utf8(name), from_utf8(filePath())));
// old_position already contains a trailing path separator
string const cleanpath = FileName(d->old_position + name).realPath();
return to_utf8(makeRelPath(from_utf8(cleanpath), from_utf8(filePath())));
}
} // namespace lyx

View File

@ -707,6 +707,12 @@ public:
///
void checkMasterBuffer();
/// If the document is being saved to a new location, return the
/// updated path of an included file relative to the new buffer path
/// if possible, otherwise return its absolute path.
/// In all other cases, this is a no-op and name is returned unchanged.
std::string includedFilePath(std::string const & name) const;
/// compute statistics between \p from and \p to
/// \p from initial position
/// \p to points to the end position

View File

@ -1025,6 +1025,12 @@ docstring InsetBibtex::xhtml(XHTMLStream & xs, OutputParams const &) const
}
void InsetBibtex::write(ostream & os) const
{
params().Write(os, &buffer());
}
string InsetBibtex::contextMenuName() const
{
return "context-bibtex";

View File

@ -38,6 +38,8 @@ public:
bool addDatabase(docstring const &);
///
bool delDatabase(docstring const &);
///
void write(std::ostream &) const;
/// \name Public functions inherited from Inset class
//@{

View File

@ -28,6 +28,7 @@
#include "InsetRef.h"
#include "InsetTOC.h"
#include "Buffer.h"
#include "Encoding.h"
#include "Lexer.h"
#include "OutputParams.h"
@ -320,6 +321,12 @@ void InsetCommandParams::read(Lexer & lex)
void InsetCommandParams::write(ostream & os) const
{
Write(os, 0);
}
void InsetCommandParams::Write(ostream & os, Buffer const * buffer) const
{
os << "CommandInset " << insetType() << '\n';
os << "LatexCommand " << cmdName_ << '\n';
@ -328,12 +335,27 @@ void InsetCommandParams::write(ostream & os) const
ParamInfo::const_iterator it = info_.begin();
ParamInfo::const_iterator end = info_.end();
for (; it != end; ++it) {
std::string const & name = it->name();
docstring const & data = (*this)[name];
string const & name = it->name();
string data = to_utf8((*this)[name]);
if (!data.empty()) {
// FIXME UNICODE
// Adjust path of files if document was moved
if (buffer && name == "filename") {
data = buffer->includedFilePath(data);
} else if (buffer && name == "bibfiles") {
int i = 0;
string newdata;
string bib = token(data, ',', i);
while (!bib.empty()) {
bib = buffer->includedFilePath(bib);
if (!newdata.empty())
newdata.append(1, ',');
newdata.append(bib);
bib = token(data, ',', ++i);
}
data = newdata;
}
os << name << ' '
<< Lexer::quoteString(to_utf8(data))
<< Lexer::quoteString(data)
<< '\n';
}
}

View File

@ -28,6 +28,7 @@
namespace lyx {
class Lexer;
class Buffer;
class ParamInfo {
public:
@ -117,6 +118,8 @@ public:
/// Parse the command
///
void write(std::ostream &) const;
///
void Write(std::ostream & os, Buffer const * buf) const;
/// Build the complete LaTeX command
docstring getCommand(OutputParams const &) const;
/// Return the command name

View File

@ -1030,6 +1030,12 @@ void InsetInclude::draw(PainterInfo & pi, int x, int y) const
}
void InsetInclude::write(ostream & os) const
{
params().Write(os, &buffer());
}
string InsetInclude::contextMenuName() const
{
return "context-include";

View File

@ -64,6 +64,8 @@ public:
///
void updateCommand();
///
void write(std::ostream &) const;
/// \name Public functions inherited from Inset class
//@{

View File

@ -82,6 +82,9 @@ What's new
* DOCUMENT INPUT/OUTPUT
- Update path of included files when saving a document to a different
location (bugs 9528, 5115).
- Fix LaTeX errors caused by too late loading of fixltx2e package
(bugs 9452, 9361).