+ implement FileWriter class based on files and a specialized sub-class for recovery purposes
This commit is contained in:
parent
300e176eb3
commit
bb05d17596
|
@ -202,6 +202,8 @@ void Writer::decInd(void)
|
|||
indBuf[indent] = '\0';
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
ZipWriter::ZipWriter(const char* FileName)
|
||||
: ZipStream(FileName)
|
||||
{
|
||||
|
@ -245,3 +247,53 @@ ZipWriter::~ZipWriter()
|
|||
{
|
||||
ZipStream.close();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
FileWriter::FileWriter(const char* DirName) : DirName(DirName)
|
||||
{
|
||||
}
|
||||
|
||||
FileWriter::~FileWriter()
|
||||
{
|
||||
}
|
||||
|
||||
void FileWriter::putNextEntry(const char* file)
|
||||
{
|
||||
std::string fileName = DirName + "/" + file;
|
||||
this->FileStream.open(fileName.c_str(), std::ios::out);
|
||||
}
|
||||
|
||||
bool FileWriter::shouldWrite(const Base::Persistence *) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void FileWriter::writeFiles(void)
|
||||
{
|
||||
// use a while loop because it is possible that while
|
||||
// processing the files new ones can be added
|
||||
size_t index = 0;
|
||||
this->FileStream.close();
|
||||
while (index < FileList.size()) {
|
||||
FileEntry entry = FileList.begin()[index];
|
||||
|
||||
if (shouldWrite(entry.Object)) {
|
||||
std::string filePath = entry.FileName;
|
||||
std::string::size_type pos = 0;
|
||||
while ((pos = filePath.find("/", pos)) != std::string::npos) {
|
||||
std::string dirName = DirName + "/" + filePath.substr(0, pos);
|
||||
pos++;
|
||||
Base::FileInfo fi(dirName);
|
||||
fi.createDirectory();
|
||||
}
|
||||
|
||||
std::string fileName = DirName + "/" + entry.FileName;
|
||||
this->FileStream.open(fileName.c_str(), std::ios::out | std::ios::binary);
|
||||
entry.Object->SaveDocFile(*this);
|
||||
this->FileStream.close();
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -130,11 +130,10 @@ protected:
|
|||
*/
|
||||
class BaseExport ZipWriter : public Writer
|
||||
{
|
||||
|
||||
public:
|
||||
ZipWriter(const char* FileName);
|
||||
ZipWriter(std::ostream&);
|
||||
~ZipWriter();
|
||||
virtual ~ZipWriter();
|
||||
|
||||
virtual void writeFiles(void);
|
||||
|
||||
|
@ -159,13 +158,40 @@ class BaseExport StringWriter : public Writer
|
|||
|
||||
public:
|
||||
virtual std::ostream &Stream(void){return StrStream;}
|
||||
std::string getString(void){return StrStream.str();}
|
||||
virtual void writeFiles(void){assert(0);}
|
||||
std::string getString(void) const {return StrStream.str();}
|
||||
virtual void writeFiles(void){}
|
||||
|
||||
private:
|
||||
std::stringstream StrStream;
|
||||
};
|
||||
|
||||
/*! The FileWriter class
|
||||
This class writes out the data into files into a given directory name.
|
||||
\see Base::Persistence
|
||||
\author Werner Mayer
|
||||
*/
|
||||
class BaseExport FileWriter : public Writer
|
||||
{
|
||||
public:
|
||||
FileWriter(const char* DirName);
|
||||
virtual ~FileWriter();
|
||||
|
||||
void putNextEntry(const char* file);
|
||||
virtual void writeFiles(void);
|
||||
|
||||
virtual std::ostream &Stream(void){return FileStream;}
|
||||
/*!
|
||||
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 *Object) const;
|
||||
|
||||
private:
|
||||
std::string DirName;
|
||||
std::ofstream FileStream;
|
||||
};
|
||||
|
||||
|
||||
} //namespace Base
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
# include <QFile>
|
||||
# include <QTextStream>
|
||||
# include <boost/bind.hpp>
|
||||
# include <sstream>
|
||||
#endif
|
||||
|
||||
#include "AutoSaver.h"
|
||||
|
@ -38,9 +39,11 @@
|
|||
#include <App/Application.h>
|
||||
#include <App/Document.h>
|
||||
|
||||
#include "Document.h"
|
||||
#include "WaitCursor.h"
|
||||
#include "Widgets.h"
|
||||
#include "MainWindow.h"
|
||||
#include "ViewProvider.h"
|
||||
|
||||
using namespace Gui;
|
||||
|
||||
|
@ -69,11 +72,11 @@ void AutoSaver::setTimeout(int ms)
|
|||
timeout = Base::clamp<int>(ms, 0, 3600000); // between 0 and 60 min
|
||||
|
||||
// go through the attached documents and apply the new timeout
|
||||
for (std::map<std::string, int>::iterator it = timerMap.begin(); it != timerMap.end(); ++it) {
|
||||
if (it->second > 0)
|
||||
killTimer(it->second);
|
||||
for (std::map<std::string, AutoSaveProperty*>::iterator it = saverMap.begin(); it != saverMap.end(); ++it) {
|
||||
if (it->second->timerId > 0)
|
||||
killTimer(it->second->timerId);
|
||||
int id = timeout > 0 ? startTimer(timeout) : 0;
|
||||
it->second = id;
|
||||
it->second->timerId = id;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -81,21 +84,24 @@ void AutoSaver::slotCreateDocument(const App::Document& Doc)
|
|||
{
|
||||
std::string name = Doc.getName();
|
||||
int id = timeout > 0 ? startTimer(timeout) : 0;
|
||||
timerMap[name] = id;
|
||||
AutoSaveProperty* as = new AutoSaveProperty(&Doc);
|
||||
as->timerId = id;
|
||||
saverMap.insert(std::make_pair(name, as));
|
||||
}
|
||||
|
||||
void AutoSaver::slotDeleteDocument(const App::Document& Doc)
|
||||
{
|
||||
std::string name = Doc.getName();
|
||||
std::map<std::string, int>::iterator it = timerMap.find(name);
|
||||
if (it != timerMap.end()) {
|
||||
if (it->second > 0)
|
||||
killTimer(it->second);
|
||||
timerMap.erase(it);
|
||||
std::map<std::string, AutoSaveProperty*>::iterator it = saverMap.find(name);
|
||||
if (it != saverMap.end()) {
|
||||
if (it->second->timerId > 0)
|
||||
killTimer(it->second->timerId);
|
||||
delete it->second;
|
||||
saverMap.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
void AutoSaver::saveDocument(const std::string& name)
|
||||
void AutoSaver::saveDocument(const std::string& name, const std::set<std::string>& data)
|
||||
{
|
||||
Gui::WaitCursor wc;
|
||||
App::Document* doc = App::GetApplication().getDocument(name.c_str());
|
||||
|
@ -168,10 +174,11 @@ void AutoSaver::saveDocument(const std::string& name)
|
|||
void AutoSaver::timerEvent(QTimerEvent * event)
|
||||
{
|
||||
int id = event->timerId();
|
||||
for (std::map<std::string, int>::iterator it = timerMap.begin(); it != timerMap.end(); ++it) {
|
||||
if (it->second == id) {
|
||||
for (std::map<std::string, AutoSaveProperty*>::iterator it = saverMap.begin(); it != saverMap.end(); ++it) {
|
||||
if (it->second->timerId == id) {
|
||||
try {
|
||||
saveDocument(it->first);
|
||||
saveDocument(it->first, it->second->objects);
|
||||
it->second->objects.clear();
|
||||
break;
|
||||
}
|
||||
catch (...) {
|
||||
|
@ -181,4 +188,65 @@ void AutoSaver::timerEvent(QTimerEvent * event)
|
|||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
AutoSaveProperty::AutoSaveProperty(const App::Document* doc) : timerId(-1)
|
||||
{
|
||||
document = const_cast<App::Document*>(doc)->signalChangedObject.connect
|
||||
(boost::bind(&AutoSaveProperty::slotChangePropertyData, this, _2));
|
||||
}
|
||||
|
||||
AutoSaveProperty::~AutoSaveProperty()
|
||||
{
|
||||
document.disconnect();
|
||||
}
|
||||
|
||||
void AutoSaveProperty::slotChangePropertyData(const App::Property& prop)
|
||||
{
|
||||
std::stringstream str;
|
||||
str << static_cast<const void *>(&prop) << std::ends;
|
||||
std::string address = str.str();
|
||||
this->objects.insert(address);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
RecoveryWriter::RecoveryWriter(const char* DirName)
|
||||
: Base::FileWriter(DirName)
|
||||
{
|
||||
}
|
||||
|
||||
RecoveryWriter::~RecoveryWriter()
|
||||
{
|
||||
}
|
||||
|
||||
void RecoveryWriter::setModifiedData(const std::set<std::string>& m)
|
||||
{
|
||||
data = m;
|
||||
}
|
||||
|
||||
bool RecoveryWriter::shouldWrite(const Base::Persistence *object) const
|
||||
{
|
||||
// Property files of a view provider can always be written because
|
||||
// these are rather small files.
|
||||
if (object->isDerivedFrom(App::Property::getClassTypeId())) {
|
||||
const App::Property* prop = static_cast<const App::Property*>(object);
|
||||
const App::PropertyContainer* parent = prop->getContainer();
|
||||
if (parent && parent->isDerivedFrom(Gui::ViewProvider::getClassTypeId()))
|
||||
return true;
|
||||
}
|
||||
else if (object->isDerivedFrom(Gui::Document::getClassTypeId())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// These are the addresses of touched properties of a document object.
|
||||
std::stringstream str;
|
||||
str << static_cast<const void *>(object) << std::ends;
|
||||
std::string address = str.str();
|
||||
|
||||
std::set<std::string>::const_iterator it = data.find(address);
|
||||
return (it != data.end());
|
||||
}
|
||||
|
||||
|
||||
#include "moc_AutoSaver.cpp"
|
||||
|
|
|
@ -25,14 +25,33 @@
|
|||
#define GUI_AUTOSAVER_H
|
||||
|
||||
#include <QObject>
|
||||
#include <Base/Writer.h>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <boost/signals.hpp>
|
||||
|
||||
namespace App {
|
||||
class Document;
|
||||
class Property;
|
||||
}
|
||||
|
||||
namespace Gui {
|
||||
class ViewProvider;
|
||||
|
||||
class AutoSaveProperty
|
||||
{
|
||||
public:
|
||||
AutoSaveProperty(const App::Document* doc);
|
||||
~AutoSaveProperty();
|
||||
int timerId;
|
||||
std::set<std::string> objects;
|
||||
|
||||
private:
|
||||
void slotChangePropertyData(const App::Property&);
|
||||
typedef boost::BOOST_SIGNALS_NAMESPACE::connection Connection;
|
||||
Connection document;
|
||||
};
|
||||
|
||||
/*!
|
||||
The class AutoSaver is used to automatically save a document to a temporary file.
|
||||
|
@ -58,11 +77,29 @@ protected:
|
|||
void slotCreateDocument(const App::Document& Doc);
|
||||
void slotDeleteDocument(const App::Document& Doc);
|
||||
void timerEvent(QTimerEvent * event);
|
||||
void saveDocument(const std::string&);
|
||||
void saveDocument(const std::string&, const std::set<std::string>&);
|
||||
|
||||
private:
|
||||
int timeout; /*!< Timeout in milliseconds */
|
||||
std::map<std::string, int> timerMap;
|
||||
std::map<std::string, AutoSaveProperty*> saverMap;
|
||||
};
|
||||
|
||||
class RecoveryWriter : public Base::FileWriter
|
||||
{
|
||||
public:
|
||||
RecoveryWriter(const char* DirName);
|
||||
virtual ~RecoveryWriter();
|
||||
void setModifiedData(const std::set<std::string> &);
|
||||
|
||||
/*!
|
||||
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;
|
||||
|
||||
private:
|
||||
std::set<std::string> data;
|
||||
};
|
||||
|
||||
} //namespace Gui
|
||||
|
|
Loading…
Reference in New Issue
Block a user