diff --git a/include/SetupDialog.h b/include/SetupDialog.h index a382df91787..b229d082520 100644 --- a/include/SetupDialog.h +++ b/include/SetupDialog.h @@ -93,6 +93,7 @@ private slots: void resetAutoSave(); void toggleAutoSave(bool enabled); void toggleRunningAutoSave(bool enabled); + void toggleVersionedAutoSave(bool enabled); void toggleSmoothScroll(bool enabled); void toggleAnimateAFP(bool enabled); void vstEmbedMethodChanged(); @@ -158,10 +159,12 @@ private slots: int m_saveInterval; bool m_enableAutoSave; bool m_enableRunningAutoSave; + bool m_enableVersionedAutoSave; QSlider * m_saveIntervalSlider; QLabel * m_saveIntervalLbl; QCheckBox * m_autoSave; QCheckBox * m_runningAutoSave; + QCheckBox * m_versionedAutoSave; bool m_smoothScroll; bool m_animateAFP; QLabel * m_vstEmbedLbl; diff --git a/include/Song.h b/include/Song.h index 9bc400dc491..0e127807121 100644 --- a/include/Song.h +++ b/include/Song.h @@ -278,6 +278,12 @@ class LMMS_EXPORT Song : public TrackContainer return m_modified; } + + bool isModifiedAutosave() const + { + return m_modifiedautosave; + } + QString nodeName() const override { return "song"; @@ -340,6 +346,7 @@ public slots: void setModified(); + void setModifiedAutosave(bool value); void clearProject(); @@ -417,6 +424,7 @@ private slots: QString m_fileName; QString m_oldFileName; bool m_modified; + bool m_modifiedautosave; bool m_loadOnLaunch; volatile bool m_recording; diff --git a/src/core/Song.cpp b/src/core/Song.cpp index 0b42c219b0c..e4182a3fe03 100644 --- a/src/core/Song.cpp +++ b/src/core/Song.cpp @@ -451,11 +451,25 @@ void Song::processMetronome(size_t bufferOffset) void Song::setModified(bool value) { + //Split in two for performance reasons? if( !m_loadingProject && m_modified != value) { m_modified = value; + m_modifiedautosave = value; emit modified(); } + else if ( !m_loadingProject && m_modified == value) + { + m_modifiedautosave = value; + } +} + +void Song::setModifiedAutosave(bool value) +{ + if( !m_loadingProject && m_modifiedautosave != value) + { + m_modifiedautosave = value; + } } bool Song::isExportDone() const diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index 69360111c72..494028e19cd 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -1366,7 +1366,9 @@ void MainWindow::browseHelp() void MainWindow::autoSave() { - if( !Engine::getSong()->isExporting() && + + if ( Engine::getSong()->isModifiedAutosave() && + !Engine::getSong()->isExporting() && !Engine::getSong()->isLoadingProject() && !RemotePluginBase::isMainThreadWaiting() && !QApplication::mouseButtons() && @@ -1374,7 +1376,20 @@ void MainWindow::autoSave() "enablerunningautosave" ).toInt() || ! Engine::getSong()->isPlaying() ) ) { + //Recovery file is still needed for post-crash recovery dialog. Engine::getSong()->saveProjectFile(ConfigManager::inst()->recoveryFile()); + if (Engine::getSong()->projectFileName() != "" && + ConfigManager::inst()->value( "ui", "enableversionedautosave" ).toInt()) + { + QString currentProjectName = Engine::getSong()->projectFileName(); + QString autoSaveTimestamp = QDateTime::currentDateTime().toString("yyyy-MM-dd_hh-mm-ss"); + QString autoSaveVersionedName = currentProjectName.section('.', 0, 0).append(".autosave.") //filename.autosave. + .append(autoSaveTimestamp).append(".") //timestamp. + .append(currentProjectName.section('.', -1)); //extension + + Engine::getSong()->saveProjectFile(autoSaveVersionedName); + } + Engine::getSong()->setModifiedAutosave(false); autoSaveTimerReset(); // Reset timer } else @@ -1476,7 +1491,6 @@ void MainWindow::exportProject(bool multiExport) if( efd.exec() == QDialog::Accepted && !efd.selectedFiles().isEmpty() && !efd.selectedFiles()[0].isEmpty() ) { - QString exportFileName = efd.selectedFiles()[0]; if ( !multiExport ) { diff --git a/src/gui/modals/SetupDialog.cpp b/src/gui/modals/SetupDialog.cpp index d31657ab810..1842df89f4e 100644 --- a/src/gui/modals/SetupDialog.cpp +++ b/src/gui/modals/SetupDialog.cpp @@ -132,6 +132,8 @@ SetupDialog::SetupDialog(ConfigTab tab_to_open) : "ui", "enableautosave", "1").toInt()), m_enableRunningAutoSave(ConfigManager::inst()->value( "ui", "enablerunningautosave", "0").toInt()), + m_enableVersionedAutoSave(ConfigManager::inst()->value( + "ui", "enableversionedautosave", "0").toInt()), m_smoothScroll(ConfigManager::inst()->value( "ui", "smoothscroll").toInt()), m_animateAFP(ConfigManager::inst()->value( @@ -413,8 +415,12 @@ SetupDialog::SetupDialog(ConfigTab tab_to_open) : m_runningAutoSave = addCheckBox(tr("Allow autosave while playing"), autoSaveBox, autoSaveLayout, m_enableRunningAutoSave, SLOT(toggleRunningAutoSave(bool)), false); + m_versionedAutoSave = addCheckBox(tr("Create timestamped autosaves"), autoSaveBox, autoSaveLayout, + m_enableVersionedAutoSave, SLOT(toggleVersionedAutoSave(bool)), false); + m_saveIntervalSlider->setEnabled(m_enableAutoSave); m_runningAutoSave->setVisible(m_enableAutoSave); + m_versionedAutoSave->setVisible(m_enableAutoSave); // UI effect vs. performance tab. @@ -1000,6 +1006,8 @@ void SetupDialog::accept() QString::number(m_enableAutoSave)); ConfigManager::inst()->setValue("ui", "enablerunningautosave", QString::number(m_enableRunningAutoSave)); + ConfigManager::inst()->setValue("ui", "enableversionedautosave", + QString::number(m_enableVersionedAutoSave)); ConfigManager::inst()->setValue("ui", "smoothscroll", QString::number(m_smoothScroll)); ConfigManager::inst()->setValue("ui", "animateafp", @@ -1168,6 +1176,7 @@ void SetupDialog::toggleAutoSave(bool enabled) m_enableAutoSave = enabled; m_saveIntervalSlider->setEnabled(enabled); m_runningAutoSave->setVisible(enabled); + m_versionedAutoSave->setVisible(enabled); setAutoSaveInterval(m_saveIntervalSlider->value()); } @@ -1177,12 +1186,18 @@ void SetupDialog::toggleRunningAutoSave(bool enabled) m_enableRunningAutoSave = enabled; } +void SetupDialog::toggleVersionedAutoSave(bool enabled) +{ + m_enableVersionedAutoSave = enabled; +} + void SetupDialog::resetAutoSave() { setAutoSaveInterval(MainWindow::DEFAULT_SAVE_INTERVAL_MINUTES); m_autoSave->setChecked(true); m_runningAutoSave->setChecked(false); + m_versionedAutoSave->setChecked(false); }