Handle file writing errors for movies and all tools.

This commit is contained in:
SuuperW 2025-07-21 02:48:17 -05:00
parent 5559b48319
commit 1e57b74fb2
14 changed files with 298 additions and 174 deletions

View File

@ -5,6 +5,13 @@ using System.Diagnostics;
namespace BizHawk.Client.Common
{
public enum TryAgainResult
{
Saved,
IgnoredFailure,
Canceled,
}
public static class DialogControllerExtensions
{
public static void AddOnScreenMessage(this IDialogParent dialogParent, string message, int? duration = null)
@ -80,7 +87,7 @@ namespace BizHawk.Client.Common
/// The user will be repeatedly asked if they want to try again until either success or the user says no.
/// </summary>
/// <returns>Returns true on success or if the user said no. Returns false if the user said cancel.</returns>
public static bool DoWithTryAgainBox(
public static TryAgainResult DoWithTryAgainBox(
this IDialogParent dialogParent,
Func<FileWriteResult> action,
string message)
@ -94,12 +101,12 @@ namespace BizHawk.Client.Common
$"{fileResult.UserFriendlyErrorMessage()}\n{fileResult.Exception!.Message}",
caption: "Error",
icon: EMsgBoxIcon.Error);
if (askResult == null) return false;
if (askResult == false) return true;
if (askResult == null) return TryAgainResult.Canceled;
if (askResult == false) return TryAgainResult.IgnoredFailure;
if (askResult == true) fileResult = action();
}
return true;
return TryAgainResult.Saved;
}
/// <summary>Creates and shows a <c>System.Windows.Forms.OpenFileDialog</c> or equivalent with the receiver (<paramref name="dialogParent"/>) as its parent</summary>

View File

@ -56,6 +56,22 @@ namespace BizHawk.Client.Common
return createResult.Value.CloseAndDispose(backupPath);
}
public static FileWriteResult Write(string path, Action<Stream> writeCallback, string? backupPath = null)
{
FileWriteResult<FileWriter> createResult = Create(path);
if (createResult.IsError) return createResult;
try
{
writeCallback(createResult.Value!.Stream);
}
catch (Exception ex)
{
return new(FileWriteEnum.FailedDuringWrite, createResult.Value!.Paths, ex);
}
return createResult.Value.CloseAndDispose(backupPath);
}
/// <summary>
/// Create a FileWriter instance, or return an error if unable to access the file.
@ -76,6 +92,7 @@ namespace BizHawk.Client.Common
FileWritePaths paths = new(path, writePath);
try
{
Directory.CreateDirectory(Path.GetDirectoryName(path));
FileStream fs = new(writePath, FileMode.Create, FileAccess.Write);
return new(new FileWriter(paths, fs), paths);
}

View File

@ -102,9 +102,8 @@ namespace BizHawk.Client.Common
return true;
}
public void Save(string path)
public FileWriteResult Save(string path)
{
using var sw = new StreamWriter(path);
var sb = new StringBuilder();
var saveDirectory = Path.GetDirectoryName(Path.GetFullPath(path));
foreach (var file in this)
@ -123,10 +122,19 @@ namespace BizHawk.Client.Common
}
}
sw.Write(sb.ToString());
FileWriteResult result = FileWriter.Write(path, (fs) =>
{
using var sw = new StreamWriter(fs);
sw.Write(sb.ToString());
});
Filename = path;
Changes = false;
if (!result.IsError)
{
Filename = path;
Changes = false;
}
return result;
}
}
}

View File

@ -385,6 +385,8 @@ namespace BizHawk.Client.Common
switch (Settings.MovieEndAction)
{
case MovieEndAction.Stop:
// Technically this can save the movie, but it'd be weird to be in that situation.
// Do we want that?
StopMovie();
break;
case MovieEndAction.Record:

View File

@ -88,20 +88,10 @@ namespace BizHawk.Client.Common
return file.Exists && Load(domains, file.FullName, false);
}
public void NewList(string defaultFileName, bool autosave = false)
public void NewList(string defaultFileName)
{
_defaultFileName = defaultFileName;
if (autosave && _changes && _cheatList.Count is not 0)
{
if (string.IsNullOrEmpty(CurrentFileName))
{
CurrentFileName = _defaultFileName;
}
Save();
}
_cheatList.Clear();
CurrentFileName = "";
Changes = false;
@ -220,7 +210,7 @@ namespace BizHawk.Client.Common
public bool IsActive(MemoryDomain domain, long address)
=> _cheatList.Exists(cheat => !cheat.IsSeparator && cheat.Enabled && cheat.Domain == domain && cheat.Contains(address));
public void SaveOnClose()
public FileWriteResult SaveOnClose()
{
if (_config.AutoSaveOnClose)
{
@ -231,17 +221,27 @@ namespace BizHawk.Client.Common
CurrentFileName = _defaultFileName;
}
SaveFile(CurrentFileName);
return SaveFile(CurrentFileName);
}
else if (_cheatList.Count is 0 && !string.IsNullOrWhiteSpace(CurrentFileName))
{
File.Delete(CurrentFileName);
try
{
File.Delete(CurrentFileName);
}
catch (Exception ex)
{
return new(FileWriteEnum.FailedToDeleteGeneric, new(CurrentFileName, ""), ex);
}
_config.Recent.Remove(CurrentFileName);
return new();
}
}
return new();
}
public bool Save()
public FileWriteResult Save()
{
if (string.IsNullOrWhiteSpace(CurrentFileName))
{
@ -251,54 +251,51 @@ namespace BizHawk.Client.Common
return SaveFile(CurrentFileName);
}
public bool SaveFile(string path)
public FileWriteResult SaveFile(string path)
{
try
var sb = new StringBuilder();
foreach (var cheat in _cheatList)
{
new FileInfo(path).Directory?.Create();
var sb = new StringBuilder();
foreach (var cheat in _cheatList)
if (cheat.IsSeparator)
{
if (cheat.IsSeparator)
{
sb.AppendLine("----");
}
else
{
// Set to hex for saving
var tempCheatType = cheat.Type;
cheat.SetType(WatchDisplayType.Hex);
sb
.Append(cheat.AddressStr).Append('\t')
.Append(cheat.ValueStr).Append('\t')
.Append(cheat.Compare is null ? "N" : cheat.CompareStr).Append('\t')
.Append(cheat.Domain != null ? cheat.Domain.Name : "").Append('\t')
.Append(cheat.Enabled ? '1' : '0').Append('\t')
.Append(cheat.Name).Append('\t')
.Append(cheat.SizeAsChar).Append('\t')
.Append(cheat.TypeAsChar).Append('\t')
.Append(cheat.BigEndian is true ? '1' : '0').Append('\t')
.Append(cheat.ComparisonType).Append('\t')
.AppendLine();
cheat.SetType(tempCheatType);
}
sb.AppendLine("----");
}
else
{
// Set to hex for saving
var tempCheatType = cheat.Type;
File.WriteAllText(path, sb.ToString());
cheat.SetType(WatchDisplayType.Hex);
sb
.Append(cheat.AddressStr).Append('\t')
.Append(cheat.ValueStr).Append('\t')
.Append(cheat.Compare is null ? "N" : cheat.CompareStr).Append('\t')
.Append(cheat.Domain != null ? cheat.Domain.Name : "").Append('\t')
.Append(cheat.Enabled ? '1' : '0').Append('\t')
.Append(cheat.Name).Append('\t')
.Append(cheat.SizeAsChar).Append('\t')
.Append(cheat.TypeAsChar).Append('\t')
.Append(cheat.BigEndian is true ? '1' : '0').Append('\t')
.Append(cheat.ComparisonType).Append('\t')
.AppendLine();
cheat.SetType(tempCheatType);
}
}
FileWriteResult result = FileWriter.Write(path, (fs) =>
{
StreamWriter sw = new(fs);
sw.Write(sb.ToString());
});
if (!result.IsError)
{
CurrentFileName = path;
_config.Recent.Add(CurrentFileName);
Changes = false;
return true;
}
catch
{
return false;
}
return result;
}
public bool Load(IMemoryDomains domains, string path, bool append)

View File

@ -1,5 +1,6 @@
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
@ -338,39 +339,37 @@ namespace BizHawk.Client.Common
}
}
public bool Save()
public FileWriteResult Save()
{
if (string.IsNullOrWhiteSpace(CurrentFileName))
{
return false;
return new();
}
using (var sw = new StreamWriter(CurrentFileName))
var sb = new StringBuilder();
sb.Append("SystemID ").AppendLine(_systemId);
foreach (var watch in _watchList)
{
var sb = new StringBuilder();
sb.Append("SystemID ").AppendLine(_systemId);
foreach (var watch in _watchList)
{
sb.AppendLine(watch.ToString());
}
sw.WriteLine(sb.ToString());
sb.AppendLine(watch.ToString());
}
Changes = false;
return true;
FileWriteResult result = FileWriter.Write(CurrentFileName, (fs) =>
{
using var sw = new StreamWriter(fs);
sw.WriteLine(sb.ToString());
});
if (!result.IsError) Changes = false;
return result;
}
public bool SaveAs(FileInfo file)
public FileWriteResult SaveAs(FileInfo file)
{
if (file != null)
{
CurrentFileName = file.FullName;
return Save();
}
Debug.Assert(file != null, "Cannot save as without a file name.");
return false;
CurrentFileName = file.FullName;
return Save();
}
private bool LoadFile(string path, bool append)

View File

@ -3934,7 +3934,7 @@ namespace BizHawk.Client.EmuHawk
if (previousRom != CurrentlyOpenRom)
{
CheatList.NewList(Tools.GenerateDefaultCheatFilename(), autosave: true);
CheatList.NewList(Tools.GenerateDefaultCheatFilename());
if (Config.Cheats.LoadFileByGame && Emulator.HasMemoryDomains())
{
if (CheatList.AttemptToLoadCheatFile(Emulator.AsMemoryDomains()))
@ -3951,7 +3951,7 @@ namespace BizHawk.Client.EmuHawk
}
else
{
CheatList.NewList(Tools.GenerateDefaultCheatFilename(), autosave: true);
CheatList.NewList(Tools.GenerateDefaultCheatFilename());
}
}
@ -3988,7 +3988,7 @@ namespace BizHawk.Client.EmuHawk
DisplayManager.UpdateGlobals(Config, Emulator);
DisplayManager.Blank();
ExtToolManager.BuildToolStrip();
CheatList.NewList("", autosave: true);
CheatList.NewList("");
OnRomChanged();
return false;
}
@ -4050,25 +4050,30 @@ namespace BizHawk.Client.EmuHawk
{
CommitCoreSettingsToConfig(); // Must happen before stopping the movie, since it checks for active movie.
GameIsClosing = true;
if (!Tools.AskSave())
{
GameIsClosing = false;
return false;
}
// There is a cheats tool, but cheats can be active while the "cheats tool" is not. And have auto-save option.
CheatList.SaveOnClose();
GameIsClosing = true;
FileWriteResult saveResult = MovieSession.StopMovie();
GameIsClosing = false;
if (saveResult.IsError)
TryAgainResult cheatSaveResult = this.DoWithTryAgainBox(CheatList.SaveOnClose, "Failed to save cheats.");
if (cheatSaveResult == TryAgainResult.Canceled)
{
if (!this.ModalMessageBox2(
caption: "Quit anyway?",
icon: EMsgBoxIcon.Question,
text: "The currently playing movie could not be saved. Continue and quit anyway? All unsaved changes will be lost."))
{
return false;
}
GameIsClosing = false;
return false;
}
// If TAStudio is open, we already asked about saving the movie.
if (Tools.IsLoaded<TAStudio>())
{
GameIsClosing = false;
}
else
{
TryAgainResult saveMovieResult = this.DoWithTryAgainBox(() => MovieSession.StopMovie(), "Failed to save movie.");
GameIsClosing = false;
if (saveMovieResult == TryAgainResult.Canceled) return false;
}
if (clearSram)
@ -4076,7 +4081,7 @@ namespace BizHawk.Client.EmuHawk
var path = Config.PathEntries.SaveRamAbsolutePath(Game, MovieSession.Movie);
if (File.Exists(path))
{
bool clearResult = this.DoWithTryAgainBox(() => {
TryAgainResult clearResult = this.DoWithTryAgainBox(() => {
try
{
File.Delete(path);
@ -4088,7 +4093,7 @@ namespace BizHawk.Client.EmuHawk
return new(FileWriteEnum.FailedToDeleteGeneric, new(path, ""), ex);
}
}, "Failed to clear SRAM.");
if (!clearResult)
if (clearResult == TryAgainResult.Canceled)
{
return false;
}
@ -4096,14 +4101,14 @@ namespace BizHawk.Client.EmuHawk
}
else if (Emulator.HasSaveRam())
{
bool flushResult = this.DoWithTryAgainBox(
TryAgainResult flushResult = this.DoWithTryAgainBox(
() => FlushSaveRAM(),
"Failed flushing the game's Save RAM to your disk.");
if (!flushResult) return false;
if (flushResult == TryAgainResult.Canceled) return false;
}
bool stateSaveResult = this.DoWithTryAgainBox(AutoSaveStateIfConfigured, "Failed to auto-save state.");
if (!stateSaveResult) return false;
TryAgainResult stateSaveResult = this.DoWithTryAgainBox(AutoSaveStateIfConfigured, "Failed to auto-save state.");
if (stateSaveResult == TryAgainResult.Canceled) return false;
StopAv();
@ -4146,7 +4151,7 @@ namespace BizHawk.Client.EmuHawk
PauseOnFrame = null;
CurrentlyOpenRom = null;
CurrentlyOpenRomArgs = null;
CheatList.NewList("", autosave: true);
CheatList.NewList("");
OnRomChanged();
}
}

View File

@ -214,19 +214,23 @@ namespace BizHawk.Client.EmuHawk
{
if (_currentFilename != null)
{
RunSave();
bool saveResult2 = RunSave();
ShutdownCDL();
return true;
return saveResult2;
}
}
// TODO - I don't like this system. It's hard to figure out how to use it. It should be done in multiple passes.
var result = DialogController.ShowMessageBox2("Save changes to CDL session?", "CDL Auto Save", EMsgBoxIcon.Question);
if (!result)
var result = DialogController.ShowMessageBox3("Save changes to CDL session?", "CDL Save", EMsgBoxIcon.Question);
if (result == false)
{
ShutdownCDL();
return true;
}
else if (result == null)
{
ShutdownCDL();
return false;
}
if (string.IsNullOrWhiteSpace(_currentFilename))
{
@ -240,9 +244,9 @@ namespace BizHawk.Client.EmuHawk
return false;
}
RunSave();
bool saveResult = RunSave();
ShutdownCDL();
return true;
return saveResult;
}
private bool _autoloading;
@ -341,11 +345,20 @@ namespace BizHawk.Client.EmuHawk
LoadFile(file.FullName);
}
private void RunSave()
/// <summary>
/// returns false if the operation was canceled
/// </summary>
private bool RunSave()
{
_recent.Add(_currentFilename);
using var fs = new FileStream(_currentFilename, FileMode.Create, FileAccess.Write);
_cdl.Save(fs);
TryAgainResult result = this.DoWithTryAgainBox(
() => FileWriter.Write(_currentFilename, _cdl.Save),
"Failed to save CDL session.");
if (result == TryAgainResult.Saved)
{
_recent.Add(_currentFilename);
return true;
}
return result != TryAgainResult.Canceled;
}
private void SaveMenuItem_Click(object sender, EventArgs e)
@ -386,8 +399,7 @@ namespace BizHawk.Client.EmuHawk
return false;
SetCurrentFilename(file.FullName);
RunSave();
return true;
return RunSave();
}
private void SaveAsMenuItem_Click(object sender, EventArgs e)

View File

@ -142,7 +142,7 @@ namespace BizHawk.Client.EmuHawk
}
}
private bool SaveAs()
private FileWriteResult SaveAs()
{
var fileName = MainForm.CheatList.CurrentFileName;
if (string.IsNullOrWhiteSpace(fileName))
@ -156,7 +156,8 @@ namespace BizHawk.Client.EmuHawk
CheatsFSFilterSet,
this);
return file != null && MainForm.CheatList.SaveFile(file.FullName);
if (file == null) return new();
else return MainForm.CheatList.SaveFile(file.FullName);
}
private void Cheats_Load(object sender, EventArgs e)
@ -361,7 +362,12 @@ namespace BizHawk.Client.EmuHawk
{
if (MainForm.CheatList.Changes)
{
if (MainForm.CheatList.Save())
FileWriteResult result = MainForm.CheatList.Save();
if (result.IsError)
{
this.ErrorMessageBox(result);
}
else
{
UpdateMessageLabel(saved: true);
}
@ -374,7 +380,12 @@ namespace BizHawk.Client.EmuHawk
private void SaveAsMenuItem_Click(object sender, EventArgs e)
{
if (SaveAs())
FileWriteResult result = SaveAs();
if (result.IsError)
{
this.ErrorMessageBox(result);
}
else
{
UpdateMessageLabel(saved: true);
}

View File

@ -681,15 +681,25 @@ namespace BizHawk.Client.EmuHawk
return result is not null ? new FileInfo(result) : null;
}
private void SaveSessionAs()
private FileWriteResult SaveSessionAs()
{
var file = GetSaveFileFromUser();
if (file != null)
{
LuaImp.ScriptList.Save(file.FullName);
Config.RecentLuaSession.Add(file.FullName);
OutputMessages.Text = $"{file.Name} saved.";
FileWriteResult saveResult = LuaImp.ScriptList.Save(file.FullName);
if (saveResult.IsError)
{
this.ErrorMessageBox(saveResult);
OutputMessages.Text = $"Lua session could not be saved to {file.Name}";
}
else
{
Config.RecentLuaSession.Add(file.FullName);
OutputMessages.Text = $"{file.Name} saved.";
}
return saveResult;
}
return new();
}
private void LoadSessionFromRecent(string path)
@ -717,7 +727,11 @@ namespace BizHawk.Client.EmuHawk
icon: EMsgBoxIcon.Question,
text: $"Save {WindowTitleStatic} session?"));
if (result is null) return false;
if (result.Value) SaveOrSaveAs();
if (result.Value)
{
TryAgainResult saveResult = this.DoWithTryAgainBox(SaveOrSaveAs, "Failed to save Lua session.");
return saveResult != TryAgainResult.Canceled;
}
else LuaImp.ScriptList.Changes = false;
return true;
}
@ -732,16 +746,20 @@ namespace BizHawk.Client.EmuHawk
}
}
private void SaveOrSaveAs()
private FileWriteResult SaveOrSaveAs()
{
if (!string.IsNullOrWhiteSpace(LuaImp.ScriptList.Filename))
{
LuaImp.ScriptList.Save(LuaImp.ScriptList.Filename);
Config.RecentLuaSession.Add(LuaImp.ScriptList.Filename);
FileWriteResult result = LuaImp.ScriptList.Save(LuaImp.ScriptList.Filename);
if (!result.IsError)
{
Config.RecentLuaSession.Add(LuaImp.ScriptList.Filename);
}
return result;
}
else
{
SaveSessionAs();
return SaveSessionAs();
}
}
@ -784,8 +802,16 @@ namespace BizHawk.Client.EmuHawk
{
if (LuaImp.ScriptList.Changes)
{
SaveOrSaveAs();
OutputMessages.Text = $"{Path.GetFileName(LuaImp.ScriptList.Filename)} saved.";
FileWriteResult result = SaveOrSaveAs();
if (result.IsError)
{
this.ErrorMessageBox(result, "Failed to save Lua session.");
OutputMessages.Text = $"Failed to save {Path.GetFileName(LuaImp.ScriptList.Filename)}";
}
else
{
OutputMessages.Text = $"{Path.GetFileName(LuaImp.ScriptList.Filename)} saved.";
}
}
}

View File

@ -112,6 +112,7 @@ namespace BizHawk.Client.EmuHawk
return true;
}
// Intentionally not updating this to use FileWriter because this tool is going to be removed later.
foreach (var zone in _unsavedZones)
{
SaveMacroAs(_zones[zone]);

View File

@ -161,15 +161,8 @@ namespace BizHawk.Client.EmuHawk
text: $"Save {WindowTitleStatic} project?"));
if (shouldSaveResult == true)
{
FileWriteResult saveResult = SaveTas();
while (saveResult.IsError && shouldSaveResult != true)
{
shouldSaveResult = this.ModalMessageBox3(
$"Failed to save movie. {saveResult.UserFriendlyErrorMessage()}\n{saveResult.Exception.Message}\n\nTry again?",
"Error",
EMsgBoxIcon.Error);
if (shouldSaveResult == true) saveResult = SaveTas();
}
TryAgainResult saveResult = this.DoWithTryAgainBox(() => SaveTas(), "Failed to save movie.");
return saveResult != TryAgainResult.Canceled;
}
if (shouldSaveResult is null) return false;
else CurrentTasMovie.ClearChanges();

View File

@ -1008,7 +1008,13 @@ namespace BizHawk.Client.EmuHawk
if (!string.IsNullOrWhiteSpace(watches.CurrentFileName))
{
if (watches.Save())
FileWriteResult saveResult = watches.Save();
if (saveResult.IsError)
{
this.ErrorMessageBox(saveResult);
MessageLabel.Text = $"Failed to save {Path.GetFileName(_currentFileName)}";
}
else
{
_currentFileName = watches.CurrentFileName;
MessageLabel.Text = $"{Path.GetFileName(_currentFileName)} saved";
@ -1017,11 +1023,20 @@ namespace BizHawk.Client.EmuHawk
}
else
{
var result = watches.SaveAs(GetWatchSaveFileFromUser(CurrentFileName()));
if (result)
FileInfo/*?*/ file = GetWatchSaveFileFromUser(CurrentFileName());
if (file != null)
{
MessageLabel.Text = $"{Path.GetFileName(_currentFileName)} saved";
Settings.RecentSearches.Add(watches.CurrentFileName);
var result = watches.SaveAs(file);
if (result.IsError)
{
this.ErrorMessageBox(result);
MessageLabel.Text = $"Failed to save {Path.GetFileName(_currentFileName)}";
}
else
{
MessageLabel.Text = $"{Path.GetFileName(_currentFileName)} saved";
Settings.RecentSearches.Add(watches.CurrentFileName);
}
}
}
}
@ -1035,7 +1050,15 @@ namespace BizHawk.Client.EmuHawk
watches.Add(_searches[i]);
}
if (watches.SaveAs(GetWatchSaveFileFromUser(CurrentFileName())))
FileInfo/*?*/ file = GetWatchSaveFileFromUser(CurrentFileName());
if (file == null) return;
FileWriteResult result = watches.SaveAs(file);
if (result.IsError)
{
this.ErrorMessageBox(result);
MessageLabel.Text = $"Failed to save {Path.GetFileName(_currentFileName)}";
}
else
{
_currentFileName = watches.CurrentFileName;
MessageLabel.Text = $"{Path.GetFileName(_currentFileName)} saved";

View File

@ -213,15 +213,8 @@ namespace BizHawk.Client.EmuHawk
if (result is null) return false;
if (result.Value)
{
if (string.IsNullOrWhiteSpace(_watches.CurrentFileName))
{
SaveAs();
}
else
{
_watches.Save();
Config.RecentWatches.Add(_watches.CurrentFileName);
}
TryAgainResult saveResult = this.DoWithTryAgainBox(Save, "Failed to save watch list.");
return saveResult != TryAgainResult.Canceled;
}
else
{
@ -591,14 +584,47 @@ namespace BizHawk.Client.EmuHawk
: Game.FilesystemSafeName();
}
private void SaveAs()
private FileWriteResult SaveAs()
{
var result = _watches.SaveAs(GetWatchSaveFileFromUser(CurrentFileName()));
if (result)
FileInfo/*?*/ file = GetWatchSaveFileFromUser(CurrentFileName());
if (file == null) return new();
FileWriteResult result = _watches.SaveAs(file);
if (result.IsError)
{
UpdateStatusBar(saved: true);
Config.RecentWatches.Add(_watches.CurrentFileName);
MessageLabel.Text = $"Failed to save {Path.GetFileName(_watches.CurrentFileName)}";
}
else
{
MessageLabel.Text = $"{Path.GetFileName(_watches.CurrentFileName)} saved";
Config.RecentWatches.Add(_watches.CurrentFileName);
UpdateStatusBar(saved: true);
}
return result;
}
private FileWriteResult Save()
{
if (string.IsNullOrWhiteSpace(_watches.CurrentFileName))
{
return SaveAs();
}
else
{
FileWriteResult saveResult = _watches.Save();
if (saveResult.IsError)
{
MessageLabel.Text = $"Failed to save {Path.GetFileName(_watches.CurrentFileName)}";
}
else
{
MessageLabel.Text = $"{Path.GetFileName(_watches.CurrentFileName)} saved";
Config.RecentWatches.Add(_watches.CurrentFileName);
UpdateStatusBar(saved: true);
}
return saveResult;
}
}
private void SaveConfigSettings()
@ -727,23 +753,20 @@ namespace BizHawk.Client.EmuHawk
private void SaveMenuItem_Click(object sender, EventArgs e)
{
if (!string.IsNullOrWhiteSpace(_watches.CurrentFileName))
FileWriteResult saveResult = Save();
if (saveResult.IsError)
{
if (_watches.Save())
{
Config.RecentWatches.Add(_watches.CurrentFileName);
UpdateStatusBar(saved: true);
}
}
else
{
SaveAs();
this.ErrorMessageBox(saveResult, "Failed to save watch list.");
}
}
private void SaveAsMenuItem_Click(object sender, EventArgs e)
{
SaveAs();
FileWriteResult saveResult = SaveAs();
if (saveResult.IsError)
{
this.ErrorMessageBox(saveResult, "Failed to save watch list.");
}
}
private void RecentSubMenu_DropDownOpened(object sender, EventArgs e)