Move all rom import code to Core.

This commit is contained in:
2020-08-23 22:17:49 +01:00
parent 8f289e3939
commit c0c8f8f5e1
4 changed files with 237 additions and 115 deletions

View File

@@ -0,0 +1,34 @@
/******************************************************************************
// RomRepoMgr - ROM repository manager
// ----------------------------------------------------------------------------
//
// Author(s) : Natalia Portillo <claunia@claunia.com>
//
// --[ 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 <http://www.gnu.org/licenses/>.
//
// ----------------------------------------------------------------------------
// Copyright © 2020 Natalia Portillo
*******************************************************************************/
using RomRepoMgr.Core.Models;
namespace RomRepoMgr.Core.EventArgs
{
public sealed class ImportedRomItemEventArgs : System.EventArgs
{
public ImportRomItem Item { get; set; }
}
}

View File

@@ -0,0 +1,33 @@
/******************************************************************************
// RomRepoMgr - ROM repository manager
// ----------------------------------------------------------------------------
//
// Author(s) : Natalia Portillo <claunia@claunia.com>
//
// --[ 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 <http://www.gnu.org/licenses/>.
//
// ----------------------------------------------------------------------------
// Copyright © 2020 Natalia Portillo
*******************************************************************************/
namespace RomRepoMgr.Core.Models
{
public sealed class ImportRomItem
{
public string Filename { get; set; }
public string Status { get; set; }
}
}

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using RomRepoMgr.Core.EventArgs; using RomRepoMgr.Core.EventArgs;
using RomRepoMgr.Core.Models;
using RomRepoMgr.Database; using RomRepoMgr.Database;
using RomRepoMgr.Database.Models; using RomRepoMgr.Database.Models;
using SharpCompress.Compressors; using SharpCompress.Compressors;
@@ -18,21 +19,114 @@ namespace RomRepoMgr.Core.Workers
readonly Dictionary<string, DbFile> _pendingFiles; readonly Dictionary<string, DbFile> _pendingFiles;
string _lastMessage;
long _position;
long _totalFiles;
public FileImporter(bool onlyKnown, bool deleteAfterImport) public FileImporter(bool onlyKnown, bool deleteAfterImport)
{ {
_pendingFiles = new Dictionary<string, DbFile>(); _pendingFiles = new Dictionary<string, DbFile>();
_onlyKnown = onlyKnown; _onlyKnown = onlyKnown;
_deleteAfterImport = deleteAfterImport; _deleteAfterImport = deleteAfterImport;
_position = 0;
} }
public string LastMessage { get; private set; } public event EventHandler SetIndeterminateProgress2;
public event EventHandler<ProgressBoundsEventArgs> SetProgressBounds2;
public event EventHandler<ProgressEventArgs> SetProgress2;
public event EventHandler<MessageEventArgs> SetMessage2;
public event EventHandler SetIndeterminateProgress;
public event EventHandler<ProgressBoundsEventArgs> SetProgressBounds;
public event EventHandler<ProgressEventArgs> SetProgress;
public event EventHandler<MessageEventArgs> SetMessage;
public event EventHandler Finished;
public event EventHandler<ImportedRomItemEventArgs> ImportedRom;
public event EventHandler SetIndeterminateProgress; public void ProcessPath(string path, bool rootPath, bool removePathOnFinish)
public event EventHandler<ProgressBoundsEventArgs> SetProgressBounds; {
public event EventHandler<ProgressEventArgs> SetProgress; try
public event EventHandler<MessageEventArgs> SetMessage; {
SetIndeterminateProgress?.Invoke(this, System.EventArgs.Empty);
public bool ImportRom(string path) SetMessage?.Invoke(this, new MessageEventArgs
{
Message = "Enumerating files..."
});
string[] files = Directory.GetFiles(path, "*", SearchOption.AllDirectories);
_totalFiles += files.LongLength;
SetProgressBounds?.Invoke(this, new ProgressBoundsEventArgs
{
Minimum = 0,
Maximum = _totalFiles
});
foreach(string file in files)
{
SetProgress?.Invoke(this, new ProgressEventArgs
{
Value = _position
});
SetMessage?.Invoke(this, new MessageEventArgs
{
Message = string.Format("Importing {0}...", Path.GetFileName(file))
});
bool ret = ImportRom(file);
if(ret)
{
ImportedRom?.Invoke(this, new ImportedRomItemEventArgs
{
Item = new ImportRomItem
{
Filename = Path.GetFileName(file),
Status = "OK"
}
});
}
else
{
ImportedRom?.Invoke(this, new ImportedRomItemEventArgs
{
Item = new ImportRomItem
{
Filename = Path.GetFileName(file),
Status = string.Format("Error: {0}", _lastMessage)
}
});
}
_position++;
}
if(removePathOnFinish)
{
SetMessage?.Invoke(this, new MessageEventArgs
{
Message = "Removing temporary path..."
});
Directory.Delete(path, true);
}
if(!rootPath)
return;
SaveChanges();
Finished?.Invoke(this, System.EventArgs.Empty);
}
catch(Exception)
{
// TODO: Send error back
if(rootPath)
Finished?.Invoke(this, System.EventArgs.Empty);
}
}
bool ImportRom(string path)
{ {
try try
{ {
@@ -40,7 +134,7 @@ namespace RomRepoMgr.Core.Workers
byte[] dataBuffer; byte[] dataBuffer;
SetMessage?.Invoke(this, new MessageEventArgs SetMessage2?.Invoke(this, new MessageEventArgs
{ {
Message = "Hashing file..." Message = "Hashing file..."
}); });
@@ -49,7 +143,7 @@ namespace RomRepoMgr.Core.Workers
if(inFs.Length > BUFFER_SIZE) if(inFs.Length > BUFFER_SIZE)
{ {
SetProgressBounds?.Invoke(this, new ProgressBoundsEventArgs SetProgressBounds2?.Invoke(this, new ProgressBoundsEventArgs
{ {
Minimum = 0, Minimum = 0,
Maximum = inFs.Length Maximum = inFs.Length
@@ -60,7 +154,7 @@ namespace RomRepoMgr.Core.Workers
for(offset = 0; offset < inFs.Length - remainder; offset += (int)BUFFER_SIZE) for(offset = 0; offset < inFs.Length - remainder; offset += (int)BUFFER_SIZE)
{ {
SetProgress?.Invoke(this, new ProgressEventArgs SetProgress2?.Invoke(this, new ProgressEventArgs
{ {
Value = offset Value = offset
}); });
@@ -70,7 +164,7 @@ namespace RomRepoMgr.Core.Workers
checksumWorker.Update(dataBuffer); checksumWorker.Update(dataBuffer);
} }
SetProgress?.Invoke(this, new ProgressEventArgs SetProgress2?.Invoke(this, new ProgressEventArgs
{ {
Value = offset Value = offset
}); });
@@ -81,7 +175,7 @@ namespace RomRepoMgr.Core.Workers
} }
else else
{ {
SetIndeterminateProgress?.Invoke(this, System.EventArgs.Empty); SetIndeterminateProgress2?.Invoke(this, System.EventArgs.Empty);
dataBuffer = new byte[inFs.Length]; dataBuffer = new byte[inFs.Length];
inFs.Read(dataBuffer, 0, (int)inFs.Length); inFs.Read(dataBuffer, 0, (int)inFs.Length);
checksumWorker.Update(dataBuffer); checksumWorker.Update(dataBuffer);
@@ -112,7 +206,7 @@ namespace RomRepoMgr.Core.Workers
{ {
if(_onlyKnown) if(_onlyKnown)
{ {
LastMessage = "Unknown file."; _lastMessage = "Unknown file.";
return false; return false;
} }
@@ -232,13 +326,13 @@ namespace RomRepoMgr.Core.Workers
Stream zStream = null; Stream zStream = null;
zStream = new LZipStream(outFs, CompressionMode.Compress); zStream = new LZipStream(outFs, CompressionMode.Compress);
SetProgressBounds?.Invoke(this, new ProgressBoundsEventArgs SetProgressBounds2?.Invoke(this, new ProgressBoundsEventArgs
{ {
Minimum = 0, Minimum = 0,
Maximum = inFs.Length Maximum = inFs.Length
}); });
SetMessage?.Invoke(this, new MessageEventArgs SetMessage2?.Invoke(this, new MessageEventArgs
{ {
Message = "Compressing file..." Message = "Compressing file..."
}); });
@@ -247,7 +341,7 @@ namespace RomRepoMgr.Core.Workers
while(inFs.Position + BUFFER_SIZE <= inFs.Length) while(inFs.Position + BUFFER_SIZE <= inFs.Length)
{ {
SetProgress?.Invoke(this, new ProgressEventArgs SetProgress2?.Invoke(this, new ProgressEventArgs
{ {
Value = inFs.Position Value = inFs.Position
}); });
@@ -258,7 +352,7 @@ namespace RomRepoMgr.Core.Workers
buffer = new byte[inFs.Length - inFs.Position]; buffer = new byte[inFs.Length - inFs.Position];
SetProgress?.Invoke(this, new ProgressEventArgs SetProgress2?.Invoke(this, new ProgressEventArgs
{ {
Value = inFs.Position Value = inFs.Position
}); });
@@ -266,9 +360,9 @@ namespace RomRepoMgr.Core.Workers
inFs.Read(buffer, 0, buffer.Length); inFs.Read(buffer, 0, buffer.Length);
zStream.Write(buffer, 0, buffer.Length); zStream.Write(buffer, 0, buffer.Length);
SetIndeterminateProgress?.Invoke(this, System.EventArgs.Empty); SetIndeterminateProgress2?.Invoke(this, System.EventArgs.Empty);
SetMessage?.Invoke(this, new MessageEventArgs SetMessage2?.Invoke(this, new MessageEventArgs
{ {
Message = "Finishing..." Message = "Finishing..."
}); });
@@ -290,17 +384,17 @@ namespace RomRepoMgr.Core.Workers
} }
catch(Exception e) catch(Exception e)
{ {
LastMessage = "Unhandled exception when importing file."; _lastMessage = "Unhandled exception when importing file.";
return false; return false;
} }
} }
public void SaveChanges() void SaveChanges()
{ {
SetIndeterminateProgress?.Invoke(this, System.EventArgs.Empty); SetIndeterminateProgress2?.Invoke(this, System.EventArgs.Empty);
SetMessage?.Invoke(this, new MessageEventArgs SetMessage2?.Invoke(this, new MessageEventArgs
{ {
Message = "Saving changes to database..." Message = "Saving changes to database..."
}); });

View File

@@ -25,14 +25,13 @@
using System; using System;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Reactive; using System.Reactive;
using System.Threading.Tasks; using System.Threading.Tasks;
using Avalonia.Threading; using Avalonia.Threading;
using JetBrains.Annotations; using JetBrains.Annotations;
using ReactiveUI; using ReactiveUI;
using RomRepoMgr.Core.EventArgs; using RomRepoMgr.Core.EventArgs;
using RomRepoMgr.Core.Models;
using RomRepoMgr.Core.Workers; using RomRepoMgr.Core.Workers;
using RomRepoMgr.Views; using RomRepoMgr.Views;
@@ -69,7 +68,7 @@ namespace RomRepoMgr.ViewModels
_removeFilesChecked = false; _removeFilesChecked = false;
_knownOnlyChecked = true; _knownOnlyChecked = true;
_recurseArchivesChecked = Settings.Settings.UnArUsable; _recurseArchivesChecked = Settings.Settings.UnArUsable;
ImportResults = new ObservableCollection<ImportRomFolderItem>(); ImportResults = new ObservableCollection<ImportRomItem>();
CloseCommand = ReactiveCommand.Create(ExecuteCloseCommand); CloseCommand = ReactiveCommand.Create(ExecuteCloseCommand);
StartCommand = ReactiveCommand.Create(ExecuteStartCommand); StartCommand = ReactiveCommand.Create(ExecuteStartCommand);
IsReady = true; IsReady = true;
@@ -203,11 +202,11 @@ namespace RomRepoMgr.ViewModels
[NotNull] [NotNull]
public string Title => "Import ROM files from folder..."; public string Title => "Import ROM files from folder...";
public ObservableCollection<ImportRomFolderItem> ImportResults { get; } public ObservableCollection<ImportRomItem> ImportResults { get; }
public string ResultFilenameLabel => "Filename"; public string ResultFilenameLabel => "Filename";
public string ResultStatusLabel => "Status"; public string ResultStatusLabel => "Status";
public string CloseLabel => "Close"; public string CloseLabel => "Close";
public string StartLabel => "Start"; public string StartLabel => "Start";
public bool CanClose public bool CanClose
{ {
@@ -228,106 +227,68 @@ namespace RomRepoMgr.ViewModels
void ExecuteStartCommand() void ExecuteStartCommand()
{ {
IsReady = false; IsReady = false;
ProgressVisible = true; ProgressVisible = true;
ProgressIsIndeterminate = true; IsImporting = true;
StatusMessage = "Enumerating files..."; CanStart = false;
IsImporting = true; CanClose = false;
CanStart = false;
CanClose = false;
Task.Run(() => var worker = new FileImporter(KnownOnlyChecked, RemoveFilesChecked);
{ worker.SetIndeterminateProgress += OnWorkerOnSetIndeterminateProgress;
var watch = new Stopwatch(); worker.SetMessage += OnWorkerOnSetMessage;
string[] files = Directory.GetFiles(FolderPath, "*", SearchOption.AllDirectories); worker.SetProgress += OnWorkerOnSetProgress;
worker.SetProgressBounds += OnWorkerOnSetProgressBounds;
worker.SetIndeterminateProgress2 += OnWorkerOnSetIndeterminateProgress2;
worker.SetMessage2 += OnWorkerOnSetMessage2;
worker.SetProgress2 += OnWorkerOnSetProgress2;
worker.SetProgressBounds2 += OnWorkerOnSetProgressBounds2;
worker.Finished += OnWorkerOnFinished;
worker.ImportedRom += OnWorkerOnImportedRom;
Dispatcher.UIThread.Post(() => Task.Run(() => worker.ProcessPath(FolderPath, true, false));
{
ProgressIsIndeterminate = false;
ProgressMinimum = 0;
ProgressMaximum = files.LongLength;
ProgressValue = 0;
Progress2Visible = true;
});
var worker = new FileImporter(KnownOnlyChecked, RemoveFilesChecked);
worker.SetIndeterminateProgress += OnWorkerOnSetIndeterminateProgress;
worker.SetMessage += OnWorkerOnSetMessage;
worker.SetProgress += OnWorkerOnSetProgress;
worker.SetProgressBounds += OnWorkerOnSetProgressBounds;
long position = 0;
watch.Start();
foreach(string file in files)
{
Dispatcher.UIThread.Post(() =>
{
StatusMessage = string.Format("Importing {0}...", Path.GetFileName(file));
ProgressValue = position;
});
bool ret = worker.ImportRom(file);
Dispatcher.UIThread.Post(() =>
{
if(ret)
{
ImportResults.Add(new ImportRomFolderItem
{
Filename = Path.GetFileName(file),
Status = "OK"
});
}
else
{
ImportResults.Add(new ImportRomFolderItem
{
Filename = Path.GetFileName(file),
Status = string.Format("Error: {0}", worker.LastMessage)
});
}
});
position++;
}
worker.SaveChanges();
watch.Stop();
Dispatcher.UIThread.Post(() =>
{
ProgressVisible = false;
StatusMessage = "Finished!";
CanClose = true;
Progress2Visible = false;
Console.WriteLine($"Took {watch.Elapsed.TotalSeconds} seconds");
});
});
} }
void OnWorkerOnImportedRom(object? sender, ImportedRomItemEventArgs args) =>
Dispatcher.UIThread.Post(() => ImportResults.Add(args.Item));
void OnWorkerOnFinished(object? sender, EventArgs args) => Dispatcher.UIThread.Post(() =>
{
ProgressVisible = false;
StatusMessage = "Finished!";
CanClose = true;
Progress2Visible = false;
});
void OnWorkerOnSetProgressBounds(object sender, ProgressBoundsEventArgs args) => Dispatcher.UIThread.Post(() => void OnWorkerOnSetProgressBounds(object sender, ProgressBoundsEventArgs args) => Dispatcher.UIThread.Post(() =>
{
ProgressIsIndeterminate = false;
ProgressMaximum = args.Maximum;
ProgressMinimum = args.Minimum;
});
void OnWorkerOnSetProgress(object sender, ProgressEventArgs args) =>
Dispatcher.UIThread.Post(() => ProgressValue = args.Value);
void OnWorkerOnSetMessage(object sender, MessageEventArgs args) =>
Dispatcher.UIThread.Post(() => StatusMessage = args.Message);
void OnWorkerOnSetIndeterminateProgress(object sender, EventArgs args) =>
Dispatcher.UIThread.Post(() => ProgressIsIndeterminate = true);
void OnWorkerOnSetProgressBounds2(object sender, ProgressBoundsEventArgs args) => Dispatcher.UIThread.Post(() =>
{ {
Progress2IsIndeterminate = false; Progress2IsIndeterminate = false;
Progress2Maximum = args.Maximum; Progress2Maximum = args.Maximum;
Progress2Minimum = args.Minimum; Progress2Minimum = args.Minimum;
}); });
void OnWorkerOnSetProgress(object sender, ProgressEventArgs args) => void OnWorkerOnSetProgress2(object sender, ProgressEventArgs args) =>
Dispatcher.UIThread.Post(() => Progress2Value = args.Value); Dispatcher.UIThread.Post(() => Progress2Value = args.Value);
void OnWorkerOnSetMessage(object sender, MessageEventArgs args) => void OnWorkerOnSetMessage2(object sender, MessageEventArgs args) =>
Dispatcher.UIThread.Post(() => Status2Message = args.Message); Dispatcher.UIThread.Post(() => Status2Message = args.Message);
void OnWorkerOnSetIndeterminateProgress(object sender, EventArgs args) => void OnWorkerOnSetIndeterminateProgress2(object sender, EventArgs args) =>
Dispatcher.UIThread.Post(() => Progress2IsIndeterminate = true); Dispatcher.UIThread.Post(() => Progress2IsIndeterminate = true);
} }
public sealed class ImportRomFolderItem
{
public string Filename { get; set; }
public string Status { get; set; }
}
} }