From 8db1280a4d185bac0108dd553fd32bcc801cbf04 Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 18 Sep 2015 15:32:33 +0200 Subject: [PATCH] + make RecoveryWriter more robust --- src/Base/Writer.cpp | 4 +-- src/Base/Writer.h | 4 +-- src/Gui/AutoSaver.cpp | 62 ++++++++++++++++++++++++++++++++++--------- src/Gui/AutoSaver.h | 21 ++++++++++----- 4 files changed, 67 insertions(+), 24 deletions(-) diff --git a/src/Base/Writer.cpp b/src/Base/Writer.cpp index 9d0d048c6ee5..1955bf883bdb 100644 --- a/src/Base/Writer.cpp +++ b/src/Base/Writer.cpp @@ -264,7 +264,7 @@ void FileWriter::putNextEntry(const char* file) this->FileStream.open(fileName.c_str(), std::ios::out); } -bool FileWriter::shouldWrite(const Base::Persistence *) const +bool FileWriter::shouldWrite(const std::string& , const Base::Persistence *) const { return true; } @@ -278,7 +278,7 @@ void FileWriter::writeFiles(void) while (index < FileList.size()) { FileEntry entry = FileList.begin()[index]; - if (shouldWrite(entry.Object)) { + if (shouldWrite(entry.FileName, entry.Object)) { std::string filePath = entry.FileName; std::string::size_type pos = 0; while ((pos = filePath.find("/", pos)) != std::string::npos) { diff --git a/src/Base/Writer.h b/src/Base/Writer.h index fa867d06f11a..53f86e38362b 100644 --- a/src/Base/Writer.h +++ b/src/Base/Writer.h @@ -165,7 +165,7 @@ class BaseExport StringWriter : public Writer std::stringstream StrStream; }; -/*! The FileWriter class +/*! The FileWriter class This class writes out the data into files into a given directory name. \see Base::Persistence \author Werner Mayer @@ -185,7 +185,7 @@ class BaseExport FileWriter : public Writer to write out certain objects. The default implementation always returns true. */ - virtual bool shouldWrite(const Base::Persistence *Object) const; + virtual bool shouldWrite(const std::string& name, const Base::Persistence *Object) const; private: std::string DirName; diff --git a/src/Gui/AutoSaver.cpp b/src/Gui/AutoSaver.cpp index c645a3acb951..16ad020ec91e 100644 --- a/src/Gui/AutoSaver.cpp +++ b/src/Gui/AutoSaver.cpp @@ -33,11 +33,13 @@ #include "AutoSaver.h" #include +#include #include #include #include #include #include +#include #include "Document.h" #include "WaitCursor.h" @@ -86,6 +88,11 @@ void AutoSaver::slotCreateDocument(const App::Document& Doc) int id = timeout > 0 ? startTimer(timeout) : 0; AutoSaveProperty* as = new AutoSaveProperty(&Doc); as->timerId = id; + std::string dirName = Doc.TransientDir.getValue(); + dirName += "/fc_recovery_files"; + Base::FileInfo fi(dirName); + fi.createDirectory(); + as->dirName = dirName; saverMap.insert(std::make_pair(name, as)); } @@ -101,7 +108,7 @@ void AutoSaver::slotDeleteDocument(const App::Document& Doc) } } -void AutoSaver::saveDocument(const std::string& name, const std::set& data) +void AutoSaver::saveDocument(const std::string& name, AutoSaveProperty& saver) { Gui::WaitCursor wc; App::Document* doc = App::GetApplication().getDocument(name.c_str()); @@ -145,6 +152,7 @@ void AutoSaver::saveDocument(const std::string& name, const std::setGetBool("SaveBinaryBrep", true)) writer.setMode("BinaryBrep"); @@ -177,8 +185,8 @@ void AutoSaver::timerEvent(QTimerEvent * event) for (std::map::iterator it = saverMap.begin(); it != saverMap.end(); ++it) { if (it->second->timerId == id) { try { - saveDocument(it->first, it->second->objects); - it->second->objects.clear(); + saveDocument(it->first, *it->second); + it->second->touched.clear(); break; } catch (...) { @@ -192,13 +200,28 @@ void AutoSaver::timerEvent(QTimerEvent * event) AutoSaveProperty::AutoSaveProperty(const App::Document* doc) : timerId(-1) { - document = const_cast(doc)->signalChangedObject.connect + documentNew = const_cast(doc)->signalNewObject.connect + (boost::bind(&AutoSaveProperty::slotNewObject, this, _1)); + documentMod = const_cast(doc)->signalChangedObject.connect (boost::bind(&AutoSaveProperty::slotChangePropertyData, this, _2)); } AutoSaveProperty::~AutoSaveProperty() { - document.disconnect(); + documentNew.disconnect(); + documentMod.disconnect(); +} + +void AutoSaveProperty::slotNewObject(const App::DocumentObject& obj) +{ + std::vector props; + obj.getPropertyList(props); + + // if an object was deleted and then restored by an undo then add all properties + // because this might be the data files which we may want to re-write + for (std::vector::iterator it = props.begin(); it != props.end(); ++it) { + slotChangePropertyData(*(*it)); + } } void AutoSaveProperty::slotChangePropertyData(const App::Property& prop) @@ -206,13 +229,13 @@ void AutoSaveProperty::slotChangePropertyData(const App::Property& prop) std::stringstream str; str << static_cast(&prop) << std::ends; std::string address = str.str(); - this->objects.insert(address); + this->touched.insert(address); } // ---------------------------------------------------------------------------- -RecoveryWriter::RecoveryWriter(const char* DirName) - : Base::FileWriter(DirName) +RecoveryWriter::RecoveryWriter(AutoSaveProperty& saver) + : Base::FileWriter(saver.dirName.c_str()), saver(saver) { } @@ -220,12 +243,17 @@ RecoveryWriter::~RecoveryWriter() { } -void RecoveryWriter::setModifiedData(const std::set& m) +void RecoveryWriter::setLevel(int) { - data = m; + // not implemented } -bool RecoveryWriter::shouldWrite(const Base::Persistence *object) const +void RecoveryWriter::setComment(const char*) +{ + // not implemented +} + +bool RecoveryWriter::shouldWrite(const std::string& name, const Base::Persistence *object) const { // Property files of a view provider can always be written because // these are rather small files. @@ -244,8 +272,16 @@ bool RecoveryWriter::shouldWrite(const Base::Persistence *object) const str << static_cast(object) << std::ends; std::string address = str.str(); - std::set::const_iterator it = data.find(address); - return (it != data.end()); + // Check if the property will be exported to the same file. If the file has changed or if the property hasn't been + // yet exported then (re-)write the file. + std::map::iterator it = saver.fileMap.find(address); + if (it == saver.fileMap.end() || it->second != name) { + saver.fileMap[address] = name; + return true; + } + + std::set::const_iterator jt = saver.touched.find(address); + return (jt != saver.touched.end()); } diff --git a/src/Gui/AutoSaver.h b/src/Gui/AutoSaver.h index b97f8da7003a..3cd5c445a1a0 100644 --- a/src/Gui/AutoSaver.h +++ b/src/Gui/AutoSaver.h @@ -33,6 +33,7 @@ namespace App { class Document; +class DocumentObject; class Property; } @@ -45,12 +46,16 @@ class AutoSaveProperty AutoSaveProperty(const App::Document* doc); ~AutoSaveProperty(); int timerId; - std::set objects; + std::set touched; + std::string dirName; + std::map fileMap; private: + void slotNewObject(const App::DocumentObject&); void slotChangePropertyData(const App::Property&); typedef boost::BOOST_SIGNALS_NAMESPACE::connection Connection; - Connection document; + Connection documentNew; + Connection documentMod; }; /*! @@ -77,7 +82,7 @@ class AutoSaver : public QObject void slotCreateDocument(const App::Document& Doc); void slotDeleteDocument(const App::Document& Doc); void timerEvent(QTimerEvent * event); - void saveDocument(const std::string&, const std::set&); + void saveDocument(const std::string&, AutoSaveProperty&); private: int timeout; /*!< Timeout in milliseconds */ @@ -87,19 +92,21 @@ class AutoSaver : public QObject class RecoveryWriter : public Base::FileWriter { public: - RecoveryWriter(const char* DirName); + RecoveryWriter(AutoSaveProperty&); virtual ~RecoveryWriter(); - void setModifiedData(const std::set &); + + void setLevel(int); + void setComment(const char*); /*! This method can be re-implemented in sub-classes to avoid to write out certain objects. The default implementation always returns true. */ - virtual bool shouldWrite(const Base::Persistence *) const; + virtual bool shouldWrite(const std::string&, const Base::Persistence *) const; private: - std::set data; + AutoSaveProperty& saver; }; } //namespace Gui