diff --git a/toonz/sources/toonz/iocommand.cpp b/toonz/sources/toonz/iocommand.cpp index 4cbb585..1b2c4f6 100644 --- a/toonz/sources/toonz/iocommand.cpp +++ b/toonz/sources/toonz/iocommand.cpp @@ -1762,6 +1762,25 @@ bool IoCmd::loadScene(const TFilePath &path, bool updateRecentFile, } if (!TSystem::doesExistFileOrLevel(scenePath)) return false; + TFilePath scenePathTemp(scenePath.getWideString() + + QString(".tmp").toStdWString()); + if (TSystem::doesExistFileOrLevel(scenePathTemp)) { + QString question = + QObject::tr( + "A prior save of Scene '%1' was critically interupted. \n\ +\nA partial save file was generated and changes may be manually salvaged from '%2'.\n\ +\nDo you wish to continue loading the last good save or stop and try to salvage the prior save?") + .arg(QString::fromStdWString(scenePath.getWideString())) + .arg(QString::fromStdWString(scenePathTemp.getWideString())); + QString continueAnswer = QObject::tr("Continue"); + QString cancelAnswer = QObject::tr("Cancel"); + int ret = DVGui::MsgBox(question, continueAnswer, cancelAnswer, 0); + if (ret == 2) + return false; + else + TSystem::removeFileOrLevel(scenePathTemp); + } + TProjectManager *pm = TProjectManager::instance(); TProjectP sceneProject = pm->loadSceneProject(scenePath); if (!sceneProject) { diff --git a/toonz/sources/toonzlib/toonzscene.cpp b/toonz/sources/toonzlib/toonzscene.cpp index a1f8700..60a3ccc 100644 --- a/toonz/sources/toonzlib/toonzscene.cpp +++ b/toonz/sources/toonzlib/toonzscene.cpp @@ -632,74 +632,88 @@ void ToonzScene::save(const TFilePath &fp, TXsheet *subxsh) { "scene.\n All resources have been saved."); TFilePath scenePath = decodeFilePath(fp); + TFilePath scenePathTemp(scenePath.getWideString() + + QString(".tmp").toStdWString()); // if(TFileStatus(scenePath).doesExist()) saveBackup(scenePath); - TSystem::touchFile(scenePath); + if (TFileStatus(scenePathTemp).doesExist()) + TSystem::removeFileOrLevel(scenePathTemp); + + // TSystem::touchFile(scenePath); + TSystem::touchFile(scenePathTemp); makeSceneIcon(this); // TOStream os(scenePath, compressionEnabled); - TOStream os(scenePath, false); - if (!os.checkStatus()) throw TException("Could not open file"); - - TXsheet *xsh = subxsh; - if (xsh == 0) xsh = m_childStack->getTopXsheet(); - - std::map attr; - attr["version"] = - (QString::number(l_currentVersion.first) + - "." // From now on, version numbers in saved files will have - + QString::number( - l_currentVersion.second)) // the signature "MAJOR.MINOR", where: - .toStdString(); // - attr["framecount"] = - QString::number( // MAJOR = Toonz version number * 10 (eg 7.0 => 70) - xsh->getFrameCount()) - .toStdString(); // MINOR = Reset to 0 after each major increment, - // and - // advancing on its own when fixing bugs. - os.openChild("tnz", attr); - - os.child("generator") << TEnv::getApplicationFullName(); - os.openChild("properties"); - m_properties->saveData(os); - os.closeChild(); + // TOStream os(scenePath, false); + { + TOStream os(scenePathTemp, false); + if (!os.checkStatus()) + throw TException("Could not open temporary save file"); + + TXsheet *xsh = subxsh; + if (xsh == 0) xsh = m_childStack->getTopXsheet(); + + std::map attr; + attr["version"] = + (QString::number(l_currentVersion.first) + + "." // From now on, version numbers in saved files will have + + QString::number( + l_currentVersion.second)) // the signature "MAJOR.MINOR", where: + .toStdString(); // + attr["framecount"] = + QString::number( // MAJOR = Toonz version number * 10 (eg 7.0 => 70) + xsh->getFrameCount()) + .toStdString(); // MINOR = Reset to 0 after each major + // increment, + // and + // advancing on its own when fixing bugs. + os.openChild("tnz", attr); + + os.child("generator") << TEnv::getApplicationFullName(); + os.openChild("properties"); + m_properties->saveData(os); + os.closeChild(); - if (subxsh) { - std::set saveSet; - subxsh->getUsedLevels(saveSet); - m_levelSet->setSaveSet(saveSet); - } - os.openChild("levelSet"); - m_levelSet->saveData(os); - os.closeChild(); - std::set emptySaveSet; - m_levelSet->setSaveSet(emptySaveSet); - - os.openChild("xsheet"); - os << *xsh; - os.closeChild(); - - if (getContentHistory()) { - os.openChild("history"); - QString data = getContentHistory()->serialize(); - int i = 0, j; - // non scrivo tutta la std::string di seguito per evitare problemi se - // diventa - // troppo lunga. Cerco di spezzarla in modo che sia "bella da leggere" nel - // tnz - while ((j = data.indexOf("||", i)) >= i) { - os << data.mid(i, j - i + 1).toStdWString(); - os.cr(); - i = j + 1; + if (subxsh) { + std::set saveSet; + subxsh->getUsedLevels(saveSet); + m_levelSet->setSaveSet(saveSet); + } + os.openChild("levelSet"); + m_levelSet->saveData(os); + os.closeChild(); + std::set emptySaveSet; + m_levelSet->setSaveSet(emptySaveSet); + + os.openChild("xsheet"); + os << *xsh; + os.closeChild(); + + if (getContentHistory()) { + os.openChild("history"); + QString data = getContentHistory()->serialize(); + int i = 0, j; + // non scrivo tutta la std::string di seguito per evitare problemi se + // diventa + // troppo lunga. Cerco di spezzarla in modo che sia "bella da leggere" nel + // tnz + while ((j = data.indexOf("||", i)) >= i) { + os << data.mid(i, j - i + 1).toStdWString(); + os.cr(); + i = j + 1; + } + os << data.mid(i).toStdWString(); + os.closeChild(); } - os << data.mid(i).toStdWString(); + os.closeChild(); + bool status = os.checkStatus(); + if (!status) throw TException("Could not complete the temporary save"); } - os.closeChild(); - bool status = os.checkStatus(); - if (!status) throw TException("Could not complete the save"); + if (TFileStatus(scenePathTemp).doesExist()) + TSystem::renameFile(scenePath, scenePathTemp, true); if (subxsh) { setScenePath(oldScenePath);