From 0eb940012dcba536a16c73223e7638e722427c4f Mon Sep 17 00:00:00 2001 From: adroslice Date: Sat, 16 Nov 2019 02:47:07 +0100 Subject: [PATCH] Implemented preview TODO, modified exception handling - Better handles unexpected exceptions - Expected exceptions should be OperationException - Leaves files unchanged even if the exception occurs at *any* point of the operation - TODO: Probably have to optimize this. - Operations now operate on IList instead of List to maintain compatibility with AvaloniaList - Slightly better comments --- BFR/MainWindow.xaml.cs | 4 +++- BFR/MainWindowUIProperties.cs | 2 ++ BFR/Operations/Operation.cs | 27 ++++++++++++++++++++------- BFR/Operations/OperationException.cs | 11 +++++++++++ BFR/Operations/Overwrite.cs | 2 +- 5 files changed, 37 insertions(+), 9 deletions(-) create mode 100644 BFR/Operations/OperationException.cs diff --git a/BFR/MainWindow.xaml.cs b/BFR/MainWindow.xaml.cs index 82bfbf1..325366b 100644 --- a/BFR/MainWindow.xaml.cs +++ b/BFR/MainWindow.xaml.cs @@ -43,7 +43,9 @@ namespace BFR foreach (var file in Files) file.Path = file.OldPath; - // TODO: Apply operations + // Apply operations + foreach (var operation in Operations) + operation.ApplyTo(Files); // Refresh the file list to guarantee that changes are displayed. TODO: Find a better way to do this. Files.ReplaceAll(new List(Files)); diff --git a/BFR/MainWindowUIProperties.cs b/BFR/MainWindowUIProperties.cs index 40ffad9..8cb8e42 100644 --- a/BFR/MainWindowUIProperties.cs +++ b/BFR/MainWindowUIProperties.cs @@ -3,6 +3,7 @@ using Avalonia.Collections; using Avalonia.Controls; using BFR.DataModels; +using BFR.Operations; namespace BFR { @@ -14,6 +15,7 @@ namespace BFR public AvaloniaList AllFiles { get; } = new AvaloniaList(); public AvaloniaList Files { get; } = new AvaloniaList(); + public AvaloniaList Operations { get; } = new AvaloniaList(); // Filters public string FilterExtension { get; set; } = ""; diff --git a/BFR/Operations/Operation.cs b/BFR/Operations/Operation.cs index 302ca93..89228a9 100644 --- a/BFR/Operations/Operation.cs +++ b/BFR/Operations/Operation.cs @@ -1,15 +1,16 @@ using System; using System.Collections.Generic; - +using System.Linq; using Avalonia; using BFR.DataModels; +using BFR.Helpers; namespace BFR.Operations { public abstract class Operation : AvaloniaObject { - // Needs to be an avalonia property to update the UI with with any potential error. + // Needs to be avalonia property to update UI with any potential error. public AvaloniaProperty errorProperty = AvaloniaProperty.Register(nameof(Error), defaultValue: ""); public string Error { get => GetValue(errorProperty); set => SetValue(errorProperty, value); } public bool IsEnabled { get; set; } = true; @@ -17,13 +18,25 @@ namespace BFR.Operations public abstract string Description { get; } public abstract OperationType OperationType { get; } - protected abstract void ApplyToInternal(List files); + protected abstract void ApplyToInternal(IList files); - // Updates the UI with the appropriate error if the operation fails - public void ApplyTo(List files) + public void ApplyTo(IList files) { - try { ApplyToInternal(files); Error = ""; } - catch (Exception e) { Error = e.Message; } + // Backup of all changes thus far, in case something goes wrong + var backup = files.Select(file => file.Path).ToList(); + try + { + ApplyToInternal(files); // Try to apply operation + Error = ""; // If successul, remove any previous error + } + catch (OperationException e) { Error = e.Message; } // If expected, show user a concise and descriptive message + catch (Exception e) { Error = $"Unexpected {e}"; } // If not, hint with the exception thrown that this is unexpected behaviour + finally + { + if (Error != "") // If something went wrong, restore backup + for (int i = 0; i < files.Count; i++) + files[i].Path = backup[i]; + } } } } diff --git a/BFR/Operations/OperationException.cs b/BFR/Operations/OperationException.cs new file mode 100644 index 0000000..ca89a22 --- /dev/null +++ b/BFR/Operations/OperationException.cs @@ -0,0 +1,11 @@ +using System; + +namespace BFR.Operations +{ + public class OperationException : Exception + { + public OperationException(string message) : + base(message) + { } + } +} diff --git a/BFR/Operations/Overwrite.cs b/BFR/Operations/Overwrite.cs index 96153bb..a007a3e 100644 --- a/BFR/Operations/Overwrite.cs +++ b/BFR/Operations/Overwrite.cs @@ -15,7 +15,7 @@ namespace BFR.Operations public string Replacement { get; set; } = ""; public bool FullName { get; set; } = false; - protected override void ApplyToInternal(List files) + protected override void ApplyToInternal(IList files) { // Fail conditions: No fail conditions // Apply Operation