Merge pull request #2514 from manongjohn/backup_scene_with_levels

Backup scene file

N.B. The backup feature is turned ON for all users by default.
This commit is contained in:
shun-iwasawa 2019-09-10 15:20:50 +09:00 committed by GitHub
commit 55a8816333
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 126 additions and 90 deletions

View file

@ -121,8 +121,11 @@ public:
return m_autosaveOtherFilesEnabled; return m_autosaveOtherFilesEnabled;
} }
void enableLevelsBackup(bool enabled); void enableBackup(bool enabled);
bool isLevelsBackupEnabled() const { return m_levelsBackupEnabled; } bool isBackupEnabled() const { return m_backupEnabled; }
void setBackupKeepCount(int count);
int getBackupKeepCount() { return m_backupKeepCount; }
void enableSceneNumbering(bool enabled); void enableSceneNumbering(bool enabled);
bool isSceneNumberingEnabled() const { return m_sceneNumberingEnabled; } bool isSceneNumberingEnabled() const { return m_sceneNumberingEnabled; }
@ -635,9 +638,8 @@ private:
m_expandFunctionHeader, m_showColumnNumbers, m_animatedGuidedDrawing; m_expandFunctionHeader, m_showColumnNumbers, m_animatedGuidedDrawing;
bool m_rasterOptimizedMemory, m_saveUnpaintedInCleanup, bool m_rasterOptimizedMemory, m_saveUnpaintedInCleanup,
m_askForOverrideRender, m_automaticSVNFolderRefreshEnabled, m_SVNEnabled, m_askForOverrideRender, m_automaticSVNFolderRefreshEnabled, m_SVNEnabled,
m_levelsBackupEnabled, m_minimizeSaveboxAfterEditing, m_backupEnabled, m_minimizeSaveboxAfterEditing, m_sceneNumberingEnabled,
m_sceneNumberingEnabled, m_animationSheetEnabled, m_inksOnly, m_animationSheetEnabled, m_inksOnly, m_startupPopupEnabled;
m_startupPopupEnabled;
bool m_fillOnlySavebox, m_show0ThickLines, m_regionAntialias; bool m_fillOnlySavebox, m_show0ThickLines, m_regionAntialias;
bool m_onionSkinDuringPlayback, m_ignoreImageDpi, bool m_onionSkinDuringPlayback, m_ignoreImageDpi,
m_syncLevelRenumberWithXsheet; m_syncLevelRenumberWithXsheet;
@ -724,6 +726,8 @@ private:
bool m_enableWinInk = false; bool m_enableWinInk = false;
bool m_useOnionColorsForShiftAndTraceGhosts = false; bool m_useOnionColorsForShiftAndTraceGhosts = false;
int m_backupKeepCount;
private: private:
Preferences(); Preferences();
~Preferences(); ~Preferences();

View file

@ -927,8 +927,14 @@ void PreferencesPopup::onLineTestFpsCapture(int index) {
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void PreferencesPopup::onLevelsBackupChanged(int index) { void PreferencesPopup::onBackupChanged(bool enabled) {
m_pref->enableLevelsBackup(index == Qt::Checked); m_pref->enableBackup(enabled);
}
//-----------------------------------------------------------------------------
void PreferencesPopup::onBackupKeepCountChanged() {
m_pref->setBackupKeepCount(m_backupKeepCount->getValue());
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -1312,7 +1318,10 @@ PreferencesPopup::PreferencesPopup()
m_undoMemorySize = m_undoMemorySize =
new DVGui::IntLineEdit(this, m_pref->getUndoMemorySize(), 0, 2000); new DVGui::IntLineEdit(this, m_pref->getUndoMemorySize(), 0, 2000);
m_levelsBackup = new CheckBox(tr("Backup Animation Levels when Saving")); m_backup = new QGroupBox(tr("Backup Scene and Animation Levels when Saving"));
m_backup->setCheckable(true);
m_backupKeepCount =
new DVGui::IntLineEdit(this, m_pref->getBackupKeepCount(), 1);
m_chunkSizeFld = m_chunkSizeFld =
new DVGui::IntLineEdit(this, m_pref->getDefaultTaskChunkSize(), 1, 2000); new DVGui::IntLineEdit(this, m_pref->getDefaultTaskChunkSize(), 1, 2000);
CheckBox *sceneNumberingCB = new CheckBox(tr("Show Info in Rendered Frames")); CheckBox *sceneNumberingCB = new CheckBox(tr("Show Info in Rendered Frames"));
@ -1649,7 +1658,7 @@ PreferencesPopup::PreferencesPopup()
replaceAfterSaveLevelAsCB->setChecked( replaceAfterSaveLevelAsCB->setChecked(
m_pref->isReplaceAfterSaveLevelAsEnabled()); m_pref->isReplaceAfterSaveLevelAsEnabled());
m_levelsBackup->setChecked(m_pref->isLevelsBackupEnabled()); m_backup->setChecked(m_pref->isBackupEnabled());
sceneNumberingCB->setChecked(m_pref->isSceneNumberingEnabled()); sceneNumberingCB->setChecked(m_pref->isSceneNumberingEnabled());
watchFileSystemCB->setChecked(m_pref->isWatchFileSystemEnabled()); watchFileSystemCB->setChecked(m_pref->isWatchFileSystemEnabled());
@ -2039,8 +2048,24 @@ PreferencesPopup::PreferencesPopup()
generalFrameLay->addWidget(replaceAfterSaveLevelAsCB, 0, generalFrameLay->addWidget(replaceAfterSaveLevelAsCB, 0,
Qt::AlignLeft | Qt::AlignVCenter); Qt::AlignLeft | Qt::AlignVCenter);
generalFrameLay->addWidget(m_levelsBackup, 0,
Qt::AlignLeft | Qt::AlignVCenter); QVBoxLayout *backupLay = new QVBoxLayout();
backupLay->setMargin(10);
{
QHBoxLayout *backupCountLay = new QHBoxLayout();
backupCountLay->setMargin(0);
backupCountLay->setSpacing(5);
{
backupCountLay->addWidget(
new QLabel(tr("# of backups to keep: "), this));
backupCountLay->addWidget(m_backupKeepCount, 0);
backupCountLay->addStretch(1);
}
backupLay->addLayout(backupCountLay, 0);
}
m_backup->setLayout(backupLay);
generalFrameLay->addWidget(m_backup);
generalFrameLay->addWidget(sceneNumberingCB, 0, generalFrameLay->addWidget(sceneNumberingCB, 0,
Qt::AlignLeft | Qt::AlignVCenter); Qt::AlignLeft | Qt::AlignVCenter);
generalFrameLay->addWidget(watchFileSystemCB, 0, generalFrameLay->addWidget(watchFileSystemCB, 0,
@ -2792,8 +2817,10 @@ PreferencesPopup::PreferencesPopup()
SLOT(onDragCellsBehaviourChanged(int))); SLOT(onDragCellsBehaviourChanged(int)));
ret = ret && connect(m_undoMemorySize, SIGNAL(editingFinished()), ret = ret && connect(m_undoMemorySize, SIGNAL(editingFinished()),
SLOT(onUndoMemorySizeChanged())); SLOT(onUndoMemorySizeChanged()));
ret = ret && connect(m_levelsBackup, SIGNAL(stateChanged(int)), ret = ret &&
SLOT(onLevelsBackupChanged(int))); connect(m_backup, SIGNAL(toggled(bool)), SLOT(onBackupChanged(bool)));
ret = ret && connect(m_backupKeepCount, SIGNAL(editingFinished()), this,
SLOT(onBackupKeepCountChanged()));
ret = ret && connect(sceneNumberingCB, SIGNAL(stateChanged(int)), ret = ret && connect(sceneNumberingCB, SIGNAL(stateChanged(int)),
SLOT(onSceneNumberingChanged(int))); SLOT(onSceneNumberingChanged(int)));
ret = ret && connect(watchFileSystemCB, SIGNAL(stateChanged(int)), ret = ret && connect(watchFileSystemCB, SIGNAL(stateChanged(int)),

View file

@ -70,14 +70,14 @@ private:
DVGui::IntLineEdit *m_minuteFld, *m_chunkSizeFld, *m_iconSizeLx, DVGui::IntLineEdit *m_minuteFld, *m_chunkSizeFld, *m_iconSizeLx,
*m_iconSizeLy, *m_viewShrink, *m_viewStep, *m_blanksCount, *m_iconSizeLy, *m_viewShrink, *m_viewStep, *m_blanksCount,
*m_onionPaperThickness, *m_animationStepField, *m_undoMemorySize, *m_onionPaperThickness, *m_animationStepField, *m_undoMemorySize,
*m_xsheetStep, *m_ffmpegTimeout; *m_xsheetStep, *m_ffmpegTimeout, *m_backupKeepCount;
QPushButton *m_addLevelFormat, *m_removeLevelFormat, *m_editLevelFormat; QPushButton *m_addLevelFormat, *m_removeLevelFormat, *m_editLevelFormat;
DVGui::CheckBox *m_inksOnly, *m_enableVersionControl, *m_levelsBackup, DVGui::CheckBox *m_inksOnly, *m_enableVersionControl, *m_onionSkinVisibility,
*m_onionSkinVisibility, *m_pixelsOnlyCB, *m_projectRootDocuments, *m_pixelsOnlyCB, *m_projectRootDocuments, *m_projectRootDesktop,
*m_projectRootDesktop, *m_projectRootCustom, *m_projectRootStuff, *m_projectRootCustom, *m_projectRootStuff, *m_onionSkinDuringPlayback,
*m_onionSkinDuringPlayback, *m_autoSaveSceneCB, *m_autoSaveOtherFilesCB, *m_autoSaveSceneCB, *m_autoSaveOtherFilesCB,
*m_useNumpadForSwitchingStyles, *m_expandFunctionHeader, *m_useNumpadForSwitchingStyles, *m_expandFunctionHeader,
*m_useHigherDpiOnVectorSimplifyCB, *m_keepFillOnVectorSimplifyCB, *m_useHigherDpiOnVectorSimplifyCB, *m_keepFillOnVectorSimplifyCB,
*m_newLevelToCameraSizeCB, *m_ignoreImageDpiCB, *m_newLevelToCameraSizeCB, *m_ignoreImageDpiCB,
@ -90,7 +90,8 @@ private:
DVGui::FileField *m_ffmpegPathFileFld, *m_fastRenderPathFileField, DVGui::FileField *m_ffmpegPathFileFld, *m_fastRenderPathFileField,
*m_lutPathFileField; *m_lutPathFileField;
QGroupBox *m_autoSaveGroup, *m_showXSheetToolbar, *m_colorCalibration; QGroupBox *m_autoSaveGroup, *m_showXSheetToolbar, *m_colorCalibration,
*m_backup;
DVGui::ColorField *m_currentColumnColor; DVGui::ColorField *m_currentColumnColor;
@ -147,7 +148,7 @@ private slots:
void onSVNEnabledChanged(int); void onSVNEnabledChanged(int);
void onAutomaticSVNRefreshChanged(int); void onAutomaticSVNRefreshChanged(int);
void onDragCellsBehaviourChanged(int); void onDragCellsBehaviourChanged(int);
void onLevelsBackupChanged(int); void onBackupChanged(bool enabled);
void onSceneNumberingChanged(int); void onSceneNumberingChanged(int);
void onChunkSizeChanged(); void onChunkSizeChanged();
void onDefLevelTypeChanged(int); void onDefLevelTypeChanged(int);
@ -223,6 +224,7 @@ private slots:
void onEnableTouchGesturesTriggered(bool checked); void onEnableTouchGesturesTriggered(bool checked);
void onEnableWinInkChanged(int index); void onEnableWinInkChanged(int index);
void onRasterBackgroundColorChanged(const TPixel32 &, bool isDragging); void onRasterBackgroundColorChanged(const TPixel32 &, bool isDragging);
void onBackupKeepCountChanged();
}; };
//********************************************************************************** //**********************************************************************************

View file

@ -286,7 +286,7 @@ Preferences::Preferences()
, m_automaticSVNFolderRefreshEnabled(true) , m_automaticSVNFolderRefreshEnabled(true)
, m_SVNEnabled(false) , m_SVNEnabled(false)
, m_minimizeSaveboxAfterEditing(true) , m_minimizeSaveboxAfterEditing(true)
, m_levelsBackupEnabled(false) , m_backupEnabled(true)
, m_sceneNumberingEnabled(false) , m_sceneNumberingEnabled(false)
, m_animationSheetEnabled(false) , m_animationSheetEnabled(false)
, m_inksOnly(false) , m_inksOnly(false)
@ -347,7 +347,8 @@ Preferences::Preferences()
, m_currentColumnColor(TPixel::Black) , m_currentColumnColor(TPixel::Black)
, m_enableWinInk(false) , m_enableWinInk(false)
, m_useOnionColorsForShiftAndTraceGhosts(false) , m_useOnionColorsForShiftAndTraceGhosts(false)
, m_rasterBackgroundColor(TPixel::White) { , m_rasterBackgroundColor(TPixel::White)
, m_backupKeepCount(1) {
TCamera camera; TCamera camera;
m_defLevelType = PLI_XSHLEVEL; m_defLevelType = PLI_XSHLEVEL;
m_defLevelWidth = camera.getSize().lx; m_defLevelWidth = camera.getSize().lx;
@ -390,7 +391,8 @@ Preferences::Preferences()
getValue(*m_settings, "SVNEnabled", m_SVNEnabled); getValue(*m_settings, "SVNEnabled", m_SVNEnabled);
getValue(*m_settings, "minimizeSaveboxAfterEditing", getValue(*m_settings, "minimizeSaveboxAfterEditing",
m_minimizeSaveboxAfterEditing); m_minimizeSaveboxAfterEditing);
getValue(*m_settings, "levelsBackupEnabled", m_levelsBackupEnabled); getValue(*m_settings, "backupEnabled", m_backupEnabled);
getValue(*m_settings, "backupKeepCount", m_backupKeepCount);
getValue(*m_settings, "sceneNumberingEnabled", m_sceneNumberingEnabled); getValue(*m_settings, "sceneNumberingEnabled", m_sceneNumberingEnabled);
getValue(*m_settings, "animationSheetEnabled", m_animationSheetEnabled); getValue(*m_settings, "animationSheetEnabled", m_animationSheetEnabled);
getValue(*m_settings, "autosaveEnabled", m_autosaveEnabled); getValue(*m_settings, "autosaveEnabled", m_autosaveEnabled);
@ -1433,9 +1435,16 @@ void Preferences::setDownArrowLevelStripNewFrame(bool on) {
//----------------------------------------------------------------- //-----------------------------------------------------------------
void Preferences::enableLevelsBackup(bool enabled) { void Preferences::enableBackup(bool enabled) {
m_levelsBackupEnabled = enabled; m_backupEnabled = enabled;
m_settings->setValue("levelsBackupEnabled", enabled ? "1" : "0"); m_settings->setValue("backupEnabled", enabled ? "1" : "0");
}
//-----------------------------------------------------------------
void Preferences::setBackupKeepCount(int count) {
m_backupKeepCount = count;
m_settings->setValue("backupKeepCount", count);
} }
//----------------------------------------------------------------- //-----------------------------------------------------------------

View file

@ -169,71 +169,33 @@ void deleteUntitledScene(const TFilePath &fp) {
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/*-- TODO: オプション化して復活させるか、検討のこと --*/
/*
void saveBackup(const TFilePath &fp)
{
if(!TFileStatus(fp).doesExist()) return;
wstring sceneName = fp.getWideName();
TFilePath bckDir = fp.getParentDir() + "backups" + sceneName;
if(!TFileStatus(bckDir).doesExist())
{
try {TSystem::mkDir(bckDir);}
catch(...) {return;}
}
std::map<int, TFilePath> oldBackups; static void saveBackup(TFilePath path) {
TFilePathSet lst = TSystem::readDirectory(bckDir); int totalBackups = Preferences::instance()->getBackupKeepCount();
for(TFilePathSet::iterator it = lst.begin(); it != lst.end(); ++it) totalBackups -= 1;
{ TFilePath backup = path.withType(path.getType() + ".bak");
TFilePath fp2 = *it; TFilePath prevBackup =
if(fp2.getType() != "tnz" && fp2.getType() != "tab") continue; path.withType(path.getType() + ".bak" + std::to_string(totalBackups));
wstring name = fp2.getWideName(); while (--totalBackups >= 0) {
if(name.find_first_of(L"0123456789") == wstring::npos) continue; std::string bakExt =
int i = name.find(sceneName); ".bak" + (totalBackups > 0 ? std::to_string(totalBackups) : "");
if(i != wstring::npos) backup = path.withType(path.getType() + bakExt);
name = name.substr(sceneName.size()+1); if (TSystem::doesExistFileOrLevel(backup)) {
if(name == L"" || name.find_first_not_of(L"0123456789") != wstring::npos) try {
continue; TSystem::copyFileOrLevel_throw(prevBackup, backup);
int index = toInt(name); } catch (...) {
assert(0<index); }
assert(oldBackups.count(index)==0);
oldBackups[index] = fp2;
}
int m = 3;
if((int)oldBackups.size()>m)
{
std::map<int, TFilePath>::iterator it = oldBackups.begin();
for(int i=0;i+m<(int)oldBackups.size();i++)
{
assert(it != oldBackups.end());
TFilePath toKill = it->second;
try {TSystem::deleteFile(toKill); } catch(...) {}
++it;
} }
prevBackup = backup;
} }
TFilePath bckFp; try {
if(oldBackups.empty()) if (TSystem::doesExistFileOrLevel(backup))
{ TSystem::removeFileOrLevel_throw(backup);
if(fp.getType() == "tnz") TSystem::copyFileOrLevel_throw(backup, path);
bckFp = bckDir + TFilePath(sceneName + L"_1.tnz"); } catch (...) {
else if(fp.getType() == "tab")
bckFp = bckDir + TFilePath(sceneName + L"_1.tab");
} }
else
{
int id = oldBackups.rbegin()->first + 1;
if(fp.getType() == "tnz")
bckFp = bckDir + TFilePath(sceneName + L"_" + ::to_wstring(id) + L".tnz");
else if(fp.getType() == "tab")
bckFp = bckDir + TFilePath(sceneName + L"_" + ::to_wstring(id) + L".tab");
}
TSystem::renameFile(bckFp, fp);
} }
*/
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -635,7 +597,9 @@ void ToonzScene::save(const TFilePath &fp, TXsheet *subxsh) {
TFilePath scenePathTemp(scenePath.getWideString() + TFilePath scenePathTemp(scenePath.getWideString() +
QString(".tmp").toStdWString()); QString(".tmp").toStdWString());
// if(TFileStatus(scenePath).doesExist()) saveBackup(scenePath); if (Preferences::instance()->isBackupEnabled() &&
oldScenePath == newScenePath && TFileStatus(scenePath).doesExist())
saveBackup(scenePath);
if (TFileStatus(scenePathTemp).doesExist()) if (TFileStatus(scenePathTemp).doesExist())
TSystem::removeFileOrLevel(scenePathTemp); TSystem::removeFileOrLevel(scenePathTemp);

View file

@ -1375,8 +1375,38 @@ void TXshSimpleLevel::save() {
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
static void saveBackup(TFilePath path) { static void saveBackup(TFilePath path) {
// The additional .bak extension keeps it from being detected as a sequence.
// If the original path is a sequence, find the individual files and back it
// up individually
if (path.isLevelName()) {
TFilePathSet files =
TSystem::readDirectory(path.getParentDir(), false, true);
for (TFilePathSet::iterator file = files.begin(); file != files.end();
file++) {
if (file->getLevelName() == path.getLevelName()) saveBackup(*file);
}
return;
}
int totalBackups = Preferences::instance()->getBackupKeepCount();
totalBackups -= 1;
TFilePath backup = path.withType(path.getType() + ".bak");
TFilePath prevBackup =
path.withType(path.getType() + ".bak" + std::to_string(totalBackups));
while (--totalBackups >= 0) {
std::string bakExt =
".bak" + (totalBackups > 0 ? std::to_string(totalBackups) : "");
backup = path.withType(path.getType() + bakExt);
if (TSystem::doesExistFileOrLevel(backup)) {
try {
TSystem::copyFileOrLevel_throw(prevBackup, backup);
} catch (...) {
}
}
prevBackup = backup;
}
try { try {
TFilePath backup = path.withName(path.getName() + "_backup");
if (TSystem::doesExistFileOrLevel(backup)) if (TSystem::doesExistFileOrLevel(backup))
TSystem::removeFileOrLevel_throw(backup); TSystem::removeFileOrLevel_throw(backup);
TSystem::copyFileOrLevel_throw(backup, path); TSystem::copyFileOrLevel_throw(backup, path);
@ -1398,8 +1428,8 @@ void TXshSimpleLevel::save(const TFilePath &fp, const TFilePath &oldFp,
"The level cannot be saved: failed to access the target folder."); "The level cannot be saved: failed to access the target folder.");
// backup // backup
if (Preferences::instance()->isLevelsBackupEnabled() && if (Preferences::instance()->isBackupEnabled() && dOldPath == dDstPath &&
dOldPath == dDstPath && TSystem::doesExistFileOrLevel(dDstPath)) TSystem::doesExistFileOrLevel(dDstPath))
saveBackup(dDstPath); saveBackup(dDstPath);
if (isAreadOnlyLevel(dDstPath)) { if (isAreadOnlyLevel(dDstPath)) {
@ -1644,7 +1674,7 @@ void TXshSimpleLevel::saveSimpleLevel(const TFilePath &decodedFp,
lw = TLevelWriterP(); // TLevelWriterP's destructor saves the palette lw = TLevelWriterP(); // TLevelWriterP's destructor saves the palette
} else if (isPaletteModified && overwritePalette) { } else if (isPaletteModified && overwritePalette) {
TFilePath palettePath = decodedFp.withNoFrame().withType("tpl"); TFilePath palettePath = decodedFp.withNoFrame().withType("tpl");
if (Preferences::instance()->isLevelsBackupEnabled() && if (Preferences::instance()->isBackupEnabled() &&
TSystem::doesExistFileOrLevel(palettePath)) TSystem::doesExistFileOrLevel(palettePath))
saveBackup(palettePath); saveBackup(palettePath);
TOStream os(palettePath); TOStream os(palettePath);