From 37d1696e16a23700443dea33eed0294d54f2532c Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 17 May 2013 13:29:11 +0200 Subject: [PATCH] 0000175: Auto save function (first step) --- src/Gui/Application.cpp | 79 +++++++++++++++++++++++++++++++++++++++++ src/Gui/Application.h | 1 + src/Gui/MainWindow.cpp | 2 ++ 3 files changed, 82 insertions(+) diff --git a/src/Gui/Application.cpp b/src/Gui/Application.cpp index 0ae0513cf..915de9b8d 100644 --- a/src/Gui/Application.cpp +++ b/src/Gui/Application.cpp @@ -41,8 +41,11 @@ # include #endif # include +# include #endif +#include + // FreeCAD Base header #include @@ -1748,9 +1751,24 @@ void Application::runApplication(void) Base::Console().Log("Init: Entering event loop\n"); try { + std::stringstream s; + s << Base::FileInfo::getTempPath() << App::GetApplication().getExecutableName() + << "_" << QCoreApplication::applicationPid() << ".lock"; + // open a lock file with the PID + Base::FileInfo fi(s.str()); + Base::ofstream lock(fi); + boost::interprocess::file_lock flock(s.str().c_str()); + flock.lock(); + int ret = mainApp.exec(); if (ret == systemExit) throw Base::SystemExitException(); + + // close the lock file, in case of a crash we can see the existing lock file + // on the next restart and try to repair the documents, if needed. + flock.unlock(); + lock.close(); + fi.deleteFile(); } catch (const Base::SystemExitException&) { Base::Console().Message("System exit\n"); @@ -1765,3 +1783,64 @@ void Application::runApplication(void) Base::Console().Log("Finish: Event loop left\n"); } + +void Application::checkForPreviousCrashes() +{ + QDir tmp = QDir::temp(); + tmp.setNameFilters(QStringList() << QString::fromAscii("*.lock")); + tmp.setFilter(QDir::Files); + + QList restoreDocFiles; + QString exeName = QString::fromAscii(App::GetApplication().getExecutableName()); + QList locks = tmp.entryInfoList(); + for (QList::iterator it = locks.begin(); it != locks.end(); ++it) { + QString bn = it->baseName(); + if (bn.startsWith(exeName)) { + QString fn = it->absoluteFilePath(); + boost::interprocess::file_lock flock((const char*)fn.toLocal8Bit()); + if (flock.try_lock()) { + // OK, this file is a leftover from a previous crash + QString crashed_pid = bn.mid(exeName.length()+1); + // search for transient directories with this PID + QString filter; + QTextStream str(&filter); + str << exeName << "_Doc_*_" << crashed_pid; + tmp.setNameFilters(QStringList() << filter); + tmp.setFilter(QDir::Dirs); + QList dirs = tmp.entryInfoList(); + if (dirs.isEmpty()) { + // delete the lock file immediately if not transient directories are related + tmp.remove(fn); + } + else { + int countDeletedDocs = 0; + for (QList::iterator it = dirs.begin(); it != dirs.end(); ++it) { + QDir doc_dir(it->absoluteFilePath()); + doc_dir.setFilter(QDir::NoDotAndDotDot|QDir::AllEntries); + uint entries = doc_dir.entryList().count(); + if (entries == 0) { + // in this case we can delete the transient directory because + // we cannot do anything + if (tmp.rmdir(it->filePath())) + countDeletedDocs++; + } + else { + // store the transient directory in case it's not empty + restoreDocFiles << *it; + } + } + + // all directories corresponding to the lock file have been deleted + // so delete the lock file, too + if (countDeletedDocs == dirs.size()) { + tmp.remove(fn); + } + } + } + } + } + + if (!restoreDocFiles.isEmpty()) { + //TODO: + } +} diff --git a/src/Gui/Application.h b/src/Gui/Application.h index 1901c3694..42e739254 100644 --- a/src/Gui/Application.h +++ b/src/Gui/Application.h @@ -157,6 +157,7 @@ public: /// true when the application shuting down bool isClosing(void); + void checkForPreviousCrashes(); /** @name workbench handling */ //@{ diff --git a/src/Gui/MainWindow.cpp b/src/Gui/MainWindow.cpp index 6c91f19ed..e9b621430 100644 --- a/src/Gui/MainWindow.cpp +++ b/src/Gui/MainWindow.cpp @@ -1174,6 +1174,8 @@ void MainWindow::delayedStartup() if (hGrp->GetBool("CreateNewDoc", false)) { App::GetApplication().newDocument(); } + + Application::Instance->checkForPreviousCrashes(); } void MainWindow::appendRecentFile(const QString& filename)