Gui: AutoSaver and recovery changes
* Fix AutoSaver inconsistent BinaryBrep setting * Use temperary name when auto saving, so that it won't overwrite the original file, which may cause corruption when crashing in the middel of auto saving, especially if auto saving in a separate thread. * Support auto recovery document containing external links * Do not mark success after auto recover, in case the program crash again before the user remember to save the just recovered file. Only mark when user saves the document.
This commit is contained in:
@@ -47,6 +47,7 @@
|
||||
# include <sstream>
|
||||
#endif
|
||||
|
||||
#include <Base/Console.h>
|
||||
#include "DocumentRecovery.h"
|
||||
#include "ui_DocumentRecovery.h"
|
||||
#include "WaitCursor.h"
|
||||
@@ -63,6 +64,8 @@
|
||||
#include <QDomDocument>
|
||||
#include <boost/interprocess/sync/file_lock.hpp>
|
||||
|
||||
FC_LOG_LEVEL_INIT("Gui",true,true);
|
||||
|
||||
using namespace Gui;
|
||||
using namespace Gui::Dialog;
|
||||
|
||||
@@ -81,8 +84,10 @@ std::string DocumentRecovery::doctools =
|
||||
" self.dirname = dirname\n"
|
||||
"\n"
|
||||
" def startElement(self, name, attributes):\n"
|
||||
" if name == 'XLink':\n"
|
||||
" return\n"
|
||||
" item=attributes.get(\"file\")\n"
|
||||
" if item != None:\n"
|
||||
" if item:\n"
|
||||
" self.files.append(os.path.join(self.dirname,str(item)))\n"
|
||||
"\n"
|
||||
" def characters(self, data):\n"
|
||||
@@ -237,33 +242,25 @@ void DocumentRecovery::accept()
|
||||
if (!d->recovered) {
|
||||
|
||||
WaitCursor wc;
|
||||
int index = 0;
|
||||
for (QList<DocumentRecoveryPrivate::Info>::iterator it = d->recoveryInfo.begin(); it != d->recoveryInfo.end(); ++it, index++) {
|
||||
int index = -1;
|
||||
std::vector<int> indices;
|
||||
std::vector<std::string> filenames, pathes, labels, errs;
|
||||
for(auto &info : d->recoveryInfo) {
|
||||
++index;
|
||||
std::string documentName;
|
||||
QString errorInfo;
|
||||
QTreeWidgetItem* item = d_ptr->ui.treeWidget->topLevelItem(index);
|
||||
|
||||
try {
|
||||
QString file = it->projectFile;
|
||||
QString file = info.projectFile;
|
||||
QFileInfo fi(file);
|
||||
if (fi.fileName() == QLatin1String("Document.xml"))
|
||||
file = createProjectFile(it->projectFile);
|
||||
App::Document* document = App::GetApplication().newDocument();
|
||||
documentName = document->getName();
|
||||
document->FileName.setValue(file.toUtf8().constData());
|
||||
file = createProjectFile(info.projectFile);
|
||||
|
||||
// If something goes wrong an exception will be thrown here
|
||||
document->restore();
|
||||
|
||||
file = it->fileName;
|
||||
document->FileName.setValue(file.toUtf8().constData());
|
||||
document->Label.setValue(it->label.toUtf8().constData());
|
||||
|
||||
// Set the modified flag so that the user cannot close by accident
|
||||
Gui::Document* guidoc = Gui::Application::Instance->getDocument(document);
|
||||
if (guidoc) {
|
||||
guidoc->setModified(true);
|
||||
}
|
||||
pathes.emplace_back(file.toUtf8().constData());
|
||||
filenames.emplace_back(info.fileName.toUtf8().constData());
|
||||
labels.emplace_back(info.label.toUtf8().constData());
|
||||
indices.push_back(index);
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
errorInfo = QString::fromLatin1(e.what());
|
||||
@@ -275,31 +272,71 @@ void DocumentRecovery::accept()
|
||||
errorInfo = tr("Unknown problem occurred");
|
||||
}
|
||||
|
||||
// an error occurred so close the document again
|
||||
if (!errorInfo.isEmpty()) {
|
||||
if (!documentName.empty())
|
||||
App::GetApplication().closeDocument(documentName.c_str());
|
||||
|
||||
it->status = DocumentRecoveryPrivate::Failure;
|
||||
|
||||
info.status = DocumentRecoveryPrivate::Failure;
|
||||
if (item) {
|
||||
item->setText(1, tr("Failed to recover"));
|
||||
item->setToolTip(1, errorInfo);
|
||||
item->setForeground(1, QColor(170,0,0));
|
||||
}
|
||||
d->writeRecoveryInfo(info);
|
||||
}
|
||||
// everything OK
|
||||
else {
|
||||
it->status = DocumentRecoveryPrivate::Success;
|
||||
}
|
||||
|
||||
auto docs = App::GetApplication().openDocuments(filenames,&pathes,&labels,&errs);
|
||||
|
||||
for(int i=0;i<(int)docs.size();++i) {
|
||||
auto &info = d->recoveryInfo[indices[i]];
|
||||
QTreeWidgetItem* item = d_ptr->ui.treeWidget->topLevelItem(indices[i]);
|
||||
if(!docs[i] || errs[i].size()) {
|
||||
if(docs[i])
|
||||
App::GetApplication().closeDocument(docs[i]->getName());
|
||||
info.status = DocumentRecoveryPrivate::Failure;
|
||||
if (item) {
|
||||
item->setText(1, tr("Failed to recover"));
|
||||
item->setToolTip(1, QString::fromUtf8(errs[index].c_str()));
|
||||
item->setForeground(1, QColor(170,0,0));
|
||||
}
|
||||
// write back current status
|
||||
d->writeRecoveryInfo(info);
|
||||
}else{
|
||||
auto gdoc = Application::Instance->getDocument(docs[i]);
|
||||
if(gdoc)
|
||||
gdoc->setModified(true);
|
||||
|
||||
info.status = DocumentRecoveryPrivate::Success;
|
||||
if (item) {
|
||||
item->setText(1, tr("Successfully recovered"));
|
||||
item->setForeground(1, QColor(0,170,0));
|
||||
}
|
||||
}
|
||||
|
||||
// write back current status
|
||||
d->writeRecoveryInfo(*it);
|
||||
QDir transDir(QString::fromUtf8(docs[i]->TransientDir.getValue()));
|
||||
|
||||
QFileInfo xfi(info.xmlFile);
|
||||
QFileInfo fi(info.projectFile);
|
||||
bool res = false;
|
||||
if(fi.fileName() == QLatin1String("fc_recovery_file.fcstd")) {
|
||||
transDir.remove(fi.fileName());
|
||||
res = transDir.rename(fi.absoluteFilePath(),fi.fileName());
|
||||
}else{
|
||||
transDir.rmdir(fi.dir().dirName());
|
||||
res = transDir.rename(fi.absolutePath(),fi.dir().dirName());
|
||||
}
|
||||
if(res) {
|
||||
transDir.remove(xfi.fileName());
|
||||
res = transDir.rename(xfi.absoluteFilePath(),xfi.fileName());
|
||||
}
|
||||
if(!res) {
|
||||
FC_WARN("Failed to move recovery file of document '"
|
||||
<< docs[i]->Label.getValue() << "'");
|
||||
}else{
|
||||
clearDirectory(xfi.absolutePath());
|
||||
QDir().rmdir(xfi.absolutePath());
|
||||
}
|
||||
|
||||
// DO NOT write success into recovery info, in case the program
|
||||
// crash again before the user save the just recovered file.
|
||||
}
|
||||
}
|
||||
|
||||
d->ui.buttonBox->button(QDialogButtonBox::Ok)->setText(tr("Finish"));
|
||||
|
||||
Reference in New Issue
Block a user