diff --git a/include/history.hpp b/include/history.hpp index 8e13b01c..52943c9e 100644 --- a/include/history.hpp +++ b/include/history.hpp @@ -150,8 +150,11 @@ struct CableRemove : InverseAction { struct State { std::vector actions; - int actionIndex = 0; + int actionIndex; + /** Action index of saved patch state. */ + int savedIndex; + State(); ~State(); void clear(); void push(Action *action); @@ -161,6 +164,8 @@ struct State { bool canRedo(); std::string getUndoName(); std::string getRedoName(); + void setSaved(); + bool isSaved(); }; diff --git a/src/history.cpp b/src/history.cpp index ef380047..57f898fc 100644 --- a/src/history.cpp +++ b/src/history.cpp @@ -163,6 +163,10 @@ void CableAdd::redo() { } +State::State() { + clear(); +} + State::~State() { clear(); } @@ -173,6 +177,7 @@ void State::clear() { } actions.clear(); actionIndex = 0; + savedIndex = -1; } void State::push(Action *action) { @@ -182,6 +187,10 @@ void State::push(Action *action) { actions.resize(actionIndex); actions.push_back(action); actionIndex++; + // Unset the savedIndex if we just permanently overwrote the saved state + if (actionIndex == savedIndex) { + savedIndex = -1; + } } void State::undo() { @@ -218,6 +227,14 @@ std::string State::getRedoName() { return actions[actionIndex]->name; } +void State::setSaved() { + savedIndex = actionIndex; +} + +bool State::isSaved() { + return actionIndex == savedIndex; +} + } // namespace history } // namespace rack diff --git a/src/patch.cpp b/src/patch.cpp index cba230be..d017ee5c 100644 --- a/src/patch.cpp +++ b/src/patch.cpp @@ -66,9 +66,10 @@ void PatchManager::reset() { } void PatchManager::resetDialog() { - if (osdialog_message(OSDIALOG_INFO, OSDIALOG_OK_CANCEL, "Clear patch and start over?")) { - reset(); - } + if (!(APP->history->isSaved() || osdialog_message(OSDIALOG_INFO, OSDIALOG_OK_CANCEL, "The current patch is unsaved. Clear it and start a new patch?"))) + return; + + reset(); } void PatchManager::save(std::string path) { @@ -95,6 +96,7 @@ void PatchManager::save(std::string path) { void PatchManager::saveDialog() { if (!path.empty()) { save(path); + APP->history->setSaved(); } else { saveAsDialog(); @@ -124,10 +126,9 @@ void PatchManager::saveAsDialog() { return; } DEFER({ - free(pathC); + std::free(pathC); }); - std::string pathStr = pathC; if (string::extension(pathStr).empty()) { pathStr += ".vcv"; @@ -135,12 +136,15 @@ void PatchManager::saveAsDialog() { save(pathStr); path = pathStr; + APP->history->setSaved(); } void PatchManager::saveTemplateDialog() { - if (osdialog_message(OSDIALOG_INFO, OSDIALOG_OK_CANCEL, "Overwrite template patch?")) { - save(asset::user("template.vcv")); - } + // Even if /template.vcv doesn't exist, this message is still valid because it overrides the /template.vcv patch. + if (!osdialog_message(OSDIALOG_INFO, OSDIALOG_OK_CANCEL, "Overwrite template patch?")) + return; + + save(asset::user("template.vcv")); } bool PatchManager::load(std::string path) { @@ -174,6 +178,9 @@ bool PatchManager::load(std::string path) { } void PatchManager::loadDialog() { + if (!(APP->history->isSaved() || osdialog_message(OSDIALOG_INFO, OSDIALOG_OK_CANCEL, "The current patch is unsaved. Clear it and open a new patch?"))) + return; + std::string dir; if (path.empty()) { dir = asset::user("patches"); @@ -194,26 +201,26 @@ void PatchManager::loadDialog() { return; } DEFER({ - free(pathC); + std::free(pathC); }); load(pathC); path = pathC; + APP->history->setSaved(); } void PatchManager::revertDialog() { if (path.empty()) return; - if (osdialog_message(OSDIALOG_INFO, OSDIALOG_OK_CANCEL, "Revert patch to the last saved state?")) { - load(path); - } + + if (!(APP->history->isSaved() || osdialog_message(OSDIALOG_INFO, OSDIALOG_OK_CANCEL, "Revert patch to the last saved state?"))) + return; + + load(path); + APP->history->setSaved(); } void PatchManager::disconnectDialog() { - // Since we have undo history, no need for a warning. - // if (!osdialog_message(OSDIALOG_WARNING, OSDIALOG_OK_CANCEL, "Remove all patch cables?")) - // return; - APP->scene->rack->clearCablesAction(); } diff --git a/src/window.cpp b/src/window.cpp index 27b2ec95..eabf7024 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -325,6 +325,8 @@ void Window::run() { windowTitle += app::APP_VERSION; if (!APP->patch->path.empty()) { windowTitle += " - "; + if (!APP->history->isSaved()) + windowTitle += "*"; windowTitle += string::filename(APP->patch->path); } if (windowTitle != internal->lastWindowTitle) {