+ implement auto-save function for documents
This commit is contained in:
@@ -62,6 +62,7 @@
|
||||
#include <App/DocumentObjectPy.h>
|
||||
|
||||
#include "Application.h"
|
||||
#include "AutoSaver.h"
|
||||
#include "GuiApplicationNativeEventAware.h"
|
||||
#include "MainWindow.h"
|
||||
#include "Document.h"
|
||||
@@ -1695,6 +1696,8 @@ void Application::runApplication(void)
|
||||
MainWindow mw;
|
||||
mw.setWindowTitle(mainApp.applicationName());
|
||||
|
||||
AutoSaver::instance()->setTimeout(3);
|
||||
|
||||
// set toolbar icon size
|
||||
ParameterGrp::handle hGrp = WindowParameter::getDefaultParameter()->GetGroup("General");
|
||||
int size = hGrp->GetInt("ToolbarIconSize", 0);
|
||||
|
||||
140
src/Gui/AutoSaver.cpp
Normal file
140
src/Gui/AutoSaver.cpp
Normal file
@@ -0,0 +1,140 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2010 Werner Mayer <wmayer[at]users.sourceforge.net> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#include "PreCompiled.h"
|
||||
|
||||
#ifndef _PreComp_
|
||||
# include <QApplication>
|
||||
# include <boost/bind.hpp>
|
||||
#endif
|
||||
|
||||
#include "AutoSaver.h"
|
||||
#include <Base/Console.h>
|
||||
#include <Base/Stream.h>
|
||||
#include <Base/Tools.h>
|
||||
#include <Base/Writer.h>
|
||||
#include <App/Application.h>
|
||||
#include <App/Document.h>
|
||||
|
||||
#include "WaitCursor.h"
|
||||
|
||||
using namespace Gui;
|
||||
|
||||
AutoSaver* AutoSaver::self = 0;
|
||||
|
||||
AutoSaver::AutoSaver(QObject* parent)
|
||||
: QObject(parent), timeout(5)
|
||||
{
|
||||
App::GetApplication().signalNewDocument.connect(boost::bind(&AutoSaver::slotCreateDocument, this, _1));
|
||||
App::GetApplication().signalDeleteDocument.connect(boost::bind(&AutoSaver::slotDeleteDocument, this, _1));
|
||||
}
|
||||
|
||||
AutoSaver::~AutoSaver()
|
||||
{
|
||||
}
|
||||
|
||||
AutoSaver* AutoSaver::instance()
|
||||
{
|
||||
if (!self)
|
||||
self = new AutoSaver(QApplication::instance());
|
||||
return self;
|
||||
}
|
||||
|
||||
void AutoSaver::setTimeout(int s)
|
||||
{
|
||||
timeout = Base::clamp<int>(s, 0, 30);
|
||||
}
|
||||
|
||||
void AutoSaver::slotCreateDocument(const App::Document& Doc)
|
||||
{
|
||||
std::string name = Doc.getName();
|
||||
if (timeout > 0) {
|
||||
int id = startTimer(timeout * 60000);
|
||||
timerMap[name] = id;
|
||||
}
|
||||
}
|
||||
|
||||
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()) {
|
||||
killTimer(it->second);
|
||||
timerMap.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
void AutoSaver::saveDocument(const std::string& name)
|
||||
{
|
||||
Gui::WaitCursor wc;
|
||||
App::Document* doc = App::GetApplication().getDocument(name.c_str());
|
||||
if (doc) {
|
||||
std::string fn = doc->TransientDir.getValue();
|
||||
fn += "/fc_autosave_file.fcstd";
|
||||
Base::FileInfo tmp(fn);
|
||||
|
||||
// make sure to tmp. disable saving thumbnails because this causes trouble if the
|
||||
// associated 3d view is not active
|
||||
Base::Reference<ParameterGrp> hGrp = App::GetApplication().GetParameterGroupByPath
|
||||
("User parameter:BaseApp/Preferences/Document");
|
||||
bool save = hGrp->GetBool("SaveThumbnail",false);
|
||||
hGrp->SetBool("SaveThumbnail",false);
|
||||
|
||||
// open extra scope to close ZipWriter properly
|
||||
{
|
||||
Base::ofstream file(tmp, std::ios::out | std::ios::binary);
|
||||
Base::ZipWriter writer(file);
|
||||
|
||||
writer.setComment("FreeCAD Document");
|
||||
writer.setLevel(0);
|
||||
writer.putNextEntry("Document.xml");
|
||||
|
||||
doc->Save(writer);
|
||||
|
||||
// Special handling for Gui document.
|
||||
doc->signalSaveDocument(writer);
|
||||
|
||||
// write additional files
|
||||
writer.writeFiles();
|
||||
}
|
||||
hGrp->SetBool("SaveThumbnail",save);
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
try {
|
||||
saveDocument(it->first);
|
||||
break;
|
||||
}
|
||||
catch (...) {
|
||||
Base::Console().Error("Failed to auto-save document '%s'\n", it->first.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#include "moc_AutoSaver.cpp"
|
||||
71
src/Gui/AutoSaver.h
Normal file
71
src/Gui/AutoSaver.h
Normal file
@@ -0,0 +1,71 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2010 Werner Mayer <wmayer[at]users.sourceforge.net> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#ifndef GUI_AUTOSAVER_H
|
||||
#define GUI_AUTOSAVER_H
|
||||
|
||||
#include <QObject>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
namespace App {
|
||||
class Document;
|
||||
}
|
||||
|
||||
namespace Gui {
|
||||
|
||||
/*!
|
||||
The class AutoSaver is used to automatically save a document to a temporary file.
|
||||
@author Werner Mayer
|
||||
*/
|
||||
class AutoSaver : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
static AutoSaver* self;
|
||||
AutoSaver(QObject* parent);
|
||||
virtual ~AutoSaver();
|
||||
|
||||
public:
|
||||
static AutoSaver* instance();
|
||||
/*!
|
||||
Sets the timeout in minutes. A value of 0 means that no timer is used.
|
||||
*/
|
||||
void setTimeout(int s);
|
||||
|
||||
protected:
|
||||
void slotCreateDocument(const App::Document& Doc);
|
||||
void slotDeleteDocument(const App::Document& Doc);
|
||||
void timerEvent(QTimerEvent * event);
|
||||
void saveDocument(const std::string&);
|
||||
|
||||
private:
|
||||
int timeout; /*!< Timeout in minutes */
|
||||
std::map<std::string, int> timerMap;
|
||||
};
|
||||
|
||||
} //namespace Gui
|
||||
|
||||
|
||||
#endif //GUI_AUTOSAVER_H
|
||||
@@ -155,6 +155,7 @@ set(Gui_MOC_HDRS
|
||||
Action.h
|
||||
ActionFunction.h
|
||||
Assistant.h
|
||||
AutoSaver.h
|
||||
CallTips.h
|
||||
CombiView.h
|
||||
Control.h
|
||||
@@ -955,6 +956,7 @@ SOURCE_GROUP("Selection" FILES ${Selection_SRCS})
|
||||
SET(FreeCADGui_CPP_SRCS
|
||||
Application.cpp
|
||||
ApplicationPy.cpp
|
||||
AutoSaver.cpp
|
||||
BitmapFactory.cpp
|
||||
Document.cpp
|
||||
DocumentModel.cpp
|
||||
@@ -975,6 +977,7 @@ SET(FreeCADGui_CPP_SRCS
|
||||
)
|
||||
SET(FreeCADGui_SRCS
|
||||
Application.h
|
||||
AutoSaver.h
|
||||
BitmapFactory.h
|
||||
Document.h
|
||||
DocumentModel.h
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
|
||||
#include <Base/Console.h>
|
||||
#include <Base/Sequencer.h>
|
||||
#include <Base/Writer.h>
|
||||
#include <Base/Interpreter.h>
|
||||
#include <App/Application.h>
|
||||
#include <App/Document.h>
|
||||
@@ -229,3 +230,41 @@ void DocumentTestThread::run()
|
||||
dp.recompute();
|
||||
op.execute(Callable<SandboxObject,&SandboxObject::resetValue>(obj));
|
||||
}
|
||||
|
||||
|
||||
DocumentSaverThread::DocumentSaverThread(App::Document* doc, QObject* parent)
|
||||
: QThread(parent), doc(doc)
|
||||
{
|
||||
}
|
||||
|
||||
DocumentSaverThread::~DocumentSaverThread()
|
||||
{
|
||||
}
|
||||
|
||||
void DocumentSaverThread::run()
|
||||
{
|
||||
std::string uuid = Base::Uuid::createUuid();
|
||||
std::string fn = doc->TransientDir.getValue();
|
||||
fn += "/";
|
||||
fn += uuid;
|
||||
fn += ".autosave";
|
||||
Base::FileInfo tmp(fn);
|
||||
|
||||
// open extra scope to close ZipWriter properly
|
||||
{
|
||||
Base::ofstream file(tmp, std::ios::out | std::ios::binary);
|
||||
Base::ZipWriter writer(file);
|
||||
|
||||
writer.setComment("FreeCAD Document");
|
||||
writer.setLevel(0);
|
||||
writer.putNextEntry("Document.xml");
|
||||
|
||||
doc->Save(writer);
|
||||
|
||||
// Special handling for Gui document.
|
||||
doc->signalSaveDocument(writer);
|
||||
|
||||
// write additional files
|
||||
writer.writeFiles();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,6 +113,19 @@ protected:
|
||||
void run();
|
||||
};
|
||||
|
||||
class SandboxAppExport DocumentSaverThread : public QThread
|
||||
{
|
||||
public:
|
||||
DocumentSaverThread(App::Document* doc, QObject* parent=0);
|
||||
~DocumentSaverThread();
|
||||
|
||||
protected:
|
||||
void run();
|
||||
|
||||
private:
|
||||
App::Document* doc;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // SANDBOX_DOCUMENTTHREAD_H
|
||||
|
||||
@@ -130,6 +130,34 @@ void CmdSandboxDocumentTestThread::activated(int iMsg)
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
|
||||
DEF_STD_CMD_A(CmdSandboxDocumentSaveThread);
|
||||
|
||||
CmdSandboxDocumentSaveThread::CmdSandboxDocumentSaveThread()
|
||||
:Command("Sandbox_SaveThread")
|
||||
{
|
||||
sAppModule = "Sandbox";
|
||||
sGroup = QT_TR_NOOP("Sandbox");
|
||||
sMenuText = QT_TR_NOOP("Save thread");
|
||||
sToolTipText = QT_TR_NOOP("Sandbox save function");
|
||||
sWhatsThis = QT_TR_NOOP("Sandbox save function");
|
||||
sStatusTip = QT_TR_NOOP("Sandbox save function");
|
||||
}
|
||||
|
||||
void CmdSandboxDocumentSaveThread::activated(int iMsg)
|
||||
{
|
||||
App::Document* doc = App::GetApplication().getActiveDocument();
|
||||
Sandbox::DocumentSaverThread* dt = new Sandbox::DocumentSaverThread(doc);
|
||||
QObject::connect(dt, SIGNAL(finished()), dt, SLOT(deleteLater()));
|
||||
dt->start();
|
||||
}
|
||||
|
||||
bool CmdSandboxDocumentSaveThread::isActive()
|
||||
{
|
||||
return App::GetApplication().getActiveDocument() != 0;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
|
||||
DEF_STD_CMD(CmdSandboxDocThreadWithSeq);
|
||||
|
||||
CmdSandboxDocThreadWithSeq::CmdSandboxDocThreadWithSeq()
|
||||
@@ -1410,6 +1438,7 @@ void CreateSandboxCommands(void)
|
||||
Gui::CommandManager &rcCmdMgr = Gui::Application::Instance->commandManager();
|
||||
rcCmdMgr.addCommand(new CmdSandboxDocumentThread());
|
||||
rcCmdMgr.addCommand(new CmdSandboxDocumentTestThread());
|
||||
rcCmdMgr.addCommand(new CmdSandboxDocumentSaveThread());
|
||||
rcCmdMgr.addCommand(new CmdSandboxDocThreadWithSeq());
|
||||
rcCmdMgr.addCommand(new CmdSandboxDocThreadBusy());
|
||||
rcCmdMgr.addCommand(new CmdSandboxDocumentNoThread());
|
||||
|
||||
@@ -84,7 +84,8 @@ Gui::MenuItem* Workbench::setupMenuBar() const
|
||||
*threads << "Sandbox_PythonLockThread" << "Sandbox_NolockPython"
|
||||
<< "Sandbox_PyQtThread" << "Sandbox_PythonThread" << "Sandbox_PythonMainThread";
|
||||
test->setCommand("Threads");
|
||||
*test << "Sandbox_Thread" << "Sandbox_TestThread" << "Sandbox_WorkerThread" << "Sandbox_SeqThread"
|
||||
*test << "Sandbox_Thread" << "Sandbox_TestThread" << "Sandbox_SaveThread"
|
||||
<< "Sandbox_WorkerThread" << "Sandbox_SeqThread"
|
||||
<< "Sandbox_BlockThread" << "Sandbox_NoThread" << threads << "Separator"
|
||||
<< "Sandbox_Dialog" << "Sandbox_FileDialog";
|
||||
Gui::MenuItem* misc = new Gui::MenuItem;
|
||||
|
||||
Reference in New Issue
Block a user