From 95bd206e930d2bc61eb97ade98169c202c74b39f Mon Sep 17 00:00:00 2001 From: maiko3tattun Date: Sun, 21 Apr 2024 00:59:51 +0900 Subject: [PATCH 1/2] Improved translation of error messages for more flexibility --- OpenUtau.Core/Classic/Frq.cs | 3 +- OpenUtau.Core/Commands/Notifications.cs | 24 +++++----- OpenUtau.Core/DiffSinger/DiffSingerVocoder.cs | 2 +- OpenUtau.Core/PlaybackManager.cs | 15 ++++--- OpenUtau.Core/Render/RenderEngine.cs | 3 +- .../Util/MessageCustomizableException.cs | 37 +++++++++++++++ OpenUtau/Strings/Strings.axaml | 22 +++++++-- OpenUtau/Strings/Strings.ja-JP.axaml | 22 +++++++-- OpenUtau/ViewModels/EditSubbanksViewModel.cs | 6 ++- OpenUtau/ViewModels/ExpressionsViewModel.cs | 27 +++++------ OpenUtau/ViewModels/MainWindowViewModel.cs | 9 ++-- OpenUtau/ViewModels/PianoRollViewModel.cs | 3 +- OpenUtau/ViewModels/SingersViewModel.cs | 21 ++++++--- OpenUtau/Views/EditSubbanksDialog.axaml.cs | 6 ++- OpenUtau/Views/MainWindow.axaml.cs | 45 +++++++++---------- OpenUtau/Views/MessageBox.axaml.cs | 17 ++++++- OpenUtau/Views/PianoRollWindow.axaml.cs | 6 ++- 17 files changed, 183 insertions(+), 85 deletions(-) create mode 100644 OpenUtau.Core/Util/MessageCustomizableException.cs diff --git a/OpenUtau.Core/Classic/Frq.cs b/OpenUtau.Core/Classic/Frq.cs index 01b1c71cb..bde7446de 100644 --- a/OpenUtau.Core/Classic/Frq.cs +++ b/OpenUtau.Core/Classic/Frq.cs @@ -135,7 +135,8 @@ public bool Load(string wavPath) { } return true; } catch (Exception e) { - DocManager.Inst.ExecuteCmd(new ErrorMessageNotificationWithTranslation("errors.failed.load", ": frq file", e)); + var customEx = new MessageCustomizableException("Failed to load frq file", ": frq file", e); + DocManager.Inst.ExecuteCmd(new ErrorMessageNotification(customEx)); return false; } } diff --git a/OpenUtau.Core/Commands/Notifications.cs b/OpenUtau.Core/Commands/Notifications.cs index b1f6ce18f..19ba82c2a 100644 --- a/OpenUtau.Core/Commands/Notifications.cs +++ b/OpenUtau.Core/Commands/Notifications.cs @@ -23,21 +23,17 @@ public ErrorMessageNotification(string message, Exception e) { this.message = message; this.e = e; } - public override string ToString() => $"Error message: {message} {e}"; - } - - public class ErrorMessageNotificationWithTranslation : ErrorMessageNotification { - public readonly string stringKey = string.Empty; - public ErrorMessageNotificationWithTranslation(string stringKey) : base(string.Empty) { - this.stringKey = stringKey; - } - public ErrorMessageNotificationWithTranslation(string stringKey, Exception e) : base(e) { - this.stringKey = stringKey; - } - public ErrorMessageNotificationWithTranslation(string stringKey, string additionalMessage, Exception e) : base(additionalMessage, e) { - this.stringKey = stringKey; + public override string ToString() { + if (e is MessageCustomizableException mce) { + if (string.IsNullOrWhiteSpace(mce.Message)) { + return $"Error message: {mce.SubstanceException.Message} {mce.SubstanceException}"; + } else { + return $"Error message: {mce.Message} {mce.SubstanceException}"; + } + } else { + return $"Error message: {message} {e}"; + } } - public override string ToString() => $"Error message: {stringKey}{message} {e}"; } public class LoadingNotification : UNotification { diff --git a/OpenUtau.Core/DiffSinger/DiffSingerVocoder.cs b/OpenUtau.Core/DiffSinger/DiffSingerVocoder.cs index 9b8aa5ad6..9c37888d9 100644 --- a/OpenUtau.Core/DiffSinger/DiffSingerVocoder.cs +++ b/OpenUtau.Core/DiffSinger/DiffSingerVocoder.cs @@ -29,7 +29,7 @@ public DsVocoder(string name) { model = File.ReadAllBytes(Path.Combine(Location, config.model)); } catch (Exception ex) { - throw new Exception($"Error loading vocoder {name}. Please download vocoder from https://github.com/xunmengshe/OpenUtau/wiki/Vocoders"); + throw new MessageCustomizableException($"Error loading vocoder {name}", $"{name}https://github.com/xunmengshe/OpenUtau/wiki/Vocoders", new Exception($"Error loading vocoder {name}")); } session = Onnx.getInferenceSession(model); } diff --git a/OpenUtau.Core/PlaybackManager.cs b/OpenUtau.Core/PlaybackManager.cs index 2961bdc22..3f26a713c 100644 --- a/OpenUtau.Core/PlaybackManager.cs +++ b/OpenUtau.Core/PlaybackManager.cs @@ -132,7 +132,8 @@ private void Render(UProject project, int tick, int endTick, int trackNo) { } catch (Exception e) { Log.Error(e, "Failed to render."); StopPlayback(); - DocManager.Inst.ExecuteCmd(new ErrorMessageNotificationWithTranslation("errors.failed.render", e)); + var customEx = new MessageCustomizableException("Failed to render.", "", e); + DocManager.Inst.ExecuteCmd(new ErrorMessageNotification(customEx)); } }); } @@ -161,10 +162,12 @@ await Task.Run(() => { WaveFileWriter.CreateWaveFile16(exportPath, new ExportAdapter(projectMix).ToMono(1, 0)); DocManager.Inst.ExecuteCmd(new ProgressBarNotification(0, $"Exported to {exportPath}.")); } catch (IOException ioe) { - DocManager.Inst.ExecuteCmd(new ErrorMessageNotificationWithTranslation("errors.failed.export", $": {exportPath}", ioe)); + var customEx = new MessageCustomizableException($"Failed to export {exportPath}.", $": {exportPath}", ioe); + DocManager.Inst.ExecuteCmd(new ErrorMessageNotification(customEx)); DocManager.Inst.ExecuteCmd(new ProgressBarNotification(0, $"Failed to export {exportPath}.")); } catch (Exception e) { - DocManager.Inst.ExecuteCmd(new ErrorMessageNotificationWithTranslation("errors.failed.render", e)); + var customEx = new MessageCustomizableException("Failed to render.", $": {exportPath}", e); + DocManager.Inst.ExecuteCmd(new ErrorMessageNotification(customEx)); DocManager.Inst.ExecuteCmd(new ProgressBarNotification(0, $"Failed to render.")); } }); @@ -189,10 +192,12 @@ await Task.Run(() => { DocManager.Inst.ExecuteCmd(new ProgressBarNotification(0, $"Exported to {file}.")); } } catch (IOException ioe) { - DocManager.Inst.ExecuteCmd(new ErrorMessageNotificationWithTranslation("errors.failed.export", $": {file}", ioe)); + var customEx = new MessageCustomizableException($"Failed to export {file}.", $": {file}", ioe); + DocManager.Inst.ExecuteCmd(new ErrorMessageNotification(customEx)); DocManager.Inst.ExecuteCmd(new ProgressBarNotification(0, $"Failed to export {file}.")); } catch (Exception e) { - DocManager.Inst.ExecuteCmd(new ErrorMessageNotificationWithTranslation("errors.failed.render", e)); + var customEx = new MessageCustomizableException("Failed to render.", "", e); + DocManager.Inst.ExecuteCmd(new ErrorMessageNotification(customEx)); DocManager.Inst.ExecuteCmd(new ProgressBarNotification(0, $"Failed to render.")); } }); diff --git a/OpenUtau.Core/Render/RenderEngine.cs b/OpenUtau.Core/Render/RenderEngine.cs index 6749de200..fc54c4ae4 100644 --- a/OpenUtau.Core/Render/RenderEngine.cs +++ b/OpenUtau.Core/Render/RenderEngine.cs @@ -107,7 +107,8 @@ public Tuple> RenderMixdown(TaskScheduler uiScheduler, ref if (task.IsFaulted && !wait) { Log.Error(task.Exception.Flatten(), "Failed to render."); PlaybackManager.Inst.StopPlayback(); - DocManager.Inst.ExecuteCmd(new ErrorMessageNotificationWithTranslation("errors.failed.render", task.Exception)); + var customEx = new MessageCustomizableException("Failed to render.", "", task.Exception); + DocManager.Inst.ExecuteCmd(new ErrorMessageNotification(customEx)); } }, CancellationToken.None, TaskContinuationOptions.OnlyOnFaulted, uiScheduler); if (wait) { diff --git a/OpenUtau.Core/Util/MessageCustomizableException.cs b/OpenUtau.Core/Util/MessageCustomizableException.cs new file mode 100644 index 000000000..4b08c5fa5 --- /dev/null +++ b/OpenUtau.Core/Util/MessageCustomizableException.cs @@ -0,0 +1,37 @@ +using System; + +namespace OpenUtau.Core { + public class MessageCustomizableException : Exception { + + public override string Message { get; } = string.Empty; + public string TranslatableMessage { get; set; } = string.Empty; + public Exception SubstanceException { get; } + public bool ShowStackTrace { get; } = true; + + /// + /// This allows the use of translatable messages and the hiding of stack traces in the message box. + /// + /// untranslated message + /// By enclosing the resource key with a tag like "", only that part will be translated. + /// underlying exception + public MessageCustomizableException(string message, string translatableMessage, Exception e) { + Message = message; + TranslatableMessage = translatableMessage; + SubstanceException = e; + } + + /// + /// This allows the use of translatable messages and the hiding of stack traces in the message box. + /// + /// untranslated message + /// By enclosing the resource key with a tag like "", only that part will be translated. + /// underlying exception + /// Can be omitted. Default is true. + public MessageCustomizableException(string message, string translatableMessage, Exception e, bool showStackTrace) { + Message = message; + TranslatableMessage = translatableMessage; + SubstanceException = e; + ShowStackTrace = showStackTrace; + } + } +} diff --git a/OpenUtau/Strings/Strings.axaml b/OpenUtau/Strings/Strings.axaml index acfb9da52..36e8af3db 100644 --- a/OpenUtau/Strings/Strings.axaml +++ b/OpenUtau/Strings/Strings.axaml @@ -62,13 +62,27 @@ Error Error Details + Error loading vocoder + . Please download vocoder from + Abbreviation must be between 1 and 4 characters long + Abbreviation must be set + Abbreviations must be unique + Default value must be between min and max + Flags must be unique + Min must be smaller than max + Name must be set Failed to export + Failed to import files + Failed to import audio + Failed to import midi Failed to load - Failed to open - Failed to render. - Failed to run editing macro. + Failed to load prefs. Initialize it. + Failed to open + Failed to open location + Failed to render + Failed to run editing macro Failed to save - Failed to save singer config file. + Failed to save singer config file Abbreviation Apply diff --git a/OpenUtau/Strings/Strings.ja-JP.axaml b/OpenUtau/Strings/Strings.ja-JP.axaml index 86f1ff194..fd6a1412d 100644 --- a/OpenUtau/Strings/Strings.ja-JP.axaml +++ b/OpenUtau/Strings/Strings.ja-JP.axaml @@ -62,13 +62,27 @@ エラー エラーの詳細 + ボコーダー + のロードに失敗しました。未インストールの場合、以下のURLからダウンロードしてください: + パラメータの略称は1~4文字で入力してください + パラメータの略称を入力してください + パラメータの略称が重複しています + デフォルト値は最小値以上、最大値以下にしてください + フラグが重複しています + 最小値は最大値より小さくしてください + 表情名を入力してください エクスポートに失敗しました + ファイルのインポートに失敗しました + オーディオのインポートに失敗しました + MIDIのインポートに失敗しました 読み込みに失敗しました - 読み込みに失敗しました - レンダリングに失敗しました。 - 一括処理に失敗しました。 + 環境設定の読み込みに失敗しました。設定を初期化します。 + 読み込みに失敗しました + フォルダを開けませんでした + レンダリングに失敗しました + 一括処理に失敗しました 保存に失敗しました - シンガー設定の保存に失敗しました。 + シンガー設定の保存に失敗しました パラメータの略称 適用 diff --git a/OpenUtau/ViewModels/EditSubbanksViewModel.cs b/OpenUtau/ViewModels/EditSubbanksViewModel.cs index 7d09634fd..feedc5ea5 100644 --- a/OpenUtau/ViewModels/EditSubbanksViewModel.cs +++ b/OpenUtau/ViewModels/EditSubbanksViewModel.cs @@ -109,7 +109,8 @@ public void LoadSubbanks() { } SelectedColor = Colors[0]; } catch (Exception e) { - DocManager.Inst.ExecuteCmd(new ErrorMessageNotificationWithTranslation("errors.failed.load", ": subbanks", e)); + var customEx = new MessageCustomizableException("Failed to load subbanks", ": subbanks", e); + DocManager.Inst.ExecuteCmd(new ErrorMessageNotification(customEx)); } } @@ -184,7 +185,8 @@ public void SaveSubbanks() { bankConfig.Save(stream); } } catch (Exception e) { - DocManager.Inst.ExecuteCmd(new ErrorMessageNotificationWithTranslation("errors.failed.save", ": subbanks", e)); + var customEx = new MessageCustomizableException("Failed to save subbanks", ": subbanks", e); + DocManager.Inst.ExecuteCmd(new ErrorMessageNotification(customEx)); } LoadSubbanks(); } diff --git a/OpenUtau/ViewModels/ExpressionsViewModel.cs b/OpenUtau/ViewModels/ExpressionsViewModel.cs index 1d048c425..6f8070ec8 100644 --- a/OpenUtau/ViewModels/ExpressionsViewModel.cs +++ b/OpenUtau/ViewModels/ExpressionsViewModel.cs @@ -70,22 +70,22 @@ public ExpressionBuilder(string name, string abbr, float min, float max, bool is .ToProperty(this, x => x.SelectedType, out selectedType); } - public string? Validate() { + public string[]? Validate() { if (string.IsNullOrWhiteSpace(Name)) { - return "Name must be set."; + return new string[] { "Name must be set.", "" }; } if (string.IsNullOrWhiteSpace(Abbr)) { - return "Abbreviation must be set."; + return new string[] { "Abbreviation must be set.", "" }; } if (ExpressionType == UExpressionType.Numerical) { if (Abbr.Trim().Length < 1 || Abbr.Trim().Length > 4) { - return "Abbreviation must be between 1 and 4 characters long."; + return new string[] { "Abbreviation must be between 1 and 4 characters long.", "" }; } if (Min >= Max) { - return "Min must be smaller than max."; + return new string[] { "Min must be smaller than max.", "" }; } if (DefaultValue < Min || DefaultValue > Max) { - return "Default value must be between min and max."; + return new string[] { "Default value must be between min and max.", "" }; } } return null; @@ -137,15 +137,16 @@ public void Apply() { if (!Expressions.All(builder => builder.Validate() == null)) { var invalid = Expressions.First(builder => builder.Validate() != null); Expression = invalid; - throw new ArgumentException(invalid.Validate()); + string[] validate = invalid.Validate()!; + throw new MessageCustomizableException(validate[0], validate[1], new ArgumentException(validate[0]), false); } - var abbrs = Expressions.Select(builder => builder.Abbr); - if (abbrs.Count() != abbrs.Distinct().Count()) { - throw new ArgumentException("Abbreviations must be unique."); + var abbrs = Expressions.GroupBy(builder => builder.Abbr).Where(g => g.Count() > 1).Select(g => g.Key); + if (abbrs.Count() > 0) { + throw new MessageCustomizableException("", $": {string.Join(", ", abbrs)}", new ArgumentException($"Abbreviations must be unique: {string.Join(", ", abbrs)}"), false); } - var flags = Expressions.Where(builder => !string.IsNullOrEmpty(builder.Flag)).Select(builder => builder.Flag); - if (flags.Count() != flags.Distinct().Count()) { - throw new ArgumentException("Flags must be unique."); + var flags = Expressions.Where(builder => !string.IsNullOrEmpty(builder.Flag)).GroupBy(builder => builder.Flag).Where(g => g.Count() > 1).Select(g => g.Key); + if (flags.Count() > 0) { + throw new MessageCustomizableException("", $": {string.Join(", ", flags)}", new ArgumentException($"Flags must be unique: {string.Join(", ", flags)}"), false); } DocManager.Inst.StartUndoGroup(); DocManager.Inst.ExecuteCmd(new ConfigureExpressionsCommand(DocManager.Inst.Project, Expressions.Select(builder => builder.Build()).ToArray())); diff --git a/OpenUtau/ViewModels/MainWindowViewModel.cs b/OpenUtau/ViewModels/MainWindowViewModel.cs index 4e0a78bf0..d60a5ab47 100644 --- a/OpenUtau/ViewModels/MainWindowViewModel.cs +++ b/OpenUtau/ViewModels/MainWindowViewModel.cs @@ -63,7 +63,8 @@ public MainWindowViewModel() { try { OpenProject(new[] { file }); } catch (Exception e) { - DocManager.Inst.ExecuteCmd(new ErrorMessageNotificationWithTranslation("errors.failed.open", ": recent project", e)); + var customEx = new MessageCustomizableException("Failed to open recent", ": recent project", e); + DocManager.Inst.ExecuteCmd(new ErrorMessageNotification(customEx)); } }); OpenTemplateCommand = ReactiveCommand.Create(file => { @@ -72,7 +73,8 @@ public MainWindowViewModel() { DocManager.Inst.Project.Saved = false; DocManager.Inst.Project.FilePath = string.Empty; } catch (Exception e) { - DocManager.Inst.ExecuteCmd(new ErrorMessageNotificationWithTranslation("errors.failed.open", ": project template", e)); + var customEx = new MessageCustomizableException("Failed to open template", ": project template", e); + DocManager.Inst.ExecuteCmd(new ErrorMessageNotification(customEx)); } }); PartDeleteCommand = ReactiveCommand.Create(part => { @@ -111,7 +113,8 @@ public void NewProject() { DocManager.Inst.Project.FilePath = string.Empty; return; } catch (Exception e) { - DocManager.Inst.ExecuteCmd(new ErrorMessageNotificationWithTranslation("errors.failed.load", ": default template", e)); + var customEx = new MessageCustomizableException("Failed to load default template", ": default template", e); + DocManager.Inst.ExecuteCmd(new ErrorMessageNotification(customEx)); } } DocManager.Inst.ExecuteCmd(new LoadProjectNotification(Core.Format.Ustx.Create())); diff --git a/OpenUtau/ViewModels/PianoRollViewModel.cs b/OpenUtau/ViewModels/PianoRollViewModel.cs index e70a1bd7c..fb98aee9f 100644 --- a/OpenUtau/ViewModels/PianoRollViewModel.cs +++ b/OpenUtau/ViewModels/PianoRollViewModel.cs @@ -171,7 +171,8 @@ public PianoRollViewModel() { try{ edit.Run(NotesViewModel.Project, NotesViewModel.Part, NotesViewModel.Selection.ToList(), DocManager.Inst); } catch (Exception e) { - DocManager.Inst.ExecuteCmd(new ErrorMessageNotificationWithTranslation("errors.failed.runeditingmacro", e)); + var customEx = new MessageCustomizableException("Failed to run editing macro", "", e); + DocManager.Inst.ExecuteCmd(new ErrorMessageNotification(customEx)); } } }); diff --git a/OpenUtau/ViewModels/SingersViewModel.cs b/OpenUtau/ViewModels/SingersViewModel.cs index 116145f18..eb1d646d6 100644 --- a/OpenUtau/ViewModels/SingersViewModel.cs +++ b/OpenUtau/ViewModels/SingersViewModel.cs @@ -159,7 +159,8 @@ private void SetEncoding(Encoding encoding) { ModifyConfig(Singer, config => config.TextFileEncoding = encoding.WebName); Refresh(); } catch (Exception e) { - DocManager.Inst.ExecuteCmd(new ErrorMessageNotificationWithTranslation("errors.failed.savesingerconfig", e)); + var customEx = new MessageCustomizableException("Failed to save singer config", "", e); + DocManager.Inst.ExecuteCmd(new ErrorMessageNotification(customEx)); } } @@ -171,7 +172,8 @@ public void SetImage(string filepath) { ModifyConfig(Singer, config => config.Image = filepath); Refresh(); } catch (Exception e) { - DocManager.Inst.ExecuteCmd(new ErrorMessageNotificationWithTranslation("errors.failed.savesingerconfig", e)); + var customEx = new MessageCustomizableException("Failed to save singer config", "", e); + DocManager.Inst.ExecuteCmd(new ErrorMessageNotification(customEx)); } } @@ -183,7 +185,8 @@ public void SetPortrait(string filepath) { ModifyConfig(Singer, config => config.Portrait = filepath); Refresh(); } catch (Exception e) { - DocManager.Inst.ExecuteCmd(new ErrorMessageNotificationWithTranslation("errors.failed.savesingerconfig", e)); + var customEx = new MessageCustomizableException("Failed to save singer config", "", e); + DocManager.Inst.ExecuteCmd(new ErrorMessageNotification(customEx)); } } @@ -195,7 +198,8 @@ private void SetSingerType(string singerType) { ModifyConfig(Singer, config => config.SingerType = singerType); Refresh(); } catch (Exception e) { - DocManager.Inst.ExecuteCmd(new ErrorMessageNotificationWithTranslation("errors.failed.savesingerconfig", e)); + var customEx = new MessageCustomizableException("Failed to save singer config", "", e); + DocManager.Inst.ExecuteCmd(new ErrorMessageNotification(customEx)); } } @@ -207,7 +211,8 @@ private void SetDefaultPhonemizer(Api.PhonemizerFactory factory) { ModifyConfig(Singer, config => config.DefaultPhonemizer = factory.type.FullName ?? string.Empty); Refresh(); } catch (Exception e) { - DocManager.Inst.ExecuteCmd(new ErrorMessageNotificationWithTranslation("errors.failed.savesingerconfig", e)); + var customEx = new MessageCustomizableException("Failed to save singer config", "", e); + DocManager.Inst.ExecuteCmd(new ErrorMessageNotification(customEx)); } } @@ -219,7 +224,8 @@ public void SetUseFilenameAsAlias() { ModifyConfig(Singer, config => config.UseFilenameAsAlias = !this.UseFilenameAsAlias); Refresh(); } catch (Exception e) { - DocManager.Inst.ExecuteCmd(new ErrorMessageNotificationWithTranslation("errors.failed.savesingerconfig", e)); + var customEx = new MessageCustomizableException("Failed to save singer config", "", e); + DocManager.Inst.ExecuteCmd(new ErrorMessageNotification(customEx)); } } @@ -338,7 +344,8 @@ public void LoadSubbanks() { try { Subbanks.AddRange(Singer.Subbanks); } catch (Exception e) { - DocManager.Inst.ExecuteCmd(new ErrorMessageNotificationWithTranslation("errors.failed.load", ": subbanks", e)); + var customEx = new MessageCustomizableException("Failed to load subbanks", ": subbanks", e); + DocManager.Inst.ExecuteCmd(new ErrorMessageNotification(customEx)); } } diff --git a/OpenUtau/Views/EditSubbanksDialog.axaml.cs b/OpenUtau/Views/EditSubbanksDialog.axaml.cs index 6bed81065..86c3b47f9 100644 --- a/OpenUtau/Views/EditSubbanksDialog.axaml.cs +++ b/OpenUtau/Views/EditSubbanksDialog.axaml.cs @@ -83,7 +83,8 @@ async void OnImportMap(object sender, RoutedEventArgs args) { } } } catch (Exception e) { - DocManager.Inst.ExecuteCmd(new ErrorMessageNotificationWithTranslation("errors.failed.load", ": prefix map", e)); + var customEx = new MessageCustomizableException("Failed to load prefix map", ": prefix map", e); + DocManager.Inst.ExecuteCmd(new ErrorMessageNotification(customEx)); } } } @@ -102,7 +103,8 @@ async void OnExportMap(object sender, RoutedEventArgs args) { } } } catch (Exception e) { - DocManager.Inst.ExecuteCmd(new ErrorMessageNotificationWithTranslation("errors.failed.save", ": prefix map", e)); + var customEx = new MessageCustomizableException("Failed to save prefix map", ": prefix map", e); + DocManager.Inst.ExecuteCmd(new ErrorMessageNotification(customEx)); } } } diff --git a/OpenUtau/Views/MainWindow.axaml.cs b/OpenUtau/Views/MainWindow.axaml.cs index 48b7130ab..de00d0b0a 100644 --- a/OpenUtau/Views/MainWindow.axaml.cs +++ b/OpenUtau/Views/MainWindow.axaml.cs @@ -174,8 +174,8 @@ void OnMenuRemapTimeaxis(object sender, RoutedEventArgs e){ DocManager.Inst.EndUndoGroup(); } } catch (Exception e) { - Log.Error(e, "Failed to open project location."); - MessageBox.ShowError(this, e); + Log.Error(e, "Failed to open project location"); + MessageBox.ShowError(this, new MessageCustomizableException("Failed to open project location", ": project location", e)); } }; dialog.ShowDialog(this); @@ -229,7 +229,7 @@ async void Open() { viewModel.OpenProject(files); } catch (Exception e) { Log.Error(e, $"Failed to open files {string.Join("\n", files)}"); - _ = await MessageBox.ShowError(this, e); + _ = await MessageBox.ShowError(this, new MessageCustomizableException($"Failed to open files {string.Join("\n", files)}", $":\n{string.Join("\n", files)}", e)); } } @@ -265,7 +265,7 @@ void OnMenuOpenProjectLocation(object sender, RoutedEventArgs args) { } } catch (Exception e) { Log.Error(e, "Failed to open project location."); - MessageBox.ShowError(this, e); + MessageBox.ShowError(this, new MessageCustomizableException("Failed to open project location.", ": project location", e)); } } @@ -351,7 +351,7 @@ async void OnMenuImportTracks(object sender, RoutedEventArgs args) { viewModel.ImportTracks(loadedProjects, importTempo); } catch (Exception e) { Log.Error(e, $"Failed to import files"); - _ = await MessageBox.ShowError(this, e); + _ = await MessageBox.ShowError(this, new MessageCustomizableException("Failed to import files", "", e)); } ValidateTracksVoiceColor(); } @@ -366,7 +366,7 @@ async void OnMenuImportAudio(object sender, RoutedEventArgs args) { viewModel.ImportAudio(file); } catch (Exception e) { Log.Error(e, "Failed to import audio"); - _ = await MessageBox.ShowError(this, e); + _ = await MessageBox.ShowError(this, new MessageCustomizableException("Failed to import audio", "", e)); } } @@ -380,7 +380,7 @@ async void OnMenuImportMidi(bool UseDrywetmidi = false) { viewModel.ImportMidi(file, UseDrywetmidi); } catch (Exception e) { Log.Error(e, "Failed to import midi"); - _ = await MessageBox.ShowError(this, e); + _ = await MessageBox.ShowError(this, new MessageCustomizableException("Failed to import midi", "", e)); } } @@ -594,15 +594,16 @@ async void OnMenuInstallSinger(object sender, RoutedEventArgs args) { if (file == null) { return; } - if (file.EndsWith(Core.Vogen.VogenSingerInstaller.FileExt)) { - Core.Vogen.VogenSingerInstaller.Install(file); - return; - } - if (file.EndsWith(DependencyInstaller.FileExt)) { - DependencyInstaller.Install(file); - return; - } try { + if (file.EndsWith(Core.Vogen.VogenSingerInstaller.FileExt)) { + Core.Vogen.VogenSingerInstaller.Install(file); + return; + } + if (file.EndsWith(DependencyInstaller.FileExt)) { + DependencyInstaller.Install(file); + return; + } + var setup = new SingerSetupDialog() { DataContext = new SingerSetupViewModel() { ArchiveFilePath = file, @@ -635,7 +636,7 @@ void OnMenuPreferences(object sender, RoutedEventArgs args) { dataContext = new PreferencesViewModel(); } catch (Exception e) { Log.Error(e, "Failed to load prefs. Initialize it."); - MessageBox.ShowError(this, e); + MessageBox.ShowError(this, new MessageCustomizableException("Failed to load prefs. Initialize it.", "", e)); Preferences.Reset(); dataContext = new PreferencesViewModel(); } @@ -841,14 +842,14 @@ async void OnDrop(object? sender, DragEventArgs args) { viewModel.OpenProject(new string[] { file }); } catch (Exception e) { Log.Error(e, $"Failed to open file {file}"); - _ = await MessageBox.ShowError(this, e); + _ = await MessageBox.ShowError(this, new MessageCustomizableException($"Failed to open file {file}", $": {file}", e)); } } else if (ext == ".mid" || ext == ".midi") { try { viewModel.ImportMidi(file); } catch (Exception e) { Log.Error(e, "Failed to import midi"); - _ = await MessageBox.ShowError(this, e); + _ = await MessageBox.ShowError(this, new MessageCustomizableException("Failed to import midi", "", e)); } } else if (ext == ".zip" || ext == ".rar" || ext == ".uar") { var setup = new SingerSetupDialog() { @@ -893,7 +894,7 @@ async void OnDrop(object? sender, DragEventArgs args) { viewModel.ImportAudio(file); } catch (Exception e) { Log.Error(e, "Failed to import audio"); - _ = await MessageBox.ShowError(this, e); + _ = await MessageBox.ShowError(this, new MessageCustomizableException("Failed to import audio", "", e)); } } else { _ = await MessageBox.Show( @@ -1328,11 +1329,7 @@ public void OnNext(UCommand cmd, bool isUndo) { MessageBox.MessageBoxButtons.Ok); break; default: - if (notif is ErrorMessageNotificationWithTranslation translatedNotif) { - MessageBox.ShowError(this, ThemeManager.GetString(translatedNotif.stringKey) + translatedNotif.message, translatedNotif.e); - } else { - MessageBox.ShowError(this, notif.message, notif.e); - } + MessageBox.ShowError(this, notif.message, notif.e); break; } } else if (cmd is LoadingNotification loadingNotif && loadingNotif.window == typeof(MainWindow)) { diff --git a/OpenUtau/Views/MessageBox.axaml.cs b/OpenUtau/Views/MessageBox.axaml.cs index e5771e1af..46940a2d9 100644 --- a/OpenUtau/Views/MessageBox.axaml.cs +++ b/OpenUtau/Views/MessageBox.axaml.cs @@ -6,7 +6,9 @@ using Avalonia.Controls; using Avalonia.Interactivity; using Avalonia.Threading; +using OpenUtau.Core; using Serilog; +using SharpCompress; namespace OpenUtau.App.Views { public partial class MessageBox : Window { @@ -31,6 +33,20 @@ public static Task ShowError(Window parent, Exception? e) { public static Task ShowError(Window parent, string message, Exception? e) { string text = message; + string title = ThemeManager.GetString("errors.caption"); + + if (e is MessageCustomizableException mce) { + if (!string.IsNullOrEmpty(mce.TranslatableMessage)) { + var matches = Regex.Matches(mce.TranslatableMessage, ""); + matches.ForEach(m => mce.TranslatableMessage = mce.TranslatableMessage.Replace(m.Value, ThemeManager.GetString(m.Groups[1].Value))); + text = mce.TranslatableMessage; + e = mce.SubstanceException; + } + + if (!mce.ShowStackTrace) { + return Show(parent, text, null, title, MessageBoxButtons.Ok); + } + } var builder = new StringBuilder(); if (e != null) { @@ -54,7 +70,6 @@ public static Task ShowError(Window parent, string message, Ex builder.AppendLine(); builder.AppendLine(); builder.AppendLine(System.Reflection.Assembly.GetEntryAssembly()?.GetName().Version?.ToString() ?? "Unknown Version"); - string title = ThemeManager.GetString("errors.caption"); return Show(parent, text, builder.ToString(), title, MessageBoxButtons.OkCopy); } diff --git a/OpenUtau/Views/PianoRollWindow.axaml.cs b/OpenUtau/Views/PianoRollWindow.axaml.cs index 9808b48d1..2f5e1ae1e 100644 --- a/OpenUtau/Views/PianoRollWindow.axaml.cs +++ b/OpenUtau/Views/PianoRollWindow.axaml.cs @@ -245,7 +245,8 @@ void AddBreathNote() { try { edit.Run(notesVM.Project, notesVM.Part, notesVM.Selection.ToList(), DocManager.Inst); } catch (Exception e) { - DocManager.Inst.ExecuteCmd(new ErrorMessageNotificationWithTranslation("errors.failed.runeditingmacro", e)); + var customEx = new MessageCustomizableException("Failed to run editing macro", "", e); + DocManager.Inst.ExecuteCmd(new ErrorMessageNotification(customEx)); } } } @@ -273,7 +274,8 @@ void LengthenCrossfade() { try { edit.Run(notesVM.Project, notesVM.Part, notesVM.Selection.ToList(), DocManager.Inst); } catch (Exception e) { - DocManager.Inst.ExecuteCmd(new ErrorMessageNotificationWithTranslation("errors.failed.runeditingmacro", e)); + var customEx = new MessageCustomizableException("Failed to run editing macro", "", e); + DocManager.Inst.ExecuteCmd(new ErrorMessageNotification(customEx)); } }; dialog.ShowDialog(this); From 89c149425b2667d4a6d0804c93e404c9a1bb9103 Mon Sep 17 00:00:00 2001 From: maiko3tattun Date: Sun, 21 Apr 2024 02:04:50 +0900 Subject: [PATCH 2/2] Fix AggregateException message --- OpenUtau.Core/Util/MessageCustomizableException.cs | 4 ++++ OpenUtau/Views/MessageBox.axaml.cs | 14 ++++++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/OpenUtau.Core/Util/MessageCustomizableException.cs b/OpenUtau.Core/Util/MessageCustomizableException.cs index 4b08c5fa5..1f9c2ca93 100644 --- a/OpenUtau.Core/Util/MessageCustomizableException.cs +++ b/OpenUtau.Core/Util/MessageCustomizableException.cs @@ -33,5 +33,9 @@ public MessageCustomizableException(string message, string translatableMessage, SubstanceException = e; ShowStackTrace = showStackTrace; } + + public override string ToString() { + return SubstanceException.ToString(); + } } } diff --git a/OpenUtau/Views/MessageBox.axaml.cs b/OpenUtau/Views/MessageBox.axaml.cs index 46940a2d9..fa9e7e739 100644 --- a/OpenUtau/Views/MessageBox.axaml.cs +++ b/OpenUtau/Views/MessageBox.axaml.cs @@ -55,8 +55,18 @@ public static Task ShowError(Window parent, string message, Ex builder.AppendLine(ae.InnerExceptions.First().Message); builder.AppendLine(); builder.Append(ae.ToString()); - if (string.IsNullOrEmpty(text)) { - text = ae.InnerExceptions.First().Message; + + if (!string.IsNullOrWhiteSpace(text)) { + text += "\n"; + } + if (ae.InnerExceptions.First() is MessageCustomizableException innnerMce) { + if (!string.IsNullOrEmpty(innnerMce.TranslatableMessage)) { + var matches = Regex.Matches(innnerMce.TranslatableMessage, ""); + matches.ForEach(m => innnerMce.TranslatableMessage = innnerMce.TranslatableMessage.Replace(m.Value, ThemeManager.GetString(m.Groups[1].Value))); + text += innnerMce.TranslatableMessage; + } else { + text += ae.InnerExceptions.First().Message; + } } } else { builder.AppendLine(e.Message);