diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..2f4429a --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "SabreTools"] + path = SabreTools + url = https://github.com/SabreTools/SabreTools diff --git a/RomRepoMgr.Core/EventArgs/ErrorEventArgs.cs b/RomRepoMgr.Core/EventArgs/ErrorEventArgs.cs new file mode 100644 index 0000000..a97cd68 --- /dev/null +++ b/RomRepoMgr.Core/EventArgs/ErrorEventArgs.cs @@ -0,0 +1,32 @@ +/****************************************************************************** +// RomRepoMgr - ROM repository manager +// ---------------------------------------------------------------------------- +// +// Author(s) : Natalia Portillo +// +// --[ License ] -------------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2020 Natalia Portillo +*******************************************************************************/ + +namespace RomRepoMgr.Core.EventArgs +{ + public sealed class ErrorEventArgs : System.EventArgs + { + public string Message { get; set; } + } +} \ No newline at end of file diff --git a/RomRepoMgr.Core/EventArgs/MessageEventArgs.cs b/RomRepoMgr.Core/EventArgs/MessageEventArgs.cs new file mode 100644 index 0000000..dee4401 --- /dev/null +++ b/RomRepoMgr.Core/EventArgs/MessageEventArgs.cs @@ -0,0 +1,32 @@ +/****************************************************************************** +// RomRepoMgr - ROM repository manager +// ---------------------------------------------------------------------------- +// +// Author(s) : Natalia Portillo +// +// --[ License ] -------------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2020 Natalia Portillo +*******************************************************************************/ + +namespace RomRepoMgr.Core.EventArgs +{ + public sealed class MessageEventArgs : System.EventArgs + { + public string Message { get; set; } + } +} \ No newline at end of file diff --git a/RomRepoMgr.Core/EventArgs/ProgressBoundsEventArgs.cs b/RomRepoMgr.Core/EventArgs/ProgressBoundsEventArgs.cs new file mode 100644 index 0000000..4416ffe --- /dev/null +++ b/RomRepoMgr.Core/EventArgs/ProgressBoundsEventArgs.cs @@ -0,0 +1,33 @@ +/****************************************************************************** +// RomRepoMgr - ROM repository manager +// ---------------------------------------------------------------------------- +// +// Author(s) : Natalia Portillo +// +// --[ License ] -------------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2020 Natalia Portillo +*******************************************************************************/ + +namespace RomRepoMgr.Core.EventArgs +{ + public sealed class ProgressBoundsEventArgs : System.EventArgs + { + public double Minimum { get; set; } + public double Maximum { get; set; } + } +} \ No newline at end of file diff --git a/RomRepoMgr.Core/EventArgs/ProgressEventArgs.cs b/RomRepoMgr.Core/EventArgs/ProgressEventArgs.cs new file mode 100644 index 0000000..da89a2b --- /dev/null +++ b/RomRepoMgr.Core/EventArgs/ProgressEventArgs.cs @@ -0,0 +1,32 @@ +/****************************************************************************** +// RomRepoMgr - ROM repository manager +// ---------------------------------------------------------------------------- +// +// Author(s) : Natalia Portillo +// +// --[ License ] -------------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2020 Natalia Portillo +*******************************************************************************/ + +namespace RomRepoMgr.Core.EventArgs +{ + public sealed class ProgressEventArgs : System.EventArgs + { + public double Value { get; set; } + } +} \ No newline at end of file diff --git a/RomRepoMgr.Core/RomRepoMgr.Core.csproj b/RomRepoMgr.Core/RomRepoMgr.Core.csproj index 57ce2a0..44f44d0 100644 --- a/RomRepoMgr.Core/RomRepoMgr.Core.csproj +++ b/RomRepoMgr.Core/RomRepoMgr.Core.csproj @@ -8,4 +8,8 @@ + + + + diff --git a/RomRepoMgr.Core/Workers/DatImporter.cs b/RomRepoMgr.Core/Workers/DatImporter.cs new file mode 100644 index 0000000..9312087 --- /dev/null +++ b/RomRepoMgr.Core/Workers/DatImporter.cs @@ -0,0 +1,79 @@ +/****************************************************************************** +// RomRepoMgr - ROM repository manager +// ---------------------------------------------------------------------------- +// +// Author(s) : Natalia Portillo +// +// --[ License ] -------------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2020 Natalia Portillo +*******************************************************************************/ + +using System; +using System.Diagnostics; +using RomRepoMgr.Core.EventArgs; +using SabreTools.Library.DatFiles; + +namespace RomRepoMgr.Core.Workers +{ + public sealed class DatImporter + { + readonly string _datPath; + bool _aborted; + + public DatImporter(string datPath) => _datPath = datPath; + + public void Import() + { + try + { + SetIndeterminateProgress?.Invoke(this, System.EventArgs.Empty); + + SetMessage?.Invoke(this, new MessageEventArgs + { + Message = "Parsing DAT file..." + }); + + DateTime start = DateTime.UtcNow; + var datFile = DatFile.CreateAndParse(_datPath); + DateTime end = DateTime.UtcNow; + double elapsed = (end - start).TotalSeconds; + + WorkFinished?.Invoke(this, System.EventArgs.Empty); + } + catch(Exception e) + { + if(Debugger.IsAttached) + throw; + + ErrorOccurred?.Invoke(this, new ErrorEventArgs + { + Message = "Unhandled exception occurred." + }); + } + } + + public void Abort() => _aborted = true; + + public event EventHandler SetIndeterminateProgress; + public event EventHandler WorkFinished; + public event EventHandler ErrorOccurred; + public event EventHandler SetProgressBounds; + public event EventHandler SetProgress; + public event EventHandler SetMessage; + } +} \ No newline at end of file diff --git a/RomRepoMgr.sln b/RomRepoMgr.sln index 8c0b7e3..d47579d 100644 --- a/RomRepoMgr.sln +++ b/RomRepoMgr.sln @@ -8,6 +8,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RomRepoMgr.Settings", "RomR EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RomRepoMgr.Core", "RomRepoMgr.Core\RomRepoMgr.Core.csproj", "{1C7E7286-1BA6-43B0-A042-4A3C378BDDC1}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SabreTools.Library", "SabreTools\SabreTools.Library\SabreTools.Library.csproj", "{9DFA390F-1E96-476B-92CB-0C96EFF3CC9D}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -30,5 +32,9 @@ Global {1C7E7286-1BA6-43B0-A042-4A3C378BDDC1}.Debug|Any CPU.Build.0 = Debug|Any CPU {1C7E7286-1BA6-43B0-A042-4A3C378BDDC1}.Release|Any CPU.ActiveCfg = Release|Any CPU {1C7E7286-1BA6-43B0-A042-4A3C378BDDC1}.Release|Any CPU.Build.0 = Release|Any CPU + {9DFA390F-1E96-476B-92CB-0C96EFF3CC9D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9DFA390F-1E96-476B-92CB-0C96EFF3CC9D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9DFA390F-1E96-476B-92CB-0C96EFF3CC9D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9DFA390F-1E96-476B-92CB-0C96EFF3CC9D}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection EndGlobal diff --git a/RomRepoMgr/RomRepoMgr.csproj b/RomRepoMgr/RomRepoMgr.csproj index 09576ed..0bcaecf 100644 --- a/RomRepoMgr/RomRepoMgr.csproj +++ b/RomRepoMgr/RomRepoMgr.csproj @@ -23,5 +23,6 @@ + diff --git a/RomRepoMgr/ViewModels/ImportDatViewModel.cs b/RomRepoMgr/ViewModels/ImportDatViewModel.cs new file mode 100644 index 0000000..d9b7f50 --- /dev/null +++ b/RomRepoMgr/ViewModels/ImportDatViewModel.cs @@ -0,0 +1,161 @@ +/****************************************************************************** +// RomRepoMgr - ROM repository manager +// ---------------------------------------------------------------------------- +// +// Author(s) : Natalia Portillo +// +// --[ License ] -------------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2020 Natalia Portillo +*******************************************************************************/ + +using System; +using System.Reactive; +using System.Threading.Tasks; +using Avalonia.Threading; +using JetBrains.Annotations; +using ReactiveUI; +using RomRepoMgr.Core.EventArgs; +using RomRepoMgr.Core.Workers; +using RomRepoMgr.Views; + +namespace RomRepoMgr.ViewModels +{ + public sealed class ImportDatViewModel : ViewModelBase + { + readonly ImportDat _view; + readonly DatImporter _worker; + bool _canClose; + double _currentValue; + string _errorMessage; + bool _errorVisible; + bool _indeterminateProgress; + double _maximumValue; + double _minimumValue; + bool _progressVisible; + string _statusMessage; + + public ImportDatViewModel(ImportDat view, string datPath) + { + _view = view; + CloseCommand = ReactiveCommand.Create(ExecuteCloseCommand); + IndeterminateProgress = true; + ProgressVisible = false; + ErrorVisible = false; + _worker = new DatImporter(datPath); + _worker.ErrorOccurred += OnWorkerOnErrorOccurred; + _worker.SetIndeterminateProgress += OnWorkerOnSetIndeterminateProgress; + _worker.SetMessage += OnWorkerOnSetMessage; + _worker.SetProgress += OnWorkerOnSetProgress; + _worker.SetProgressBounds += OnWorkerOnSetProgressBounds; + _worker.WorkFinished += OnWorkerOnWorkFinished; + } + + [NotNull] + public string Title => "Importing DAT file..."; + + public string StatusMessage + { + get => _statusMessage; + set => this.RaiseAndSetIfChanged(ref _statusMessage, value); + } + + public bool IndeterminateProgress + { + get => _indeterminateProgress; + set => this.RaiseAndSetIfChanged(ref _indeterminateProgress, value); + } + + public double MaximumValue + { + get => _maximumValue; + set => this.RaiseAndSetIfChanged(ref _maximumValue, value); + } + + public double MinimumValue + { + get => _minimumValue; + set => this.RaiseAndSetIfChanged(ref _minimumValue, value); + } + + public double CurrentValue + { + get => _currentValue; + set => this.RaiseAndSetIfChanged(ref _currentValue, value); + } + + public bool ProgressVisible + { + get => _progressVisible; + set => this.RaiseAndSetIfChanged(ref _progressVisible, value); + } + + public bool ErrorVisible + { + get => _errorVisible; + set => this.RaiseAndSetIfChanged(ref _errorVisible, value); + } + + public string ErrorMessage + { + get => _errorMessage; + set => this.RaiseAndSetIfChanged(ref _errorMessage, value); + } + + public bool CanClose + { + get => _canClose; + set => this.RaiseAndSetIfChanged(ref _canClose, value); + } + + public string CloseLabel => "Close"; + public ReactiveCommand CloseCommand { get; } + + void OnWorkerOnWorkFinished(object sender, EventArgs args) => Dispatcher.UIThread.Post(() => CanClose = true); + + void OnWorkerOnSetProgressBounds(object sender, ProgressBoundsEventArgs args) => Dispatcher.UIThread.Post(() => + { + IndeterminateProgress = false; + MaximumValue = args.Maximum; + MinimumValue = args.Minimum; + }); + + void OnWorkerOnSetProgress(object sender, ProgressEventArgs args) => + Dispatcher.UIThread.Post(() => CurrentValue = args.Value); + + void OnWorkerOnSetMessage(object sender, MessageEventArgs args) => + Dispatcher.UIThread.Post(() => StatusMessage = args.Message); + + void OnWorkerOnSetIndeterminateProgress(object sender, EventArgs args) => + Dispatcher.UIThread.Post(() => IndeterminateProgress = true); + + void OnWorkerOnErrorOccurred(object sender, ErrorEventArgs args) => Dispatcher.UIThread.Post(() => + { + ErrorMessage = args.Message; + ErrorVisible = true; + CanClose = true; + }); + + void ExecuteCloseCommand() => _view.Close(); + + internal void OnOpened() + { + ProgressVisible = true; + Task.Run(_worker.Import); + } + } +} \ No newline at end of file diff --git a/RomRepoMgr/ViewModels/MainWindowViewModel.cs b/RomRepoMgr/ViewModels/MainWindowViewModel.cs index cc30efd..84b0108 100644 --- a/RomRepoMgr/ViewModels/MainWindowViewModel.cs +++ b/RomRepoMgr/ViewModels/MainWindowViewModel.cs @@ -23,6 +23,7 @@ // Copyright © 2020 Natalia Portillo *******************************************************************************/ +using System.Collections.Generic; using System.Collections.ObjectModel; using System.Reactive; using Avalonia; @@ -40,11 +41,12 @@ namespace RomRepoMgr.ViewModels public MainWindowViewModel(MainWindow view) { - _view = view; - ExitCommand = ReactiveCommand.Create(ExecuteExitCommand); - SettingsCommand = ReactiveCommand.Create(ExecuteSettingsCommand); - AboutCommand = ReactiveCommand.Create(ExecuteAboutCommand); - RomSets = new ObservableCollection(); + _view = view; + ExitCommand = ReactiveCommand.Create(ExecuteExitCommand); + SettingsCommand = ReactiveCommand.Create(ExecuteSettingsCommand); + AboutCommand = ReactiveCommand.Create(ExecuteAboutCommand); + ImportDatCommand = ReactiveCommand.Create(ExecuteImportDatCommand); + RomSets = new ObservableCollection(); } public ObservableCollection RomSets { get; } @@ -57,9 +59,10 @@ namespace RomRepoMgr.ViewModels NativeMenu.GetIsNativeMenuExported((Application.Current.ApplicationLifetime as IClassicDesktopStyleApplicationLifetime)?.MainWindow); - public ReactiveCommand AboutCommand { get; } - public ReactiveCommand ExitCommand { get; } - public ReactiveCommand SettingsCommand { get; } + public ReactiveCommand AboutCommand { get; } + public ReactiveCommand ExitCommand { get; } + public ReactiveCommand SettingsCommand { get; } + public ReactiveCommand ImportDatCommand { get; } internal async void ExecuteSettingsCommand() { @@ -77,5 +80,40 @@ namespace RomRepoMgr.ViewModels dialog.DataContext = new AboutViewModel(dialog); dialog.ShowDialog(_view); } + + internal async void ExecuteImportDatCommand() + { + var dlgOpen = new OpenFileDialog(); + dlgOpen.AllowMultiple = false; + dlgOpen.Title = "Import DAT file..."; + + dlgOpen.Filters.Add(new FileDialogFilter + { + Extensions = new List + { + "*.dat", + "*.xml" + }, + Name = "DAT files" + }); + + dlgOpen.Filters.Add(new FileDialogFilter + { + Extensions = new List + { + "*.*" + }, + Name = "All files" + }); + + string[] result = await dlgOpen.ShowAsync(_view); + + if(result?.Length != 1) + return; + + var dialog = new ImportDat(); + dialog.DataContext = new ImportDatViewModel(dialog, result[0]); + await dialog.ShowDialog(_view); + } } } \ No newline at end of file diff --git a/RomRepoMgr/Views/ImportDat.xaml b/RomRepoMgr/Views/ImportDat.xaml new file mode 100644 index 0000000..5ce512b --- /dev/null +++ b/RomRepoMgr/Views/ImportDat.xaml @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/RomRepoMgr/Views/ImportDat.xaml.cs b/RomRepoMgr/Views/ImportDat.xaml.cs new file mode 100644 index 0000000..ca9df63 --- /dev/null +++ b/RomRepoMgr/Views/ImportDat.xaml.cs @@ -0,0 +1,45 @@ +/****************************************************************************** +// RomRepoMgr - ROM repository manager +// ---------------------------------------------------------------------------- +// +// Author(s) : Natalia Portillo +// +// --[ License ] -------------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2020 Natalia Portillo +*******************************************************************************/ + +using System; +using Avalonia.Controls; +using Avalonia.Markup.Xaml; +using RomRepoMgr.ViewModels; + +namespace RomRepoMgr.Views +{ + public sealed class ImportDat : Window + { + public ImportDat() => InitializeComponent(); + + void InitializeComponent() => AvaloniaXamlLoader.Load(this); + + protected override void OnOpened(EventArgs e) + { + base.OnOpened(e); + (DataContext as ImportDatViewModel)?.OnOpened(); + } + } +} \ No newline at end of file diff --git a/RomRepoMgr/Views/MainWindow.xaml b/RomRepoMgr/Views/MainWindow.xaml index 39c87ec..55259d5 100644 --- a/RomRepoMgr/Views/MainWindow.xaml +++ b/RomRepoMgr/Views/MainWindow.xaml @@ -9,6 +9,7 @@ + diff --git a/SabreTools b/SabreTools new file mode 160000 index 0000000..b01217c --- /dev/null +++ b/SabreTools @@ -0,0 +1 @@ +Subproject commit b01217cffbc69fa8c75787ea3e35359a49f42387