From 22b7fb660c52ab4f1dd5ee7caab02108cf018159 Mon Sep 17 00:00:00 2001 From: wmayer Date: Wed, 16 Sep 2015 22:58:47 +0200 Subject: [PATCH] + save Brep in binary format for recovery files --- src/Base/Reader.cpp | 11 +- src/Base/Reader.h | 6 +- src/Base/Writer.cpp | 18 +++ src/Base/Writer.h | 8 ++ src/Gui/AutoSaver.cpp | 2 + src/Mod/Part/App/PropertyTopoShape.cpp | 174 ++++++++++++++----------- src/Mod/Sandbox/Gui/AppSandboxGui.cpp | 13 ++ 7 files changed, 151 insertions(+), 81 deletions(-) diff --git a/src/Base/Reader.cpp b/src/Base/Reader.cpp index de5474b91f..61ff606495 100644 --- a/src/Base/Reader.cpp +++ b/src/Base/Reader.cpp @@ -319,7 +319,7 @@ void Base::XMLReader::readFiles(zipios::ZipInputStream &zipstream) const // no file name for the current entry in the zip was registered. if (jt != FileList.end()) { try { - Base::Reader reader(zipstream,DocumentSchema); + Base::Reader reader(zipstream, jt->FileName, DocumentSchema); jt->Object->RestoreDocFile(reader); } catch(...) { @@ -506,11 +506,16 @@ void Base::XMLReader::resetErrors() // ---------------------------------------------------------- -Base::Reader::Reader(std::istream& str, int version) - : std::istream(str.rdbuf()), _str(str), fileVersion(version) +Base::Reader::Reader(std::istream& str, const std::string& name, int version) + : std::istream(str.rdbuf()), _str(str), _name(name), fileVersion(version) { } +std::string Base::Reader::getFileName() const +{ + return this->_name; +} + int Base::Reader::getFileVersion() const { return fileVersion; diff --git a/src/Base/Reader.h b/src/Base/Reader.h index 4d8a535729..0560c264ea 100644 --- a/src/Base/Reader.h +++ b/src/Base/Reader.h @@ -257,12 +257,14 @@ protected: class BaseExport Reader : public std::istream { public: - Reader(std::istream&, int version); - int getFileVersion() const; + Reader(std::istream&, const std::string&, int version); std::istream& getStream(); + std::string getFileName() const; + int getFileVersion() const; private: std::istream& _str; + std::string _name; int fileVersion; }; diff --git a/src/Base/Writer.cpp b/src/Base/Writer.cpp index 4b05564f33..2b3645f0e8 100644 --- a/src/Base/Writer.cpp +++ b/src/Base/Writer.cpp @@ -108,6 +108,24 @@ int Writer::getFileVersion() const return fileVersion; } +void Writer::setMode(const std::string& mode) +{ + Modes.insert(mode); +} + +bool Writer::getMode(const std::string& mode) const +{ + std::set::const_iterator it = Modes.find(mode); + return (it != Modes.end()); +} + +void Writer::clearMode(const std::string& mode) +{ + std::set::iterator it = Modes.find(mode); + if (it != Modes.end()) + Modes.erase(it); +} + std::string Writer::addFile(const char* Name,const Base::Persistence *Object) { // always check isForceXML() before requesting a file! diff --git a/src/Base/Writer.h b/src/Base/Writer.h index 3d3396f71f..af795a43a5 100644 --- a/src/Base/Writer.h +++ b/src/Base/Writer.h @@ -24,6 +24,7 @@ #define BASE_WRITER_H +#include #include #include #include @@ -80,6 +81,12 @@ public: virtual void writeFiles(void)=0; /// get all registered file names const std::vector& getFilenames() const; + /// Set mode + void setMode(const std::string& mode); + /// Get mode + bool getMode(const std::string& mode) const; + /// Clear mode + void clearMode(const std::string& mode); //@} /** @name pretty formating for XML */ @@ -105,6 +112,7 @@ protected: }; std::vector FileList; std::vector FileNames; + std::set Modes; short indent; char indBuf[1024]; diff --git a/src/Gui/AutoSaver.cpp b/src/Gui/AutoSaver.cpp index 8a1170b5a3..a9023f67a7 100644 --- a/src/Gui/AutoSaver.cpp +++ b/src/Gui/AutoSaver.cpp @@ -139,6 +139,8 @@ void AutoSaver::saveDocument(const std::string& name) Base::ofstream file(tmp, std::ios::out | std::ios::binary); if (file.is_open()) { Base::ZipWriter writer(file); + if (hGrp->GetBool("SaveBinaryBrep", true)) + writer.setMode("BinaryBrep"); writer.setComment("AutoRecovery file"); writer.setLevel(1); // apparently the fastest compression diff --git a/src/Mod/Part/App/PropertyTopoShape.cpp b/src/Mod/Part/App/PropertyTopoShape.cpp index 38f802ba09..ed4059ed0b 100644 --- a/src/Mod/Part/App/PropertyTopoShape.cpp +++ b/src/Mod/Part/App/PropertyTopoShape.cpp @@ -232,9 +232,16 @@ void PropertyPartShape::Save (Base::Writer &writer) const { if(!writer.isForceXML()) { //See SaveDocFile(), RestoreDocFile() - writer.Stream() << writer.ind() << "" << std::endl; + if (writer.getMode("BinaryBrep")) { + writer.Stream() << writer.ind() << "" << std::endl; + } + else { + writer.Stream() << writer.ind() << "" << std::endl; + } } } @@ -261,92 +268,107 @@ void PropertyPartShape::SaveDocFile (Base::Writer &writer) const const TopoDS_Shape& myShape = copy.Shape(); BRepTools::Clean(myShape); // remove triangulation - // create a temporary file and copy the content to the zip stream - // once the tmp. filename is known use always the same because otherwise - // we may run into some problems on the Linux platform - static Base::FileInfo fi(Base::FileInfo::getTempFileName()); - - if (!BRepTools::Write(myShape,(const Standard_CString)fi.filePath().c_str())) { - // Note: Do NOT throw an exception here because if the tmp. file could - // not be created we should not abort. - // We only print an error message but continue writing the next files to the - // stream... - App::PropertyContainer* father = this->getContainer(); - if (father && father->isDerivedFrom(App::DocumentObject::getClassTypeId())) { - App::DocumentObject* obj = static_cast(father); - Base::Console().Error("Shape of '%s' cannot be written to BRep file '%s'\n", - obj->Label.getValue(),fi.filePath().c_str()); - } - else { - Base::Console().Error("Cannot save BRep file '%s'\n", fi.filePath().c_str()); - } + if (writer.getMode("BinaryBrep")) { + TopoShape shape; + shape._Shape = myShape; + shape.exportBinary(writer.Stream()); } + else { + // create a temporary file and copy the content to the zip stream + // once the tmp. filename is known use always the same because otherwise + // we may run into some problems on the Linux platform + static Base::FileInfo fi(Base::FileInfo::getTempFileName()); - Base::ifstream file(fi, std::ios::in | std::ios::binary); - if (file){ - unsigned long ulSize = 0; - std::streambuf* buf = file.rdbuf(); - if (buf) { - unsigned long ulCurr; - ulCurr = buf->pubseekoff(0, std::ios::cur, std::ios::in); - ulSize = buf->pubseekoff(0, std::ios::end, std::ios::in); - buf->pubseekoff(ulCurr, std::ios::beg, std::ios::in); - } - - // read in the ASCII file and write back to the stream - std::strstreambuf sbuf(ulSize); - file >> &sbuf; - writer.Stream() << &sbuf; - } - - file.close(); - // remove temp file - fi.deleteFile(); -} - -void PropertyPartShape::RestoreDocFile(Base::Reader &reader) -{ - BRep_Builder builder; - - // create a temporary file and copy the content from the zip stream - Base::FileInfo fi(Base::FileInfo::getTempFileName()); - - // read in the ASCII file and write back to the file stream - Base::ofstream file(fi, std::ios::out | std::ios::binary); - unsigned long ulSize = 0; - if (reader) { - std::streambuf* buf = file.rdbuf(); - reader >> buf; - file.flush(); - ulSize = buf->pubseekoff(0, std::ios::cur, std::ios::in); - } - file.close(); - - // Read the shape from the temp file, if the file is empty the stored shape was already empty. - // If it's still empty after reading the (non-empty) file there must occurred an error. - TopoDS_Shape shape; - if (ulSize > 0) { - if (!BRepTools::Read(shape, (const Standard_CString)fi.filePath().c_str(), builder)) { - // Note: Do NOT throw an exception here because if the tmp. created file could - // not be read it's NOT an indication for an invalid input stream 'reader'. - // We only print an error message but continue reading the next files from the + if (!BRepTools::Write(myShape,(const Standard_CString)fi.filePath().c_str())) { + // Note: Do NOT throw an exception here because if the tmp. file could + // not be created we should not abort. + // We only print an error message but continue writing the next files to the // stream... App::PropertyContainer* father = this->getContainer(); if (father && father->isDerivedFrom(App::DocumentObject::getClassTypeId())) { App::DocumentObject* obj = static_cast(father); - Base::Console().Error("BRep file '%s' with shape of '%s' seems to be empty\n", - fi.filePath().c_str(),obj->Label.getValue()); + Base::Console().Error("Shape of '%s' cannot be written to BRep file '%s'\n", + obj->Label.getValue(),fi.filePath().c_str()); } else { - Base::Console().Warning("Loaded BRep file '%s' seems to be empty\n", fi.filePath().c_str()); + Base::Console().Error("Cannot save BRep file '%s'\n", fi.filePath().c_str()); } } + + Base::ifstream file(fi, std::ios::in | std::ios::binary); + if (file){ + unsigned long ulSize = 0; + std::streambuf* buf = file.rdbuf(); + if (buf) { + unsigned long ulCurr; + ulCurr = buf->pubseekoff(0, std::ios::cur, std::ios::in); + ulSize = buf->pubseekoff(0, std::ios::end, std::ios::in); + buf->pubseekoff(ulCurr, std::ios::beg, std::ios::in); + } + + // read in the ASCII file and write back to the stream + std::strstreambuf sbuf(ulSize); + file >> &sbuf; + writer.Stream() << &sbuf; + } + + file.close(); + // remove temp file + fi.deleteFile(); } +} - // delete the temp file - fi.deleteFile(); +void PropertyPartShape::RestoreDocFile(Base::Reader &reader) +{ + Base::FileInfo brep(reader.getFileName()); + if (brep.hasExtension("bin")) { + TopoShape shape; + shape.importBinary(reader); + setValue(shape); + } + else { + BRep_Builder builder; - setValue(shape); + // create a temporary file and copy the content from the zip stream + Base::FileInfo fi(Base::FileInfo::getTempFileName()); + + // read in the ASCII file and write back to the file stream + Base::ofstream file(fi, std::ios::out | std::ios::binary); + unsigned long ulSize = 0; + if (reader) { + std::streambuf* buf = file.rdbuf(); + reader >> buf; + file.flush(); + ulSize = buf->pubseekoff(0, std::ios::cur, std::ios::in); + } + file.close(); + + // Read the shape from the temp file, if the file is empty the stored shape was already empty. + // If it's still empty after reading the (non-empty) file there must occurred an error. + TopoDS_Shape shape; + if (ulSize > 0) { + if (!BRepTools::Read(shape, (const Standard_CString)fi.filePath().c_str(), builder)) { + // Note: Do NOT throw an exception here because if the tmp. created file could + // not be read it's NOT an indication for an invalid input stream 'reader'. + // We only print an error message but continue reading the next files from the + // stream... + App::PropertyContainer* father = this->getContainer(); + if (father && father->isDerivedFrom(App::DocumentObject::getClassTypeId())) { + App::DocumentObject* obj = static_cast(father); + Base::Console().Error("BRep file '%s' with shape of '%s' seems to be empty\n", + fi.filePath().c_str(),obj->Label.getValue()); + } + else { + Base::Console().Warning("Loaded BRep file '%s' seems to be empty\n", fi.filePath().c_str()); + } + } + } + + // delete the temp file + fi.deleteFile(); + + setValue(shape); + } } // ------------------------------------------------------------------------- diff --git a/src/Mod/Sandbox/Gui/AppSandboxGui.cpp b/src/Mod/Sandbox/Gui/AppSandboxGui.cpp index 4185cb3277..bb0bfd12cc 100644 --- a/src/Mod/Sandbox/Gui/AppSandboxGui.cpp +++ b/src/Mod/Sandbox/Gui/AppSandboxGui.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -194,6 +195,8 @@ public: { add_varargs_method("interactiveFilletArc",&SandboxModuleGui::interactiveFilletArc, "Interactive fillet arc"); + add_varargs_method("xmlReader",&SandboxModuleGui::xmlReader, + "Read XML"); initialize("This module is the SandboxGui module"); // register with Python } @@ -223,6 +226,16 @@ private: } return Py::None(); } + Py::Object xmlReader(const Py::Tuple& args) + { + std::string file = static_cast(Py::String(args[0])); + App::Document* doc = App::GetApplication().newDocument(); + + std::ifstream str(file.c_str(), std::ios::in); + Base::XMLReader reader(file.c_str(), str); + doc->Restore(reader); + return Py::None(); + } };