From dadc87eff85966b463d05dfef9a2d7ef3d4c9bc6 Mon Sep 17 00:00:00 2001 From: wmayer Date: Mon, 30 Mar 2015 02:23:49 +0200 Subject: [PATCH] + fixes #0002029: VRML inline ignored --- src/App/PropertyFile.cpp | 7 ++++++- src/App/VRMLObject.cpp | 33 ++++++++++++++++++++++++++++++--- src/App/VRMLObject.h | 3 ++- 3 files changed, 38 insertions(+), 5 deletions(-) diff --git a/src/App/PropertyFile.cpp b/src/App/PropertyFile.cpp index 4bffd9d3a..d9b6f378a 100644 --- a/src/App/PropertyFile.cpp +++ b/src/App/PropertyFile.cpp @@ -412,11 +412,16 @@ void PropertyFileIncluded::SaveDocFile (Base::Writer &writer) const void PropertyFileIncluded::RestoreDocFile(Base::Reader &reader) { Base::FileInfo fi(_cValue.c_str()); + if (fi.exists() && !fi.isWritable()) { + // This happens when an object is being restored and tries to reference the + // same file of another object (e.g. for copy&paste of objects inside the same document). + return; + } Base::ofstream to(fi, std::ios::out | std::ios::binary); if (!to) { std::stringstream str; str << "PropertyFileIncluded::RestoreDocFile(): " - << "File '" << _cValue << "' in transient directory doesn't exist."; + << "File '" << _cValue << "' in transient directory cannot be created."; throw Base::Exception(str.str()); } diff --git a/src/App/VRMLObject.cpp b/src/App/VRMLObject.cpp index ecf3d262c..7752f2ffa 100644 --- a/src/App/VRMLObject.cpp +++ b/src/App/VRMLObject.cpp @@ -75,7 +75,7 @@ void VRMLObject::onChanged(const App::Property* prop) const std::vector& urls = Urls.getValues(); int index=0; for (std::vector::const_iterator it = urls.begin(); it != urls.end(); ++it, ++index) { - std::string output = getOutputFile(this->vrmlPath, *it); + std::string output = getRelativePath(this->vrmlPath, *it); Resources.set1Value(index, output); } } @@ -91,7 +91,7 @@ PyObject *VRMLObject::getPyObject() return Py::new_reference_to(PythonObject); } -std::string VRMLObject::getOutputFile(const std::string& prefix, const std::string& resource) const +std::string VRMLObject::getRelativePath(const std::string& prefix, const std::string& resource) const { std::string str; std::string intname = this->getNameInDocument(); @@ -110,6 +110,20 @@ std::string VRMLObject::getOutputFile(const std::string& prefix, const std::stri return str; } +std::string VRMLObject::fixRelativePath(const std::string& name, const std::string& resource) const +{ + // the part before the first '/' must match with object's internal name + std::string::size_type pos = resource.find('/'); + if (pos != std::string::npos) { + std::string prefix = resource.substr(0, pos); + std::string suffix = resource.substr(pos); + if (prefix != name) { + return name + suffix; + } + } + return resource; +} + void VRMLObject::makeDirectories(const std::string& path, const std::string& subdir) { std::string::size_type pos = subdir.find('/'); @@ -155,9 +169,19 @@ void VRMLObject::SaveDocFile (Base::Writer &writer) const // store the inline files of the VRML file if (this->index < Urls.getSize()) { std::string url = Urls[this->index]; - this->index++; Base::FileInfo fi(url); + // it can happen that the transient directory has changed after + // saving the 'URLs' in RestoreDocFile() and then we have to + // try again with the new transient directory. + if (!fi.exists()) { + std::string path = getDocument()->TransientDir.getValue(); + url = Resources[this->index]; + url = path + "/" + url; + fi.setFile(url); + } + + this->index++; Base::ifstream file(fi, std::ios::in | std::ios::binary); if (file) { writer.Stream() << file.rdbuf(); @@ -170,6 +194,9 @@ void VRMLObject::RestoreDocFile(Base::Reader &reader) if (this->index < Resources.getSize()) { std::string path = getDocument()->TransientDir.getValue(); std::string url = Resources[this->index]; + std::string intname = this->getNameInDocument(); + url = fixRelativePath(intname, url); + Resources.set1Value(this->index, url); makeDirectories(path, url); url = path + "/" + url; diff --git a/src/App/VRMLObject.h b/src/App/VRMLObject.h index 9a774391c..33d78cfb0 100644 --- a/src/App/VRMLObject.h +++ b/src/App/VRMLObject.h @@ -60,7 +60,8 @@ public: protected: void onChanged(const App::Property*); - std::string getOutputFile(const std::string&, const std::string&) const; + std::string getRelativePath(const std::string&, const std::string&) const; + std::string fixRelativePath(const std::string&, const std::string&) const; void makeDirectories(const std::string&, const std::string&); private: