mirror of
https://github.com/claunia/romrepomgr.git
synced 2025-12-16 11:14:45 +00:00
Full code refactor and clean-up.
This commit is contained in:
@@ -35,201 +35,227 @@ using System.Diagnostics.CodeAnalysis;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
namespace RomRepoMgr.Core.Aaru
|
||||
namespace RomRepoMgr.Core.Aaru;
|
||||
|
||||
// TODO: This should be taken from Aaru as a nuget package in the future
|
||||
public static class FAT
|
||||
{
|
||||
// TODO: This should be taken from Aaru as a nuget package in the future
|
||||
public static class FAT
|
||||
static int CountBits(uint number)
|
||||
{
|
||||
static int CountBits(uint number)
|
||||
{
|
||||
number -= (number >> 1) & 0x55555555;
|
||||
number = (number & 0x33333333) + ((number >> 2) & 0x33333333);
|
||||
number -= number >> 1 & 0x55555555;
|
||||
number = (number & 0x33333333) + (number >> 2 & 0x33333333);
|
||||
|
||||
return (int)((((number + (number >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24);
|
||||
return (int)((number + (number >> 4) & 0x0F0F0F0F) * 0x01010101 >> 24);
|
||||
}
|
||||
|
||||
public static bool Identify(string path)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Identify(new FileStream(path, FileMode.Open, FileAccess.Read));
|
||||
}
|
||||
|
||||
public static bool Identify(string path)
|
||||
catch(Exception e)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Identify(new FileStream(path, FileMode.Open, FileAccess.Read));
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
[SuppressMessage("ReSharper", "JoinDeclarationAndInitializer")]
|
||||
static bool Identify(Stream imageStream)
|
||||
{
|
||||
ushort bps;
|
||||
byte spc;
|
||||
byte numberOfFats;
|
||||
ushort reservedSecs;
|
||||
ushort rootEntries;
|
||||
ushort sectors;
|
||||
ushort fatSectors;
|
||||
uint bigSectors;
|
||||
byte bpbSignature;
|
||||
byte fat32Signature;
|
||||
ulong hugeSectors;
|
||||
byte[] fat32Id = new byte[8];
|
||||
byte[] msxId = new byte[6];
|
||||
byte[] dosOem = new byte[8];
|
||||
byte[] atariOem = new byte[6];
|
||||
ushort bootable = 0;
|
||||
|
||||
byte[] bpbSector = new byte[512];
|
||||
byte[] fatSector = new byte[512];
|
||||
imageStream.Position = 0;
|
||||
imageStream.Read(bpbSector, 0, 512);
|
||||
imageStream.Read(fatSector, 0, 512);
|
||||
|
||||
Array.Copy(bpbSector, 0x02, atariOem, 0, 6);
|
||||
Array.Copy(bpbSector, 0x03, dosOem, 0, 8);
|
||||
bps = BitConverter.ToUInt16(bpbSector, 0x00B);
|
||||
spc = bpbSector[0x00D];
|
||||
reservedSecs = BitConverter.ToUInt16(bpbSector, 0x00E);
|
||||
numberOfFats = bpbSector[0x010];
|
||||
rootEntries = BitConverter.ToUInt16(bpbSector, 0x011);
|
||||
sectors = BitConverter.ToUInt16(bpbSector, 0x013);
|
||||
fatSectors = BitConverter.ToUInt16(bpbSector, 0x016);
|
||||
Array.Copy(bpbSector, 0x052, msxId, 0, 6);
|
||||
bigSectors = BitConverter.ToUInt32(bpbSector, 0x020);
|
||||
bpbSignature = bpbSector[0x026];
|
||||
fat32Signature = bpbSector[0x042];
|
||||
Array.Copy(bpbSector, 0x052, fat32Id, 0, 8);
|
||||
hugeSectors = BitConverter.ToUInt64(bpbSector, 0x052);
|
||||
int bitsInBps = CountBits(bps);
|
||||
|
||||
bootable = BitConverter.ToUInt16(bpbSector, 0x1FE);
|
||||
|
||||
bool correctSpc = spc == 1 || spc == 2 || spc == 4 || spc == 8 || spc == 16 || spc == 32 || spc == 64;
|
||||
string msxString = Encoding.ASCII.GetString(msxId);
|
||||
string fat32String = Encoding.ASCII.GetString(fat32Id);
|
||||
|
||||
string oemString = Encoding.ASCII.GetString(dosOem);
|
||||
|
||||
ushort apricotBps = BitConverter.ToUInt16(bpbSector, 0x50);
|
||||
byte apricotSpc = bpbSector[0x52];
|
||||
ushort apricotReservedSecs = BitConverter.ToUInt16(bpbSector, 0x53);
|
||||
byte apricotFatsNo = bpbSector[0x55];
|
||||
ushort apricotRootEntries = BitConverter.ToUInt16(bpbSector, 0x56);
|
||||
ushort apricotSectors = BitConverter.ToUInt16(bpbSector, 0x58);
|
||||
ushort apricotFatSectors = BitConverter.ToUInt16(bpbSector, 0x5B);
|
||||
|
||||
bool apricotCorrectSpc = apricotSpc == 1 || apricotSpc == 2 || apricotSpc == 4 || apricotSpc == 8 ||
|
||||
apricotSpc == 16 || apricotSpc == 32 || apricotSpc == 64;
|
||||
|
||||
int bitsInApricotBps = CountBits(apricotBps);
|
||||
byte apricotPartitions = bpbSector[0x0C];
|
||||
|
||||
switch(oemString)
|
||||
{
|
||||
// exFAT
|
||||
case "EXFAT ": return false;
|
||||
|
||||
// NTFS
|
||||
case "NTFS " when bootable == 0xAA55 && numberOfFats == 0 && fatSectors == 0: return false;
|
||||
|
||||
// QNX4
|
||||
case "FQNX4FS ": return false;
|
||||
}
|
||||
|
||||
ulong imageSectors = (ulong)imageStream.Length / 512;
|
||||
|
||||
switch(bitsInBps)
|
||||
{
|
||||
// FAT32 for sure
|
||||
case 1 when correctSpc && numberOfFats <= 2 && sectors == 0 && fatSectors == 0 &&
|
||||
fat32Signature == 0x29 && fat32String == "FAT32 ": return true;
|
||||
|
||||
// short FAT32
|
||||
case 1
|
||||
when correctSpc && numberOfFats <= 2 && sectors == 0 && fatSectors == 0 && fat32Signature == 0x28:
|
||||
return bigSectors == 0 ? hugeSectors <= imageSectors : bigSectors <= imageSectors;
|
||||
|
||||
// MSX-DOS FAT12
|
||||
case 1 when correctSpc && numberOfFats <= 2 && rootEntries > 0 && sectors <= imageSectors &&
|
||||
fatSectors > 0 && msxString == "VOL_ID": return true;
|
||||
|
||||
// EBPB
|
||||
case 1 when correctSpc && numberOfFats <= 2 && rootEntries > 0 && fatSectors > 0 &&
|
||||
(bpbSignature == 0x28 || bpbSignature == 0x29):
|
||||
return sectors == 0 ? bigSectors <= imageSectors : sectors <= imageSectors;
|
||||
|
||||
// BPB
|
||||
case 1 when correctSpc && reservedSecs < imageSectors - 1 && numberOfFats <= 2 && rootEntries > 0 &&
|
||||
fatSectors > 0: return sectors == 0 ? bigSectors <= imageSectors : sectors <= imageSectors;
|
||||
}
|
||||
|
||||
// Apricot BPB
|
||||
if(bitsInApricotBps == 1 &&
|
||||
apricotCorrectSpc &&
|
||||
apricotReservedSecs < imageSectors - 1 &&
|
||||
apricotFatsNo <= 2 &&
|
||||
apricotRootEntries > 0 &&
|
||||
apricotFatSectors > 0 &&
|
||||
apricotSectors <= imageSectors &&
|
||||
apricotPartitions == 0)
|
||||
return true;
|
||||
|
||||
// DEC Rainbow, lacks a BPB but has a very concrete structure...
|
||||
if(imageSectors != 800)
|
||||
return false;
|
||||
|
||||
// DEC Rainbow boots up with a Z80, first byte should be DI (disable interrupts)
|
||||
byte z80Di = bpbSector[0];
|
||||
|
||||
// First FAT1 sector resides at LBA 0x14
|
||||
byte[] fat1Sector0 = new byte[512];
|
||||
imageStream.Position = 0x14 * 512;
|
||||
imageStream.Read(fat1Sector0, 0, 512);
|
||||
|
||||
// First FAT2 sector resides at LBA 0x1A
|
||||
byte[] fat2Sector0 = new byte[512];
|
||||
imageStream.Position = 0x1A * 512;
|
||||
imageStream.Read(fat2Sector0, 0, 512);
|
||||
bool equalFatIds = fat1Sector0[0] == fat2Sector0[0] && fat1Sector0[1] == fat2Sector0[1];
|
||||
|
||||
// Volume is software interleaved 2:1
|
||||
var rootMs = new MemoryStream();
|
||||
|
||||
byte[] tmp = new byte[512];
|
||||
|
||||
foreach(long position in new long[]
|
||||
{
|
||||
0x17, 0x19, 0x1B, 0x1D, 0x1E, 0x20
|
||||
})
|
||||
{
|
||||
imageStream.Position = position * 512;
|
||||
imageStream.Read(tmp, 0, 512);
|
||||
rootMs.Write(tmp, 0, tmp.Length);
|
||||
}
|
||||
|
||||
byte[] rootDir = rootMs.ToArray();
|
||||
bool validRootDir = true;
|
||||
|
||||
// Iterate all root directory
|
||||
for(int e = 0; e < 96 * 32; e += 32)
|
||||
{
|
||||
for(int c = 0; c < 11; c++)
|
||||
if((rootDir[c + e] < 0x20 && rootDir[c + e] != 0x00 && rootDir[c + e] != 0x05) ||
|
||||
rootDir[c + e] == 0xFF ||
|
||||
rootDir[c + e] == 0x2E)
|
||||
{
|
||||
validRootDir = false;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if(!validRootDir)
|
||||
break;
|
||||
}
|
||||
|
||||
return z80Di == 0xF3 && equalFatIds && (fat1Sector0[0] & 0xF0) == 0xF0 && fat1Sector0[1] == 0xFF &&
|
||||
validRootDir;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
[SuppressMessage("ReSharper", "JoinDeclarationAndInitializer")]
|
||||
static bool Identify(Stream imageStream)
|
||||
{
|
||||
ushort bps;
|
||||
byte spc;
|
||||
byte numberOfFats;
|
||||
ushort reservedSecs;
|
||||
ushort rootEntries;
|
||||
ushort sectors;
|
||||
ushort fatSectors;
|
||||
uint bigSectors;
|
||||
byte bpbSignature;
|
||||
byte fat32Signature;
|
||||
ulong hugeSectors;
|
||||
var fat32Id = new byte[8];
|
||||
var msxId = new byte[6];
|
||||
var dosOem = new byte[8];
|
||||
var atariOem = new byte[6];
|
||||
ushort bootable = 0;
|
||||
|
||||
var bpbSector = new byte[512];
|
||||
var fatSector = new byte[512];
|
||||
imageStream.Position = 0;
|
||||
imageStream.Read(bpbSector, 0, 512);
|
||||
imageStream.Read(fatSector, 0, 512);
|
||||
|
||||
Array.Copy(bpbSector, 0x02, atariOem, 0, 6);
|
||||
Array.Copy(bpbSector, 0x03, dosOem, 0, 8);
|
||||
bps = BitConverter.ToUInt16(bpbSector, 0x00B);
|
||||
spc = bpbSector[0x00D];
|
||||
reservedSecs = BitConverter.ToUInt16(bpbSector, 0x00E);
|
||||
numberOfFats = bpbSector[0x010];
|
||||
rootEntries = BitConverter.ToUInt16(bpbSector, 0x011);
|
||||
sectors = BitConverter.ToUInt16(bpbSector, 0x013);
|
||||
fatSectors = BitConverter.ToUInt16(bpbSector, 0x016);
|
||||
Array.Copy(bpbSector, 0x052, msxId, 0, 6);
|
||||
bigSectors = BitConverter.ToUInt32(bpbSector, 0x020);
|
||||
bpbSignature = bpbSector[0x026];
|
||||
fat32Signature = bpbSector[0x042];
|
||||
Array.Copy(bpbSector, 0x052, fat32Id, 0, 8);
|
||||
hugeSectors = BitConverter.ToUInt64(bpbSector, 0x052);
|
||||
int bitsInBps = CountBits(bps);
|
||||
|
||||
bootable = BitConverter.ToUInt16(bpbSector, 0x1FE);
|
||||
|
||||
bool correctSpc = spc == 1 || spc == 2 || spc == 4 || spc == 8 || spc == 16 || spc == 32 || spc == 64;
|
||||
string msxString = Encoding.ASCII.GetString(msxId);
|
||||
string fat32String = Encoding.ASCII.GetString(fat32Id);
|
||||
|
||||
string oemString = Encoding.ASCII.GetString(dosOem);
|
||||
|
||||
var apricotBps = BitConverter.ToUInt16(bpbSector, 0x50);
|
||||
byte apricotSpc = bpbSector[0x52];
|
||||
var apricotReservedSecs = BitConverter.ToUInt16(bpbSector, 0x53);
|
||||
byte apricotFatsNo = bpbSector[0x55];
|
||||
var apricotRootEntries = BitConverter.ToUInt16(bpbSector, 0x56);
|
||||
var apricotSectors = BitConverter.ToUInt16(bpbSector, 0x58);
|
||||
var apricotFatSectors = BitConverter.ToUInt16(bpbSector, 0x5B);
|
||||
|
||||
bool apricotCorrectSpc = apricotSpc == 1 ||
|
||||
apricotSpc == 2 ||
|
||||
apricotSpc == 4 ||
|
||||
apricotSpc == 8 ||
|
||||
apricotSpc == 16 ||
|
||||
apricotSpc == 32 ||
|
||||
apricotSpc == 64;
|
||||
|
||||
int bitsInApricotBps = CountBits(apricotBps);
|
||||
byte apricotPartitions = bpbSector[0x0C];
|
||||
|
||||
switch(oemString)
|
||||
{
|
||||
// exFAT
|
||||
case "EXFAT ":
|
||||
return false;
|
||||
|
||||
// NTFS
|
||||
case "NTFS " when bootable == 0xAA55 && numberOfFats == 0 && fatSectors == 0:
|
||||
return false;
|
||||
|
||||
// QNX4
|
||||
case "FQNX4FS ":
|
||||
return false;
|
||||
}
|
||||
|
||||
ulong imageSectors = (ulong)imageStream.Length / 512;
|
||||
|
||||
switch(bitsInBps)
|
||||
{
|
||||
// FAT32 for sure
|
||||
case 1 when correctSpc &&
|
||||
numberOfFats <= 2 &&
|
||||
sectors == 0 &&
|
||||
fatSectors == 0 &&
|
||||
fat32Signature == 0x29 &&
|
||||
fat32String == "FAT32 ":
|
||||
return true;
|
||||
|
||||
// short FAT32
|
||||
case 1 when correctSpc && numberOfFats <= 2 && sectors == 0 && fatSectors == 0 && fat32Signature == 0x28:
|
||||
return bigSectors == 0 ? hugeSectors <= imageSectors : bigSectors <= imageSectors;
|
||||
|
||||
// MSX-DOS FAT12
|
||||
case 1 when correctSpc &&
|
||||
numberOfFats <= 2 &&
|
||||
rootEntries > 0 &&
|
||||
sectors <= imageSectors &&
|
||||
fatSectors > 0 &&
|
||||
msxString == "VOL_ID":
|
||||
return true;
|
||||
|
||||
// EBPB
|
||||
case 1 when correctSpc &&
|
||||
numberOfFats <= 2 &&
|
||||
rootEntries > 0 &&
|
||||
fatSectors > 0 &&
|
||||
(bpbSignature == 0x28 || bpbSignature == 0x29):
|
||||
return sectors == 0 ? bigSectors <= imageSectors : sectors <= imageSectors;
|
||||
|
||||
// BPB
|
||||
case 1 when correctSpc &&
|
||||
reservedSecs < imageSectors - 1 &&
|
||||
numberOfFats <= 2 &&
|
||||
rootEntries > 0 &&
|
||||
fatSectors > 0:
|
||||
return sectors == 0 ? bigSectors <= imageSectors : sectors <= imageSectors;
|
||||
}
|
||||
|
||||
// Apricot BPB
|
||||
if(bitsInApricotBps == 1 &&
|
||||
apricotCorrectSpc &&
|
||||
apricotReservedSecs < imageSectors - 1 &&
|
||||
apricotFatsNo <= 2 &&
|
||||
apricotRootEntries > 0 &&
|
||||
apricotFatSectors > 0 &&
|
||||
apricotSectors <= imageSectors &&
|
||||
apricotPartitions == 0)
|
||||
return true;
|
||||
|
||||
// DEC Rainbow, lacks a BPB but has a very concrete structure...
|
||||
if(imageSectors != 800) return false;
|
||||
|
||||
// DEC Rainbow boots up with a Z80, first byte should be DI (disable interrupts)
|
||||
byte z80Di = bpbSector[0];
|
||||
|
||||
// First FAT1 sector resides at LBA 0x14
|
||||
var fat1Sector0 = new byte[512];
|
||||
imageStream.Position = 0x14 * 512;
|
||||
imageStream.Read(fat1Sector0, 0, 512);
|
||||
|
||||
// First FAT2 sector resides at LBA 0x1A
|
||||
var fat2Sector0 = new byte[512];
|
||||
imageStream.Position = 0x1A * 512;
|
||||
imageStream.Read(fat2Sector0, 0, 512);
|
||||
bool equalFatIds = fat1Sector0[0] == fat2Sector0[0] && fat1Sector0[1] == fat2Sector0[1];
|
||||
|
||||
// Volume is software interleaved 2:1
|
||||
var rootMs = new MemoryStream();
|
||||
|
||||
var tmp = new byte[512];
|
||||
|
||||
foreach(long position in new long[]
|
||||
{
|
||||
0x17, 0x19, 0x1B, 0x1D, 0x1E, 0x20
|
||||
})
|
||||
{
|
||||
imageStream.Position = position * 512;
|
||||
imageStream.Read(tmp, 0, 512);
|
||||
rootMs.Write(tmp, 0, tmp.Length);
|
||||
}
|
||||
|
||||
byte[] rootDir = rootMs.ToArray();
|
||||
var validRootDir = true;
|
||||
|
||||
// Iterate all root directory
|
||||
for(var e = 0; e < 96 * 32; e += 32)
|
||||
{
|
||||
for(var c = 0; c < 11; c++)
|
||||
{
|
||||
if(rootDir[c + e] < 0x20 && rootDir[c + e] != 0x00 && rootDir[c + e] != 0x05 ||
|
||||
rootDir[c + e] == 0xFF ||
|
||||
rootDir[c + e] == 0x2E)
|
||||
{
|
||||
validRootDir = false;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!validRootDir) break;
|
||||
}
|
||||
|
||||
return z80Di == 0xF3 &&
|
||||
equalFatIds &&
|
||||
(fat1Sector0[0] & 0xF0) == 0xF0 &&
|
||||
fat1Sector0[1] == 0xFF &&
|
||||
validRootDir;
|
||||
}
|
||||
}
|
||||
@@ -8,98 +8,76 @@ using System;
|
||||
using System.Text;
|
||||
using RomRepoMgr.Core.Resources;
|
||||
|
||||
namespace RomRepoMgr.Core
|
||||
namespace RomRepoMgr.Core;
|
||||
|
||||
/// <summary>Class used for conversion between byte array and Base32 notation</summary>
|
||||
public sealed class Base32
|
||||
{
|
||||
/// <summary>Class used for conversion between byte array and Base32 notation</summary>
|
||||
public sealed class Base32
|
||||
/// <summary>Size of the regular byte in bits</summary>
|
||||
const int _inByteSize = 8;
|
||||
|
||||
/// <summary>Size of converted byte in bits</summary>
|
||||
const int _outByteSize = 5;
|
||||
|
||||
/// <summary>Alphabet</summary>
|
||||
const string _base32Alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
|
||||
|
||||
/// <summary>Convert byte array to Base32 format</summary>
|
||||
/// <param name="bytes">An array of bytes to convert to Base32 format</param>
|
||||
/// <returns>Returns a string representing byte array</returns>
|
||||
public static string ToBase32String(byte[] bytes)
|
||||
{
|
||||
/// <summary>Size of the regular byte in bits</summary>
|
||||
const int _inByteSize = 8;
|
||||
// Check if byte array is null
|
||||
if(bytes == null) return null;
|
||||
|
||||
/// <summary>Size of converted byte in bits</summary>
|
||||
const int _outByteSize = 5;
|
||||
// Check if empty
|
||||
|
||||
/// <summary>Alphabet</summary>
|
||||
const string _base32Alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
|
||||
if(bytes.Length == 0) return string.Empty;
|
||||
|
||||
/// <summary>Convert byte array to Base32 format</summary>
|
||||
/// <param name="bytes">An array of bytes to convert to Base32 format</param>
|
||||
/// <returns>Returns a string representing byte array</returns>
|
||||
public static string ToBase32String(byte[] bytes)
|
||||
// Prepare container for the final value
|
||||
var builder = new StringBuilder(bytes.Length * _inByteSize / _outByteSize);
|
||||
|
||||
// Position in the input buffer
|
||||
var bytesPosition = 0;
|
||||
|
||||
// Offset inside a single byte that <bytesPosition> points to (from left to right)
|
||||
// 0 - highest bit, 7 - lowest bit
|
||||
var bytesSubPosition = 0;
|
||||
|
||||
// Byte to look up in the dictionary
|
||||
byte outputBase32Byte = 0;
|
||||
|
||||
// The number of bits filled in the current output byte
|
||||
var outputBase32BytePosition = 0;
|
||||
|
||||
// Iterate through input buffer until we reach past the end of it
|
||||
while(bytesPosition < bytes.Length)
|
||||
{
|
||||
// Check if byte array is null
|
||||
if(bytes == null)
|
||||
return null;
|
||||
// Calculate the number of bits we can extract out of current input byte to fill missing bits in the output byte
|
||||
int bitsAvailableInByte = Math.Min(_inByteSize - bytesSubPosition, _outByteSize - outputBase32BytePosition);
|
||||
|
||||
// Check if empty
|
||||
// Make space in the output byte
|
||||
outputBase32Byte <<= bitsAvailableInByte;
|
||||
|
||||
if(bytes.Length == 0)
|
||||
return string.Empty;
|
||||
// Extract the part of the input byte and move it to the output byte
|
||||
outputBase32Byte |= (byte)(bytes[bytesPosition] >> _inByteSize - (bytesSubPosition + bitsAvailableInByte));
|
||||
|
||||
// Prepare container for the final value
|
||||
var builder = new StringBuilder((bytes.Length * _inByteSize) / _outByteSize);
|
||||
// Update current sub-byte position
|
||||
bytesSubPosition += bitsAvailableInByte;
|
||||
|
||||
// Position in the input buffer
|
||||
int bytesPosition = 0;
|
||||
|
||||
// Offset inside a single byte that <bytesPosition> points to (from left to right)
|
||||
// 0 - highest bit, 7 - lowest bit
|
||||
int bytesSubPosition = 0;
|
||||
|
||||
// Byte to look up in the dictionary
|
||||
byte outputBase32Byte = 0;
|
||||
|
||||
// The number of bits filled in the current output byte
|
||||
int outputBase32BytePosition = 0;
|
||||
|
||||
// Iterate through input buffer until we reach past the end of it
|
||||
while(bytesPosition < bytes.Length)
|
||||
// Check overflow
|
||||
if(bytesSubPosition >= _inByteSize)
|
||||
{
|
||||
// Calculate the number of bits we can extract out of current input byte to fill missing bits in the output byte
|
||||
int bitsAvailableInByte =
|
||||
Math.Min(_inByteSize - bytesSubPosition, _outByteSize - outputBase32BytePosition);
|
||||
|
||||
// Make space in the output byte
|
||||
outputBase32Byte <<= bitsAvailableInByte;
|
||||
|
||||
// Extract the part of the input byte and move it to the output byte
|
||||
outputBase32Byte |=
|
||||
(byte)(bytes[bytesPosition] >> (_inByteSize - (bytesSubPosition + bitsAvailableInByte)));
|
||||
|
||||
// Update current sub-byte position
|
||||
bytesSubPosition += bitsAvailableInByte;
|
||||
|
||||
// Check overflow
|
||||
if(bytesSubPosition >= _inByteSize)
|
||||
{
|
||||
// Move to the next byte
|
||||
bytesPosition++;
|
||||
bytesSubPosition = 0;
|
||||
}
|
||||
|
||||
// Update current base32 byte completion
|
||||
outputBase32BytePosition += bitsAvailableInByte;
|
||||
|
||||
// Check overflow or end of input array
|
||||
if(outputBase32BytePosition < _outByteSize)
|
||||
continue;
|
||||
|
||||
// Drop the overflow bits
|
||||
outputBase32Byte &= 0x1F; // 0x1F = 00011111 in binary
|
||||
|
||||
// Add current Base32 byte and convert it to character
|
||||
builder.Append(_base32Alphabet[outputBase32Byte]);
|
||||
|
||||
// Move to the next byte
|
||||
outputBase32BytePosition = 0;
|
||||
bytesPosition++;
|
||||
bytesSubPosition = 0;
|
||||
}
|
||||
|
||||
// Check if we have a remainder
|
||||
if(outputBase32BytePosition <= 0)
|
||||
return builder.ToString();
|
||||
// Update current base32 byte completion
|
||||
outputBase32BytePosition += bitsAvailableInByte;
|
||||
|
||||
// Move to the right bits
|
||||
outputBase32Byte <<= _outByteSize - outputBase32BytePosition;
|
||||
// Check overflow or end of input array
|
||||
if(outputBase32BytePosition < _outByteSize) continue;
|
||||
|
||||
// Drop the overflow bits
|
||||
outputBase32Byte &= 0x1F; // 0x1F = 00011111 in binary
|
||||
@@ -107,91 +85,103 @@ namespace RomRepoMgr.Core
|
||||
// Add current Base32 byte and convert it to character
|
||||
builder.Append(_base32Alphabet[outputBase32Byte]);
|
||||
|
||||
return builder.ToString();
|
||||
// Move to the next byte
|
||||
outputBase32BytePosition = 0;
|
||||
}
|
||||
|
||||
/// <summary>Convert base32 string to array of bytes</summary>
|
||||
/// <param name="base32String">Base32 string to convert</param>
|
||||
/// <returns>Returns a byte array converted from the string</returns>
|
||||
public static byte[] FromBase32String(string base32String)
|
||||
// Check if we have a remainder
|
||||
if(outputBase32BytePosition <= 0) return builder.ToString();
|
||||
|
||||
// Move to the right bits
|
||||
outputBase32Byte <<= _outByteSize - outputBase32BytePosition;
|
||||
|
||||
// Drop the overflow bits
|
||||
outputBase32Byte &= 0x1F; // 0x1F = 00011111 in binary
|
||||
|
||||
// Add current Base32 byte and convert it to character
|
||||
builder.Append(_base32Alphabet[outputBase32Byte]);
|
||||
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
/// <summary>Convert base32 string to array of bytes</summary>
|
||||
/// <param name="base32String">Base32 string to convert</param>
|
||||
/// <returns>Returns a byte array converted from the string</returns>
|
||||
public static byte[] FromBase32String(string base32String)
|
||||
{
|
||||
// Check if string is null
|
||||
if(base32String == null) return null;
|
||||
|
||||
// Check if empty
|
||||
if(base32String == string.Empty) return new byte[0];
|
||||
|
||||
// Convert to upper-case
|
||||
string base32StringUpperCase = base32String.ToUpperInvariant();
|
||||
|
||||
// Prepare output byte array
|
||||
var outputBytes = new byte[base32StringUpperCase.Length * _outByteSize / _inByteSize];
|
||||
|
||||
// Check the size
|
||||
if(outputBytes.Length == 0) throw new ArgumentException(Localization.Base32_Not_enought_data);
|
||||
|
||||
// Position in the string
|
||||
var base32Position = 0;
|
||||
|
||||
// Offset inside the character in the string
|
||||
var base32SubPosition = 0;
|
||||
|
||||
// Position within outputBytes array
|
||||
var outputBytePosition = 0;
|
||||
|
||||
// The number of bits filled in the current output byte
|
||||
var outputByteSubPosition = 0;
|
||||
|
||||
// Normally we would iterate on the input array but in this case we actually iterate on the output array
|
||||
// We do it because output array doesn't have overflow bits, while input does and it will cause output array overflow if we don''t stop in time
|
||||
while(outputBytePosition < outputBytes.Length)
|
||||
{
|
||||
// Check if string is null
|
||||
if(base32String == null)
|
||||
return null;
|
||||
// Look up current character in the dictionary to convert it to byte
|
||||
int currentBase32Byte = _base32Alphabet.IndexOf(base32StringUpperCase[base32Position]);
|
||||
|
||||
// Check if empty
|
||||
if(base32String == string.Empty)
|
||||
return new byte[0];
|
||||
|
||||
// Convert to upper-case
|
||||
string base32StringUpperCase = base32String.ToUpperInvariant();
|
||||
|
||||
// Prepare output byte array
|
||||
byte[] outputBytes = new byte[(base32StringUpperCase.Length * _outByteSize) / _inByteSize];
|
||||
|
||||
// Check the size
|
||||
if(outputBytes.Length == 0)
|
||||
throw new ArgumentException(Localization.Base32_Not_enought_data);
|
||||
|
||||
// Position in the string
|
||||
int base32Position = 0;
|
||||
|
||||
// Offset inside the character in the string
|
||||
int base32SubPosition = 0;
|
||||
|
||||
// Position within outputBytes array
|
||||
int outputBytePosition = 0;
|
||||
|
||||
// The number of bits filled in the current output byte
|
||||
int outputByteSubPosition = 0;
|
||||
|
||||
// Normally we would iterate on the input array but in this case we actually iterate on the output array
|
||||
// We do it because output array doesn't have overflow bits, while input does and it will cause output array overflow if we don''t stop in time
|
||||
while(outputBytePosition < outputBytes.Length)
|
||||
// Check if found
|
||||
if(currentBase32Byte < 0)
|
||||
{
|
||||
// Look up current character in the dictionary to convert it to byte
|
||||
int currentBase32Byte = _base32Alphabet.IndexOf(base32StringUpperCase[base32Position]);
|
||||
|
||||
// Check if found
|
||||
if(currentBase32Byte < 0)
|
||||
throw new ArgumentException(string.Format(Localization.Base32_Invalid_format,
|
||||
base32String[base32Position]));
|
||||
|
||||
// Calculate the number of bits we can extract out of current input character to fill missing bits in the output byte
|
||||
int bitsAvailableInByte =
|
||||
Math.Min(_outByteSize - base32SubPosition, _inByteSize - outputByteSubPosition);
|
||||
|
||||
// Make space in the output byte
|
||||
outputBytes[outputBytePosition] <<= bitsAvailableInByte;
|
||||
|
||||
// Extract the part of the input character and move it to the output byte
|
||||
outputBytes[outputBytePosition] |=
|
||||
(byte)(currentBase32Byte >> (_outByteSize - (base32SubPosition + bitsAvailableInByte)));
|
||||
|
||||
// Update current sub-byte position
|
||||
outputByteSubPosition += bitsAvailableInByte;
|
||||
|
||||
// Check overflow
|
||||
if(outputByteSubPosition >= _inByteSize)
|
||||
{
|
||||
// Move to the next byte
|
||||
outputBytePosition++;
|
||||
outputByteSubPosition = 0;
|
||||
}
|
||||
|
||||
// Update current base32 byte completion
|
||||
base32SubPosition += bitsAvailableInByte;
|
||||
|
||||
// Check overflow or end of input array
|
||||
if(base32SubPosition < _outByteSize)
|
||||
continue;
|
||||
|
||||
// Move to the next character
|
||||
base32Position++;
|
||||
base32SubPosition = 0;
|
||||
throw new ArgumentException(string.Format(Localization.Base32_Invalid_format,
|
||||
base32String[base32Position]));
|
||||
}
|
||||
|
||||
return outputBytes;
|
||||
// Calculate the number of bits we can extract out of current input character to fill missing bits in the output byte
|
||||
int bitsAvailableInByte = Math.Min(_outByteSize - base32SubPosition, _inByteSize - outputByteSubPosition);
|
||||
|
||||
// Make space in the output byte
|
||||
outputBytes[outputBytePosition] <<= bitsAvailableInByte;
|
||||
|
||||
// Extract the part of the input character and move it to the output byte
|
||||
outputBytes[outputBytePosition] |=
|
||||
(byte)(currentBase32Byte >> _outByteSize - (base32SubPosition + bitsAvailableInByte));
|
||||
|
||||
// Update current sub-byte position
|
||||
outputByteSubPosition += bitsAvailableInByte;
|
||||
|
||||
// Check overflow
|
||||
if(outputByteSubPosition >= _inByteSize)
|
||||
{
|
||||
// Move to the next byte
|
||||
outputBytePosition++;
|
||||
outputByteSubPosition = 0;
|
||||
}
|
||||
|
||||
// Update current base32 byte completion
|
||||
base32SubPosition += bitsAvailableInByte;
|
||||
|
||||
// Check overflow or end of input array
|
||||
if(base32SubPosition < _outByteSize) continue;
|
||||
|
||||
// Move to the next character
|
||||
base32Position++;
|
||||
base32SubPosition = 0;
|
||||
}
|
||||
|
||||
return outputBytes;
|
||||
}
|
||||
}
|
||||
@@ -33,288 +33,287 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace Aaru.Helpers
|
||||
namespace Aaru.Helpers;
|
||||
|
||||
/// <summary>
|
||||
/// Converts base data types to an array of bytes, and an array of bytes to base data types. All info taken from
|
||||
/// the meta data of System.BitConverter. This implementation allows for Endianness consideration.
|
||||
/// </summary>
|
||||
public static class BigEndianBitConverter
|
||||
{
|
||||
/// <summary>Converts the specified double-precision floating point number to a 64-bit signed integer.</summary>
|
||||
/// <param name="value">The number to convert.</param>
|
||||
/// <returns>A 64-bit signed integer whose value is equivalent to value.</returns>
|
||||
/// <exception cref="NotImplementedException">It is not currently implemented</exception>
|
||||
public static long DoubleToInt64Bits(double value) => throw new NotImplementedException();
|
||||
|
||||
/// <summary>Returns the specified Boolean value as an array of bytes.</summary>
|
||||
/// <param name="value">A Boolean value.</param>
|
||||
/// <returns>An array of bytes with length 1.</returns>
|
||||
public static byte[] GetBytes(bool value) => BitConverter.GetBytes(value).Reverse().ToArray();
|
||||
|
||||
/// <summary>Returns the specified Unicode character value as an array of bytes.</summary>
|
||||
/// <param name="value">A character to convert.</param>
|
||||
/// <returns>An array of bytes with length 2.</returns>
|
||||
public static byte[] GetBytes(char value) => BitConverter.GetBytes(value).Reverse().ToArray();
|
||||
|
||||
/// <summary>Returns the specified double-precision floating point value as an array of bytes.</summary>
|
||||
/// <param name="value">The number to convert.</param>
|
||||
/// <returns>An array of bytes with length 8.</returns>
|
||||
public static byte[] GetBytes(double value) => BitConverter.GetBytes(value).Reverse().ToArray();
|
||||
|
||||
/// <summary>Returns the specified single-precision floating point value as an array of bytes.</summary>
|
||||
/// <param name="value">The number to convert.</param>
|
||||
/// <returns>An array of bytes with length 4.</returns>
|
||||
public static byte[] GetBytes(float value) => BitConverter.GetBytes(value).Reverse().ToArray();
|
||||
|
||||
/// <summary>Returns the specified 32-bit signed integer value as an array of bytes.</summary>
|
||||
/// <param name="value">The number to convert.</param>
|
||||
/// <returns>An array of bytes with length 4.</returns>
|
||||
public static byte[] GetBytes(int value) => BitConverter.GetBytes(value).Reverse().ToArray();
|
||||
|
||||
/// <summary>Returns the specified 64-bit signed integer value as an array of bytes.</summary>
|
||||
/// <param name="value">The number to convert.</param>
|
||||
/// <returns>An array of bytes with length 8.</returns>
|
||||
public static byte[] GetBytes(long value) => BitConverter.GetBytes(value).Reverse().ToArray();
|
||||
|
||||
/// <summary>Returns the specified 16-bit signed integer value as an array of bytes.</summary>
|
||||
/// <param name="value">The number to convert.</param>
|
||||
/// <returns>An array of bytes with length 2.</returns>
|
||||
public static byte[] GetBytes(short value) => BitConverter.GetBytes(value).Reverse().ToArray();
|
||||
|
||||
/// <summary>Returns the specified 32-bit unsigned integer value as an array of bytes.</summary>
|
||||
/// <param name="value">The number to convert.</param>
|
||||
/// <returns>An array of bytes with length 4.</returns>
|
||||
public static byte[] GetBytes(uint value) => BitConverter.GetBytes(value).Reverse().ToArray();
|
||||
|
||||
/// <summary>Returns the specified 64-bit unsigned integer value as an array of bytes.</summary>
|
||||
/// <param name="value">The number to convert.</param>
|
||||
/// <returns>An array of bytes with length 8.</returns>
|
||||
public static byte[] GetBytes(ulong value) => BitConverter.GetBytes(value).Reverse().ToArray();
|
||||
|
||||
/// <summary>Returns the specified 16-bit unsigned integer value as an array of bytes.</summary>
|
||||
/// <param name="value">The number to convert.</param>
|
||||
/// <returns>An array of bytes with length 2.</returns>
|
||||
public static byte[] GetBytes(ushort value) => BitConverter.GetBytes(value).Reverse().ToArray();
|
||||
|
||||
/// <summary>Converts the specified 64-bit signed integer to a double-precision floating point number.</summary>
|
||||
/// <param name="value">The number to convert.</param>
|
||||
/// <returns>A double-precision floating point number whose value is equivalent to value.</returns>
|
||||
public static double Int64BitsToDouble(long value) => throw new NotImplementedException();
|
||||
|
||||
/// <summary>Returns a Boolean value converted from one byte at a specified position in a byte array.</summary>
|
||||
/// <param name="value">An array of bytes.</param>
|
||||
/// <param name="startIndex">The starting position within value.</param>
|
||||
/// <returns>true if the byte at <see cref="startIndex" /> in value is nonzero; otherwise, false.</returns>
|
||||
/// <exception cref="System.ArgumentNullException">value is null.</exception>
|
||||
/// <exception cref="System.ArgumentOutOfRangeException">
|
||||
/// <see cref="startIndex" /> is less than zero or greater than the
|
||||
/// length of value minus 1.
|
||||
/// </exception>
|
||||
public static bool ToBoolean(byte[] value, int startIndex) => throw new NotImplementedException();
|
||||
|
||||
/// <summary>Returns a Unicode character converted from two bytes at a specified position in a byte array.</summary>
|
||||
/// <param name="value">An array.</param>
|
||||
/// <param name="startIndex">The starting position within value.</param>
|
||||
/// <returns>A character formed by two bytes beginning at <see cref="startIndex" />.</returns>
|
||||
/// <exception cref="System.ArgumentException"><see cref="startIndex" /> equals the length of value minus 1.</exception>
|
||||
/// <exception cref="System.ArgumentNullException">value is null.</exception>
|
||||
/// <exception cref="System.ArgumentOutOfRangeException">
|
||||
/// <see cref="startIndex" /> is less than zero or greater than the
|
||||
/// length of value minus 1.
|
||||
/// </exception>
|
||||
public static char ToChar(byte[] value, int startIndex) => throw new NotImplementedException();
|
||||
|
||||
/// <summary>
|
||||
/// Converts base data types to an array of bytes, and an array of bytes to base data types. All info taken from
|
||||
/// the meta data of System.BitConverter. This implementation allows for Endianness consideration.
|
||||
/// Returns a double-precision floating point number converted from eight bytes at a specified position in a byte
|
||||
/// array.
|
||||
/// </summary>
|
||||
public static class BigEndianBitConverter
|
||||
{
|
||||
/// <summary>Converts the specified double-precision floating point number to a 64-bit signed integer.</summary>
|
||||
/// <param name="value">The number to convert.</param>
|
||||
/// <returns>A 64-bit signed integer whose value is equivalent to value.</returns>
|
||||
/// <exception cref="NotImplementedException">It is not currently implemented</exception>
|
||||
public static long DoubleToInt64Bits(double value) => throw new NotImplementedException();
|
||||
/// <param name="value">An array of bytes.</param>
|
||||
/// <param name="startIndex">The starting position within value.</param>
|
||||
/// <returns>A double precision floating point number formed by eight bytes beginning at <see cref="startIndex" />.</returns>
|
||||
/// <exception cref="System.ArgumentException">
|
||||
/// <see cref="startIndex" /> is greater than or equal to the length of value
|
||||
/// minus 7, and is less than or equal to the length of value minus 1.
|
||||
/// </exception>
|
||||
/// <exception cref="System.ArgumentNullException">value is null.</exception>
|
||||
/// <exception cref="System.ArgumentOutOfRangeException">
|
||||
/// <see cref="startIndex" /> is less than zero or greater than the
|
||||
/// length of value minus 1.
|
||||
/// </exception>
|
||||
public static double ToDouble(byte[] value, int startIndex) => throw new NotImplementedException();
|
||||
|
||||
/// <summary>Returns the specified Boolean value as an array of bytes.</summary>
|
||||
/// <param name="value">A Boolean value.</param>
|
||||
/// <returns>An array of bytes with length 1.</returns>
|
||||
public static byte[] GetBytes(bool value) => BitConverter.GetBytes(value).Reverse().ToArray();
|
||||
/// <summary>Returns a 16-bit signed integer converted from two bytes at a specified position in a byte array.</summary>
|
||||
/// <param name="value">An array of bytes.</param>
|
||||
/// <param name="startIndex">The starting position within value.</param>
|
||||
/// <returns>A 16-bit signed integer formed by two bytes beginning at <see cref="startIndex" />.</returns>
|
||||
/// <exception cref="System.ArgumentException"><see cref="startIndex" /> equals the length of value minus 1.</exception>
|
||||
/// <exception cref="System.ArgumentNullException">value is null.</exception>
|
||||
/// <exception cref="System.ArgumentOutOfRangeException">
|
||||
/// startIndex is less than zero or greater than the length of value
|
||||
/// minus 1.
|
||||
/// </exception>
|
||||
public static short ToInt16(byte[] value, int startIndex) =>
|
||||
BitConverter.ToInt16(value.Reverse().ToArray(), value.Length - sizeof(short) - startIndex);
|
||||
|
||||
/// <summary>Returns the specified Unicode character value as an array of bytes.</summary>
|
||||
/// <param name="value">A character to convert.</param>
|
||||
/// <returns>An array of bytes with length 2.</returns>
|
||||
public static byte[] GetBytes(char value) => BitConverter.GetBytes(value).Reverse().ToArray();
|
||||
/// <summary>Returns a 32-bit signed integer converted from four bytes at a specified position in a byte array.</summary>
|
||||
/// <param name="value">An array of bytes.</param>
|
||||
/// <param name="startIndex">The starting position within value.</param>
|
||||
/// <returns>A 32-bit signed integer formed by four bytes beginning at <see cref="startIndex" />.</returns>
|
||||
/// <exception cref="System.ArgumentException">
|
||||
/// <see cref="startIndex" /> is greater than or equal to the length of value
|
||||
/// minus 3, and is less than or equal to the length of value minus 1.
|
||||
/// </exception>
|
||||
/// <exception cref="System.ArgumentNullException">value is null.</exception>
|
||||
/// <exception cref="System.ArgumentOutOfRangeException">
|
||||
/// startIndex is less than zero or greater than the length of value
|
||||
/// minus 1.
|
||||
/// </exception>
|
||||
public static int ToInt32(byte[] value, int startIndex) =>
|
||||
BitConverter.ToInt32(value.Reverse().ToArray(), value.Length - sizeof(int) - startIndex);
|
||||
|
||||
/// <summary>Returns the specified double-precision floating point value as an array of bytes.</summary>
|
||||
/// <param name="value">The number to convert.</param>
|
||||
/// <returns>An array of bytes with length 8.</returns>
|
||||
public static byte[] GetBytes(double value) => BitConverter.GetBytes(value).Reverse().ToArray();
|
||||
/// <summary>Returns a 64-bit signed integer converted from eight bytes at a specified position in a byte array.</summary>
|
||||
/// <param name="value">An array of bytes.</param>
|
||||
/// <param name="startIndex">The starting position within value.</param>
|
||||
/// <returns>A 64-bit signed integer formed by eight bytes beginning at <see cref="startIndex" />.</returns>
|
||||
/// <exception cref="System.ArgumentException">
|
||||
/// <see cref="startIndex" /> is greater than or equal to the length of value
|
||||
/// minus 7, and is less than or equal to the length of value minus 1.
|
||||
/// </exception>
|
||||
/// <exception cref="System.ArgumentNullException">value is null.</exception>
|
||||
/// <exception cref="System.ArgumentOutOfRangeException">
|
||||
/// <see cref="startIndex" /> is less than zero or greater than the
|
||||
/// length of value minus 1.
|
||||
/// </exception>
|
||||
public static long ToInt64(byte[] value, int startIndex) =>
|
||||
BitConverter.ToInt64(value.Reverse().ToArray(), value.Length - sizeof(long) - startIndex);
|
||||
|
||||
/// <summary>Returns the specified single-precision floating point value as an array of bytes.</summary>
|
||||
/// <param name="value">The number to convert.</param>
|
||||
/// <returns>An array of bytes with length 4.</returns>
|
||||
public static byte[] GetBytes(float value) => BitConverter.GetBytes(value).Reverse().ToArray();
|
||||
/// <summary>
|
||||
/// Returns a single-precision floating point number converted from four bytes at a specified position in a byte
|
||||
/// array.
|
||||
/// </summary>
|
||||
/// <param name="value">An array of bytes.</param>
|
||||
/// <param name="startIndex">The starting position within value.</param>
|
||||
/// <returns>A single-precision floating point number formed by four bytes beginning at <see cref="startIndex" />.</returns>
|
||||
/// <exception cref="System.ArgumentException">
|
||||
/// <see cref="startIndex" /> is greater than or equal to the length of value
|
||||
/// minus 3, and is less than or equal to the length of value minus 1.
|
||||
/// </exception>
|
||||
/// <exception cref="System.ArgumentNullException">value is null.</exception>
|
||||
/// <exception cref="System.ArgumentOutOfRangeException">
|
||||
/// <see cref="startIndex" /> is less than zero or greater than the
|
||||
/// length of value minus 1.
|
||||
/// </exception>
|
||||
public static float ToSingle(byte[] value, int startIndex) =>
|
||||
BitConverter.ToSingle(value.Reverse().ToArray(), value.Length - sizeof(float) - startIndex);
|
||||
|
||||
/// <summary>Returns the specified 32-bit signed integer value as an array of bytes.</summary>
|
||||
/// <param name="value">The number to convert.</param>
|
||||
/// <returns>An array of bytes with length 4.</returns>
|
||||
public static byte[] GetBytes(int value) => BitConverter.GetBytes(value).Reverse().ToArray();
|
||||
/// <summary>
|
||||
/// Converts the numeric value of each element of a specified array of bytes to its equivalent hexadecimal string
|
||||
/// representation.
|
||||
/// </summary>
|
||||
/// <param name="value">An array of bytes.</param>
|
||||
/// <returns>
|
||||
/// A System.String of hexadecimal pairs separated by hyphens, where each pair represents the corresponding
|
||||
/// element in value; for example, "7F-2C-4A".
|
||||
/// </returns>
|
||||
/// <exception cref="System.ArgumentNullException">value is null.</exception>
|
||||
public static string ToString(byte[] value) => BitConverter.ToString(value.Reverse().ToArray());
|
||||
|
||||
/// <summary>Returns the specified 64-bit signed integer value as an array of bytes.</summary>
|
||||
/// <param name="value">The number to convert.</param>
|
||||
/// <returns>An array of bytes with length 8.</returns>
|
||||
public static byte[] GetBytes(long value) => BitConverter.GetBytes(value).Reverse().ToArray();
|
||||
/// <summary>
|
||||
/// Converts the numeric value of each element of a specified subarray of bytes to its equivalent hexadecimal
|
||||
/// string representation.
|
||||
/// </summary>
|
||||
/// <param name="value">An array of bytes.</param>
|
||||
/// <param name="startIndex">The starting position within value.</param>
|
||||
/// <returns>
|
||||
/// A System.String of hexadecimal pairs separated by hyphens, where each pair represents the corresponding
|
||||
/// element in a subarray of value; for example, "7F-2C-4A".
|
||||
/// </returns>
|
||||
/// <exception cref="System.ArgumentNullException">value is null.</exception>
|
||||
/// <exception cref="System.ArgumentOutOfRangeException">
|
||||
/// startIndex is less than zero or greater than the length of value
|
||||
/// minus 1.
|
||||
/// </exception>
|
||||
public static string ToString(byte[] value, int startIndex) =>
|
||||
BitConverter.ToString(value.Reverse().ToArray(), startIndex);
|
||||
|
||||
/// <summary>Returns the specified 16-bit signed integer value as an array of bytes.</summary>
|
||||
/// <param name="value">The number to convert.</param>
|
||||
/// <returns>An array of bytes with length 2.</returns>
|
||||
public static byte[] GetBytes(short value) => BitConverter.GetBytes(value).Reverse().ToArray();
|
||||
/// <summary>
|
||||
/// Converts the numeric value of each element of a specified subarray of bytes to its equivalent hexadecimal
|
||||
/// string representation.
|
||||
/// </summary>
|
||||
/// <param name="value">An array of bytes.</param>
|
||||
/// <param name="startIndex">The starting position within value.</param>
|
||||
/// <param name="length">The number of array elements in value to convert.</param>
|
||||
/// <returns>
|
||||
/// A System.String of hexadecimal pairs separated by hyphens, where each pair represents the corresponding
|
||||
/// element in a subarray of value; for example, "7F-2C-4A".
|
||||
/// </returns>
|
||||
/// <exception cref="System.ArgumentNullException">value is null.</exception>
|
||||
/// <exception cref="System.ArgumentOutOfRangeException">
|
||||
/// startIndex or length is less than zero. -or- startIndex is greater
|
||||
/// than zero and is greater than or equal to the length of value.
|
||||
/// </exception>
|
||||
/// <exception cref="System.ArgumentException">
|
||||
/// The combination of startIndex and length does not specify a position within
|
||||
/// value; that is, the startIndex parameter is greater than the length of value minus the length parameter.
|
||||
/// </exception>
|
||||
public static string ToString(byte[] value, int startIndex, int length) =>
|
||||
BitConverter.ToString(value.Reverse().ToArray(), startIndex, length);
|
||||
|
||||
/// <summary>Returns the specified 32-bit unsigned integer value as an array of bytes.</summary>
|
||||
/// <param name="value">The number to convert.</param>
|
||||
/// <returns>An array of bytes with length 4.</returns>
|
||||
public static byte[] GetBytes(uint value) => BitConverter.GetBytes(value).Reverse().ToArray();
|
||||
/// <summary>Returns a 16-bit unsigned integer converted from two bytes at a specified position in a byte array.</summary>
|
||||
/// <param name="value">The array of bytes.</param>
|
||||
/// <param name="startIndex">The starting position within value.</param>
|
||||
/// <returns>A 16-bit unsigned integer formed by two bytes beginning at startIndex.</returns>
|
||||
/// <exception cref="System.ArgumentException">startIndex equals the length of value minus 1.</exception>
|
||||
/// <exception cref="System.ArgumentNullException">value is null.</exception>
|
||||
/// <exception cref="System.ArgumentOutOfRangeException">
|
||||
/// startIndex is less than zero or greater than the length of value
|
||||
/// minus 1.
|
||||
/// </exception>
|
||||
public static ushort ToUInt16(byte[] value, int startIndex) =>
|
||||
BitConverter.ToUInt16(value.Reverse().ToArray(), value.Length - sizeof(ushort) - startIndex);
|
||||
|
||||
/// <summary>Returns the specified 64-bit unsigned integer value as an array of bytes.</summary>
|
||||
/// <param name="value">The number to convert.</param>
|
||||
/// <returns>An array of bytes with length 8.</returns>
|
||||
public static byte[] GetBytes(ulong value) => BitConverter.GetBytes(value).Reverse().ToArray();
|
||||
/// <summary>Returns a 32-bit unsigned integer converted from four bytes at a specified position in a byte array.</summary>
|
||||
/// <param name="value">An array of bytes.</param>
|
||||
/// <param name="startIndex">The starting position within value.</param>
|
||||
/// <returns>A 32-bit unsigned integer formed by four bytes beginning at startIndex.</returns>
|
||||
/// <exception cref="System.ArgumentException">
|
||||
/// startIndex is greater than or equal to the length of value minus 3, and is
|
||||
/// less than or equal to the length of value minus 1.
|
||||
/// </exception>
|
||||
/// <exception cref="System.ArgumentNullException">value is null.</exception>
|
||||
/// <exception cref="System.ArgumentOutOfRangeException">
|
||||
/// startIndex is less than zero or greater than the length of value
|
||||
/// minus 1.
|
||||
/// </exception>
|
||||
public static uint ToUInt32(byte[] value, int startIndex) =>
|
||||
BitConverter.ToUInt32(value.Reverse().ToArray(), value.Length - sizeof(uint) - startIndex);
|
||||
|
||||
/// <summary>Returns the specified 16-bit unsigned integer value as an array of bytes.</summary>
|
||||
/// <param name="value">The number to convert.</param>
|
||||
/// <returns>An array of bytes with length 2.</returns>
|
||||
public static byte[] GetBytes(ushort value) => BitConverter.GetBytes(value).Reverse().ToArray();
|
||||
/// <summary>Returns a 64-bit unsigned integer converted from eight bytes at a specified position in a byte array.</summary>
|
||||
/// <param name="value">An array of bytes.</param>
|
||||
/// <param name="startIndex">The starting position within value.</param>
|
||||
/// <returns>A 64-bit unsigned integer formed by the eight bytes beginning at startIndex.</returns>
|
||||
/// <exception cref="System.ArgumentException">
|
||||
/// startIndex is greater than or equal to the length of value minus 7, and is
|
||||
/// less than or equal to the length of value minus 1.
|
||||
/// </exception>
|
||||
/// <exception cref="System.ArgumentNullException">value is null.</exception>
|
||||
/// <exception cref="System.ArgumentOutOfRangeException">
|
||||
/// startIndex is less than zero or greater than the length of value
|
||||
/// minus 1.
|
||||
/// </exception>
|
||||
public static ulong ToUInt64(byte[] value, int startIndex) =>
|
||||
BitConverter.ToUInt64(value.Reverse().ToArray(), value.Length - sizeof(ulong) - startIndex);
|
||||
|
||||
/// <summary>Converts the specified 64-bit signed integer to a double-precision floating point number.</summary>
|
||||
/// <param name="value">The number to convert.</param>
|
||||
/// <returns>A double-precision floating point number whose value is equivalent to value.</returns>
|
||||
public static double Int64BitsToDouble(long value) => throw new NotImplementedException();
|
||||
|
||||
/// <summary>Returns a Boolean value converted from one byte at a specified position in a byte array.</summary>
|
||||
/// <param name="value">An array of bytes.</param>
|
||||
/// <param name="startIndex">The starting position within value.</param>
|
||||
/// <returns>true if the byte at <see cref="startIndex" /> in value is nonzero; otherwise, false.</returns>
|
||||
/// <exception cref="System.ArgumentNullException">value is null.</exception>
|
||||
/// <exception cref="System.ArgumentOutOfRangeException">
|
||||
/// <see cref="startIndex" /> is less than zero or greater than the
|
||||
/// length of value minus 1.
|
||||
/// </exception>
|
||||
public static bool ToBoolean(byte[] value, int startIndex) => throw new NotImplementedException();
|
||||
|
||||
/// <summary>Returns a Unicode character converted from two bytes at a specified position in a byte array.</summary>
|
||||
/// <param name="value">An array.</param>
|
||||
/// <param name="startIndex">The starting position within value.</param>
|
||||
/// <returns>A character formed by two bytes beginning at <see cref="startIndex" />.</returns>
|
||||
/// <exception cref="System.ArgumentException"><see cref="startIndex" /> equals the length of value minus 1.</exception>
|
||||
/// <exception cref="System.ArgumentNullException">value is null.</exception>
|
||||
/// <exception cref="System.ArgumentOutOfRangeException">
|
||||
/// <see cref="startIndex" /> is less than zero or greater than the
|
||||
/// length of value minus 1.
|
||||
/// </exception>
|
||||
public static char ToChar(byte[] value, int startIndex) => throw new NotImplementedException();
|
||||
|
||||
/// <summary>
|
||||
/// Returns a double-precision floating point number converted from eight bytes at a specified position in a byte
|
||||
/// array.
|
||||
/// </summary>
|
||||
/// <param name="value">An array of bytes.</param>
|
||||
/// <param name="startIndex">The starting position within value.</param>
|
||||
/// <returns>A double precision floating point number formed by eight bytes beginning at <see cref="startIndex" />.</returns>
|
||||
/// <exception cref="System.ArgumentException">
|
||||
/// <see cref="startIndex" /> is greater than or equal to the length of value
|
||||
/// minus 7, and is less than or equal to the length of value minus 1.
|
||||
/// </exception>
|
||||
/// <exception cref="System.ArgumentNullException">value is null.</exception>
|
||||
/// <exception cref="System.ArgumentOutOfRangeException">
|
||||
/// <see cref="startIndex" /> is less than zero or greater than the
|
||||
/// length of value minus 1.
|
||||
/// </exception>
|
||||
public static double ToDouble(byte[] value, int startIndex) => throw new NotImplementedException();
|
||||
|
||||
/// <summary>Returns a 16-bit signed integer converted from two bytes at a specified position in a byte array.</summary>
|
||||
/// <param name="value">An array of bytes.</param>
|
||||
/// <param name="startIndex">The starting position within value.</param>
|
||||
/// <returns>A 16-bit signed integer formed by two bytes beginning at <see cref="startIndex" />.</returns>
|
||||
/// <exception cref="System.ArgumentException"><see cref="startIndex" /> equals the length of value minus 1.</exception>
|
||||
/// <exception cref="System.ArgumentNullException">value is null.</exception>
|
||||
/// <exception cref="System.ArgumentOutOfRangeException">
|
||||
/// startIndex is less than zero or greater than the length of value
|
||||
/// minus 1.
|
||||
/// </exception>
|
||||
public static short ToInt16(byte[] value, int startIndex) =>
|
||||
BitConverter.ToInt16(value.Reverse().ToArray(), value.Length - sizeof(short) - startIndex);
|
||||
|
||||
/// <summary>Returns a 32-bit signed integer converted from four bytes at a specified position in a byte array.</summary>
|
||||
/// <param name="value">An array of bytes.</param>
|
||||
/// <param name="startIndex">The starting position within value.</param>
|
||||
/// <returns>A 32-bit signed integer formed by four bytes beginning at <see cref="startIndex" />.</returns>
|
||||
/// <exception cref="System.ArgumentException">
|
||||
/// <see cref="startIndex" /> is greater than or equal to the length of value
|
||||
/// minus 3, and is less than or equal to the length of value minus 1.
|
||||
/// </exception>
|
||||
/// <exception cref="System.ArgumentNullException">value is null.</exception>
|
||||
/// <exception cref="System.ArgumentOutOfRangeException">
|
||||
/// startIndex is less than zero or greater than the length of value
|
||||
/// minus 1.
|
||||
/// </exception>
|
||||
public static int ToInt32(byte[] value, int startIndex) =>
|
||||
BitConverter.ToInt32(value.Reverse().ToArray(), value.Length - sizeof(int) - startIndex);
|
||||
|
||||
/// <summary>Returns a 64-bit signed integer converted from eight bytes at a specified position in a byte array.</summary>
|
||||
/// <param name="value">An array of bytes.</param>
|
||||
/// <param name="startIndex">The starting position within value.</param>
|
||||
/// <returns>A 64-bit signed integer formed by eight bytes beginning at <see cref="startIndex" />.</returns>
|
||||
/// <exception cref="System.ArgumentException">
|
||||
/// <see cref="startIndex" /> is greater than or equal to the length of value
|
||||
/// minus 7, and is less than or equal to the length of value minus 1.
|
||||
/// </exception>
|
||||
/// <exception cref="System.ArgumentNullException">value is null.</exception>
|
||||
/// <exception cref="System.ArgumentOutOfRangeException">
|
||||
/// <see cref="startIndex" /> is less than zero or greater than the
|
||||
/// length of value minus 1.
|
||||
/// </exception>
|
||||
public static long ToInt64(byte[] value, int startIndex) =>
|
||||
BitConverter.ToInt64(value.Reverse().ToArray(), value.Length - sizeof(long) - startIndex);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a single-precision floating point number converted from four bytes at a specified position in a byte
|
||||
/// array.
|
||||
/// </summary>
|
||||
/// <param name="value">An array of bytes.</param>
|
||||
/// <param name="startIndex">The starting position within value.</param>
|
||||
/// <returns>A single-precision floating point number formed by four bytes beginning at <see cref="startIndex" />.</returns>
|
||||
/// <exception cref="System.ArgumentException">
|
||||
/// <see cref="startIndex" /> is greater than or equal to the length of value
|
||||
/// minus 3, and is less than or equal to the length of value minus 1.
|
||||
/// </exception>
|
||||
/// <exception cref="System.ArgumentNullException">value is null.</exception>
|
||||
/// <exception cref="System.ArgumentOutOfRangeException">
|
||||
/// <see cref="startIndex" /> is less than zero or greater than the
|
||||
/// length of value minus 1.
|
||||
/// </exception>
|
||||
public static float ToSingle(byte[] value, int startIndex) =>
|
||||
BitConverter.ToSingle(value.Reverse().ToArray(), value.Length - sizeof(float) - startIndex);
|
||||
|
||||
/// <summary>
|
||||
/// Converts the numeric value of each element of a specified array of bytes to its equivalent hexadecimal string
|
||||
/// representation.
|
||||
/// </summary>
|
||||
/// <param name="value">An array of bytes.</param>
|
||||
/// <returns>
|
||||
/// A System.String of hexadecimal pairs separated by hyphens, where each pair represents the corresponding
|
||||
/// element in value; for example, "7F-2C-4A".
|
||||
/// </returns>
|
||||
/// <exception cref="System.ArgumentNullException">value is null.</exception>
|
||||
public static string ToString(byte[] value) => BitConverter.ToString(value.Reverse().ToArray());
|
||||
|
||||
/// <summary>
|
||||
/// Converts the numeric value of each element of a specified subarray of bytes to its equivalent hexadecimal
|
||||
/// string representation.
|
||||
/// </summary>
|
||||
/// <param name="value">An array of bytes.</param>
|
||||
/// <param name="startIndex">The starting position within value.</param>
|
||||
/// <returns>
|
||||
/// A System.String of hexadecimal pairs separated by hyphens, where each pair represents the corresponding
|
||||
/// element in a subarray of value; for example, "7F-2C-4A".
|
||||
/// </returns>
|
||||
/// <exception cref="System.ArgumentNullException">value is null.</exception>
|
||||
/// <exception cref="System.ArgumentOutOfRangeException">
|
||||
/// startIndex is less than zero or greater than the length of value
|
||||
/// minus 1.
|
||||
/// </exception>
|
||||
public static string ToString(byte[] value, int startIndex) =>
|
||||
BitConverter.ToString(value.Reverse().ToArray(), startIndex);
|
||||
|
||||
/// <summary>
|
||||
/// Converts the numeric value of each element of a specified subarray of bytes to its equivalent hexadecimal
|
||||
/// string representation.
|
||||
/// </summary>
|
||||
/// <param name="value">An array of bytes.</param>
|
||||
/// <param name="startIndex">The starting position within value.</param>
|
||||
/// <param name="length">The number of array elements in value to convert.</param>
|
||||
/// <returns>
|
||||
/// A System.String of hexadecimal pairs separated by hyphens, where each pair represents the corresponding
|
||||
/// element in a subarray of value; for example, "7F-2C-4A".
|
||||
/// </returns>
|
||||
/// <exception cref="System.ArgumentNullException">value is null.</exception>
|
||||
/// <exception cref="System.ArgumentOutOfRangeException">
|
||||
/// startIndex or length is less than zero. -or- startIndex is greater
|
||||
/// than zero and is greater than or equal to the length of value.
|
||||
/// </exception>
|
||||
/// <exception cref="System.ArgumentException">
|
||||
/// The combination of startIndex and length does not specify a position within
|
||||
/// value; that is, the startIndex parameter is greater than the length of value minus the length parameter.
|
||||
/// </exception>
|
||||
public static string ToString(byte[] value, int startIndex, int length) =>
|
||||
BitConverter.ToString(value.Reverse().ToArray(), startIndex, length);
|
||||
|
||||
/// <summary>Returns a 16-bit unsigned integer converted from two bytes at a specified position in a byte array.</summary>
|
||||
/// <param name="value">The array of bytes.</param>
|
||||
/// <param name="startIndex">The starting position within value.</param>
|
||||
/// <returns>A 16-bit unsigned integer formed by two bytes beginning at startIndex.</returns>
|
||||
/// <exception cref="System.ArgumentException">startIndex equals the length of value minus 1.</exception>
|
||||
/// <exception cref="System.ArgumentNullException">value is null.</exception>
|
||||
/// <exception cref="System.ArgumentOutOfRangeException">
|
||||
/// startIndex is less than zero or greater than the length of value
|
||||
/// minus 1.
|
||||
/// </exception>
|
||||
public static ushort ToUInt16(byte[] value, int startIndex) =>
|
||||
BitConverter.ToUInt16(value.Reverse().ToArray(), value.Length - sizeof(ushort) - startIndex);
|
||||
|
||||
/// <summary>Returns a 32-bit unsigned integer converted from four bytes at a specified position in a byte array.</summary>
|
||||
/// <param name="value">An array of bytes.</param>
|
||||
/// <param name="startIndex">The starting position within value.</param>
|
||||
/// <returns>A 32-bit unsigned integer formed by four bytes beginning at startIndex.</returns>
|
||||
/// <exception cref="System.ArgumentException">
|
||||
/// startIndex is greater than or equal to the length of value minus 3, and is
|
||||
/// less than or equal to the length of value minus 1.
|
||||
/// </exception>
|
||||
/// <exception cref="System.ArgumentNullException">value is null.</exception>
|
||||
/// <exception cref="System.ArgumentOutOfRangeException">
|
||||
/// startIndex is less than zero or greater than the length of value
|
||||
/// minus 1.
|
||||
/// </exception>
|
||||
public static uint ToUInt32(byte[] value, int startIndex) =>
|
||||
BitConverter.ToUInt32(value.Reverse().ToArray(), value.Length - sizeof(uint) - startIndex);
|
||||
|
||||
/// <summary>Returns a 64-bit unsigned integer converted from eight bytes at a specified position in a byte array.</summary>
|
||||
/// <param name="value">An array of bytes.</param>
|
||||
/// <param name="startIndex">The starting position within value.</param>
|
||||
/// <returns>A 64-bit unsigned integer formed by the eight bytes beginning at startIndex.</returns>
|
||||
/// <exception cref="System.ArgumentException">
|
||||
/// startIndex is greater than or equal to the length of value minus 7, and is
|
||||
/// less than or equal to the length of value minus 1.
|
||||
/// </exception>
|
||||
/// <exception cref="System.ArgumentNullException">value is null.</exception>
|
||||
/// <exception cref="System.ArgumentOutOfRangeException">
|
||||
/// startIndex is less than zero or greater than the length of value
|
||||
/// minus 1.
|
||||
/// </exception>
|
||||
public static ulong ToUInt64(byte[] value, int startIndex) =>
|
||||
BitConverter.ToUInt64(value.Reverse().ToArray(), value.Length - sizeof(ulong) - startIndex);
|
||||
|
||||
public static Guid ToGuid(byte[] value, int startIndex) => new Guid(ToUInt32(value, 0 + startIndex),
|
||||
ToUInt16(value, 4 + startIndex),
|
||||
ToUInt16(value, 6 + startIndex),
|
||||
value[8 + startIndex + 0],
|
||||
value[8 + startIndex + 1],
|
||||
value[8 + startIndex + 2],
|
||||
value[8 + startIndex + 3],
|
||||
value[8 + startIndex + 5],
|
||||
value[8 + startIndex + 5],
|
||||
value[8 + startIndex + 6],
|
||||
value[8 + startIndex + 7]);
|
||||
}
|
||||
public static Guid ToGuid(byte[] value, int startIndex) => new(ToUInt32(value, 0 + startIndex),
|
||||
ToUInt16(value, 4 + startIndex),
|
||||
ToUInt16(value, 6 + startIndex),
|
||||
value[8 + startIndex + 0],
|
||||
value[8 + startIndex + 1],
|
||||
value[8 + startIndex + 2],
|
||||
value[8 + startIndex + 3],
|
||||
value[8 + startIndex + 5],
|
||||
value[8 + startIndex + 5],
|
||||
value[8 + startIndex + 6],
|
||||
value[8 + startIndex + 7]);
|
||||
}
|
||||
@@ -35,199 +35,202 @@ using System.Text;
|
||||
using Aaru.CommonTypes.Interfaces;
|
||||
using Aaru.Helpers;
|
||||
|
||||
namespace Aaru.Checksums
|
||||
namespace Aaru.Checksums;
|
||||
|
||||
/// <summary>Implements a CRC32 algorithm</summary>
|
||||
public sealed class Crc32Context : IChecksum
|
||||
{
|
||||
/// <summary>Implements a CRC32 algorithm</summary>
|
||||
public sealed class Crc32Context : IChecksum
|
||||
const uint CRC32_ISO_POLY = 0xEDB88320;
|
||||
const uint CRC32_ISO_SEED = 0xFFFFFFFF;
|
||||
|
||||
readonly uint _finalSeed;
|
||||
readonly uint[] _table;
|
||||
uint _hashInt;
|
||||
|
||||
/// <summary>Initializes the CRC32 table and seed as CRC32-ISO</summary>
|
||||
public Crc32Context()
|
||||
{
|
||||
const uint CRC32_ISO_POLY = 0xEDB88320;
|
||||
const uint CRC32_ISO_SEED = 0xFFFFFFFF;
|
||||
_hashInt = CRC32_ISO_SEED;
|
||||
_finalSeed = CRC32_ISO_SEED;
|
||||
|
||||
readonly uint _finalSeed;
|
||||
readonly uint[] _table;
|
||||
uint _hashInt;
|
||||
_table = new uint[256];
|
||||
|
||||
/// <summary>Initializes the CRC32 table and seed as CRC32-ISO</summary>
|
||||
public Crc32Context()
|
||||
for(var i = 0; i < 256; i++)
|
||||
{
|
||||
_hashInt = CRC32_ISO_SEED;
|
||||
_finalSeed = CRC32_ISO_SEED;
|
||||
var entry = (uint)i;
|
||||
|
||||
_table = new uint[256];
|
||||
|
||||
for(int i = 0; i < 256; i++)
|
||||
for(var j = 0; j < 8; j++)
|
||||
{
|
||||
uint entry = (uint)i;
|
||||
|
||||
for(int j = 0; j < 8; j++)
|
||||
if((entry & 1) == 1)
|
||||
entry = (entry >> 1) ^ CRC32_ISO_POLY;
|
||||
else
|
||||
entry = entry >> 1;
|
||||
|
||||
_table[i] = entry;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Initializes the CRC32 table with a custom polynomial and seed</summary>
|
||||
public Crc32Context(uint polynomial, uint seed)
|
||||
{
|
||||
_hashInt = seed;
|
||||
_finalSeed = seed;
|
||||
|
||||
_table = new uint[256];
|
||||
|
||||
for(int i = 0; i < 256; i++)
|
||||
{
|
||||
uint entry = (uint)i;
|
||||
|
||||
for(int j = 0; j < 8; j++)
|
||||
if((entry & 1) == 1)
|
||||
entry = (entry >> 1) ^ polynomial;
|
||||
else
|
||||
entry = entry >> 1;
|
||||
|
||||
_table[i] = entry;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Updates the hash with data.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
/// <param name="len">Length of buffer to hash.</param>
|
||||
public void Update(byte[] data, uint len)
|
||||
{
|
||||
for(int i = 0; i < len; i++)
|
||||
_hashInt = (_hashInt >> 8) ^ _table[data[i] ^ (_hashInt & 0xff)];
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Updates the hash with data.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
public void Update(byte[] data) => Update(data, (uint)data.Length);
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Returns a byte array of the hash value.</summary>
|
||||
public byte[] Final() => BigEndianBitConverter.GetBytes(_hashInt ^ _finalSeed);
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Returns a hexadecimal representation of the hash value.</summary>
|
||||
public string End()
|
||||
{
|
||||
var crc32Output = new StringBuilder();
|
||||
|
||||
for(int i = 0; i < BigEndianBitConverter.GetBytes(_hashInt ^ _finalSeed).Length; i++)
|
||||
crc32Output.Append(BigEndianBitConverter.GetBytes(_hashInt ^ _finalSeed)[i].ToString("x2"));
|
||||
|
||||
return crc32Output.ToString();
|
||||
}
|
||||
|
||||
/// <summary>Gets the hash of a file</summary>
|
||||
/// <param name="filename">File path.</param>
|
||||
public static byte[] File(string filename)
|
||||
{
|
||||
File(filename, out byte[] hash);
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
/// <summary>Gets the hash of a file in hexadecimal and as a byte array.</summary>
|
||||
/// <param name="filename">File path.</param>
|
||||
/// <param name="hash">Byte array of the hash value.</param>
|
||||
public static string File(string filename, out byte[] hash) =>
|
||||
File(filename, out hash, CRC32_ISO_POLY, CRC32_ISO_SEED);
|
||||
|
||||
/// <summary>Gets the hash of a file in hexadecimal and as a byte array.</summary>
|
||||
/// <param name="filename">File path.</param>
|
||||
/// <param name="hash">Byte array of the hash value.</param>
|
||||
/// <param name="polynomial">CRC polynomial</param>
|
||||
/// <param name="seed">CRC seed</param>
|
||||
public static string File(string filename, out byte[] hash, uint polynomial, uint seed)
|
||||
{
|
||||
var fileStream = new FileStream(filename, FileMode.Open, FileAccess.Read);
|
||||
|
||||
uint localhashInt = seed;
|
||||
|
||||
uint[] localTable = new uint[256];
|
||||
|
||||
for(int i = 0; i < 256; i++)
|
||||
{
|
||||
uint entry = (uint)i;
|
||||
|
||||
for(int j = 0; j < 8; j++)
|
||||
if((entry & 1) == 1)
|
||||
entry = (entry >> 1) ^ polynomial;
|
||||
else
|
||||
entry = entry >> 1;
|
||||
|
||||
localTable[i] = entry;
|
||||
if((entry & 1) == 1)
|
||||
entry = entry >> 1 ^ CRC32_ISO_POLY;
|
||||
else
|
||||
entry = entry >> 1;
|
||||
}
|
||||
|
||||
for(int i = 0; i < fileStream.Length; i++)
|
||||
localhashInt = (localhashInt >> 8) ^ localTable[fileStream.ReadByte() ^ (localhashInt & 0xff)];
|
||||
|
||||
localhashInt ^= seed;
|
||||
hash = BigEndianBitConverter.GetBytes(localhashInt);
|
||||
|
||||
var crc32Output = new StringBuilder();
|
||||
|
||||
foreach(byte h in hash)
|
||||
crc32Output.Append(h.ToString("x2"));
|
||||
|
||||
fileStream.Close();
|
||||
|
||||
return crc32Output.ToString();
|
||||
_table[i] = entry;
|
||||
}
|
||||
|
||||
/// <summary>Gets the hash of the specified data buffer.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
/// <param name="len">Length of the data buffer to hash.</param>
|
||||
/// <param name="hash">Byte array of the hash value.</param>
|
||||
public static string Data(byte[] data, uint len, out byte[] hash) =>
|
||||
Data(data, len, out hash, CRC32_ISO_POLY, CRC32_ISO_SEED);
|
||||
|
||||
/// <summary>Gets the hash of the specified data buffer.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
/// <param name="len">Length of the data buffer to hash.</param>
|
||||
/// <param name="hash">Byte array of the hash value.</param>
|
||||
/// <param name="polynomial">CRC polynomial</param>
|
||||
/// <param name="seed">CRC seed</param>
|
||||
public static string Data(byte[] data, uint len, out byte[] hash, uint polynomial, uint seed)
|
||||
{
|
||||
uint localhashInt = seed;
|
||||
|
||||
uint[] localTable = new uint[256];
|
||||
|
||||
for(int i = 0; i < 256; i++)
|
||||
{
|
||||
uint entry = (uint)i;
|
||||
|
||||
for(int j = 0; j < 8; j++)
|
||||
if((entry & 1) == 1)
|
||||
entry = (entry >> 1) ^ polynomial;
|
||||
else
|
||||
entry = entry >> 1;
|
||||
|
||||
localTable[i] = entry;
|
||||
}
|
||||
|
||||
for(int i = 0; i < len; i++)
|
||||
localhashInt = (localhashInt >> 8) ^ localTable[data[i] ^ (localhashInt & 0xff)];
|
||||
|
||||
localhashInt ^= seed;
|
||||
hash = BigEndianBitConverter.GetBytes(localhashInt);
|
||||
|
||||
var crc32Output = new StringBuilder();
|
||||
|
||||
foreach(byte h in hash)
|
||||
crc32Output.Append(h.ToString("x2"));
|
||||
|
||||
return crc32Output.ToString();
|
||||
}
|
||||
|
||||
/// <summary>Gets the hash of the specified data buffer.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
/// <param name="hash">Byte array of the hash value.</param>
|
||||
public static string Data(byte[] data, out byte[] hash) => Data(data, (uint)data.Length, out hash);
|
||||
}
|
||||
|
||||
/// <summary>Initializes the CRC32 table with a custom polynomial and seed</summary>
|
||||
public Crc32Context(uint polynomial, uint seed)
|
||||
{
|
||||
_hashInt = seed;
|
||||
_finalSeed = seed;
|
||||
|
||||
_table = new uint[256];
|
||||
|
||||
for(var i = 0; i < 256; i++)
|
||||
{
|
||||
var entry = (uint)i;
|
||||
|
||||
for(var j = 0; j < 8; j++)
|
||||
{
|
||||
if((entry & 1) == 1)
|
||||
entry = entry >> 1 ^ polynomial;
|
||||
else
|
||||
entry = entry >> 1;
|
||||
}
|
||||
|
||||
_table[i] = entry;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Updates the hash with data.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
/// <param name="len">Length of buffer to hash.</param>
|
||||
public void Update(byte[] data, uint len)
|
||||
{
|
||||
for(var i = 0; i < len; i++) _hashInt = _hashInt >> 8 ^ _table[data[i] ^ _hashInt & 0xff];
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Updates the hash with data.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
public void Update(byte[] data) => Update(data, (uint)data.Length);
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Returns a byte array of the hash value.</summary>
|
||||
public byte[] Final() => BigEndianBitConverter.GetBytes(_hashInt ^ _finalSeed);
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Returns a hexadecimal representation of the hash value.</summary>
|
||||
public string End()
|
||||
{
|
||||
var crc32Output = new StringBuilder();
|
||||
|
||||
for(var i = 0; i < BigEndianBitConverter.GetBytes(_hashInt ^ _finalSeed).Length; i++)
|
||||
crc32Output.Append(BigEndianBitConverter.GetBytes(_hashInt ^ _finalSeed)[i].ToString("x2"));
|
||||
|
||||
return crc32Output.ToString();
|
||||
}
|
||||
|
||||
/// <summary>Gets the hash of a file</summary>
|
||||
/// <param name="filename">File path.</param>
|
||||
public static byte[] File(string filename)
|
||||
{
|
||||
File(filename, out byte[] hash);
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
/// <summary>Gets the hash of a file in hexadecimal and as a byte array.</summary>
|
||||
/// <param name="filename">File path.</param>
|
||||
/// <param name="hash">Byte array of the hash value.</param>
|
||||
public static string File(string filename, out byte[] hash) =>
|
||||
File(filename, out hash, CRC32_ISO_POLY, CRC32_ISO_SEED);
|
||||
|
||||
/// <summary>Gets the hash of a file in hexadecimal and as a byte array.</summary>
|
||||
/// <param name="filename">File path.</param>
|
||||
/// <param name="hash">Byte array of the hash value.</param>
|
||||
/// <param name="polynomial">CRC polynomial</param>
|
||||
/// <param name="seed">CRC seed</param>
|
||||
public static string File(string filename, out byte[] hash, uint polynomial, uint seed)
|
||||
{
|
||||
var fileStream = new FileStream(filename, FileMode.Open, FileAccess.Read);
|
||||
|
||||
uint localhashInt = seed;
|
||||
|
||||
var localTable = new uint[256];
|
||||
|
||||
for(var i = 0; i < 256; i++)
|
||||
{
|
||||
var entry = (uint)i;
|
||||
|
||||
for(var j = 0; j < 8; j++)
|
||||
{
|
||||
if((entry & 1) == 1)
|
||||
entry = entry >> 1 ^ polynomial;
|
||||
else
|
||||
entry = entry >> 1;
|
||||
}
|
||||
|
||||
localTable[i] = entry;
|
||||
}
|
||||
|
||||
for(var i = 0; i < fileStream.Length; i++)
|
||||
localhashInt = localhashInt >> 8 ^ localTable[fileStream.ReadByte() ^ localhashInt & 0xff];
|
||||
|
||||
localhashInt ^= seed;
|
||||
hash = BigEndianBitConverter.GetBytes(localhashInt);
|
||||
|
||||
var crc32Output = new StringBuilder();
|
||||
|
||||
foreach(byte h in hash) crc32Output.Append(h.ToString("x2"));
|
||||
|
||||
fileStream.Close();
|
||||
|
||||
return crc32Output.ToString();
|
||||
}
|
||||
|
||||
/// <summary>Gets the hash of the specified data buffer.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
/// <param name="len">Length of the data buffer to hash.</param>
|
||||
/// <param name="hash">Byte array of the hash value.</param>
|
||||
public static string Data(byte[] data, uint len, out byte[] hash) =>
|
||||
Data(data, len, out hash, CRC32_ISO_POLY, CRC32_ISO_SEED);
|
||||
|
||||
/// <summary>Gets the hash of the specified data buffer.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
/// <param name="len">Length of the data buffer to hash.</param>
|
||||
/// <param name="hash">Byte array of the hash value.</param>
|
||||
/// <param name="polynomial">CRC polynomial</param>
|
||||
/// <param name="seed">CRC seed</param>
|
||||
public static string Data(byte[] data, uint len, out byte[] hash, uint polynomial, uint seed)
|
||||
{
|
||||
uint localhashInt = seed;
|
||||
|
||||
var localTable = new uint[256];
|
||||
|
||||
for(var i = 0; i < 256; i++)
|
||||
{
|
||||
var entry = (uint)i;
|
||||
|
||||
for(var j = 0; j < 8; j++)
|
||||
{
|
||||
if((entry & 1) == 1)
|
||||
entry = entry >> 1 ^ polynomial;
|
||||
else
|
||||
entry = entry >> 1;
|
||||
}
|
||||
|
||||
localTable[i] = entry;
|
||||
}
|
||||
|
||||
for(var i = 0; i < len; i++) localhashInt = localhashInt >> 8 ^ localTable[data[i] ^ localhashInt & 0xff];
|
||||
|
||||
localhashInt ^= seed;
|
||||
hash = BigEndianBitConverter.GetBytes(localhashInt);
|
||||
|
||||
var crc32Output = new StringBuilder();
|
||||
|
||||
foreach(byte h in hash) crc32Output.Append(h.ToString("x2"));
|
||||
|
||||
return crc32Output.ToString();
|
||||
}
|
||||
|
||||
/// <summary>Gets the hash of the specified data buffer.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
/// <param name="hash">Byte array of the hash value.</param>
|
||||
public static string Data(byte[] data, out byte[] hash) => Data(data, (uint)data.Length, out hash);
|
||||
}
|
||||
@@ -35,201 +35,204 @@ using System.Text;
|
||||
using Aaru.CommonTypes.Interfaces;
|
||||
using Aaru.Helpers;
|
||||
|
||||
namespace Aaru.Checksums
|
||||
namespace Aaru.Checksums;
|
||||
|
||||
/// <summary>Implements a CRC64 algorithm</summary>
|
||||
public sealed class Crc64Context : IChecksum
|
||||
{
|
||||
/// <summary>Implements a CRC64 algorithm</summary>
|
||||
public sealed class Crc64Context : IChecksum
|
||||
public const ulong CRC64_ECMA_POLY = 0xC96C5795D7870F42;
|
||||
public const ulong CRC64_ECMA_SEED = 0xFFFFFFFFFFFFFFFF;
|
||||
|
||||
readonly ulong _finalSeed;
|
||||
readonly ulong[] _table;
|
||||
ulong _hashInt;
|
||||
|
||||
/// <summary>Initializes the CRC64 table and seed as CRC64-ECMA</summary>
|
||||
public Crc64Context()
|
||||
{
|
||||
public const ulong CRC64_ECMA_POLY = 0xC96C5795D7870F42;
|
||||
public const ulong CRC64_ECMA_SEED = 0xFFFFFFFFFFFFFFFF;
|
||||
_hashInt = CRC64_ECMA_SEED;
|
||||
|
||||
readonly ulong _finalSeed;
|
||||
readonly ulong[] _table;
|
||||
ulong _hashInt;
|
||||
_table = new ulong[256];
|
||||
|
||||
/// <summary>Initializes the CRC64 table and seed as CRC64-ECMA</summary>
|
||||
public Crc64Context()
|
||||
for(var i = 0; i < 256; i++)
|
||||
{
|
||||
_hashInt = CRC64_ECMA_SEED;
|
||||
var entry = (ulong)i;
|
||||
|
||||
_table = new ulong[256];
|
||||
|
||||
for(int i = 0; i < 256; i++)
|
||||
for(var j = 0; j < 8; j++)
|
||||
{
|
||||
ulong entry = (ulong)i;
|
||||
|
||||
for(int j = 0; j < 8; j++)
|
||||
if((entry & 1) == 1)
|
||||
entry = (entry >> 1) ^ CRC64_ECMA_POLY;
|
||||
else
|
||||
entry = entry >> 1;
|
||||
|
||||
_table[i] = entry;
|
||||
if((entry & 1) == 1)
|
||||
entry = entry >> 1 ^ CRC64_ECMA_POLY;
|
||||
else
|
||||
entry = entry >> 1;
|
||||
}
|
||||
|
||||
_finalSeed = CRC64_ECMA_SEED;
|
||||
_table[i] = entry;
|
||||
}
|
||||
|
||||
/// <summary>Initializes the CRC16 table with a custom polynomial and seed</summary>
|
||||
public Crc64Context(ulong polynomial, ulong seed)
|
||||
{
|
||||
_hashInt = seed;
|
||||
|
||||
_table = new ulong[256];
|
||||
|
||||
for(int i = 0; i < 256; i++)
|
||||
{
|
||||
ulong entry = (ulong)i;
|
||||
|
||||
for(int j = 0; j < 8; j++)
|
||||
if((entry & 1) == 1)
|
||||
entry = (entry >> 1) ^ polynomial;
|
||||
else
|
||||
entry = entry >> 1;
|
||||
|
||||
_table[i] = entry;
|
||||
}
|
||||
|
||||
_finalSeed = seed;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Updates the hash with data.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
/// <param name="len">Length of buffer to hash.</param>
|
||||
public void Update(byte[] data, uint len)
|
||||
{
|
||||
for(int i = 0; i < len; i++)
|
||||
_hashInt = (_hashInt >> 8) ^ _table[data[i] ^ (_hashInt & 0xff)];
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Updates the hash with data.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
public void Update(byte[] data) => Update(data, (uint)data.Length);
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Returns a byte array of the hash value.</summary>
|
||||
public byte[] Final() => BigEndianBitConverter.GetBytes(_hashInt ^= _finalSeed);
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Returns a hexadecimal representation of the hash value.</summary>
|
||||
public string End()
|
||||
{
|
||||
var crc64Output = new StringBuilder();
|
||||
|
||||
for(int i = 0; i < BigEndianBitConverter.GetBytes(_hashInt ^= _finalSeed).Length; i++)
|
||||
crc64Output.Append(BigEndianBitConverter.GetBytes(_hashInt ^= _finalSeed)[i].ToString("x2"));
|
||||
|
||||
return crc64Output.ToString();
|
||||
}
|
||||
|
||||
/// <summary>Gets the hash of a file</summary>
|
||||
/// <param name="filename">File path.</param>
|
||||
public static byte[] File(string filename)
|
||||
{
|
||||
File(filename, out byte[] localHash);
|
||||
|
||||
return localHash;
|
||||
}
|
||||
|
||||
/// <summary>Gets the hash of a file in hexadecimal and as a byte array.</summary>
|
||||
/// <param name="filename">File path.</param>
|
||||
/// <param name="hash">Byte array of the hash value.</param>
|
||||
public static string File(string filename, out byte[] hash) =>
|
||||
File(filename, out hash, CRC64_ECMA_POLY, CRC64_ECMA_SEED);
|
||||
|
||||
/// <summary>Gets the hash of a file in hexadecimal and as a byte array.</summary>
|
||||
/// <param name="filename">File path.</param>
|
||||
/// <param name="hash">Byte array of the hash value.</param>
|
||||
/// <param name="polynomial">CRC polynomial</param>
|
||||
/// <param name="seed">CRC seed</param>
|
||||
public static string File(string filename, out byte[] hash, ulong polynomial, ulong seed)
|
||||
{
|
||||
var fileStream = new FileStream(filename, FileMode.Open, FileAccess.Read);
|
||||
|
||||
ulong localhashInt = seed;
|
||||
|
||||
ulong[] localTable = new ulong[256];
|
||||
|
||||
for(int i = 0; i < 256; i++)
|
||||
{
|
||||
ulong entry = (ulong)i;
|
||||
|
||||
for(int j = 0; j < 8; j++)
|
||||
if((entry & 1) == 1)
|
||||
entry = (entry >> 1) ^ polynomial;
|
||||
else
|
||||
entry = entry >> 1;
|
||||
|
||||
localTable[i] = entry;
|
||||
}
|
||||
|
||||
for(int i = 0; i < fileStream.Length; i++)
|
||||
localhashInt = (localhashInt >> 8) ^ localTable[(ulong)fileStream.ReadByte() ^ (localhashInt & 0xffL)];
|
||||
|
||||
localhashInt ^= seed;
|
||||
hash = BigEndianBitConverter.GetBytes(localhashInt);
|
||||
|
||||
var crc64Output = new StringBuilder();
|
||||
|
||||
foreach(byte h in hash)
|
||||
crc64Output.Append(h.ToString("x2"));
|
||||
|
||||
fileStream.Close();
|
||||
|
||||
return crc64Output.ToString();
|
||||
}
|
||||
|
||||
/// <summary>Gets the hash of the specified data buffer.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
/// <param name="len">Length of the data buffer to hash.</param>
|
||||
/// <param name="hash">Byte array of the hash value.</param>
|
||||
public static string Data(byte[] data, uint len, out byte[] hash) =>
|
||||
Data(data, len, out hash, CRC64_ECMA_POLY, CRC64_ECMA_SEED);
|
||||
|
||||
/// <summary>Gets the hash of the specified data buffer.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
/// <param name="len">Length of the data buffer to hash.</param>
|
||||
/// <param name="hash">Byte array of the hash value.</param>
|
||||
/// <param name="polynomial">CRC polynomial</param>
|
||||
/// <param name="seed">CRC seed</param>
|
||||
public static string Data(byte[] data, uint len, out byte[] hash, ulong polynomial, ulong seed)
|
||||
{
|
||||
ulong localhashInt = seed;
|
||||
|
||||
ulong[] localTable = new ulong[256];
|
||||
|
||||
for(int i = 0; i < 256; i++)
|
||||
{
|
||||
ulong entry = (ulong)i;
|
||||
|
||||
for(int j = 0; j < 8; j++)
|
||||
if((entry & 1) == 1)
|
||||
entry = (entry >> 1) ^ polynomial;
|
||||
else
|
||||
entry = entry >> 1;
|
||||
|
||||
localTable[i] = entry;
|
||||
}
|
||||
|
||||
for(int i = 0; i < len; i++)
|
||||
localhashInt = (localhashInt >> 8) ^ localTable[data[i] ^ (localhashInt & 0xff)];
|
||||
|
||||
localhashInt ^= seed;
|
||||
hash = BigEndianBitConverter.GetBytes(localhashInt);
|
||||
|
||||
var crc64Output = new StringBuilder();
|
||||
|
||||
foreach(byte h in hash)
|
||||
crc64Output.Append(h.ToString("x2"));
|
||||
|
||||
return crc64Output.ToString();
|
||||
}
|
||||
|
||||
/// <summary>Gets the hash of the specified data buffer.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
/// <param name="hash">Byte array of the hash value.</param>
|
||||
public static string Data(byte[] data, out byte[] hash) => Data(data, (uint)data.Length, out hash);
|
||||
_finalSeed = CRC64_ECMA_SEED;
|
||||
}
|
||||
|
||||
/// <summary>Initializes the CRC16 table with a custom polynomial and seed</summary>
|
||||
public Crc64Context(ulong polynomial, ulong seed)
|
||||
{
|
||||
_hashInt = seed;
|
||||
|
||||
_table = new ulong[256];
|
||||
|
||||
for(var i = 0; i < 256; i++)
|
||||
{
|
||||
var entry = (ulong)i;
|
||||
|
||||
for(var j = 0; j < 8; j++)
|
||||
{
|
||||
if((entry & 1) == 1)
|
||||
entry = entry >> 1 ^ polynomial;
|
||||
else
|
||||
entry = entry >> 1;
|
||||
}
|
||||
|
||||
_table[i] = entry;
|
||||
}
|
||||
|
||||
_finalSeed = seed;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Updates the hash with data.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
/// <param name="len">Length of buffer to hash.</param>
|
||||
public void Update(byte[] data, uint len)
|
||||
{
|
||||
for(var i = 0; i < len; i++) _hashInt = _hashInt >> 8 ^ _table[data[i] ^ _hashInt & 0xff];
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Updates the hash with data.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
public void Update(byte[] data) => Update(data, (uint)data.Length);
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Returns a byte array of the hash value.</summary>
|
||||
public byte[] Final() => BigEndianBitConverter.GetBytes(_hashInt ^= _finalSeed);
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Returns a hexadecimal representation of the hash value.</summary>
|
||||
public string End()
|
||||
{
|
||||
var crc64Output = new StringBuilder();
|
||||
|
||||
for(var i = 0; i < BigEndianBitConverter.GetBytes(_hashInt ^= _finalSeed).Length; i++)
|
||||
crc64Output.Append(BigEndianBitConverter.GetBytes(_hashInt ^= _finalSeed)[i].ToString("x2"));
|
||||
|
||||
return crc64Output.ToString();
|
||||
}
|
||||
|
||||
/// <summary>Gets the hash of a file</summary>
|
||||
/// <param name="filename">File path.</param>
|
||||
public static byte[] File(string filename)
|
||||
{
|
||||
File(filename, out byte[] localHash);
|
||||
|
||||
return localHash;
|
||||
}
|
||||
|
||||
/// <summary>Gets the hash of a file in hexadecimal and as a byte array.</summary>
|
||||
/// <param name="filename">File path.</param>
|
||||
/// <param name="hash">Byte array of the hash value.</param>
|
||||
public static string File(string filename, out byte[] hash) =>
|
||||
File(filename, out hash, CRC64_ECMA_POLY, CRC64_ECMA_SEED);
|
||||
|
||||
/// <summary>Gets the hash of a file in hexadecimal and as a byte array.</summary>
|
||||
/// <param name="filename">File path.</param>
|
||||
/// <param name="hash">Byte array of the hash value.</param>
|
||||
/// <param name="polynomial">CRC polynomial</param>
|
||||
/// <param name="seed">CRC seed</param>
|
||||
public static string File(string filename, out byte[] hash, ulong polynomial, ulong seed)
|
||||
{
|
||||
var fileStream = new FileStream(filename, FileMode.Open, FileAccess.Read);
|
||||
|
||||
ulong localhashInt = seed;
|
||||
|
||||
var localTable = new ulong[256];
|
||||
|
||||
for(var i = 0; i < 256; i++)
|
||||
{
|
||||
var entry = (ulong)i;
|
||||
|
||||
for(var j = 0; j < 8; j++)
|
||||
{
|
||||
if((entry & 1) == 1)
|
||||
entry = entry >> 1 ^ polynomial;
|
||||
else
|
||||
entry = entry >> 1;
|
||||
}
|
||||
|
||||
localTable[i] = entry;
|
||||
}
|
||||
|
||||
for(var i = 0; i < fileStream.Length; i++)
|
||||
localhashInt = localhashInt >> 8 ^ localTable[(ulong)fileStream.ReadByte() ^ localhashInt & 0xffL];
|
||||
|
||||
localhashInt ^= seed;
|
||||
hash = BigEndianBitConverter.GetBytes(localhashInt);
|
||||
|
||||
var crc64Output = new StringBuilder();
|
||||
|
||||
foreach(byte h in hash) crc64Output.Append(h.ToString("x2"));
|
||||
|
||||
fileStream.Close();
|
||||
|
||||
return crc64Output.ToString();
|
||||
}
|
||||
|
||||
/// <summary>Gets the hash of the specified data buffer.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
/// <param name="len">Length of the data buffer to hash.</param>
|
||||
/// <param name="hash">Byte array of the hash value.</param>
|
||||
public static string Data(byte[] data, uint len, out byte[] hash) =>
|
||||
Data(data, len, out hash, CRC64_ECMA_POLY, CRC64_ECMA_SEED);
|
||||
|
||||
/// <summary>Gets the hash of the specified data buffer.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
/// <param name="len">Length of the data buffer to hash.</param>
|
||||
/// <param name="hash">Byte array of the hash value.</param>
|
||||
/// <param name="polynomial">CRC polynomial</param>
|
||||
/// <param name="seed">CRC seed</param>
|
||||
public static string Data(byte[] data, uint len, out byte[] hash, ulong polynomial, ulong seed)
|
||||
{
|
||||
ulong localhashInt = seed;
|
||||
|
||||
var localTable = new ulong[256];
|
||||
|
||||
for(var i = 0; i < 256; i++)
|
||||
{
|
||||
var entry = (ulong)i;
|
||||
|
||||
for(var j = 0; j < 8; j++)
|
||||
{
|
||||
if((entry & 1) == 1)
|
||||
entry = entry >> 1 ^ polynomial;
|
||||
else
|
||||
entry = entry >> 1;
|
||||
}
|
||||
|
||||
localTable[i] = entry;
|
||||
}
|
||||
|
||||
for(var i = 0; i < len; i++) localhashInt = localhashInt >> 8 ^ localTable[data[i] ^ localhashInt & 0xff];
|
||||
|
||||
localhashInt ^= seed;
|
||||
hash = BigEndianBitConverter.GetBytes(localhashInt);
|
||||
|
||||
var crc64Output = new StringBuilder();
|
||||
|
||||
foreach(byte h in hash) crc64Output.Append(h.ToString("x2"));
|
||||
|
||||
return crc64Output.ToString();
|
||||
}
|
||||
|
||||
/// <summary>Gets the hash of the specified data buffer.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
/// <param name="hash">Byte array of the hash value.</param>
|
||||
public static string Data(byte[] data, out byte[] hash) => Data(data, (uint)data.Length, out hash);
|
||||
}
|
||||
@@ -36,23 +36,22 @@
|
||||
// Copyright © 2011-2024 Natalia Portillo
|
||||
// ****************************************************************************/
|
||||
|
||||
namespace Aaru.CommonTypes.Interfaces
|
||||
namespace Aaru.CommonTypes.Interfaces;
|
||||
|
||||
public interface IChecksum
|
||||
{
|
||||
public interface IChecksum
|
||||
{
|
||||
/// <summary>Updates the hash with data.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
/// <param name="len">Length of buffer to hash.</param>
|
||||
void Update(byte[] data, uint len);
|
||||
/// <summary>Updates the hash with data.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
/// <param name="len">Length of buffer to hash.</param>
|
||||
void Update(byte[] data, uint len);
|
||||
|
||||
/// <summary>Updates the hash with data.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
void Update(byte[] data);
|
||||
/// <summary>Updates the hash with data.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
void Update(byte[] data);
|
||||
|
||||
/// <summary>Returns a byte array of the hash value.</summary>
|
||||
byte[] Final();
|
||||
/// <summary>Returns a byte array of the hash value.</summary>
|
||||
byte[] Final();
|
||||
|
||||
/// <summary>Returns a hexadecimal representation of the hash value.</summary>
|
||||
string End();
|
||||
}
|
||||
/// <summary>Returns a hexadecimal representation of the hash value.</summary>
|
||||
string End();
|
||||
}
|
||||
@@ -35,98 +35,94 @@ using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using Aaru.CommonTypes.Interfaces;
|
||||
|
||||
namespace Aaru.Checksums
|
||||
namespace Aaru.Checksums;
|
||||
|
||||
/// <summary>Wraps up .NET MD5 implementation to a Init(), Update(), Final() context.</summary>
|
||||
public sealed class Md5Context : IChecksum
|
||||
{
|
||||
/// <summary>Wraps up .NET MD5 implementation to a Init(), Update(), Final() context.</summary>
|
||||
public sealed class Md5Context : IChecksum
|
||||
readonly MD5 _provider;
|
||||
|
||||
/// <summary>Initializes the MD5 hash provider</summary>
|
||||
public Md5Context() => _provider = MD5.Create();
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Updates the hash with data.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
/// <param name="len">Length of buffer to hash.</param>
|
||||
public void Update(byte[] data, uint len) => _provider.TransformBlock(data, 0, (int)len, data, 0);
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Updates the hash with data.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
public void Update(byte[] data) => Update(data, (uint)data.Length);
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Returns a byte array of the hash value.</summary>
|
||||
public byte[] Final()
|
||||
{
|
||||
readonly MD5 _provider;
|
||||
_provider.TransformFinalBlock(new byte[0], 0, 0);
|
||||
|
||||
/// <summary>Initializes the MD5 hash provider</summary>
|
||||
public Md5Context() => _provider = MD5.Create();
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Updates the hash with data.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
/// <param name="len">Length of buffer to hash.</param>
|
||||
public void Update(byte[] data, uint len) => _provider.TransformBlock(data, 0, (int)len, data, 0);
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Updates the hash with data.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
public void Update(byte[] data) => Update(data, (uint)data.Length);
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Returns a byte array of the hash value.</summary>
|
||||
public byte[] Final()
|
||||
{
|
||||
_provider.TransformFinalBlock(new byte[0], 0, 0);
|
||||
|
||||
return _provider.Hash;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Returns a hexadecimal representation of the hash value.</summary>
|
||||
public string End()
|
||||
{
|
||||
_provider.TransformFinalBlock(new byte[0], 0, 0);
|
||||
var md5Output = new StringBuilder();
|
||||
|
||||
foreach(byte h in _provider.Hash)
|
||||
md5Output.Append(h.ToString("x2"));
|
||||
|
||||
return md5Output.ToString();
|
||||
}
|
||||
|
||||
/// <summary>Gets the hash of a file</summary>
|
||||
/// <param name="filename">File path.</param>
|
||||
public static byte[] File(string filename)
|
||||
{
|
||||
var localMd5Provider = MD5.Create();
|
||||
var fileStream = new FileStream(filename, FileMode.Open, FileAccess.Read);
|
||||
byte[] result = localMd5Provider.ComputeHash(fileStream);
|
||||
fileStream.Close();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>Gets the hash of a file in hexadecimal and as a byte array.</summary>
|
||||
/// <param name="filename">File path.</param>
|
||||
/// <param name="hash">Byte array of the hash value.</param>
|
||||
public static string File(string filename, out byte[] hash)
|
||||
{
|
||||
var localMd5Provider = MD5.Create();
|
||||
var fileStream = new FileStream(filename, FileMode.Open, FileAccess.Read);
|
||||
hash = localMd5Provider.ComputeHash(fileStream);
|
||||
var md5Output = new StringBuilder();
|
||||
|
||||
foreach(byte h in hash)
|
||||
md5Output.Append(h.ToString("x2"));
|
||||
|
||||
fileStream.Close();
|
||||
|
||||
return md5Output.ToString();
|
||||
}
|
||||
|
||||
/// <summary>Gets the hash of the specified data buffer.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
/// <param name="len">Length of the data buffer to hash.</param>
|
||||
/// <param name="hash">Byte array of the hash value.</param>
|
||||
public static string Data(byte[] data, uint len, out byte[] hash)
|
||||
{
|
||||
var localMd5Provider = MD5.Create();
|
||||
hash = localMd5Provider.ComputeHash(data, 0, (int)len);
|
||||
var md5Output = new StringBuilder();
|
||||
|
||||
foreach(byte h in hash)
|
||||
md5Output.Append(h.ToString("x2"));
|
||||
|
||||
return md5Output.ToString();
|
||||
}
|
||||
|
||||
/// <summary>Gets the hash of the specified data buffer.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
/// <param name="hash">Byte array of the hash value.</param>
|
||||
public static string Data(byte[] data, out byte[] hash) => Data(data, (uint)data.Length, out hash);
|
||||
return _provider.Hash;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Returns a hexadecimal representation of the hash value.</summary>
|
||||
public string End()
|
||||
{
|
||||
_provider.TransformFinalBlock(new byte[0], 0, 0);
|
||||
var md5Output = new StringBuilder();
|
||||
|
||||
foreach(byte h in _provider.Hash) md5Output.Append(h.ToString("x2"));
|
||||
|
||||
return md5Output.ToString();
|
||||
}
|
||||
|
||||
/// <summary>Gets the hash of a file</summary>
|
||||
/// <param name="filename">File path.</param>
|
||||
public static byte[] File(string filename)
|
||||
{
|
||||
var localMd5Provider = MD5.Create();
|
||||
var fileStream = new FileStream(filename, FileMode.Open, FileAccess.Read);
|
||||
byte[] result = localMd5Provider.ComputeHash(fileStream);
|
||||
fileStream.Close();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>Gets the hash of a file in hexadecimal and as a byte array.</summary>
|
||||
/// <param name="filename">File path.</param>
|
||||
/// <param name="hash">Byte array of the hash value.</param>
|
||||
public static string File(string filename, out byte[] hash)
|
||||
{
|
||||
var localMd5Provider = MD5.Create();
|
||||
var fileStream = new FileStream(filename, FileMode.Open, FileAccess.Read);
|
||||
hash = localMd5Provider.ComputeHash(fileStream);
|
||||
var md5Output = new StringBuilder();
|
||||
|
||||
foreach(byte h in hash) md5Output.Append(h.ToString("x2"));
|
||||
|
||||
fileStream.Close();
|
||||
|
||||
return md5Output.ToString();
|
||||
}
|
||||
|
||||
/// <summary>Gets the hash of the specified data buffer.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
/// <param name="len">Length of the data buffer to hash.</param>
|
||||
/// <param name="hash">Byte array of the hash value.</param>
|
||||
public static string Data(byte[] data, uint len, out byte[] hash)
|
||||
{
|
||||
var localMd5Provider = MD5.Create();
|
||||
hash = localMd5Provider.ComputeHash(data, 0, (int)len);
|
||||
var md5Output = new StringBuilder();
|
||||
|
||||
foreach(byte h in hash) md5Output.Append(h.ToString("x2"));
|
||||
|
||||
return md5Output.ToString();
|
||||
}
|
||||
|
||||
/// <summary>Gets the hash of the specified data buffer.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
/// <param name="hash">Byte array of the hash value.</param>
|
||||
public static string Data(byte[] data, out byte[] hash) => Data(data, (uint)data.Length, out hash);
|
||||
}
|
||||
@@ -35,98 +35,94 @@ using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using Aaru.CommonTypes.Interfaces;
|
||||
|
||||
namespace Aaru.Checksums
|
||||
namespace Aaru.Checksums;
|
||||
|
||||
/// <summary>Wraps up .NET SHA1 implementation to a Init(), Update(), Final() context.</summary>
|
||||
public sealed class Sha1Context : IChecksum
|
||||
{
|
||||
/// <summary>Wraps up .NET SHA1 implementation to a Init(), Update(), Final() context.</summary>
|
||||
public sealed class Sha1Context : IChecksum
|
||||
readonly SHA1 _provider;
|
||||
|
||||
/// <summary>Initializes the SHA1 hash provider</summary>
|
||||
public Sha1Context() => _provider = SHA1.Create();
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Updates the hash with data.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
/// <param name="len">Length of buffer to hash.</param>
|
||||
public void Update(byte[] data, uint len) => _provider.TransformBlock(data, 0, (int)len, data, 0);
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Updates the hash with data.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
public void Update(byte[] data) => Update(data, (uint)data.Length);
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Returns a byte array of the hash value.</summary>
|
||||
public byte[] Final()
|
||||
{
|
||||
readonly SHA1 _provider;
|
||||
_provider.TransformFinalBlock(new byte[0], 0, 0);
|
||||
|
||||
/// <summary>Initializes the SHA1 hash provider</summary>
|
||||
public Sha1Context() => _provider = SHA1.Create();
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Updates the hash with data.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
/// <param name="len">Length of buffer to hash.</param>
|
||||
public void Update(byte[] data, uint len) => _provider.TransformBlock(data, 0, (int)len, data, 0);
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Updates the hash with data.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
public void Update(byte[] data) => Update(data, (uint)data.Length);
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Returns a byte array of the hash value.</summary>
|
||||
public byte[] Final()
|
||||
{
|
||||
_provider.TransformFinalBlock(new byte[0], 0, 0);
|
||||
|
||||
return _provider.Hash;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Returns a hexadecimal representation of the hash value.</summary>
|
||||
public string End()
|
||||
{
|
||||
_provider.TransformFinalBlock(new byte[0], 0, 0);
|
||||
var sha1Output = new StringBuilder();
|
||||
|
||||
foreach(byte h in _provider.Hash)
|
||||
sha1Output.Append(h.ToString("x2"));
|
||||
|
||||
return sha1Output.ToString();
|
||||
}
|
||||
|
||||
/// <summary>Gets the hash of a file</summary>
|
||||
/// <param name="filename">File path.</param>
|
||||
public static byte[] File(string filename)
|
||||
{
|
||||
var localSha1Provider = SHA1.Create();
|
||||
var fileStream = new FileStream(filename, FileMode.Open, FileAccess.Read);
|
||||
byte[] result = localSha1Provider.ComputeHash(fileStream);
|
||||
fileStream.Close();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>Gets the hash of a file in hexadecimal and as a byte array.</summary>
|
||||
/// <param name="filename">File path.</param>
|
||||
/// <param name="hash">Byte array of the hash value.</param>
|
||||
public static string File(string filename, out byte[] hash)
|
||||
{
|
||||
var localSha1Provider = SHA1.Create();
|
||||
var fileStream = new FileStream(filename, FileMode.Open, FileAccess.Read);
|
||||
hash = localSha1Provider.ComputeHash(fileStream);
|
||||
var sha1Output = new StringBuilder();
|
||||
|
||||
foreach(byte h in hash)
|
||||
sha1Output.Append(h.ToString("x2"));
|
||||
|
||||
fileStream.Close();
|
||||
|
||||
return sha1Output.ToString();
|
||||
}
|
||||
|
||||
/// <summary>Gets the hash of the specified data buffer.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
/// <param name="len">Length of the data buffer to hash.</param>
|
||||
/// <param name="hash">Byte array of the hash value.</param>
|
||||
public static string Data(byte[] data, uint len, out byte[] hash)
|
||||
{
|
||||
var localSha1Provider = SHA1.Create();
|
||||
hash = localSha1Provider.ComputeHash(data, 0, (int)len);
|
||||
var sha1Output = new StringBuilder();
|
||||
|
||||
foreach(byte h in hash)
|
||||
sha1Output.Append(h.ToString("x2"));
|
||||
|
||||
return sha1Output.ToString();
|
||||
}
|
||||
|
||||
/// <summary>Gets the hash of the specified data buffer.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
/// <param name="hash">Byte array of the hash value.</param>
|
||||
public static string Data(byte[] data, out byte[] hash) => Data(data, (uint)data.Length, out hash);
|
||||
return _provider.Hash;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Returns a hexadecimal representation of the hash value.</summary>
|
||||
public string End()
|
||||
{
|
||||
_provider.TransformFinalBlock(new byte[0], 0, 0);
|
||||
var sha1Output = new StringBuilder();
|
||||
|
||||
foreach(byte h in _provider.Hash) sha1Output.Append(h.ToString("x2"));
|
||||
|
||||
return sha1Output.ToString();
|
||||
}
|
||||
|
||||
/// <summary>Gets the hash of a file</summary>
|
||||
/// <param name="filename">File path.</param>
|
||||
public static byte[] File(string filename)
|
||||
{
|
||||
var localSha1Provider = SHA1.Create();
|
||||
var fileStream = new FileStream(filename, FileMode.Open, FileAccess.Read);
|
||||
byte[] result = localSha1Provider.ComputeHash(fileStream);
|
||||
fileStream.Close();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>Gets the hash of a file in hexadecimal and as a byte array.</summary>
|
||||
/// <param name="filename">File path.</param>
|
||||
/// <param name="hash">Byte array of the hash value.</param>
|
||||
public static string File(string filename, out byte[] hash)
|
||||
{
|
||||
var localSha1Provider = SHA1.Create();
|
||||
var fileStream = new FileStream(filename, FileMode.Open, FileAccess.Read);
|
||||
hash = localSha1Provider.ComputeHash(fileStream);
|
||||
var sha1Output = new StringBuilder();
|
||||
|
||||
foreach(byte h in hash) sha1Output.Append(h.ToString("x2"));
|
||||
|
||||
fileStream.Close();
|
||||
|
||||
return sha1Output.ToString();
|
||||
}
|
||||
|
||||
/// <summary>Gets the hash of the specified data buffer.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
/// <param name="len">Length of the data buffer to hash.</param>
|
||||
/// <param name="hash">Byte array of the hash value.</param>
|
||||
public static string Data(byte[] data, uint len, out byte[] hash)
|
||||
{
|
||||
var localSha1Provider = SHA1.Create();
|
||||
hash = localSha1Provider.ComputeHash(data, 0, (int)len);
|
||||
var sha1Output = new StringBuilder();
|
||||
|
||||
foreach(byte h in hash) sha1Output.Append(h.ToString("x2"));
|
||||
|
||||
return sha1Output.ToString();
|
||||
}
|
||||
|
||||
/// <summary>Gets the hash of the specified data buffer.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
/// <param name="hash">Byte array of the hash value.</param>
|
||||
public static string Data(byte[] data, out byte[] hash) => Data(data, (uint)data.Length, out hash);
|
||||
}
|
||||
@@ -35,98 +35,94 @@ using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using Aaru.CommonTypes.Interfaces;
|
||||
|
||||
namespace Aaru.Checksums
|
||||
namespace Aaru.Checksums;
|
||||
|
||||
/// <summary>Wraps up .NET SHA256 implementation to a Init(), Update(), Final() context.</summary>
|
||||
public sealed class Sha256Context : IChecksum
|
||||
{
|
||||
/// <summary>Wraps up .NET SHA256 implementation to a Init(), Update(), Final() context.</summary>
|
||||
public sealed class Sha256Context : IChecksum
|
||||
readonly SHA256 _provider;
|
||||
|
||||
/// <summary>Initializes the SHA256 hash provider</summary>
|
||||
public Sha256Context() => _provider = SHA256.Create();
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Updates the hash with data.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
/// <param name="len">Length of buffer to hash.</param>
|
||||
public void Update(byte[] data, uint len) => _provider.TransformBlock(data, 0, (int)len, data, 0);
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Updates the hash with data.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
public void Update(byte[] data) => Update(data, (uint)data.Length);
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Returns a byte array of the hash value.</summary>
|
||||
public byte[] Final()
|
||||
{
|
||||
readonly SHA256 _provider;
|
||||
_provider.TransformFinalBlock(new byte[0], 0, 0);
|
||||
|
||||
/// <summary>Initializes the SHA256 hash provider</summary>
|
||||
public Sha256Context() => _provider = SHA256.Create();
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Updates the hash with data.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
/// <param name="len">Length of buffer to hash.</param>
|
||||
public void Update(byte[] data, uint len) => _provider.TransformBlock(data, 0, (int)len, data, 0);
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Updates the hash with data.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
public void Update(byte[] data) => Update(data, (uint)data.Length);
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Returns a byte array of the hash value.</summary>
|
||||
public byte[] Final()
|
||||
{
|
||||
_provider.TransformFinalBlock(new byte[0], 0, 0);
|
||||
|
||||
return _provider.Hash;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Returns a hexadecimal representation of the hash value.</summary>
|
||||
public string End()
|
||||
{
|
||||
_provider.TransformFinalBlock(new byte[0], 0, 0);
|
||||
var sha256Output = new StringBuilder();
|
||||
|
||||
foreach(byte h in _provider.Hash)
|
||||
sha256Output.Append(h.ToString("x2"));
|
||||
|
||||
return sha256Output.ToString();
|
||||
}
|
||||
|
||||
/// <summary>Gets the hash of a file</summary>
|
||||
/// <param name="filename">File path.</param>
|
||||
public static byte[] File(string filename)
|
||||
{
|
||||
var localSha256Provider = SHA256.Create();
|
||||
var fileStream = new FileStream(filename, FileMode.Open, FileAccess.Read);
|
||||
byte[] result = localSha256Provider.ComputeHash(fileStream);
|
||||
fileStream.Close();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>Gets the hash of a file in hexadecimal and as a byte array.</summary>
|
||||
/// <param name="filename">File path.</param>
|
||||
/// <param name="hash">Byte array of the hash value.</param>
|
||||
public static string File(string filename, out byte[] hash)
|
||||
{
|
||||
var localSha256Provider = SHA256.Create();
|
||||
var fileStream = new FileStream(filename, FileMode.Open, FileAccess.Read);
|
||||
hash = localSha256Provider.ComputeHash(fileStream);
|
||||
var sha256Output = new StringBuilder();
|
||||
|
||||
foreach(byte h in hash)
|
||||
sha256Output.Append(h.ToString("x2"));
|
||||
|
||||
fileStream.Close();
|
||||
|
||||
return sha256Output.ToString();
|
||||
}
|
||||
|
||||
/// <summary>Gets the hash of the specified data buffer.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
/// <param name="len">Length of the data buffer to hash.</param>
|
||||
/// <param name="hash">Byte array of the hash value.</param>
|
||||
public static string Data(byte[] data, uint len, out byte[] hash)
|
||||
{
|
||||
var localSha256Provider = SHA256.Create();
|
||||
hash = localSha256Provider.ComputeHash(data, 0, (int)len);
|
||||
var sha256Output = new StringBuilder();
|
||||
|
||||
foreach(byte h in hash)
|
||||
sha256Output.Append(h.ToString("x2"));
|
||||
|
||||
return sha256Output.ToString();
|
||||
}
|
||||
|
||||
/// <summary>Gets the hash of the specified data buffer.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
/// <param name="hash">Byte array of the hash value.</param>
|
||||
public static string Data(byte[] data, out byte[] hash) => Data(data, (uint)data.Length, out hash);
|
||||
return _provider.Hash;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Returns a hexadecimal representation of the hash value.</summary>
|
||||
public string End()
|
||||
{
|
||||
_provider.TransformFinalBlock(new byte[0], 0, 0);
|
||||
var sha256Output = new StringBuilder();
|
||||
|
||||
foreach(byte h in _provider.Hash) sha256Output.Append(h.ToString("x2"));
|
||||
|
||||
return sha256Output.ToString();
|
||||
}
|
||||
|
||||
/// <summary>Gets the hash of a file</summary>
|
||||
/// <param name="filename">File path.</param>
|
||||
public static byte[] File(string filename)
|
||||
{
|
||||
var localSha256Provider = SHA256.Create();
|
||||
var fileStream = new FileStream(filename, FileMode.Open, FileAccess.Read);
|
||||
byte[] result = localSha256Provider.ComputeHash(fileStream);
|
||||
fileStream.Close();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>Gets the hash of a file in hexadecimal and as a byte array.</summary>
|
||||
/// <param name="filename">File path.</param>
|
||||
/// <param name="hash">Byte array of the hash value.</param>
|
||||
public static string File(string filename, out byte[] hash)
|
||||
{
|
||||
var localSha256Provider = SHA256.Create();
|
||||
var fileStream = new FileStream(filename, FileMode.Open, FileAccess.Read);
|
||||
hash = localSha256Provider.ComputeHash(fileStream);
|
||||
var sha256Output = new StringBuilder();
|
||||
|
||||
foreach(byte h in hash) sha256Output.Append(h.ToString("x2"));
|
||||
|
||||
fileStream.Close();
|
||||
|
||||
return sha256Output.ToString();
|
||||
}
|
||||
|
||||
/// <summary>Gets the hash of the specified data buffer.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
/// <param name="len">Length of the data buffer to hash.</param>
|
||||
/// <param name="hash">Byte array of the hash value.</param>
|
||||
public static string Data(byte[] data, uint len, out byte[] hash)
|
||||
{
|
||||
var localSha256Provider = SHA256.Create();
|
||||
hash = localSha256Provider.ComputeHash(data, 0, (int)len);
|
||||
var sha256Output = new StringBuilder();
|
||||
|
||||
foreach(byte h in hash) sha256Output.Append(h.ToString("x2"));
|
||||
|
||||
return sha256Output.ToString();
|
||||
}
|
||||
|
||||
/// <summary>Gets the hash of the specified data buffer.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
/// <param name="hash">Byte array of the hash value.</param>
|
||||
public static string Data(byte[] data, out byte[] hash) => Data(data, (uint)data.Length, out hash);
|
||||
}
|
||||
@@ -35,98 +35,94 @@ using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using Aaru.CommonTypes.Interfaces;
|
||||
|
||||
namespace Aaru.Checksums
|
||||
namespace Aaru.Checksums;
|
||||
|
||||
/// <summary>Wraps up .NET SHA384 implementation to a Init(), Update(), Final() context.</summary>
|
||||
public sealed class Sha384Context : IChecksum
|
||||
{
|
||||
/// <summary>Wraps up .NET SHA384 implementation to a Init(), Update(), Final() context.</summary>
|
||||
public sealed class Sha384Context : IChecksum
|
||||
readonly SHA384 _provider;
|
||||
|
||||
/// <summary>Initializes the SHA384 hash provider</summary>
|
||||
public Sha384Context() => _provider = SHA384.Create();
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Updates the hash with data.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
/// <param name="len">Length of buffer to hash.</param>
|
||||
public void Update(byte[] data, uint len) => _provider.TransformBlock(data, 0, (int)len, data, 0);
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Updates the hash with data.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
public void Update(byte[] data) => Update(data, (uint)data.Length);
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Returns a byte array of the hash value.</summary>
|
||||
public byte[] Final()
|
||||
{
|
||||
readonly SHA384 _provider;
|
||||
_provider.TransformFinalBlock(new byte[0], 0, 0);
|
||||
|
||||
/// <summary>Initializes the SHA384 hash provider</summary>
|
||||
public Sha384Context() => _provider = SHA384.Create();
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Updates the hash with data.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
/// <param name="len">Length of buffer to hash.</param>
|
||||
public void Update(byte[] data, uint len) => _provider.TransformBlock(data, 0, (int)len, data, 0);
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Updates the hash with data.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
public void Update(byte[] data) => Update(data, (uint)data.Length);
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Returns a byte array of the hash value.</summary>
|
||||
public byte[] Final()
|
||||
{
|
||||
_provider.TransformFinalBlock(new byte[0], 0, 0);
|
||||
|
||||
return _provider.Hash;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Returns a hexadecimal representation of the hash value.</summary>
|
||||
public string End()
|
||||
{
|
||||
_provider.TransformFinalBlock(new byte[0], 0, 0);
|
||||
var sha384Output = new StringBuilder();
|
||||
|
||||
foreach(byte h in _provider.Hash)
|
||||
sha384Output.Append(h.ToString("x2"));
|
||||
|
||||
return sha384Output.ToString();
|
||||
}
|
||||
|
||||
/// <summary>Gets the hash of a file</summary>
|
||||
/// <param name="filename">File path.</param>
|
||||
public static byte[] File(string filename)
|
||||
{
|
||||
var localSha384Provider = SHA384.Create();
|
||||
var fileStream = new FileStream(filename, FileMode.Open, FileAccess.Read);
|
||||
byte[] result = localSha384Provider.ComputeHash(fileStream);
|
||||
fileStream.Close();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>Gets the hash of a file in hexadecimal and as a byte array.</summary>
|
||||
/// <param name="filename">File path.</param>
|
||||
/// <param name="hash">Byte array of the hash value.</param>
|
||||
public static string File(string filename, out byte[] hash)
|
||||
{
|
||||
var localSha384Provider = SHA384.Create();
|
||||
var fileStream = new FileStream(filename, FileMode.Open, FileAccess.Read);
|
||||
hash = localSha384Provider.ComputeHash(fileStream);
|
||||
var sha384Output = new StringBuilder();
|
||||
|
||||
foreach(byte h in hash)
|
||||
sha384Output.Append(h.ToString("x2"));
|
||||
|
||||
fileStream.Close();
|
||||
|
||||
return sha384Output.ToString();
|
||||
}
|
||||
|
||||
/// <summary>Gets the hash of the specified data buffer.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
/// <param name="len">Length of the data buffer to hash.</param>
|
||||
/// <param name="hash">Byte array of the hash value.</param>
|
||||
public static string Data(byte[] data, uint len, out byte[] hash)
|
||||
{
|
||||
var localSha384Provider = SHA384.Create();
|
||||
hash = localSha384Provider.ComputeHash(data, 0, (int)len);
|
||||
var sha384Output = new StringBuilder();
|
||||
|
||||
foreach(byte h in hash)
|
||||
sha384Output.Append(h.ToString("x2"));
|
||||
|
||||
return sha384Output.ToString();
|
||||
}
|
||||
|
||||
/// <summary>Gets the hash of the specified data buffer.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
/// <param name="hash">Byte array of the hash value.</param>
|
||||
public static string Data(byte[] data, out byte[] hash) => Data(data, (uint)data.Length, out hash);
|
||||
return _provider.Hash;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Returns a hexadecimal representation of the hash value.</summary>
|
||||
public string End()
|
||||
{
|
||||
_provider.TransformFinalBlock(new byte[0], 0, 0);
|
||||
var sha384Output = new StringBuilder();
|
||||
|
||||
foreach(byte h in _provider.Hash) sha384Output.Append(h.ToString("x2"));
|
||||
|
||||
return sha384Output.ToString();
|
||||
}
|
||||
|
||||
/// <summary>Gets the hash of a file</summary>
|
||||
/// <param name="filename">File path.</param>
|
||||
public static byte[] File(string filename)
|
||||
{
|
||||
var localSha384Provider = SHA384.Create();
|
||||
var fileStream = new FileStream(filename, FileMode.Open, FileAccess.Read);
|
||||
byte[] result = localSha384Provider.ComputeHash(fileStream);
|
||||
fileStream.Close();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>Gets the hash of a file in hexadecimal and as a byte array.</summary>
|
||||
/// <param name="filename">File path.</param>
|
||||
/// <param name="hash">Byte array of the hash value.</param>
|
||||
public static string File(string filename, out byte[] hash)
|
||||
{
|
||||
var localSha384Provider = SHA384.Create();
|
||||
var fileStream = new FileStream(filename, FileMode.Open, FileAccess.Read);
|
||||
hash = localSha384Provider.ComputeHash(fileStream);
|
||||
var sha384Output = new StringBuilder();
|
||||
|
||||
foreach(byte h in hash) sha384Output.Append(h.ToString("x2"));
|
||||
|
||||
fileStream.Close();
|
||||
|
||||
return sha384Output.ToString();
|
||||
}
|
||||
|
||||
/// <summary>Gets the hash of the specified data buffer.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
/// <param name="len">Length of the data buffer to hash.</param>
|
||||
/// <param name="hash">Byte array of the hash value.</param>
|
||||
public static string Data(byte[] data, uint len, out byte[] hash)
|
||||
{
|
||||
var localSha384Provider = SHA384.Create();
|
||||
hash = localSha384Provider.ComputeHash(data, 0, (int)len);
|
||||
var sha384Output = new StringBuilder();
|
||||
|
||||
foreach(byte h in hash) sha384Output.Append(h.ToString("x2"));
|
||||
|
||||
return sha384Output.ToString();
|
||||
}
|
||||
|
||||
/// <summary>Gets the hash of the specified data buffer.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
/// <param name="hash">Byte array of the hash value.</param>
|
||||
public static string Data(byte[] data, out byte[] hash) => Data(data, (uint)data.Length, out hash);
|
||||
}
|
||||
@@ -35,98 +35,94 @@ using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using Aaru.CommonTypes.Interfaces;
|
||||
|
||||
namespace Aaru.Checksums
|
||||
namespace Aaru.Checksums;
|
||||
|
||||
/// <summary>Wraps up .NET SHA512 implementation to a Init(), Update(), Final() context.</summary>
|
||||
public sealed class Sha512Context : IChecksum
|
||||
{
|
||||
/// <summary>Wraps up .NET SHA512 implementation to a Init(), Update(), Final() context.</summary>
|
||||
public sealed class Sha512Context : IChecksum
|
||||
readonly SHA512 _provider;
|
||||
|
||||
/// <summary>Initializes the SHA512 hash provider</summary>
|
||||
public Sha512Context() => _provider = SHA512.Create();
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Updates the hash with data.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
/// <param name="len">Length of buffer to hash.</param>
|
||||
public void Update(byte[] data, uint len) => _provider.TransformBlock(data, 0, (int)len, data, 0);
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Updates the hash with data.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
public void Update(byte[] data) => Update(data, (uint)data.Length);
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Returns a byte array of the hash value.</summary>
|
||||
public byte[] Final()
|
||||
{
|
||||
readonly SHA512 _provider;
|
||||
_provider.TransformFinalBlock(new byte[0], 0, 0);
|
||||
|
||||
/// <summary>Initializes the SHA512 hash provider</summary>
|
||||
public Sha512Context() => _provider = SHA512.Create();
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Updates the hash with data.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
/// <param name="len">Length of buffer to hash.</param>
|
||||
public void Update(byte[] data, uint len) => _provider.TransformBlock(data, 0, (int)len, data, 0);
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Updates the hash with data.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
public void Update(byte[] data) => Update(data, (uint)data.Length);
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Returns a byte array of the hash value.</summary>
|
||||
public byte[] Final()
|
||||
{
|
||||
_provider.TransformFinalBlock(new byte[0], 0, 0);
|
||||
|
||||
return _provider.Hash;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Returns a hexadecimal representation of the hash value.</summary>
|
||||
public string End()
|
||||
{
|
||||
_provider.TransformFinalBlock(new byte[0], 0, 0);
|
||||
var sha512Output = new StringBuilder();
|
||||
|
||||
foreach(byte h in _provider.Hash)
|
||||
sha512Output.Append(h.ToString("x2"));
|
||||
|
||||
return sha512Output.ToString();
|
||||
}
|
||||
|
||||
/// <summary>Gets the hash of a file</summary>
|
||||
/// <param name="filename">File path.</param>
|
||||
public static byte[] File(string filename)
|
||||
{
|
||||
var localSha512Provider = SHA512.Create();
|
||||
var fileStream = new FileStream(filename, FileMode.Open, FileAccess.Read);
|
||||
byte[] result = localSha512Provider.ComputeHash(fileStream);
|
||||
fileStream.Close();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>Gets the hash of a file in hexadecimal and as a byte array.</summary>
|
||||
/// <param name="filename">File path.</param>
|
||||
/// <param name="hash">Byte array of the hash value.</param>
|
||||
public static string File(string filename, out byte[] hash)
|
||||
{
|
||||
var localSha512Provider = SHA512.Create();
|
||||
var fileStream = new FileStream(filename, FileMode.Open, FileAccess.Read);
|
||||
hash = localSha512Provider.ComputeHash(fileStream);
|
||||
var sha512Output = new StringBuilder();
|
||||
|
||||
foreach(byte h in hash)
|
||||
sha512Output.Append(h.ToString("x2"));
|
||||
|
||||
fileStream.Close();
|
||||
|
||||
return sha512Output.ToString();
|
||||
}
|
||||
|
||||
/// <summary>Gets the hash of the specified data buffer.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
/// <param name="len">Length of the data buffer to hash.</param>
|
||||
/// <param name="hash">Byte array of the hash value.</param>
|
||||
public static string Data(byte[] data, uint len, out byte[] hash)
|
||||
{
|
||||
var localSha512Provider = SHA512.Create();
|
||||
hash = localSha512Provider.ComputeHash(data, 0, (int)len);
|
||||
var sha512Output = new StringBuilder();
|
||||
|
||||
foreach(byte h in hash)
|
||||
sha512Output.Append(h.ToString("x2"));
|
||||
|
||||
return sha512Output.ToString();
|
||||
}
|
||||
|
||||
/// <summary>Gets the hash of the specified data buffer.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
/// <param name="hash">Byte array of the hash value.</param>
|
||||
public static string Data(byte[] data, out byte[] hash) => Data(data, (uint)data.Length, out hash);
|
||||
return _provider.Hash;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Returns a hexadecimal representation of the hash value.</summary>
|
||||
public string End()
|
||||
{
|
||||
_provider.TransformFinalBlock(new byte[0], 0, 0);
|
||||
var sha512Output = new StringBuilder();
|
||||
|
||||
foreach(byte h in _provider.Hash) sha512Output.Append(h.ToString("x2"));
|
||||
|
||||
return sha512Output.ToString();
|
||||
}
|
||||
|
||||
/// <summary>Gets the hash of a file</summary>
|
||||
/// <param name="filename">File path.</param>
|
||||
public static byte[] File(string filename)
|
||||
{
|
||||
var localSha512Provider = SHA512.Create();
|
||||
var fileStream = new FileStream(filename, FileMode.Open, FileAccess.Read);
|
||||
byte[] result = localSha512Provider.ComputeHash(fileStream);
|
||||
fileStream.Close();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>Gets the hash of a file in hexadecimal and as a byte array.</summary>
|
||||
/// <param name="filename">File path.</param>
|
||||
/// <param name="hash">Byte array of the hash value.</param>
|
||||
public static string File(string filename, out byte[] hash)
|
||||
{
|
||||
var localSha512Provider = SHA512.Create();
|
||||
var fileStream = new FileStream(filename, FileMode.Open, FileAccess.Read);
|
||||
hash = localSha512Provider.ComputeHash(fileStream);
|
||||
var sha512Output = new StringBuilder();
|
||||
|
||||
foreach(byte h in hash) sha512Output.Append(h.ToString("x2"));
|
||||
|
||||
fileStream.Close();
|
||||
|
||||
return sha512Output.ToString();
|
||||
}
|
||||
|
||||
/// <summary>Gets the hash of the specified data buffer.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
/// <param name="len">Length of the data buffer to hash.</param>
|
||||
/// <param name="hash">Byte array of the hash value.</param>
|
||||
public static string Data(byte[] data, uint len, out byte[] hash)
|
||||
{
|
||||
var localSha512Provider = SHA512.Create();
|
||||
hash = localSha512Provider.ComputeHash(data, 0, (int)len);
|
||||
var sha512Output = new StringBuilder();
|
||||
|
||||
foreach(byte h in hash) sha512Output.Append(h.ToString("x2"));
|
||||
|
||||
return sha512Output.ToString();
|
||||
}
|
||||
|
||||
/// <summary>Gets the hash of the specified data buffer.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
/// <param name="hash">Byte array of the hash value.</param>
|
||||
public static string Data(byte[] data, out byte[] hash) => Data(data, (uint)data.Length, out hash);
|
||||
}
|
||||
@@ -45,283 +45,316 @@ using System.Text;
|
||||
using Aaru.CommonTypes.Interfaces;
|
||||
using RomRepoMgr.Core.Resources;
|
||||
|
||||
namespace Aaru.Checksums
|
||||
namespace Aaru.Checksums;
|
||||
|
||||
/// <summary>Implements the SpamSum fuzzy hashing algorithm.</summary>
|
||||
public sealed class SpamSumContext : IChecksum
|
||||
{
|
||||
/// <summary>Implements the SpamSum fuzzy hashing algorithm.</summary>
|
||||
public sealed class SpamSumContext : IChecksum
|
||||
const uint ROLLING_WINDOW = 7;
|
||||
const uint MIN_BLOCKSIZE = 3;
|
||||
const uint HASH_PRIME = 0x01000193;
|
||||
const uint HASH_INIT = 0x28021967;
|
||||
const uint NUM_BLOCKHASHES = 31;
|
||||
const uint SPAMSUM_LENGTH = 64;
|
||||
const uint FUZZY_MAX_RESULT = 2 * SPAMSUM_LENGTH + 20;
|
||||
|
||||
//"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
readonly byte[] _b64 =
|
||||
{
|
||||
const uint ROLLING_WINDOW = 7;
|
||||
const uint MIN_BLOCKSIZE = 3;
|
||||
const uint HASH_PRIME = 0x01000193;
|
||||
const uint HASH_INIT = 0x28021967;
|
||||
const uint NUM_BLOCKHASHES = 31;
|
||||
const uint SPAMSUM_LENGTH = 64;
|
||||
const uint FUZZY_MAX_RESULT = (2 * SPAMSUM_LENGTH) + 20;
|
||||
0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52,
|
||||
0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A,
|
||||
0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x30, 0x31,
|
||||
0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2B, 0x2F
|
||||
};
|
||||
|
||||
//"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
readonly byte[] _b64 =
|
||||
FuzzyState _self;
|
||||
|
||||
/// <summary>Initializes the SpamSum structures</summary>
|
||||
public SpamSumContext()
|
||||
{
|
||||
_self = new FuzzyState
|
||||
{
|
||||
0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52,
|
||||
0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A,
|
||||
0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x30, 0x31,
|
||||
0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2B, 0x2F
|
||||
Bh = new BlockhashContext[NUM_BLOCKHASHES]
|
||||
};
|
||||
|
||||
FuzzyState _self;
|
||||
for(var i = 0; i < NUM_BLOCKHASHES; i++) _self.Bh[i].Digest = new byte[SPAMSUM_LENGTH];
|
||||
|
||||
/// <summary>Initializes the SpamSum structures</summary>
|
||||
public SpamSumContext()
|
||||
_self.Bhstart = 0;
|
||||
_self.Bhend = 1;
|
||||
_self.Bh[0].H = HASH_INIT;
|
||||
_self.Bh[0].Halfh = HASH_INIT;
|
||||
_self.Bh[0].Digest[0] = 0;
|
||||
_self.Bh[0].Halfdigest = 0;
|
||||
_self.Bh[0].Dlen = 0;
|
||||
_self.TotalSize = 0;
|
||||
roll_init();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Updates the hash with data.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
/// <param name="len">Length of buffer to hash.</param>
|
||||
public void Update(byte[] data, uint len)
|
||||
{
|
||||
_self.TotalSize += len;
|
||||
|
||||
for(var i = 0; i < len; i++) fuzzy_engine_step(data[i]);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Updates the hash with data.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
public void Update(byte[] data) => Update(data, (uint)data.Length);
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Returns a byte array of the hash value.</summary>
|
||||
public byte[] Final() => throw new NotImplementedException(Localization.Spamsum_no_binary);
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Returns a base64 representation of the hash value.</summary>
|
||||
public string End()
|
||||
{
|
||||
FuzzyDigest(out byte[] result);
|
||||
|
||||
return CToString(result);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
void roll_init() => _self.Roll = new RollState
|
||||
{
|
||||
Window = new byte[ROLLING_WINDOW]
|
||||
};
|
||||
|
||||
/*
|
||||
* a rolling hash, based on the Adler checksum. By using a rolling hash
|
||||
* we can perform auto resynchronisation after inserts/deletes
|
||||
|
||||
* internally, h1 is the sum of the bytes in the window and h2
|
||||
* is the sum of the bytes times the index
|
||||
|
||||
* h3 is a shift/xor based rolling hash, and is mostly needed to ensure that
|
||||
* we can cope with large blocksize values
|
||||
*/
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
void roll_hash(byte c)
|
||||
{
|
||||
_self.Roll.H2 -= _self.Roll.H1;
|
||||
_self.Roll.H2 += ROLLING_WINDOW * c;
|
||||
|
||||
_self.Roll.H1 += c;
|
||||
_self.Roll.H1 -= _self.Roll.Window[_self.Roll.N % ROLLING_WINDOW];
|
||||
|
||||
_self.Roll.Window[_self.Roll.N % ROLLING_WINDOW] = c;
|
||||
_self.Roll.N++;
|
||||
|
||||
/* The original spamsum AND'ed this value with 0xFFFFFFFF which
|
||||
* in theory should have no effect. This AND has been removed
|
||||
* for performance (jk) */
|
||||
_self.Roll.H3 <<= 5;
|
||||
_self.Roll.H3 ^= c;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
uint roll_sum() => _self.Roll.H1 + _self.Roll.H2 + _self.Roll.H3;
|
||||
|
||||
/* A simple non-rolling hash, based on the FNV hash. */
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
static uint sum_hash(byte c, uint h) => h * HASH_PRIME ^ c;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
static uint SSDEEP_BS(uint index) => MIN_BLOCKSIZE << (int)index;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
void fuzzy_try_fork_blockhash()
|
||||
{
|
||||
if(_self.Bhend >= NUM_BLOCKHASHES) return;
|
||||
|
||||
if(_self.Bhend == 0) // assert
|
||||
throw new Exception(Localization.Assertion_failed);
|
||||
|
||||
uint obh = _self.Bhend - 1;
|
||||
uint nbh = _self.Bhend;
|
||||
_self.Bh[nbh].H = _self.Bh[obh].H;
|
||||
_self.Bh[nbh].Halfh = _self.Bh[obh].Halfh;
|
||||
_self.Bh[nbh].Digest[0] = 0;
|
||||
_self.Bh[nbh].Halfdigest = 0;
|
||||
_self.Bh[nbh].Dlen = 0;
|
||||
++_self.Bhend;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
void fuzzy_try_reduce_blockhash()
|
||||
{
|
||||
if(_self.Bhstart >= _self.Bhend) throw new Exception(Localization.Assertion_failed);
|
||||
|
||||
if(_self.Bhend - _self.Bhstart < 2)
|
||||
/* Need at least two working hashes. */
|
||||
return;
|
||||
|
||||
if((ulong)SSDEEP_BS(_self.Bhstart) * SPAMSUM_LENGTH >= _self.TotalSize)
|
||||
/* Initial blocksize estimate would select this or a smaller
|
||||
* blocksize. */
|
||||
return;
|
||||
|
||||
if(_self.Bh[_self.Bhstart + 1].Dlen < SPAMSUM_LENGTH / 2)
|
||||
/* Estimate adjustment would select this blocksize. */
|
||||
return;
|
||||
|
||||
/* At this point we are clearly no longer interested in the
|
||||
* start_blocksize. Get rid of it. */
|
||||
++_self.Bhstart;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
void fuzzy_engine_step(byte c)
|
||||
{
|
||||
uint i;
|
||||
/* At each character we update the rolling hash and the normal hashes.
|
||||
* When the rolling hash hits a reset value then we emit a normal hash
|
||||
* as a element of the signature and reset the normal hash. */
|
||||
roll_hash(c);
|
||||
ulong h = roll_sum();
|
||||
|
||||
for(i = _self.Bhstart; i < _self.Bhend; ++i)
|
||||
{
|
||||
_self = new FuzzyState
|
||||
_self.Bh[i].H = sum_hash(c, _self.Bh[i].H);
|
||||
_self.Bh[i].Halfh = sum_hash(c, _self.Bh[i].Halfh);
|
||||
}
|
||||
|
||||
for(i = _self.Bhstart; i < _self.Bhend; ++i)
|
||||
{
|
||||
/* With growing blocksize almost no runs fail the next test. */
|
||||
if(h % SSDEEP_BS(i) != SSDEEP_BS(i) - 1)
|
||||
/* Once this condition is false for one bs, it is
|
||||
* automatically false for all further bs. I.e. if
|
||||
* h === -1 (mod 2*bs) then h === -1 (mod bs). */
|
||||
break;
|
||||
|
||||
/* We have hit a reset point. We now emit hashes which are
|
||||
* based on all characters in the piece of the message between
|
||||
* the last reset point and this one */
|
||||
if(0 == _self.Bh[i].Dlen) fuzzy_try_fork_blockhash();
|
||||
|
||||
_self.Bh[i].Digest[_self.Bh[i].Dlen] = _b64[_self.Bh[i].H % 64];
|
||||
_self.Bh[i].Halfdigest = _b64[_self.Bh[i].Halfh % 64];
|
||||
|
||||
if(_self.Bh[i].Dlen < SPAMSUM_LENGTH - 1)
|
||||
{
|
||||
Bh = new BlockhashContext[NUM_BLOCKHASHES]
|
||||
};
|
||||
/* We can have a problem with the tail overflowing. The
|
||||
* easiest way to cope with this is to only reset the
|
||||
* normal hash if we have room for more characters in
|
||||
* our signature. This has the effect of combining the
|
||||
* last few pieces of the message into a single piece
|
||||
* */
|
||||
_self.Bh[i].Digest[++_self.Bh[i].Dlen] = 0;
|
||||
_self.Bh[i].H = HASH_INIT;
|
||||
|
||||
for(int i = 0; i < NUM_BLOCKHASHES; i++)
|
||||
_self.Bh[i].Digest = new byte[SPAMSUM_LENGTH];
|
||||
if(_self.Bh[i].Dlen >= SPAMSUM_LENGTH / 2) continue;
|
||||
|
||||
_self.Bhstart = 0;
|
||||
_self.Bhend = 1;
|
||||
_self.Bh[0].H = HASH_INIT;
|
||||
_self.Bh[0].Halfh = HASH_INIT;
|
||||
_self.Bh[0].Digest[0] = 0;
|
||||
_self.Bh[0].Halfdigest = 0;
|
||||
_self.Bh[0].Dlen = 0;
|
||||
_self.TotalSize = 0;
|
||||
roll_init();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Updates the hash with data.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
/// <param name="len">Length of buffer to hash.</param>
|
||||
public void Update(byte[] data, uint len)
|
||||
{
|
||||
_self.TotalSize += len;
|
||||
|
||||
for(int i = 0; i < len; i++)
|
||||
fuzzy_engine_step(data[i]);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Updates the hash with data.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
public void Update(byte[] data) => Update(data, (uint)data.Length);
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Returns a byte array of the hash value.</summary>
|
||||
public byte[] Final() => throw new NotImplementedException(Localization.Spamsum_no_binary);
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Returns a base64 representation of the hash value.</summary>
|
||||
public string End()
|
||||
{
|
||||
FuzzyDigest(out byte[] result);
|
||||
|
||||
return CToString(result);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
void roll_init() => _self.Roll = new RollState
|
||||
{
|
||||
Window = new byte[ROLLING_WINDOW]
|
||||
};
|
||||
|
||||
/*
|
||||
* a rolling hash, based on the Adler checksum. By using a rolling hash
|
||||
* we can perform auto resynchronisation after inserts/deletes
|
||||
|
||||
* internally, h1 is the sum of the bytes in the window and h2
|
||||
* is the sum of the bytes times the index
|
||||
|
||||
* h3 is a shift/xor based rolling hash, and is mostly needed to ensure that
|
||||
* we can cope with large blocksize values
|
||||
*/
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
void roll_hash(byte c)
|
||||
{
|
||||
_self.Roll.H2 -= _self.Roll.H1;
|
||||
_self.Roll.H2 += ROLLING_WINDOW * c;
|
||||
|
||||
_self.Roll.H1 += c;
|
||||
_self.Roll.H1 -= _self.Roll.Window[_self.Roll.N % ROLLING_WINDOW];
|
||||
|
||||
_self.Roll.Window[_self.Roll.N % ROLLING_WINDOW] = c;
|
||||
_self.Roll.N++;
|
||||
|
||||
/* The original spamsum AND'ed this value with 0xFFFFFFFF which
|
||||
* in theory should have no effect. This AND has been removed
|
||||
* for performance (jk) */
|
||||
_self.Roll.H3 <<= 5;
|
||||
_self.Roll.H3 ^= c;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
uint roll_sum() => _self.Roll.H1 + _self.Roll.H2 + _self.Roll.H3;
|
||||
|
||||
/* A simple non-rolling hash, based on the FNV hash. */
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
static uint sum_hash(byte c, uint h) => (h * HASH_PRIME) ^ c;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
static uint SSDEEP_BS(uint index) => MIN_BLOCKSIZE << (int)index;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
void fuzzy_try_fork_blockhash()
|
||||
{
|
||||
if(_self.Bhend >= NUM_BLOCKHASHES)
|
||||
return;
|
||||
|
||||
if(_self.Bhend == 0) // assert
|
||||
throw new Exception(Localization.Assertion_failed);
|
||||
|
||||
uint obh = _self.Bhend - 1;
|
||||
uint nbh = _self.Bhend;
|
||||
_self.Bh[nbh].H = _self.Bh[obh].H;
|
||||
_self.Bh[nbh].Halfh = _self.Bh[obh].Halfh;
|
||||
_self.Bh[nbh].Digest[0] = 0;
|
||||
_self.Bh[nbh].Halfdigest = 0;
|
||||
_self.Bh[nbh].Dlen = 0;
|
||||
++_self.Bhend;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
void fuzzy_try_reduce_blockhash()
|
||||
{
|
||||
if(_self.Bhstart >= _self.Bhend)
|
||||
throw new Exception(Localization.Assertion_failed);
|
||||
|
||||
if(_self.Bhend - _self.Bhstart < 2)
|
||||
/* Need at least two working hashes. */
|
||||
return;
|
||||
|
||||
if((ulong)SSDEEP_BS(_self.Bhstart) * SPAMSUM_LENGTH >= _self.TotalSize)
|
||||
/* Initial blocksize estimate would select this or a smaller
|
||||
* blocksize. */
|
||||
return;
|
||||
|
||||
if(_self.Bh[_self.Bhstart + 1].Dlen < SPAMSUM_LENGTH / 2)
|
||||
/* Estimate adjustment would select this blocksize. */
|
||||
return;
|
||||
|
||||
/* At this point we are clearly no longer interested in the
|
||||
* start_blocksize. Get rid of it. */
|
||||
++_self.Bhstart;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
void fuzzy_engine_step(byte c)
|
||||
{
|
||||
uint i;
|
||||
/* At each character we update the rolling hash and the normal hashes.
|
||||
* When the rolling hash hits a reset value then we emit a normal hash
|
||||
* as a element of the signature and reset the normal hash. */
|
||||
roll_hash(c);
|
||||
ulong h = roll_sum();
|
||||
|
||||
for(i = _self.Bhstart; i < _self.Bhend; ++i)
|
||||
{
|
||||
_self.Bh[i].H = sum_hash(c, _self.Bh[i].H);
|
||||
_self.Bh[i].Halfh = sum_hash(c, _self.Bh[i].Halfh);
|
||||
_self.Bh[i].Halfh = HASH_INIT;
|
||||
_self.Bh[i].Halfdigest = 0;
|
||||
}
|
||||
else
|
||||
fuzzy_try_reduce_blockhash();
|
||||
}
|
||||
}
|
||||
|
||||
for(i = _self.Bhstart; i < _self.Bhend; ++i)
|
||||
// CLAUNIA: Flags seems to never be used in ssdeep, so I just removed it for code simplicity
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
void FuzzyDigest(out byte[] result)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
uint bi = _self.Bhstart;
|
||||
uint h = roll_sum();
|
||||
var remain = (int)(FUZZY_MAX_RESULT - 1); /* Exclude terminating '\0'. */
|
||||
result = new byte[FUZZY_MAX_RESULT];
|
||||
|
||||
/* Verify that our elimination was not overeager. */
|
||||
if(!(bi == 0 || (ulong)SSDEEP_BS(bi) / 2 * SPAMSUM_LENGTH < _self.TotalSize))
|
||||
throw new Exception(Localization.Assertion_failed);
|
||||
|
||||
var resultOff = 0;
|
||||
|
||||
/* Initial blocksize guess. */
|
||||
while((ulong)SSDEEP_BS(bi) * SPAMSUM_LENGTH < _self.TotalSize)
|
||||
{
|
||||
++bi;
|
||||
|
||||
if(bi >= NUM_BLOCKHASHES) throw new OverflowException(Localization.Spamsum_Input_exceeds_data);
|
||||
}
|
||||
|
||||
/* Adapt blocksize guess to actual digest length. */
|
||||
while(bi >= _self.Bhend) --bi;
|
||||
|
||||
while(bi > _self.Bhstart && _self.Bh[bi].Dlen < SPAMSUM_LENGTH / 2) --bi;
|
||||
|
||||
if(bi > 0 && _self.Bh[bi].Dlen < SPAMSUM_LENGTH / 2) throw new Exception(Localization.Assertion_failed);
|
||||
|
||||
sb.AppendFormat("{0}:", SSDEEP_BS(bi));
|
||||
int i = Encoding.ASCII.GetBytes(sb.ToString()).Length;
|
||||
|
||||
if(i <= 0)
|
||||
/* Maybe snprintf has set errno here? */
|
||||
throw new OverflowException(Localization.Spamsum_Input_exceeds_data);
|
||||
|
||||
if(i >= remain) throw new Exception(Localization.Assertion_failed);
|
||||
|
||||
remain -= i;
|
||||
|
||||
Array.Copy(Encoding.ASCII.GetBytes(sb.ToString()), 0, result, 0, i);
|
||||
|
||||
resultOff = i;
|
||||
|
||||
i = (int)_self.Bh[bi].Dlen;
|
||||
|
||||
if(i > remain) throw new Exception(Localization.Assertion_failed);
|
||||
|
||||
Array.Copy(_self.Bh[bi].Digest, 0, result, resultOff, i);
|
||||
resultOff += i;
|
||||
remain -= i;
|
||||
|
||||
if(h != 0)
|
||||
{
|
||||
if(remain <= 0) throw new Exception(Localization.Assertion_failed);
|
||||
|
||||
result[resultOff] = _b64[_self.Bh[bi].H % 64];
|
||||
|
||||
if(i < 3 ||
|
||||
result[resultOff] != result[resultOff - 1] ||
|
||||
result[resultOff] != result[resultOff - 2] ||
|
||||
result[resultOff] != result[resultOff - 3])
|
||||
{
|
||||
/* With growing blocksize almost no runs fail the next test. */
|
||||
if(h % SSDEEP_BS(i) != SSDEEP_BS(i) - 1)
|
||||
/* Once this condition is false for one bs, it is
|
||||
* automatically false for all further bs. I.e. if
|
||||
* h === -1 (mod 2*bs) then h === -1 (mod bs). */
|
||||
break;
|
||||
++resultOff;
|
||||
--remain;
|
||||
}
|
||||
}
|
||||
else if(_self.Bh[bi].Digest[i] != 0)
|
||||
{
|
||||
if(remain <= 0) throw new Exception(Localization.Assertion_failed);
|
||||
|
||||
/* We have hit a reset point. We now emit hashes which are
|
||||
* based on all characters in the piece of the message between
|
||||
* the last reset point and this one */
|
||||
if(0 == _self.Bh[i].Dlen)
|
||||
fuzzy_try_fork_blockhash();
|
||||
result[resultOff] = _self.Bh[bi].Digest[i];
|
||||
|
||||
_self.Bh[i].Digest[_self.Bh[i].Dlen] = _b64[_self.Bh[i].H % 64];
|
||||
_self.Bh[i].Halfdigest = _b64[_self.Bh[i].Halfh % 64];
|
||||
|
||||
if(_self.Bh[i].Dlen < SPAMSUM_LENGTH - 1)
|
||||
{
|
||||
/* We can have a problem with the tail overflowing. The
|
||||
* easiest way to cope with this is to only reset the
|
||||
* normal hash if we have room for more characters in
|
||||
* our signature. This has the effect of combining the
|
||||
* last few pieces of the message into a single piece
|
||||
* */
|
||||
_self.Bh[i].Digest[++_self.Bh[i].Dlen] = 0;
|
||||
_self.Bh[i].H = HASH_INIT;
|
||||
|
||||
if(_self.Bh[i].Dlen >= SPAMSUM_LENGTH / 2)
|
||||
continue;
|
||||
|
||||
_self.Bh[i].Halfh = HASH_INIT;
|
||||
_self.Bh[i].Halfdigest = 0;
|
||||
}
|
||||
else
|
||||
fuzzy_try_reduce_blockhash();
|
||||
if(i < 3 ||
|
||||
result[resultOff] != result[resultOff - 1] ||
|
||||
result[resultOff] != result[resultOff - 2] ||
|
||||
result[resultOff] != result[resultOff - 3])
|
||||
{
|
||||
++resultOff;
|
||||
--remain;
|
||||
}
|
||||
}
|
||||
|
||||
// CLAUNIA: Flags seems to never be used in ssdeep, so I just removed it for code simplicity
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
void FuzzyDigest(out byte[] result)
|
||||
if(remain <= 0) throw new Exception(Localization.Assertion_failed);
|
||||
|
||||
result[resultOff++] = 0x3A; // ':'
|
||||
--remain;
|
||||
|
||||
if(bi < _self.Bhend - 1)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
uint bi = _self.Bhstart;
|
||||
uint h = roll_sum();
|
||||
int remain = (int)(FUZZY_MAX_RESULT - 1); /* Exclude terminating '\0'. */
|
||||
result = new byte[FUZZY_MAX_RESULT];
|
||||
|
||||
/* Verify that our elimination was not overeager. */
|
||||
if(!(bi == 0 || ((ulong)SSDEEP_BS(bi) / 2) * SPAMSUM_LENGTH < _self.TotalSize))
|
||||
throw new Exception(Localization.Assertion_failed);
|
||||
|
||||
int resultOff = 0;
|
||||
|
||||
/* Initial blocksize guess. */
|
||||
while((ulong)SSDEEP_BS(bi) * SPAMSUM_LENGTH < _self.TotalSize)
|
||||
{
|
||||
++bi;
|
||||
|
||||
if(bi >= NUM_BLOCKHASHES)
|
||||
throw new OverflowException(Localization.Spamsum_Input_exceeds_data);
|
||||
}
|
||||
|
||||
/* Adapt blocksize guess to actual digest length. */
|
||||
while(bi >= _self.Bhend)
|
||||
--bi;
|
||||
|
||||
while(bi > _self.Bhstart &&
|
||||
_self.Bh[bi].Dlen < SPAMSUM_LENGTH / 2)
|
||||
--bi;
|
||||
|
||||
if(bi > 0 &&
|
||||
_self.Bh[bi].Dlen < SPAMSUM_LENGTH / 2)
|
||||
throw new Exception(Localization.Assertion_failed);
|
||||
|
||||
sb.AppendFormat("{0}:", SSDEEP_BS(bi));
|
||||
int i = Encoding.ASCII.GetBytes(sb.ToString()).Length;
|
||||
|
||||
if(i <= 0)
|
||||
/* Maybe snprintf has set errno here? */
|
||||
throw new OverflowException(Localization.Spamsum_Input_exceeds_data);
|
||||
|
||||
if(i >= remain)
|
||||
throw new Exception(Localization.Assertion_failed);
|
||||
|
||||
remain -= i;
|
||||
|
||||
Array.Copy(Encoding.ASCII.GetBytes(sb.ToString()), 0, result, 0, i);
|
||||
|
||||
resultOff = i;
|
||||
|
||||
++bi;
|
||||
i = (int)_self.Bh[bi].Dlen;
|
||||
|
||||
if(i > remain)
|
||||
throw new Exception(Localization.Assertion_failed);
|
||||
if(i > remain) throw new Exception(Localization.Assertion_failed);
|
||||
|
||||
Array.Copy(_self.Bh[bi].Digest, 0, result, resultOff, i);
|
||||
resultOff += i;
|
||||
@@ -329,10 +362,10 @@ namespace Aaru.Checksums
|
||||
|
||||
if(h != 0)
|
||||
{
|
||||
if(remain <= 0)
|
||||
throw new Exception(Localization.Assertion_failed);
|
||||
if(remain <= 0) throw new Exception(Localization.Assertion_failed);
|
||||
|
||||
result[resultOff] = _b64[_self.Bh[bi].H % 64];
|
||||
h = _self.Bh[bi].Halfh;
|
||||
result[resultOff] = _b64[h % 64];
|
||||
|
||||
if(i < 3 ||
|
||||
result[resultOff] != result[resultOff - 1] ||
|
||||
@@ -343,48 +376,15 @@ namespace Aaru.Checksums
|
||||
--remain;
|
||||
}
|
||||
}
|
||||
else if(_self.Bh[bi].Digest[i] != 0)
|
||||
else
|
||||
{
|
||||
if(remain <= 0)
|
||||
throw new Exception(Localization.Assertion_failed);
|
||||
i = _self.Bh[bi].Halfdigest;
|
||||
|
||||
result[resultOff] = _self.Bh[bi].Digest[i];
|
||||
|
||||
if(i < 3 ||
|
||||
result[resultOff] != result[resultOff - 1] ||
|
||||
result[resultOff] != result[resultOff - 2] ||
|
||||
result[resultOff] != result[resultOff - 3])
|
||||
if(i != 0)
|
||||
{
|
||||
++resultOff;
|
||||
--remain;
|
||||
}
|
||||
}
|
||||
if(remain <= 0) throw new Exception(Localization.Assertion_failed);
|
||||
|
||||
if(remain <= 0)
|
||||
throw new Exception(Localization.Assertion_failed);
|
||||
|
||||
result[resultOff++] = 0x3A; // ':'
|
||||
--remain;
|
||||
|
||||
if(bi < _self.Bhend - 1)
|
||||
{
|
||||
++bi;
|
||||
i = (int)_self.Bh[bi].Dlen;
|
||||
|
||||
if(i > remain)
|
||||
throw new Exception(Localization.Assertion_failed);
|
||||
|
||||
Array.Copy(_self.Bh[bi].Digest, 0, result, resultOff, i);
|
||||
resultOff += i;
|
||||
remain -= i;
|
||||
|
||||
if(h != 0)
|
||||
{
|
||||
if(remain <= 0)
|
||||
throw new Exception(Localization.Assertion_failed);
|
||||
|
||||
h = _self.Bh[bi].Halfh;
|
||||
result[resultOff] = _b64[h % 64];
|
||||
result[resultOff] = (byte)i;
|
||||
|
||||
if(i < 3 ||
|
||||
result[resultOff] != result[resultOff - 1] ||
|
||||
@@ -395,132 +395,108 @@ namespace Aaru.Checksums
|
||||
--remain;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
i = _self.Bh[bi].Halfdigest;
|
||||
|
||||
if(i != 0)
|
||||
{
|
||||
if(remain <= 0)
|
||||
throw new Exception(Localization.Assertion_failed);
|
||||
|
||||
result[resultOff] = (byte)i;
|
||||
|
||||
if(i < 3 ||
|
||||
result[resultOff] != result[resultOff - 1] ||
|
||||
result[resultOff] != result[resultOff - 2] ||
|
||||
result[resultOff] != result[resultOff - 3])
|
||||
{
|
||||
++resultOff;
|
||||
--remain;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(h != 0)
|
||||
{
|
||||
if(_self.Bh[bi].Dlen != 0)
|
||||
throw new Exception(Localization.Assertion_failed);
|
||||
|
||||
if(remain <= 0)
|
||||
throw new Exception(Localization.Assertion_failed);
|
||||
|
||||
result[resultOff++] = _b64[_self.Bh[bi].H % 64];
|
||||
/* No need to bother with FUZZY_FLAG_ELIMSEQ, because this
|
||||
* digest has length 1. */
|
||||
--remain;
|
||||
}
|
||||
|
||||
result[resultOff] = 0;
|
||||
}
|
||||
|
||||
/// <summary>Gets the hash of a file</summary>
|
||||
/// <param name="filename">File path.</param>
|
||||
public static byte[] File(string filename) => throw new NotImplementedException(Localization.Spamsum_no_binary);
|
||||
|
||||
/// <summary>Gets the hash of a file in hexadecimal and as a byte array.</summary>
|
||||
/// <param name="filename">File path.</param>
|
||||
/// <param name="hash">Byte array of the hash value.</param>
|
||||
public static string File(string filename, out byte[] hash) =>
|
||||
throw new NotImplementedException(Localization.Not_yet_implemented);
|
||||
|
||||
/// <summary>Gets the hash of the specified data buffer.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
/// <param name="len">Length of the data buffer to hash.</param>
|
||||
/// <param name="hash">null</param>
|
||||
/// <returns>Base64 representation of SpamSum $blocksize:$hash:$hash</returns>
|
||||
public static string Data(byte[] data, uint len, out byte[] hash)
|
||||
else if(h != 0)
|
||||
{
|
||||
var fuzzyContext = new SpamSumContext();
|
||||
if(_self.Bh[bi].Dlen != 0) throw new Exception(Localization.Assertion_failed);
|
||||
|
||||
fuzzyContext.Update(data, len);
|
||||
if(remain <= 0) throw new Exception(Localization.Assertion_failed);
|
||||
|
||||
hash = null;
|
||||
|
||||
return fuzzyContext.End();
|
||||
result[resultOff++] = _b64[_self.Bh[bi].H % 64];
|
||||
/* No need to bother with FUZZY_FLAG_ELIMSEQ, because this
|
||||
* digest has length 1. */
|
||||
--remain;
|
||||
}
|
||||
|
||||
/// <summary>Gets the hash of the specified data buffer.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
/// <param name="hash">null</param>
|
||||
/// <returns>Base64 representation of SpamSum $blocksize:$hash:$hash</returns>
|
||||
public static string Data(byte[] data, out byte[] hash) => Data(data, (uint)data.Length, out hash);
|
||||
result[resultOff] = 0;
|
||||
}
|
||||
|
||||
// Converts an ASCII null-terminated string to .NET string
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
static string CToString(byte[] cString)
|
||||
/// <summary>Gets the hash of a file</summary>
|
||||
/// <param name="filename">File path.</param>
|
||||
public static byte[] File(string filename) => throw new NotImplementedException(Localization.Spamsum_no_binary);
|
||||
|
||||
/// <summary>Gets the hash of a file in hexadecimal and as a byte array.</summary>
|
||||
/// <param name="filename">File path.</param>
|
||||
/// <param name="hash">Byte array of the hash value.</param>
|
||||
public static string File(string filename, out byte[] hash) =>
|
||||
throw new NotImplementedException(Localization.Not_yet_implemented);
|
||||
|
||||
/// <summary>Gets the hash of the specified data buffer.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
/// <param name="len">Length of the data buffer to hash.</param>
|
||||
/// <param name="hash">null</param>
|
||||
/// <returns>Base64 representation of SpamSum $blocksize:$hash:$hash</returns>
|
||||
public static string Data(byte[] data, uint len, out byte[] hash)
|
||||
{
|
||||
var fuzzyContext = new SpamSumContext();
|
||||
|
||||
fuzzyContext.Update(data, len);
|
||||
|
||||
hash = null;
|
||||
|
||||
return fuzzyContext.End();
|
||||
}
|
||||
|
||||
/// <summary>Gets the hash of the specified data buffer.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
/// <param name="hash">null</param>
|
||||
/// <returns>Base64 representation of SpamSum $blocksize:$hash:$hash</returns>
|
||||
public static string Data(byte[] data, out byte[] hash) => Data(data, (uint)data.Length, out hash);
|
||||
|
||||
// Converts an ASCII null-terminated string to .NET string
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
static string CToString(byte[] cString)
|
||||
{
|
||||
var count = 0;
|
||||
|
||||
// ReSharper disable once LoopCanBeConvertedToQuery
|
||||
// LINQ is six times slower
|
||||
foreach(byte c in cString)
|
||||
{
|
||||
int count = 0;
|
||||
if(c == 0) break;
|
||||
|
||||
// ReSharper disable once LoopCanBeConvertedToQuery
|
||||
// LINQ is six times slower
|
||||
foreach(byte c in cString)
|
||||
{
|
||||
if(c == 0)
|
||||
break;
|
||||
|
||||
count++;
|
||||
}
|
||||
|
||||
return Encoding.ASCII.GetString(cString, 0, count);
|
||||
count++;
|
||||
}
|
||||
|
||||
struct RollState
|
||||
{
|
||||
public byte[] Window;
|
||||
return Encoding.ASCII.GetString(cString, 0, count);
|
||||
}
|
||||
|
||||
// ROLLING_WINDOW
|
||||
public uint H1;
|
||||
public uint H2;
|
||||
public uint H3;
|
||||
public uint N;
|
||||
}
|
||||
struct RollState
|
||||
{
|
||||
public byte[] Window;
|
||||
|
||||
/* A blockhash contains a signature state for a specific (implicit) blocksize.
|
||||
* The blocksize is given by SSDEEP_BS(index). The h and halfh members are the
|
||||
* FNV hashes, where halfh stops to be reset after digest is SPAMSUM_LENGTH/2
|
||||
* long. The halfh hash is needed be able to truncate digest for the second
|
||||
* output hash to stay compatible with ssdeep output. */
|
||||
struct BlockhashContext
|
||||
{
|
||||
public uint H;
|
||||
public uint Halfh;
|
||||
public byte[] Digest;
|
||||
// ROLLING_WINDOW
|
||||
public uint H1;
|
||||
public uint H2;
|
||||
public uint H3;
|
||||
public uint N;
|
||||
}
|
||||
|
||||
// SPAMSUM_LENGTH
|
||||
public byte Halfdigest;
|
||||
public uint Dlen;
|
||||
}
|
||||
/* A blockhash contains a signature state for a specific (implicit) blocksize.
|
||||
* The blocksize is given by SSDEEP_BS(index). The h and halfh members are the
|
||||
* FNV hashes, where halfh stops to be reset after digest is SPAMSUM_LENGTH/2
|
||||
* long. The halfh hash is needed be able to truncate digest for the second
|
||||
* output hash to stay compatible with ssdeep output. */
|
||||
struct BlockhashContext
|
||||
{
|
||||
public uint H;
|
||||
public uint Halfh;
|
||||
public byte[] Digest;
|
||||
|
||||
struct FuzzyState
|
||||
{
|
||||
public uint Bhstart;
|
||||
public uint Bhend;
|
||||
public BlockhashContext[] Bh;
|
||||
// SPAMSUM_LENGTH
|
||||
public byte Halfdigest;
|
||||
public uint Dlen;
|
||||
}
|
||||
|
||||
//NUM_BLOCKHASHES
|
||||
public ulong TotalSize;
|
||||
public RollState Roll;
|
||||
}
|
||||
struct FuzzyState
|
||||
{
|
||||
public uint Bhstart;
|
||||
public uint Bhend;
|
||||
public BlockhashContext[] Bh;
|
||||
|
||||
//NUM_BLOCKHASHES
|
||||
public ulong TotalSize;
|
||||
public RollState Roll;
|
||||
}
|
||||
}
|
||||
@@ -23,10 +23,9 @@
|
||||
// Copyright © 2020-2024 Natalia Portillo
|
||||
*******************************************************************************/
|
||||
|
||||
namespace RomRepoMgr.Core.EventArgs
|
||||
namespace RomRepoMgr.Core.EventArgs;
|
||||
|
||||
public sealed class ErrorEventArgs : System.EventArgs
|
||||
{
|
||||
public sealed class ErrorEventArgs : System.EventArgs
|
||||
{
|
||||
public string Message { get; set; }
|
||||
}
|
||||
public string Message { get; set; }
|
||||
}
|
||||
@@ -25,10 +25,9 @@
|
||||
|
||||
using RomRepoMgr.Core.Models;
|
||||
|
||||
namespace RomRepoMgr.Core.EventArgs
|
||||
namespace RomRepoMgr.Core.EventArgs;
|
||||
|
||||
public sealed class ImportedRomItemEventArgs : System.EventArgs
|
||||
{
|
||||
public sealed class ImportedRomItemEventArgs : System.EventArgs
|
||||
{
|
||||
public ImportRomItem Item { get; set; }
|
||||
}
|
||||
public ImportRomItem Item { get; set; }
|
||||
}
|
||||
@@ -23,10 +23,9 @@
|
||||
// Copyright © 2020-2024 Natalia Portillo
|
||||
*******************************************************************************/
|
||||
|
||||
namespace RomRepoMgr.Core.EventArgs
|
||||
namespace RomRepoMgr.Core.EventArgs;
|
||||
|
||||
public sealed class MessageEventArgs : System.EventArgs
|
||||
{
|
||||
public sealed class MessageEventArgs : System.EventArgs
|
||||
{
|
||||
public string Message { get; set; }
|
||||
}
|
||||
public string Message { get; set; }
|
||||
}
|
||||
@@ -23,11 +23,10 @@
|
||||
// Copyright © 2020-2024 Natalia Portillo
|
||||
*******************************************************************************/
|
||||
|
||||
namespace RomRepoMgr.Core.EventArgs
|
||||
namespace RomRepoMgr.Core.EventArgs;
|
||||
|
||||
public sealed class ProgressBoundsEventArgs : System.EventArgs
|
||||
{
|
||||
public sealed class ProgressBoundsEventArgs : System.EventArgs
|
||||
{
|
||||
public double Minimum { get; set; }
|
||||
public double Maximum { get; set; }
|
||||
}
|
||||
public double Minimum { get; set; }
|
||||
public double Maximum { get; set; }
|
||||
}
|
||||
@@ -23,10 +23,9 @@
|
||||
// Copyright © 2020-2024 Natalia Portillo
|
||||
*******************************************************************************/
|
||||
|
||||
namespace RomRepoMgr.Core.EventArgs
|
||||
namespace RomRepoMgr.Core.EventArgs;
|
||||
|
||||
public sealed class ProgressEventArgs : System.EventArgs
|
||||
{
|
||||
public sealed class ProgressEventArgs : System.EventArgs
|
||||
{
|
||||
public double Value { get; set; }
|
||||
}
|
||||
public double Value { get; set; }
|
||||
}
|
||||
@@ -25,10 +25,9 @@
|
||||
|
||||
using RomRepoMgr.Core.Models;
|
||||
|
||||
namespace RomRepoMgr.Core.EventArgs
|
||||
namespace RomRepoMgr.Core.EventArgs;
|
||||
|
||||
public sealed class RomSetEventArgs : System.EventArgs
|
||||
{
|
||||
public sealed class RomSetEventArgs : System.EventArgs
|
||||
{
|
||||
public RomSetModel RomSet { get; set; }
|
||||
}
|
||||
public RomSetModel RomSet { get; set; }
|
||||
}
|
||||
@@ -26,10 +26,9 @@
|
||||
using System.Collections.Generic;
|
||||
using RomRepoMgr.Core.Models;
|
||||
|
||||
namespace RomRepoMgr.Core.EventArgs
|
||||
namespace RomRepoMgr.Core.EventArgs;
|
||||
|
||||
public sealed class RomSetsEventArgs : System.EventArgs
|
||||
{
|
||||
public sealed class RomSetsEventArgs : System.EventArgs
|
||||
{
|
||||
public List<RomSetModel> RomSets { get; set; }
|
||||
}
|
||||
public List<RomSetModel> RomSets { get; set; }
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -34,173 +34,165 @@ using System;
|
||||
using System.IO;
|
||||
using RomRepoMgr.Core.Resources;
|
||||
|
||||
namespace RomRepoMgr.Core
|
||||
namespace RomRepoMgr.Core;
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// ForcedSeekStream allows to seek a forward-readable stream (like System.IO.Compression streams) by doing the
|
||||
/// slow and known trick of rewinding and forward reading until arriving the desired position.
|
||||
/// </summary>
|
||||
internal sealed class ForcedSeekStream<T> : Stream where T : Stream
|
||||
{
|
||||
const int BUFFER_LEN = 1048576;
|
||||
readonly string _backFile;
|
||||
readonly FileStream _backStream;
|
||||
readonly T _baseStream;
|
||||
long _streamLength;
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// ForcedSeekStream allows to seek a forward-readable stream (like System.IO.Compression streams) by doing the
|
||||
/// slow and known trick of rewinding and forward reading until arriving the desired position.
|
||||
/// </summary>
|
||||
internal sealed class ForcedSeekStream<T> : Stream where T : Stream
|
||||
/// <summary>Initializes a new instance of the <see cref="T:RomRepoMgr.Core.ForcedSeekStream`1" /> class.</summary>
|
||||
/// <param name="length">The real (uncompressed) length of the stream.</param>
|
||||
/// <param name="args">Parameters that are used to create the base stream.</param>
|
||||
public ForcedSeekStream(long length, params object[] args)
|
||||
{
|
||||
const int BUFFER_LEN = 1048576;
|
||||
readonly string _backFile;
|
||||
readonly FileStream _backStream;
|
||||
readonly T _baseStream;
|
||||
long _streamLength;
|
||||
_streamLength = length;
|
||||
_baseStream = (T)Activator.CreateInstance(typeof(T), args);
|
||||
_backFile = Path.GetTempFileName();
|
||||
_backStream = new FileStream(_backFile, FileMode.Open, FileAccess.ReadWrite, FileShare.None);
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Initializes a new instance of the <see cref="T:RomRepoMgr.Core.ForcedSeekStream`1" /> class.</summary>
|
||||
/// <param name="length">The real (uncompressed) length of the stream.</param>
|
||||
/// <param name="args">Parameters that are used to create the base stream.</param>
|
||||
public ForcedSeekStream(long length, params object[] args)
|
||||
if(length == 0) CalculateLength();
|
||||
}
|
||||
|
||||
public override bool CanRead => _baseStream.CanRead;
|
||||
|
||||
public override bool CanSeek => true;
|
||||
|
||||
public override bool CanWrite => false;
|
||||
|
||||
public override long Length => _streamLength;
|
||||
|
||||
public override long Position
|
||||
{
|
||||
get => _backStream.Position;
|
||||
|
||||
set => SetPosition(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the real (uncompressed) length of the stream. It basically reads (decompresses) the whole stream to
|
||||
/// memory discarding its contents, so it should be used as a last resort.
|
||||
/// </summary>
|
||||
/// <returns>The length.</returns>
|
||||
void CalculateLength()
|
||||
{
|
||||
int read;
|
||||
|
||||
do
|
||||
{
|
||||
_streamLength = length;
|
||||
_baseStream = (T)Activator.CreateInstance(typeof(T), args);
|
||||
_backFile = Path.GetTempFileName();
|
||||
_backStream = new FileStream(_backFile, FileMode.Open, FileAccess.ReadWrite, FileShare.None);
|
||||
var buffer = new byte[BUFFER_LEN];
|
||||
read = _baseStream.Read(buffer, 0, BUFFER_LEN);
|
||||
_backStream.Write(buffer, 0, read);
|
||||
} while(read == BUFFER_LEN);
|
||||
|
||||
if(length == 0)
|
||||
CalculateLength();
|
||||
_streamLength = _backStream.Length;
|
||||
_backStream.Position = 0;
|
||||
}
|
||||
|
||||
void SetPosition(long position)
|
||||
{
|
||||
if(position == _backStream.Position) return;
|
||||
|
||||
if(position < _backStream.Length)
|
||||
{
|
||||
_backStream.Position = position;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
public override bool CanRead => _baseStream.CanRead;
|
||||
_backStream.Position = _backStream.Length;
|
||||
long toPosition = position - _backStream.Position;
|
||||
var fullBufferReads = (int)(toPosition / BUFFER_LEN);
|
||||
var restToRead = (int)(toPosition % BUFFER_LEN);
|
||||
byte[] buffer;
|
||||
|
||||
public override bool CanSeek => true;
|
||||
|
||||
public override bool CanWrite => false;
|
||||
|
||||
public override long Length => _streamLength;
|
||||
|
||||
public override long Position
|
||||
for(var i = 0; i < fullBufferReads; i++)
|
||||
{
|
||||
get => _backStream.Position;
|
||||
|
||||
set => SetPosition(value);
|
||||
buffer = new byte[BUFFER_LEN];
|
||||
_baseStream.Read(buffer, 0, BUFFER_LEN);
|
||||
_backStream.Write(buffer, 0, BUFFER_LEN);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the real (uncompressed) length of the stream. It basically reads (decompresses) the whole stream to
|
||||
/// memory discarding its contents, so it should be used as a last resort.
|
||||
/// </summary>
|
||||
/// <returns>The length.</returns>
|
||||
void CalculateLength()
|
||||
buffer = new byte[restToRead];
|
||||
_baseStream.Read(buffer, 0, restToRead);
|
||||
_backStream.Write(buffer, 0, restToRead);
|
||||
}
|
||||
|
||||
public override void Flush()
|
||||
{
|
||||
_baseStream.Flush();
|
||||
_backStream.Flush();
|
||||
}
|
||||
|
||||
public override int Read(byte[] buffer, int offset, int count)
|
||||
{
|
||||
if(_backStream.Position + count <= _backStream.Length) return _backStream.Read(buffer, offset, count);
|
||||
|
||||
SetPosition(_backStream.Position + count);
|
||||
SetPosition(_backStream.Position - count);
|
||||
|
||||
return _backStream.Read(buffer, offset, count);
|
||||
}
|
||||
|
||||
public override int ReadByte()
|
||||
{
|
||||
if(_backStream.Position + 1 <= _backStream.Length) return _backStream.ReadByte();
|
||||
|
||||
SetPosition(_backStream.Position + 1);
|
||||
SetPosition(_backStream.Position - 1);
|
||||
|
||||
return _backStream.ReadByte();
|
||||
}
|
||||
|
||||
public override long Seek(long offset, SeekOrigin origin)
|
||||
{
|
||||
switch(origin)
|
||||
{
|
||||
int read;
|
||||
case SeekOrigin.Begin:
|
||||
if(offset < 0) throw new IOException(Localization.Cannot_seek_before_start);
|
||||
|
||||
do
|
||||
{
|
||||
byte[] buffer = new byte[BUFFER_LEN];
|
||||
read = _baseStream.Read(buffer, 0, BUFFER_LEN);
|
||||
_backStream.Write(buffer, 0, read);
|
||||
} while(read == BUFFER_LEN);
|
||||
SetPosition(offset);
|
||||
|
||||
_streamLength = _backStream.Length;
|
||||
_backStream.Position = 0;
|
||||
break;
|
||||
case SeekOrigin.End:
|
||||
if(offset > 0) throw new IOException(Localization.Cannot_seek_after_end);
|
||||
|
||||
if(_streamLength == 0) CalculateLength();
|
||||
|
||||
SetPosition(_streamLength + offset);
|
||||
|
||||
break;
|
||||
default:
|
||||
SetPosition(_backStream.Position + offset);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
void SetPosition(long position)
|
||||
{
|
||||
if(position == _backStream.Position)
|
||||
return;
|
||||
return _backStream.Position;
|
||||
}
|
||||
|
||||
if(position < _backStream.Length)
|
||||
{
|
||||
_backStream.Position = position;
|
||||
public override void SetLength(long value) => throw new NotSupportedException();
|
||||
|
||||
return;
|
||||
}
|
||||
public override void Write(byte[] buffer, int offset, int count) => throw new NotSupportedException();
|
||||
|
||||
_backStream.Position = _backStream.Length;
|
||||
long toPosition = position - _backStream.Position;
|
||||
int fullBufferReads = (int)(toPosition / BUFFER_LEN);
|
||||
int restToRead = (int)(toPosition % BUFFER_LEN);
|
||||
byte[] buffer;
|
||||
public override void Close()
|
||||
{
|
||||
_backStream?.Close();
|
||||
File.Delete(_backFile);
|
||||
}
|
||||
|
||||
for(int i = 0; i < fullBufferReads; i++)
|
||||
{
|
||||
buffer = new byte[BUFFER_LEN];
|
||||
_baseStream.Read(buffer, 0, BUFFER_LEN);
|
||||
_backStream.Write(buffer, 0, BUFFER_LEN);
|
||||
}
|
||||
|
||||
buffer = new byte[restToRead];
|
||||
_baseStream.Read(buffer, 0, restToRead);
|
||||
_backStream.Write(buffer, 0, restToRead);
|
||||
}
|
||||
|
||||
public override void Flush()
|
||||
{
|
||||
_baseStream.Flush();
|
||||
_backStream.Flush();
|
||||
}
|
||||
|
||||
public override int Read(byte[] buffer, int offset, int count)
|
||||
{
|
||||
if(_backStream.Position + count <= _backStream.Length)
|
||||
return _backStream.Read(buffer, offset, count);
|
||||
|
||||
SetPosition(_backStream.Position + count);
|
||||
SetPosition(_backStream.Position - count);
|
||||
|
||||
return _backStream.Read(buffer, offset, count);
|
||||
}
|
||||
|
||||
public override int ReadByte()
|
||||
{
|
||||
if(_backStream.Position + 1 <= _backStream.Length)
|
||||
return _backStream.ReadByte();
|
||||
|
||||
SetPosition(_backStream.Position + 1);
|
||||
SetPosition(_backStream.Position - 1);
|
||||
|
||||
return _backStream.ReadByte();
|
||||
}
|
||||
|
||||
public override long Seek(long offset, SeekOrigin origin)
|
||||
{
|
||||
switch(origin)
|
||||
{
|
||||
case SeekOrigin.Begin:
|
||||
if(offset < 0)
|
||||
throw new IOException(Localization.Cannot_seek_before_start);
|
||||
|
||||
SetPosition(offset);
|
||||
|
||||
break;
|
||||
case SeekOrigin.End:
|
||||
if(offset > 0)
|
||||
throw new IOException(Localization.Cannot_seek_after_end);
|
||||
|
||||
if(_streamLength == 0)
|
||||
CalculateLength();
|
||||
|
||||
SetPosition(_streamLength + offset);
|
||||
|
||||
break;
|
||||
default:
|
||||
SetPosition(_backStream.Position + offset);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return _backStream.Position;
|
||||
}
|
||||
|
||||
public override void SetLength(long value) => throw new NotSupportedException();
|
||||
|
||||
public override void Write(byte[] buffer, int offset, int count) => throw new NotSupportedException();
|
||||
|
||||
public override void Close()
|
||||
{
|
||||
_backStream?.Close();
|
||||
File.Delete(_backFile);
|
||||
}
|
||||
|
||||
~ForcedSeekStream()
|
||||
{
|
||||
_backStream?.Close();
|
||||
File.Delete(_backFile);
|
||||
}
|
||||
~ForcedSeekStream()
|
||||
{
|
||||
_backStream?.Close();
|
||||
File.Delete(_backFile);
|
||||
}
|
||||
}
|
||||
@@ -23,11 +23,10 @@
|
||||
// Copyright © 2020-2024 Natalia Portillo
|
||||
*******************************************************************************/
|
||||
|
||||
namespace RomRepoMgr.Core.Models
|
||||
namespace RomRepoMgr.Core.Models;
|
||||
|
||||
public sealed class AssemblyModel
|
||||
{
|
||||
public sealed class AssemblyModel
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string Version { get; set; }
|
||||
}
|
||||
public string Name { get; set; }
|
||||
public string Version { get; set; }
|
||||
}
|
||||
@@ -23,11 +23,10 @@
|
||||
// Copyright © 2020-2024 Natalia Portillo
|
||||
*******************************************************************************/
|
||||
|
||||
namespace RomRepoMgr.Core.Models
|
||||
namespace RomRepoMgr.Core.Models;
|
||||
|
||||
public sealed class ImportRomItem
|
||||
{
|
||||
public sealed class ImportRomItem
|
||||
{
|
||||
public string Filename { get; set; }
|
||||
public string Status { get; set; }
|
||||
}
|
||||
public string Filename { get; set; }
|
||||
public string Status { get; set; }
|
||||
}
|
||||
@@ -23,26 +23,25 @@
|
||||
// Copyright © 2020-2024 Natalia Portillo
|
||||
*******************************************************************************/
|
||||
|
||||
namespace RomRepoMgr.Core.Models
|
||||
namespace RomRepoMgr.Core.Models;
|
||||
|
||||
public class RomSetModel
|
||||
{
|
||||
public class RomSetModel
|
||||
{
|
||||
public string Author { get; set; }
|
||||
public string Comment { get; set; }
|
||||
public string Date { get; set; }
|
||||
public string Description { get; set; }
|
||||
public string Homepage { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string Version { get; set; }
|
||||
public string Filename { get; set; }
|
||||
public string Sha384 { get; set; }
|
||||
public long TotalMachines { get; set; }
|
||||
public long CompleteMachines { get; set; }
|
||||
public long IncompleteMachines { get; set; }
|
||||
public long TotalRoms { get; set; }
|
||||
public long HaveRoms { get; set; }
|
||||
public long MissRoms { get; set; }
|
||||
public long Id { get; set; }
|
||||
public string Category { get; set; }
|
||||
}
|
||||
public string Author { get; set; }
|
||||
public string Comment { get; set; }
|
||||
public string Date { get; set; }
|
||||
public string Description { get; set; }
|
||||
public string Homepage { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string Version { get; set; }
|
||||
public string Filename { get; set; }
|
||||
public string Sha384 { get; set; }
|
||||
public long TotalMachines { get; set; }
|
||||
public long CompleteMachines { get; set; }
|
||||
public long IncompleteMachines { get; set; }
|
||||
public long TotalRoms { get; set; }
|
||||
public long HaveRoms { get; set; }
|
||||
public long MissRoms { get; set; }
|
||||
public long Id { get; set; }
|
||||
public string Category { get; set; }
|
||||
}
|
||||
832
RomRepoMgr.Core/Resources/Localization.Designer.cs
generated
832
RomRepoMgr.Core/Resources/Localization.Designer.cs
generated
@@ -11,32 +11,46 @@ namespace RomRepoMgr.Core.Resources {
|
||||
using System;
|
||||
|
||||
|
||||
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
|
||||
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
/// <summary>
|
||||
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||
/// </summary>
|
||||
// This class was auto-generated by the StronglyTypedResourceBuilder
|
||||
// class via a tool like ResGen or Visual Studio.
|
||||
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||
// with the /str option, or rebuild your VS project.
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class Localization {
|
||||
|
||||
private static System.Resources.ResourceManager resourceMan;
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static System.Globalization.CultureInfo resourceCulture;
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal Localization() {
|
||||
}
|
||||
|
||||
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static System.Resources.ResourceManager ResourceManager {
|
||||
/// <summary>
|
||||
/// Returns the cached ResourceManager instance used by this class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if (object.Equals(null, resourceMan)) {
|
||||
System.Resources.ResourceManager temp = new System.Resources.ResourceManager("RomRepoMgr.Core.Resources.Localization", typeof(Localization).Assembly);
|
||||
if (object.ReferenceEquals(resourceMan, null)) {
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("RomRepoMgr.Core.Resources.Localization", typeof(Localization).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static System.Globalization.CultureInfo Culture {
|
||||
/// <summary>
|
||||
/// Overrides the current thread's CurrentUICulture property for all
|
||||
/// resource lookups using this strongly typed resource class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Globalization.CultureInfo Culture {
|
||||
get {
|
||||
return resourceCulture;
|
||||
}
|
||||
@@ -45,351 +59,525 @@ namespace RomRepoMgr.Core.Resources {
|
||||
}
|
||||
}
|
||||
|
||||
internal static string Base32_Not_enought_data {
|
||||
get {
|
||||
return ResourceManager.GetString("Base32_Not_enought_data", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string Base32_Invalid_format {
|
||||
get {
|
||||
return ResourceManager.GetString("Base32_Invalid_format", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string Cannot_seek_before_start {
|
||||
get {
|
||||
return ResourceManager.GetString("Cannot_seek_before_start", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string Cannot_seek_after_end {
|
||||
get {
|
||||
return ResourceManager.GetString("Cannot_seek_after_end", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string Spamsum_no_binary {
|
||||
get {
|
||||
return ResourceManager.GetString("Spamsum_no_binary", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string Assertion_failed {
|
||||
get {
|
||||
return ResourceManager.GetString("Assertion_failed", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string Spamsum_Input_exceeds_data {
|
||||
get {
|
||||
return ResourceManager.GetString("Spamsum_Input_exceeds_data", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string Not_yet_implemented {
|
||||
get {
|
||||
return ResourceManager.GetString("Not_yet_implemented", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string DatabaseFileExistsMsgBoxTitle {
|
||||
get {
|
||||
return ResourceManager.GetString("DatabaseFileExistsMsgBoxTitle", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string UnArPathNotSet {
|
||||
get {
|
||||
return ResourceManager.GetString("UnArPathNotSet", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string CannotFindUnArAtPath {
|
||||
get {
|
||||
return ResourceManager.GetString("CannotFindUnArAtPath", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string CannotFindLsAr {
|
||||
get {
|
||||
return ResourceManager.GetString("CannotFindLsAr", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string CannotRunUnAr {
|
||||
get {
|
||||
return ResourceManager.GetString("CannotRunUnAr", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string CannotRunLsAr {
|
||||
get {
|
||||
return ResourceManager.GetString("CannotRunLsAr", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string NotCorrectUnAr {
|
||||
get {
|
||||
return ResourceManager.GetString("NotCorrectUnAr", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string NotCorrectLsAr {
|
||||
get {
|
||||
return ResourceManager.GetString("NotCorrectLsAr", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string ParsinDatFile {
|
||||
get {
|
||||
return ResourceManager.GetString("ParsinDatFile", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string HashingDatFile {
|
||||
get {
|
||||
return ResourceManager.GetString("HashingDatFile", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string DatAlreadyInDatabase {
|
||||
get {
|
||||
return ResourceManager.GetString("DatAlreadyInDatabase", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Adding DAT to database....
|
||||
/// </summary>
|
||||
internal static string AddingDatToDatabase {
|
||||
get {
|
||||
return ResourceManager.GetString("AddingDatToDatabase", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string CompressingDatFile {
|
||||
get {
|
||||
return ResourceManager.GetString("CompressingDatFile", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string GettingMachineNames {
|
||||
get {
|
||||
return ResourceManager.GetString("GettingMachineNames", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string AddingMachines {
|
||||
get {
|
||||
return ResourceManager.GetString("AddingMachines", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string SavingChangesToDatabase {
|
||||
get {
|
||||
return ResourceManager.GetString("SavingChangesToDatabase", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string RetrievingRomsAndDisks {
|
||||
get {
|
||||
return ResourceManager.GetString("RetrievingRomsAndDisks", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string AddingRoms {
|
||||
get {
|
||||
return ResourceManager.GetString("AddingRoms", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string FoundRomWithoutMachine {
|
||||
get {
|
||||
return ResourceManager.GetString("FoundRomWithoutMachine", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string UnhandledException {
|
||||
get {
|
||||
return ResourceManager.GetString("UnhandledException", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string RetrievingRomSetFromDatabase {
|
||||
get {
|
||||
return ResourceManager.GetString("RetrievingRomSetFromDatabase", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string CouldNotFindRomSetInDatabase {
|
||||
get {
|
||||
return ResourceManager.GetString("CouldNotFindRomSetInDatabase", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string ExportingRoms {
|
||||
get {
|
||||
return ResourceManager.GetString("ExportingRoms", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string Finished {
|
||||
get {
|
||||
return ResourceManager.GetString("Finished", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string CannotFindZipEntryInDictionary {
|
||||
get {
|
||||
return ResourceManager.GetString("CannotFindZipEntryInDictionary", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string CannotFindHashInRepository {
|
||||
get {
|
||||
return ResourceManager.GetString("CannotFindHashInRepository", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string Compressing {
|
||||
get {
|
||||
return ResourceManager.GetString("Compressing", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string EnumeratingFiles {
|
||||
get {
|
||||
return ResourceManager.GetString("EnumeratingFiles", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string Importing {
|
||||
get {
|
||||
return ResourceManager.GetString("Importing", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string CheckingIfFIleIsAnArchive {
|
||||
get {
|
||||
return ResourceManager.GetString("CheckingIfFIleIsAnArchive", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string OK {
|
||||
get {
|
||||
return ResourceManager.GetString("OK", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string ErrorWithMessage {
|
||||
get {
|
||||
return ResourceManager.GetString("ErrorWithMessage", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string ExtractingArchive {
|
||||
get {
|
||||
return ResourceManager.GetString("ExtractingArchive", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string RemovingTemporaryPath {
|
||||
get {
|
||||
return ResourceManager.GetString("RemovingTemporaryPath", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string ExtractedContents {
|
||||
get {
|
||||
return ResourceManager.GetString("ExtractedContents", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string HashingFile {
|
||||
get {
|
||||
return ResourceManager.GetString("HashingFile", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string UnknownFile {
|
||||
get {
|
||||
return ResourceManager.GetString("UnknownFile", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string CompressingFile {
|
||||
get {
|
||||
return ResourceManager.GetString("CompressingFile", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string Finishing {
|
||||
get {
|
||||
return ResourceManager.GetString("Finishing", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string UnhandledExceptionWhenImporting {
|
||||
get {
|
||||
return ResourceManager.GetString("UnhandledExceptionWhenImporting", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Adding disks....
|
||||
/// </summary>
|
||||
internal static string AddingDisks {
|
||||
get {
|
||||
return ResourceManager.GetString("AddingDisks", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string FoundDiskWithoutMachine {
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Adding machines (games)....
|
||||
/// </summary>
|
||||
internal static string AddingMachines {
|
||||
get {
|
||||
return ResourceManager.GetString("FoundDiskWithoutMachine", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string NotAChdFile {
|
||||
get {
|
||||
return ResourceManager.GetString("NotAChdFile", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string NoChecksumsFound {
|
||||
get {
|
||||
return ResourceManager.GetString("NoChecksumsFound", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string Copying {
|
||||
get {
|
||||
return ResourceManager.GetString("Copying", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string CopyingFile {
|
||||
get {
|
||||
return ResourceManager.GetString("CopyingFile", resourceCulture);
|
||||
return ResourceManager.GetString("AddingMachines", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Adding medias....
|
||||
/// </summary>
|
||||
internal static string AddingMedias {
|
||||
get {
|
||||
return ResourceManager.GetString("AddingMedias", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Adding ROMs....
|
||||
/// </summary>
|
||||
internal static string AddingRoms {
|
||||
get {
|
||||
return ResourceManager.GetString("AddingRoms", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Assertion failed.
|
||||
/// </summary>
|
||||
internal static string Assertion_failed {
|
||||
get {
|
||||
return ResourceManager.GetString("Assertion_failed", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Specified string is not valid Base32 format because character "{0}" does not exist in Base32 alphabet.
|
||||
/// </summary>
|
||||
internal static string Base32_Invalid_format {
|
||||
get {
|
||||
return ResourceManager.GetString("Base32_Invalid_format", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Specified string is not valid Base32 format because it doesn't have enough data to construct a complete byte array.
|
||||
/// </summary>
|
||||
internal static string Base32_Not_enought_data {
|
||||
get {
|
||||
return ResourceManager.GetString("Base32_Not_enought_data", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Cannot seek after stream end..
|
||||
/// </summary>
|
||||
internal static string Cannot_seek_after_end {
|
||||
get {
|
||||
return ResourceManager.GetString("Cannot_seek_after_end", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Cannot seek before stream start..
|
||||
/// </summary>
|
||||
internal static string Cannot_seek_before_start {
|
||||
get {
|
||||
return ResourceManager.GetString("Cannot_seek_before_start", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Cannot find file with hash {0} in the repository.
|
||||
/// </summary>
|
||||
internal static string CannotFindHashInRepository {
|
||||
get {
|
||||
return ResourceManager.GetString("CannotFindHashInRepository", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Cannot find lsar executable..
|
||||
/// </summary>
|
||||
internal static string CannotFindLsAr {
|
||||
get {
|
||||
return ResourceManager.GetString("CannotFindLsAr", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Cannot find unar executable at {0}..
|
||||
/// </summary>
|
||||
internal static string CannotFindUnArAtPath {
|
||||
get {
|
||||
return ResourceManager.GetString("CannotFindUnArAtPath", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Cannot find requested zip entry in hashes dictionary.
|
||||
/// </summary>
|
||||
internal static string CannotFindZipEntryInDictionary {
|
||||
get {
|
||||
return ResourceManager.GetString("CannotFindZipEntryInDictionary", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Cannot run lsar..
|
||||
/// </summary>
|
||||
internal static string CannotRunLsAr {
|
||||
get {
|
||||
return ResourceManager.GetString("CannotRunLsAr", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Cannot run unar..
|
||||
/// </summary>
|
||||
internal static string CannotRunUnAr {
|
||||
get {
|
||||
return ResourceManager.GetString("CannotRunUnAr", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Checking if file is an archive....
|
||||
/// </summary>
|
||||
internal static string CheckingIfFIleIsAnArchive {
|
||||
get {
|
||||
return ResourceManager.GetString("CheckingIfFIleIsAnArchive", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Compressing {0}....
|
||||
/// </summary>
|
||||
internal static string Compressing {
|
||||
get {
|
||||
return ResourceManager.GetString("Compressing", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Compressing DAT file....
|
||||
/// </summary>
|
||||
internal static string CompressingDatFile {
|
||||
get {
|
||||
return ResourceManager.GetString("CompressingDatFile", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Compressing file....
|
||||
/// </summary>
|
||||
internal static string CompressingFile {
|
||||
get {
|
||||
return ResourceManager.GetString("CompressingFile", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Copying {0}....
|
||||
/// </summary>
|
||||
internal static string Copying {
|
||||
get {
|
||||
return ResourceManager.GetString("Copying", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Copying file....
|
||||
/// </summary>
|
||||
internal static string CopyingFile {
|
||||
get {
|
||||
return ResourceManager.GetString("CopyingFile", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Could not find ROM set in database..
|
||||
/// </summary>
|
||||
internal static string CouldNotFindRomSetInDatabase {
|
||||
get {
|
||||
return ResourceManager.GetString("CouldNotFindRomSetInDatabase", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to File exists.
|
||||
/// </summary>
|
||||
internal static string DatabaseFileExistsMsgBoxTitle {
|
||||
get {
|
||||
return ResourceManager.GetString("DatabaseFileExistsMsgBoxTitle", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to DAT file is already in database, not importing duplicates..
|
||||
/// </summary>
|
||||
internal static string DatAlreadyInDatabase {
|
||||
get {
|
||||
return ResourceManager.GetString("DatAlreadyInDatabase", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Imported {0} machines with {1} ROMs..
|
||||
/// </summary>
|
||||
internal static string DatImportSuccess {
|
||||
get {
|
||||
return ResourceManager.GetString("DatImportSuccess", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Enumerating files....
|
||||
/// </summary>
|
||||
internal static string EnumeratingFiles {
|
||||
get {
|
||||
return ResourceManager.GetString("EnumeratingFiles", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Error: {0}.
|
||||
/// </summary>
|
||||
internal static string ErrorWithMessage {
|
||||
get {
|
||||
return ResourceManager.GetString("ErrorWithMessage", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Exporting ROMs....
|
||||
/// </summary>
|
||||
internal static string ExportingRoms {
|
||||
get {
|
||||
return ResourceManager.GetString("ExportingRoms", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Extracted contents.
|
||||
/// </summary>
|
||||
internal static string ExtractedContents {
|
||||
get {
|
||||
return ResourceManager.GetString("ExtractedContents", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Extracting archive contents....
|
||||
/// </summary>
|
||||
internal static string ExtractingArchive {
|
||||
get {
|
||||
return ResourceManager.GetString("ExtractingArchive", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Finished.
|
||||
/// </summary>
|
||||
internal static string Finished {
|
||||
get {
|
||||
return ResourceManager.GetString("Finished", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Finishing....
|
||||
/// </summary>
|
||||
internal static string Finishing {
|
||||
get {
|
||||
return ResourceManager.GetString("Finishing", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Found a disk with an unknown machine, this should not happen..
|
||||
/// </summary>
|
||||
internal static string FoundDiskWithoutMachine {
|
||||
get {
|
||||
return ResourceManager.GetString("FoundDiskWithoutMachine", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Found media with an unknown machine, this should not happen..
|
||||
/// </summary>
|
||||
internal static string FoundMediaWithoutMachine {
|
||||
get {
|
||||
return ResourceManager.GetString("FoundMediaWithoutMachine", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Found a ROM with an unknown machine, this should not happen..
|
||||
/// </summary>
|
||||
internal static string FoundRomWithoutMachine {
|
||||
get {
|
||||
return ResourceManager.GetString("FoundRomWithoutMachine", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Getting machine (game) names....
|
||||
/// </summary>
|
||||
internal static string GettingMachineNames {
|
||||
get {
|
||||
return ResourceManager.GetString("GettingMachineNames", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Hashing DAT file....
|
||||
/// </summary>
|
||||
internal static string HashingDatFile {
|
||||
get {
|
||||
return ResourceManager.GetString("HashingDatFile", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Hashing file....
|
||||
/// </summary>
|
||||
internal static string HashingFile {
|
||||
get {
|
||||
return ResourceManager.GetString("HashingFile", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Importing {0}....
|
||||
/// </summary>
|
||||
internal static string Importing {
|
||||
get {
|
||||
return ResourceManager.GetString("Importing", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to No checksums found..
|
||||
/// </summary>
|
||||
internal static string NoChecksumsFound {
|
||||
get {
|
||||
return ResourceManager.GetString("NoChecksumsFound", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Not yet implemented..
|
||||
/// </summary>
|
||||
internal static string Not_yet_implemented {
|
||||
get {
|
||||
return ResourceManager.GetString("Not_yet_implemented", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Not a CHD file..
|
||||
/// </summary>
|
||||
internal static string NotAChdFile {
|
||||
get {
|
||||
return ResourceManager.GetString("NotAChdFile", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Not an AaruFormat file..
|
||||
/// </summary>
|
||||
internal static string NotAnAaruFormatFile {
|
||||
get {
|
||||
return ResourceManager.GetString("NotAnAaruFormatFile", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string DatImportSuccess {
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Not the correct lsar executable.
|
||||
/// </summary>
|
||||
internal static string NotCorrectLsAr {
|
||||
get {
|
||||
return ResourceManager.GetString("DatImportSuccess", resourceCulture);
|
||||
return ResourceManager.GetString("NotCorrectLsAr", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Not the correct unar executable.
|
||||
/// </summary>
|
||||
internal static string NotCorrectUnAr {
|
||||
get {
|
||||
return ResourceManager.GetString("NotCorrectUnAr", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to OK.
|
||||
/// </summary>
|
||||
internal static string OK {
|
||||
get {
|
||||
return ResourceManager.GetString("OK", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Parsing DAT file....
|
||||
/// </summary>
|
||||
internal static string ParsinDatFile {
|
||||
get {
|
||||
return ResourceManager.GetString("ParsinDatFile", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Removing temporary path....
|
||||
/// </summary>
|
||||
internal static string RemovingTemporaryPath {
|
||||
get {
|
||||
return ResourceManager.GetString("RemovingTemporaryPath", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Retrieving ROMs and disks....
|
||||
/// </summary>
|
||||
internal static string RetrievingRomsAndDisks {
|
||||
get {
|
||||
return ResourceManager.GetString("RetrievingRomsAndDisks", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Retrieving ROM set from database..
|
||||
/// </summary>
|
||||
internal static string RetrievingRomSetFromDatabase {
|
||||
get {
|
||||
return ResourceManager.GetString("RetrievingRomSetFromDatabase", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Saving changes to database....
|
||||
/// </summary>
|
||||
internal static string SavingChangesToDatabase {
|
||||
get {
|
||||
return ResourceManager.GetString("SavingChangesToDatabase", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to The input exceeds data types..
|
||||
/// </summary>
|
||||
internal static string Spamsum_Input_exceeds_data {
|
||||
get {
|
||||
return ResourceManager.GetString("Spamsum_Input_exceeds_data", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to SpamSum does not have a binary representation..
|
||||
/// </summary>
|
||||
internal static string Spamsum_no_binary {
|
||||
get {
|
||||
return ResourceManager.GetString("Spamsum_no_binary", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to unar path is not set..
|
||||
/// </summary>
|
||||
internal static string UnArPathNotSet {
|
||||
get {
|
||||
return ResourceManager.GetString("UnArPathNotSet", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Unhandled exception occurred..
|
||||
/// </summary>
|
||||
internal static string UnhandledException {
|
||||
get {
|
||||
return ResourceManager.GetString("UnhandledException", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Unhandled exception when importing file..
|
||||
/// </summary>
|
||||
internal static string UnhandledExceptionWhenImporting {
|
||||
get {
|
||||
return ResourceManager.GetString("UnhandledExceptionWhenImporting", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Unknown file..
|
||||
/// </summary>
|
||||
internal static string UnknownFile {
|
||||
get {
|
||||
return ResourceManager.GetString("UnknownFile", resourceCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,185 +1,189 @@
|
||||
<root>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>1.3</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="AddingDatToDatabase" xml:space="preserve">
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>1.3</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<data name="AddingDatToDatabase" xml:space="preserve">
|
||||
<value>Añadiendo DAT a la base de datos...</value>
|
||||
</data>
|
||||
<data name="AddingMachines" xml:space="preserve">
|
||||
<data name="AddingMachines" xml:space="preserve">
|
||||
<value>Añadiendo máquinas (juegos)...</value>
|
||||
</data>
|
||||
<data name="AddingRoms" xml:space="preserve">
|
||||
<data name="AddingRoms" xml:space="preserve">
|
||||
<value>Añadiendo ROMs...</value>
|
||||
</data>
|
||||
<data name="Assertion_failed" xml:space="preserve">
|
||||
<data name="Assertion_failed" xml:space="preserve">
|
||||
<value>Aserción fallida</value>
|
||||
</data>
|
||||
<data name="Base32_Invalid_format" xml:space="preserve">
|
||||
<data name="Base32_Invalid_format" xml:space="preserve">
|
||||
<value>El texto especificado no tiene un formato Base32 válido porque el caracter "{0}" no existe en el alfabeto Base32</value>
|
||||
</data>
|
||||
<data name="Base32_Not_enought_data" xml:space="preserve">
|
||||
<data name="Base32_Not_enought_data" xml:space="preserve">
|
||||
<value>El texto especificado no tiene un formato Base32 válido porque no tiene datos suficientes para completar una ristra de bytes</value>
|
||||
</data>
|
||||
<data name="CannotFindHashInRepository" xml:space="preserve">
|
||||
<data name="CannotFindHashInRepository" xml:space="preserve">
|
||||
<value>No se puede encontrar el archivo con hash {0} en el repositorio</value>
|
||||
</data>
|
||||
<data name="CannotFindLsAr" xml:space="preserve">
|
||||
<data name="CannotFindLsAr" xml:space="preserve">
|
||||
<value>No se puede encontrar el ejecutable lsar.</value>
|
||||
</data>
|
||||
<data name="CannotFindUnArAtPath" xml:space="preserve">
|
||||
<data name="CannotFindUnArAtPath" xml:space="preserve">
|
||||
<value>No se puede encontrar el ejecutable unar en {0}.</value>
|
||||
</data>
|
||||
<data name="CannotFindZipEntryInDictionary" xml:space="preserve">
|
||||
<data name="CannotFindZipEntryInDictionary" xml:space="preserve">
|
||||
<value>No se puede encontrar la entrada zip solicitada en el diccionari de hashes</value>
|
||||
</data>
|
||||
<data name="CannotRunLsAr" xml:space="preserve">
|
||||
<data name="CannotRunLsAr" xml:space="preserve">
|
||||
<value>No se puede ejecutar lsar.</value>
|
||||
</data>
|
||||
<data name="CannotRunUnAr" xml:space="preserve">
|
||||
<data name="CannotRunUnAr" xml:space="preserve">
|
||||
<value>No se puede ejecutar unar.</value>
|
||||
</data>
|
||||
<data name="Cannot_seek_after_end" xml:space="preserve">
|
||||
<data name="Cannot_seek_after_end" xml:space="preserve">
|
||||
<value>No se puede posicionar antes del comienzo.</value>
|
||||
</data>
|
||||
<data name="Cannot_seek_before_start" xml:space="preserve">
|
||||
<data name="Cannot_seek_before_start" xml:space="preserve">
|
||||
<value>No se puede posicionar después del comienzo.</value>
|
||||
</data>
|
||||
<data name="CheckingIfFIleIsAnArchive" xml:space="preserve">
|
||||
<data name="CheckingIfFIleIsAnArchive" xml:space="preserve">
|
||||
<value>Comprobando si el fichero es un archivo comprimido...</value>
|
||||
</data>
|
||||
<data name="Compressing" xml:space="preserve">
|
||||
<data name="Compressing" xml:space="preserve">
|
||||
<value>Comprimiendo {0}...</value>
|
||||
</data>
|
||||
<data name="CompressingDatFile" xml:space="preserve">
|
||||
<data name="CompressingDatFile" xml:space="preserve">
|
||||
<value>Comprimiendo archivo DAT...</value>
|
||||
</data>
|
||||
<data name="CompressingFile" xml:space="preserve">
|
||||
<data name="CompressingFile" xml:space="preserve">
|
||||
<value>Comprimiendo archivo...</value>
|
||||
</data>
|
||||
<data name="CouldNotFindRomSetInDatabase" xml:space="preserve">
|
||||
<data name="CouldNotFindRomSetInDatabase" xml:space="preserve">
|
||||
<value>No se pudo encontrar el set de ROMs en la base de datos.</value>
|
||||
</data>
|
||||
<data name="DatabaseFileExistsMsgBoxTitle" xml:space="preserve">
|
||||
<data name="DatabaseFileExistsMsgBoxTitle" xml:space="preserve">
|
||||
<value>El archivo existe</value>
|
||||
</data>
|
||||
<data name="DatAlreadyInDatabase" xml:space="preserve">
|
||||
<data name="DatAlreadyInDatabase" xml:space="preserve">
|
||||
<value>El archivo DAT ya está en la base de datos, no importaré duplicados.</value>
|
||||
</data>
|
||||
<data name="EnumeratingFiles" xml:space="preserve">
|
||||
<data name="EnumeratingFiles" xml:space="preserve">
|
||||
<value>Enumerando archivos...</value>
|
||||
</data>
|
||||
<data name="ErrorWithMessage" xml:space="preserve">
|
||||
<data name="ErrorWithMessage" xml:space="preserve">
|
||||
<value>Error: {0}</value>
|
||||
</data>
|
||||
<data name="ExportingRoms" xml:space="preserve">
|
||||
<data name="ExportingRoms" xml:space="preserve">
|
||||
<value>Exportando ROMs...</value>
|
||||
</data>
|
||||
<data name="ExtractedContents" xml:space="preserve">
|
||||
<data name="ExtractedContents" xml:space="preserve">
|
||||
<value>Contenidos extraídos</value>
|
||||
</data>
|
||||
<data name="ExtractingArchive" xml:space="preserve">
|
||||
<data name="ExtractingArchive" xml:space="preserve">
|
||||
<value>Extrayendo contenidos del archivo...</value>
|
||||
</data>
|
||||
<data name="Finished" xml:space="preserve">
|
||||
<data name="Finished" xml:space="preserve">
|
||||
<value>Terminado</value>
|
||||
</data>
|
||||
<data name="Finishing" xml:space="preserve">
|
||||
<data name="Finishing" xml:space="preserve">
|
||||
<value>Terminando...</value>
|
||||
</data>
|
||||
<data name="FoundRomWithoutMachine" xml:space="preserve">
|
||||
<data name="FoundRomWithoutMachine" xml:space="preserve">
|
||||
<value>Se encontró una ROM sin máquina, esto no debería pasar.</value>
|
||||
</data>
|
||||
<data name="GettingMachineNames" xml:space="preserve">
|
||||
<data name="GettingMachineNames" xml:space="preserve">
|
||||
<value>Obteniendo nombre de las máquinas (juegos)...</value>
|
||||
</data>
|
||||
<data name="HashingDatFile" xml:space="preserve">
|
||||
<data name="HashingDatFile" xml:space="preserve">
|
||||
<value>Calculando hash del archivo DAT...</value>
|
||||
</data>
|
||||
<data name="HashingFile" xml:space="preserve">
|
||||
<data name="HashingFile" xml:space="preserve">
|
||||
<value>Calculando hash del archivo...</value>
|
||||
</data>
|
||||
<data name="Importing" xml:space="preserve">
|
||||
<data name="Importing" xml:space="preserve">
|
||||
<value>Importando {0}...</value>
|
||||
</data>
|
||||
<data name="NotCorrectLsAr" xml:space="preserve">
|
||||
<data name="NotCorrectLsAr" xml:space="preserve">
|
||||
<value>No es el ejecutable correcto de lsar</value>
|
||||
</data>
|
||||
<data name="NotCorrectUnAr" xml:space="preserve">
|
||||
<data name="NotCorrectUnAr" xml:space="preserve">
|
||||
<value>No es el ejecutable corrector de unar</value>
|
||||
</data>
|
||||
<data name="Not_yet_implemented" xml:space="preserve">
|
||||
<data name="Not_yet_implemented" xml:space="preserve">
|
||||
<value>Aún no implementado.</value>
|
||||
</data>
|
||||
<data name="OK" xml:space="preserve">
|
||||
<data name="OK" xml:space="preserve">
|
||||
<value>OK</value>
|
||||
</data>
|
||||
<data name="ParsinDatFile" xml:space="preserve">
|
||||
<data name="ParsinDatFile" xml:space="preserve">
|
||||
<value>Analizando archivo DAT...</value>
|
||||
</data>
|
||||
<data name="RemovingTemporaryPath" xml:space="preserve">
|
||||
<data name="RemovingTemporaryPath" xml:space="preserve">
|
||||
<value>Eliminando ruta remporal...</value>
|
||||
</data>
|
||||
<data name="RetrievingRomsAndDisks" xml:space="preserve">
|
||||
<data name="RetrievingRomsAndDisks" xml:space="preserve">
|
||||
<value>Recuperando ROMs y discos...</value>
|
||||
</data>
|
||||
<data name="RetrievingRomSetFromDatabase" xml:space="preserve">
|
||||
<data name="RetrievingRomSetFromDatabase" xml:space="preserve">
|
||||
<value>Recuperando set de ROMs de la base de datos...</value>
|
||||
</data>
|
||||
<data name="SavingChangesToDatabase" xml:space="preserve">
|
||||
<data name="SavingChangesToDatabase" xml:space="preserve">
|
||||
<value>Guardando cambios en la base de datos...</value>
|
||||
</data>
|
||||
<data name="Spamsum_Input_exceeds_data" xml:space="preserve">
|
||||
<data name="Spamsum_Input_exceeds_data" xml:space="preserve">
|
||||
<value>La entrada excede los tipos de datos.</value>
|
||||
</data>
|
||||
<data name="Spamsum_no_binary" xml:space="preserve">
|
||||
<data name="Spamsum_no_binary" xml:space="preserve">
|
||||
<value>SpamSum no posee una representación binaria.</value>
|
||||
</data>
|
||||
<data name="UnArPathNotSet" xml:space="preserve">
|
||||
<data name="UnArPathNotSet" xml:space="preserve">
|
||||
<value>La ruta a unar no está establecida.</value>
|
||||
</data>
|
||||
<data name="UnhandledException" xml:space="preserve">
|
||||
<data name="UnhandledException" xml:space="preserve">
|
||||
<value>Ocurrió una excepción no controlada.</value>
|
||||
</data>
|
||||
<data name="UnhandledExceptionWhenImporting" xml:space="preserve">
|
||||
<data name="UnhandledExceptionWhenImporting" xml:space="preserve">
|
||||
<value>Excepción no controlada al importar archivo.</value>
|
||||
</data>
|
||||
<data name="UnknownFile" xml:space="preserve">
|
||||
<data name="UnknownFile" xml:space="preserve">
|
||||
<value>Archivo desconocido.</value>
|
||||
</data>
|
||||
<data name="AddingDisks" xml:space="preserve">
|
||||
<data name="AddingDisks" xml:space="preserve">
|
||||
<value>Añadiendo discos...</value>
|
||||
</data>
|
||||
<data name="FoundDiskWithoutMachine" xml:space="preserve">
|
||||
<data name="FoundDiskWithoutMachine" xml:space="preserve">
|
||||
<value>Se encontró un disco sin máquina, esto no debería pasar.</value>
|
||||
</data>
|
||||
<data name="NoChecksumsFound" xml:space="preserve">
|
||||
<data name="NoChecksumsFound" xml:space="preserve">
|
||||
<value>No se encontraron hashes.</value>
|
||||
</data>
|
||||
<data name="NotAChdFile" xml:space="preserve">
|
||||
<data name="NotAChdFile" xml:space="preserve">
|
||||
<value>No es un CHD.</value>
|
||||
</data>
|
||||
<data name="Copying" xml:space="preserve">
|
||||
<data name="Copying" xml:space="preserve">
|
||||
<value>Copiando {0}...</value>
|
||||
</data>
|
||||
<data name="CopyingFile" xml:space="preserve">
|
||||
<data name="CopyingFile" xml:space="preserve">
|
||||
<value>Copiando archivo...</value>
|
||||
</data>
|
||||
<data name="FoundMediaWithoutMachine" xml:space="preserve">
|
||||
<data name="FoundMediaWithoutMachine" xml:space="preserve">
|
||||
<value>Se encontró un medio sin máquina, esto no debería pasar.</value>
|
||||
</data>
|
||||
<data name="NotAnAaruFormatFile" xml:space="preserve">
|
||||
<data name="NotAnAaruFormatFile" xml:space="preserve">
|
||||
<value>No es un archivo AaruFormat.</value>
|
||||
</data>
|
||||
<data name="AddingMedias" xml:space="preserve">
|
||||
<data name="AddingMedias" xml:space="preserve">
|
||||
<value>Añadiendo medios...</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -1,193 +1,198 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
|
||||
<root>
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:element name="root" msdata:IsDataSet="true"></xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>1.3</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="Base32_Not_enought_data" xml:space="preserve">
|
||||
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" id="root"
|
||||
xmlns="">
|
||||
<xsd:element name="root" msdata:IsDataSet="true"></xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>1.3</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<data name="Base32_Not_enought_data" xml:space="preserve">
|
||||
<value>Specified string is not valid Base32 format because it doesn't have enough data to construct a complete byte array</value>
|
||||
</data>
|
||||
<data name="Base32_Invalid_format" xml:space="preserve">
|
||||
<data name="Base32_Invalid_format" xml:space="preserve">
|
||||
<value>Specified string is not valid Base32 format because character "{0}" does not exist in Base32 alphabet</value>
|
||||
</data>
|
||||
<data name="Cannot_seek_before_start" xml:space="preserve">
|
||||
<data name="Cannot_seek_before_start" xml:space="preserve">
|
||||
<value>Cannot seek before stream start.</value>
|
||||
</data>
|
||||
<data name="Cannot_seek_after_end" xml:space="preserve">
|
||||
<data name="Cannot_seek_after_end" xml:space="preserve">
|
||||
<value>Cannot seek after stream end.</value>
|
||||
</data>
|
||||
<data name="Spamsum_no_binary" xml:space="preserve">
|
||||
<data name="Spamsum_no_binary" xml:space="preserve">
|
||||
<value>SpamSum does not have a binary representation.</value>
|
||||
</data>
|
||||
<data name="Assertion_failed" xml:space="preserve">
|
||||
<data name="Assertion_failed" xml:space="preserve">
|
||||
<value>Assertion failed</value>
|
||||
</data>
|
||||
<data name="Spamsum_Input_exceeds_data" xml:space="preserve">
|
||||
<data name="Spamsum_Input_exceeds_data" xml:space="preserve">
|
||||
<value>The input exceeds data types.</value>
|
||||
</data>
|
||||
<data name="Not_yet_implemented" xml:space="preserve">
|
||||
<data name="Not_yet_implemented" xml:space="preserve">
|
||||
<value>Not yet implemented.</value>
|
||||
</data>
|
||||
<data name="DatabaseFileExistsMsgBoxTitle" xml:space="preserve">
|
||||
<data name="DatabaseFileExistsMsgBoxTitle" xml:space="preserve">
|
||||
<value>File exists</value>
|
||||
</data>
|
||||
<data name="UnArPathNotSet" xml:space="preserve">
|
||||
<data name="UnArPathNotSet" xml:space="preserve">
|
||||
<value>unar path is not set.</value>
|
||||
</data>
|
||||
<data name="CannotFindUnArAtPath" xml:space="preserve">
|
||||
<data name="CannotFindUnArAtPath" xml:space="preserve">
|
||||
<value>Cannot find unar executable at {0}.</value>
|
||||
</data>
|
||||
<data name="CannotFindLsAr" xml:space="preserve">
|
||||
<data name="CannotFindLsAr" xml:space="preserve">
|
||||
<value>Cannot find lsar executable.</value>
|
||||
</data>
|
||||
<data name="CannotRunUnAr" xml:space="preserve">
|
||||
<data name="CannotRunUnAr" xml:space="preserve">
|
||||
<value>Cannot run unar.</value>
|
||||
</data>
|
||||
<data name="CannotRunLsAr" xml:space="preserve">
|
||||
<data name="CannotRunLsAr" xml:space="preserve">
|
||||
<value>Cannot run lsar.</value>
|
||||
</data>
|
||||
<data name="NotCorrectUnAr" xml:space="preserve">
|
||||
<data name="NotCorrectUnAr" xml:space="preserve">
|
||||
<value>Not the correct unar executable</value>
|
||||
</data>
|
||||
<data name="NotCorrectLsAr" xml:space="preserve">
|
||||
<data name="NotCorrectLsAr" xml:space="preserve">
|
||||
<value>Not the correct lsar executable</value>
|
||||
</data>
|
||||
<data name="ParsinDatFile" xml:space="preserve">
|
||||
<data name="ParsinDatFile" xml:space="preserve">
|
||||
<value>Parsing DAT file...</value>
|
||||
</data>
|
||||
<data name="HashingDatFile" xml:space="preserve">
|
||||
<data name="HashingDatFile" xml:space="preserve">
|
||||
<value>Hashing DAT file...</value>
|
||||
</data>
|
||||
<data name="DatAlreadyInDatabase" xml:space="preserve">
|
||||
<data name="DatAlreadyInDatabase" xml:space="preserve">
|
||||
<value>DAT file is already in database, not importing duplicates.</value>
|
||||
</data>
|
||||
<data name="AddingDatToDatabase" xml:space="preserve">
|
||||
<data name="AddingDatToDatabase" xml:space="preserve">
|
||||
<value>Adding DAT to database...</value>
|
||||
</data>
|
||||
<data name="CompressingDatFile" xml:space="preserve">
|
||||
<data name="CompressingDatFile" xml:space="preserve">
|
||||
<value>Compressing DAT file...</value>
|
||||
</data>
|
||||
<data name="GettingMachineNames" xml:space="preserve">
|
||||
<data name="GettingMachineNames" xml:space="preserve">
|
||||
<value>Getting machine (game) names...</value>
|
||||
</data>
|
||||
<data name="AddingMachines" xml:space="preserve">
|
||||
<data name="AddingMachines" xml:space="preserve">
|
||||
<value>Adding machines (games)...</value>
|
||||
</data>
|
||||
<data name="SavingChangesToDatabase" xml:space="preserve">
|
||||
<data name="SavingChangesToDatabase" xml:space="preserve">
|
||||
<value>Saving changes to database...</value>
|
||||
</data>
|
||||
<data name="RetrievingRomsAndDisks" xml:space="preserve">
|
||||
<data name="RetrievingRomsAndDisks" xml:space="preserve">
|
||||
<value>Retrieving ROMs and disks...</value>
|
||||
</data>
|
||||
<data name="AddingRoms" xml:space="preserve">
|
||||
<data name="AddingRoms" xml:space="preserve">
|
||||
<value>Adding ROMs...</value>
|
||||
</data>
|
||||
<data name="FoundRomWithoutMachine" xml:space="preserve">
|
||||
<data name="FoundRomWithoutMachine" xml:space="preserve">
|
||||
<value>Found a ROM with an unknown machine, this should not happen.</value>
|
||||
</data>
|
||||
<data name="UnhandledException" xml:space="preserve">
|
||||
<data name="UnhandledException" xml:space="preserve">
|
||||
<value>Unhandled exception occurred.</value>
|
||||
</data>
|
||||
<data name="RetrievingRomSetFromDatabase" xml:space="preserve">
|
||||
<data name="RetrievingRomSetFromDatabase" xml:space="preserve">
|
||||
<value>Retrieving ROM set from database.</value>
|
||||
</data>
|
||||
<data name="CouldNotFindRomSetInDatabase" xml:space="preserve">
|
||||
<data name="CouldNotFindRomSetInDatabase" xml:space="preserve">
|
||||
<value>Could not find ROM set in database.</value>
|
||||
</data>
|
||||
<data name="ExportingRoms" xml:space="preserve">
|
||||
<data name="ExportingRoms" xml:space="preserve">
|
||||
<value>Exporting ROMs...</value>
|
||||
</data>
|
||||
<data name="Finished" xml:space="preserve">
|
||||
<data name="Finished" xml:space="preserve">
|
||||
<value>Finished</value>
|
||||
</data>
|
||||
<data name="CannotFindZipEntryInDictionary" xml:space="preserve">
|
||||
<data name="CannotFindZipEntryInDictionary" xml:space="preserve">
|
||||
<value>Cannot find requested zip entry in hashes dictionary</value>
|
||||
</data>
|
||||
<data name="CannotFindHashInRepository" xml:space="preserve">
|
||||
<data name="CannotFindHashInRepository" xml:space="preserve">
|
||||
<value>Cannot find file with hash {0} in the repository</value>
|
||||
</data>
|
||||
<data name="Compressing" xml:space="preserve">
|
||||
<data name="Compressing" xml:space="preserve">
|
||||
<value>Compressing {0}...</value>
|
||||
</data>
|
||||
<data name="EnumeratingFiles" xml:space="preserve">
|
||||
<data name="EnumeratingFiles" xml:space="preserve">
|
||||
<value>Enumerating files...</value>
|
||||
</data>
|
||||
<data name="Importing" xml:space="preserve">
|
||||
<data name="Importing" xml:space="preserve">
|
||||
<value>Importing {0}...</value>
|
||||
</data>
|
||||
<data name="CheckingIfFIleIsAnArchive" xml:space="preserve">
|
||||
<data name="CheckingIfFIleIsAnArchive" xml:space="preserve">
|
||||
<value>Checking if file is an archive...</value>
|
||||
</data>
|
||||
<data name="OK" xml:space="preserve">
|
||||
<data name="OK" xml:space="preserve">
|
||||
<value>OK</value>
|
||||
</data>
|
||||
<data name="ErrorWithMessage" xml:space="preserve">
|
||||
<data name="ErrorWithMessage" xml:space="preserve">
|
||||
<value>Error: {0}</value>
|
||||
</data>
|
||||
<data name="ExtractingArchive" xml:space="preserve">
|
||||
<data name="ExtractingArchive" xml:space="preserve">
|
||||
<value>Extracting archive contents...</value>
|
||||
</data>
|
||||
<data name="RemovingTemporaryPath" xml:space="preserve">
|
||||
<data name="RemovingTemporaryPath" xml:space="preserve">
|
||||
<value>Removing temporary path...</value>
|
||||
</data>
|
||||
<data name="ExtractedContents" xml:space="preserve">
|
||||
<data name="ExtractedContents" xml:space="preserve">
|
||||
<value>Extracted contents</value>
|
||||
</data>
|
||||
<data name="HashingFile" xml:space="preserve">
|
||||
<data name="HashingFile" xml:space="preserve">
|
||||
<value>Hashing file...</value>
|
||||
</data>
|
||||
<data name="UnknownFile" xml:space="preserve">
|
||||
<data name="UnknownFile" xml:space="preserve">
|
||||
<value>Unknown file.</value>
|
||||
</data>
|
||||
<data name="CompressingFile" xml:space="preserve">
|
||||
<data name="CompressingFile" xml:space="preserve">
|
||||
<value>Compressing file...</value>
|
||||
</data>
|
||||
<data name="Finishing" xml:space="preserve">
|
||||
<data name="Finishing" xml:space="preserve">
|
||||
<value>Finishing...</value>
|
||||
</data>
|
||||
<data name="UnhandledExceptionWhenImporting" xml:space="preserve">
|
||||
<data name="UnhandledExceptionWhenImporting" xml:space="preserve">
|
||||
<value>Unhandled exception when importing file.</value>
|
||||
</data>
|
||||
<data name="AddingDisks" xml:space="preserve">
|
||||
<data name="AddingDisks" xml:space="preserve">
|
||||
<value>Adding disks...</value>
|
||||
</data>
|
||||
<data name="FoundDiskWithoutMachine" xml:space="preserve">
|
||||
<data name="FoundDiskWithoutMachine" xml:space="preserve">
|
||||
<value>Found a disk with an unknown machine, this should not happen.</value>
|
||||
</data>
|
||||
<data name="NotAChdFile" xml:space="preserve">
|
||||
<data name="NotAChdFile" xml:space="preserve">
|
||||
<value>Not a CHD file.</value>
|
||||
</data>
|
||||
<data name="NoChecksumsFound" xml:space="preserve">
|
||||
<data name="NoChecksumsFound" xml:space="preserve">
|
||||
<value>No checksums found.</value>
|
||||
</data>
|
||||
<data name="Copying" xml:space="preserve">
|
||||
<data name="Copying" xml:space="preserve">
|
||||
<value>Copying {0}...</value>
|
||||
</data>
|
||||
<data name="CopyingFile" xml:space="preserve">
|
||||
<data name="CopyingFile" xml:space="preserve">
|
||||
<value>Copying file...</value>
|
||||
</data>
|
||||
<data name="AddingMedias" xml:space="preserve">
|
||||
<data name="AddingMedias" xml:space="preserve">
|
||||
<value>Adding medias...</value>
|
||||
</data>
|
||||
<data name="FoundMediaWithoutMachine" xml:space="preserve">
|
||||
<data name="FoundMediaWithoutMachine" xml:space="preserve">
|
||||
<value>Found media with an unknown machine, this should not happen.</value>
|
||||
</data>
|
||||
<data name="NotAnAaruFormatFile" xml:space="preserve">
|
||||
<data name="NotAnAaruFormatFile" xml:space="preserve">
|
||||
<value>Not an AaruFormat file.</value>
|
||||
</data>
|
||||
<data name="DatImportSuccess" xml:space="preserve">
|
||||
<data name="DatImportSuccess" xml:space="preserve">
|
||||
<value>Imported {0} machines with {1} ROMs.</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -1,39 +1,39 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<NeutralLanguage>en</NeutralLanguage>
|
||||
<LangVersion>default</LangVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<NeutralLanguage>en</NeutralLanguage>
|
||||
<LangVersion>default</LangVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="DotNetZip" Version="1.15.0" />
|
||||
<PackageReference Include="EFCore.BulkExtensions" Version="3.2.7" />
|
||||
<PackageReference Include="Mono.Fuse.NETStandard" Version="1.1.0" />
|
||||
<PackageReference Include="SharpCompress" Version="0.26.0" />
|
||||
<PackageReference Include="System.Security.Principal.Windows" Version="5.0.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="DotNetZip" Version="1.15.0"/>
|
||||
<PackageReference Include="EFCore.BulkExtensions" Version="3.2.7"/>
|
||||
<PackageReference Include="Mono.Fuse.NETStandard" Version="1.1.0"/>
|
||||
<PackageReference Include="SharpCompress" Version="0.26.0"/>
|
||||
<PackageReference Include="System.Security.Principal.Windows" Version="5.0.0"/>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\RomRepoMgr.Database\RomRepoMgr.Database.csproj" />
|
||||
<ProjectReference Include="..\RomRepoMgr.Settings\RomRepoMgr.Settings.csproj" />
|
||||
<ProjectReference Include="..\SabreTools\SabreTools.DatFiles\SabreTools.DatFiles.csproj" />
|
||||
<ProjectReference Include="..\winfsp-netcore\winfsp-netcore.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\RomRepoMgr.Database\RomRepoMgr.Database.csproj"/>
|
||||
<ProjectReference Include="..\RomRepoMgr.Settings\RomRepoMgr.Settings.csproj"/>
|
||||
<ProjectReference Include="..\SabreTools\SabreTools.DatFiles\SabreTools.DatFiles.csproj"/>
|
||||
<ProjectReference Include="..\winfsp-netcore\winfsp-netcore.csproj"/>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Update="Resources\Localization.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Localization.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Update="Resources\Localization.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Localization.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Update="Resources\Localization.Designer.cs">
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Language.resx</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Update="Resources\Localization.Designer.cs">
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Language.resx</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -1,43 +1,42 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace RomRepoMgr.Core
|
||||
namespace RomRepoMgr.Core;
|
||||
|
||||
internal sealed class StreamWithLength : Stream
|
||||
{
|
||||
internal sealed class StreamWithLength : Stream
|
||||
readonly Stream _baseStream;
|
||||
|
||||
public StreamWithLength(Stream baseStream, long length)
|
||||
{
|
||||
readonly Stream _baseStream;
|
||||
_baseStream = baseStream;
|
||||
Length = length;
|
||||
}
|
||||
|
||||
public StreamWithLength(Stream baseStream, long length)
|
||||
{
|
||||
_baseStream = baseStream;
|
||||
Length = length;
|
||||
}
|
||||
public override bool CanRead => _baseStream.CanRead;
|
||||
public override bool CanSeek => _baseStream.CanSeek;
|
||||
public override bool CanWrite => _baseStream.CanWrite;
|
||||
public override long Length { get; }
|
||||
|
||||
public override bool CanRead => _baseStream.CanRead;
|
||||
public override bool CanSeek => _baseStream.CanSeek;
|
||||
public override bool CanWrite => _baseStream.CanWrite;
|
||||
public override long Length { get; }
|
||||
public override long Position
|
||||
{
|
||||
get => throw new NotSupportedException();
|
||||
set => throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public override long Position
|
||||
{
|
||||
get => throw new NotSupportedException();
|
||||
set => throw new NotSupportedException();
|
||||
}
|
||||
public override void Flush() => _baseStream.Flush();
|
||||
|
||||
public override void Flush() => _baseStream.Flush();
|
||||
public override int Read(byte[] buffer, int offset, int count) => _baseStream.Read(buffer, offset, count);
|
||||
|
||||
public override int Read(byte[] buffer, int offset, int count) => _baseStream.Read(buffer, offset, count);
|
||||
public override long Seek(long offset, SeekOrigin origin) => throw new NotSupportedException();
|
||||
|
||||
public override long Seek(long offset, SeekOrigin origin) => throw new NotSupportedException();
|
||||
public override void SetLength(long value) => throw new NotSupportedException();
|
||||
|
||||
public override void SetLength(long value) => throw new NotSupportedException();
|
||||
public override void Write(byte[] buffer, int offset, int count) => throw new NotSupportedException();
|
||||
|
||||
public override void Write(byte[] buffer, int offset, int count) => throw new NotSupportedException();
|
||||
|
||||
public override void Close()
|
||||
{
|
||||
_baseStream.Close();
|
||||
base.Close();
|
||||
}
|
||||
public override void Close()
|
||||
{
|
||||
_baseStream.Close();
|
||||
base.Close();
|
||||
}
|
||||
}
|
||||
@@ -34,154 +34,159 @@ using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using Aaru.Checksums;
|
||||
|
||||
namespace RomRepoMgr.Core.Workers
|
||||
namespace RomRepoMgr.Core.Workers;
|
||||
|
||||
internal enum ChecksumType
|
||||
{
|
||||
internal enum ChecksumType
|
||||
Crc32,
|
||||
Md5,
|
||||
Sha1,
|
||||
Sha256,
|
||||
Sha384,
|
||||
Sha512
|
||||
}
|
||||
|
||||
internal sealed class Checksum
|
||||
{
|
||||
readonly Crc32Context _crc32Ctx;
|
||||
readonly Md5Context _md5Ctx;
|
||||
readonly Sha1Context _sha1Ctx;
|
||||
readonly Sha256Context _sha256Ctx;
|
||||
readonly Sha384Context _sha384Ctx;
|
||||
readonly Sha512Context _sha512Ctx;
|
||||
Crc32Packet _crc32Pkt;
|
||||
Thread _crc32Thread;
|
||||
Md5Packet _md5Pkt;
|
||||
Thread _md5Thread;
|
||||
Sha1Packet _sha1Pkt;
|
||||
Thread _sha1Thread;
|
||||
Sha256Packet _sha256Pkt;
|
||||
Thread _sha256Thread;
|
||||
Sha384Packet _sha384Pkt;
|
||||
Thread _sha384Thread;
|
||||
Sha512Packet _sha512Pkt;
|
||||
Thread _sha512Thread;
|
||||
|
||||
internal Checksum()
|
||||
{
|
||||
Crc32, Md5, Sha1,
|
||||
Sha256, Sha384, Sha512
|
||||
_crc32Ctx = new Crc32Context();
|
||||
_md5Ctx = new Md5Context();
|
||||
_sha1Ctx = new Sha1Context();
|
||||
_sha256Ctx = new Sha256Context();
|
||||
_sha384Ctx = new Sha384Context();
|
||||
_sha512Ctx = new Sha512Context();
|
||||
|
||||
_crc32Thread = new Thread(UpdateCrc32);
|
||||
_md5Thread = new Thread(UpdateMd5);
|
||||
_sha1Thread = new Thread(UpdateSha1);
|
||||
_sha256Thread = new Thread(UpdateSha256);
|
||||
_sha384Thread = new Thread(UpdateSha384);
|
||||
_sha512Thread = new Thread(UpdateSha512);
|
||||
|
||||
_crc32Pkt = new Crc32Packet();
|
||||
_md5Pkt = new Md5Packet();
|
||||
_sha1Pkt = new Sha1Packet();
|
||||
_sha256Pkt = new Sha256Packet();
|
||||
_sha384Pkt = new Sha384Packet();
|
||||
_sha512Pkt = new Sha512Packet();
|
||||
|
||||
_crc32Pkt.context = _crc32Ctx;
|
||||
_md5Pkt.context = _md5Ctx;
|
||||
_sha1Pkt.context = _sha1Ctx;
|
||||
_sha256Pkt.context = _sha256Ctx;
|
||||
_sha384Pkt.context = _sha384Ctx;
|
||||
_sha512Pkt.context = _sha512Ctx;
|
||||
}
|
||||
|
||||
internal sealed class Checksum
|
||||
internal void Update(byte[] data)
|
||||
{
|
||||
readonly Crc32Context _crc32Ctx;
|
||||
readonly Md5Context _md5Ctx;
|
||||
readonly Sha1Context _sha1Ctx;
|
||||
readonly Sha256Context _sha256Ctx;
|
||||
readonly Sha384Context _sha384Ctx;
|
||||
readonly Sha512Context _sha512Ctx;
|
||||
Crc32Packet _crc32Pkt;
|
||||
Thread _crc32Thread;
|
||||
Md5Packet _md5Pkt;
|
||||
Thread _md5Thread;
|
||||
Sha1Packet _sha1Pkt;
|
||||
Thread _sha1Thread;
|
||||
Sha256Packet _sha256Pkt;
|
||||
Thread _sha256Thread;
|
||||
Sha384Packet _sha384Pkt;
|
||||
Thread _sha384Thread;
|
||||
Sha512Packet _sha512Pkt;
|
||||
Thread _sha512Thread;
|
||||
_crc32Pkt.data = data;
|
||||
_crc32Thread.Start(_crc32Pkt);
|
||||
_md5Pkt.data = data;
|
||||
_md5Thread.Start(_md5Pkt);
|
||||
_sha1Pkt.data = data;
|
||||
_sha1Thread.Start(_sha1Pkt);
|
||||
_sha256Pkt.data = data;
|
||||
_sha256Thread.Start(_sha256Pkt);
|
||||
_sha384Pkt.data = data;
|
||||
_sha384Thread.Start(_sha384Pkt);
|
||||
_sha512Pkt.data = data;
|
||||
_sha512Thread.Start(_sha512Pkt);
|
||||
|
||||
internal Checksum()
|
||||
{
|
||||
_crc32Ctx = new Crc32Context();
|
||||
_md5Ctx = new Md5Context();
|
||||
_sha1Ctx = new Sha1Context();
|
||||
_sha256Ctx = new Sha256Context();
|
||||
_sha384Ctx = new Sha384Context();
|
||||
_sha512Ctx = new Sha512Context();
|
||||
while(_crc32Thread.IsAlive ||
|
||||
_md5Thread.IsAlive ||
|
||||
_sha1Thread.IsAlive ||
|
||||
_sha256Thread.IsAlive ||
|
||||
_sha384Thread.IsAlive ||
|
||||
_sha512Thread.IsAlive) {}
|
||||
|
||||
_crc32Thread = new Thread(UpdateCrc32);
|
||||
_md5Thread = new Thread(UpdateMd5);
|
||||
_sha1Thread = new Thread(UpdateSha1);
|
||||
_sha256Thread = new Thread(UpdateSha256);
|
||||
_sha384Thread = new Thread(UpdateSha384);
|
||||
_sha512Thread = new Thread(UpdateSha512);
|
||||
|
||||
_crc32Pkt = new Crc32Packet();
|
||||
_md5Pkt = new Md5Packet();
|
||||
_sha1Pkt = new Sha1Packet();
|
||||
_sha256Pkt = new Sha256Packet();
|
||||
_sha384Pkt = new Sha384Packet();
|
||||
_sha512Pkt = new Sha512Packet();
|
||||
|
||||
_crc32Pkt.context = _crc32Ctx;
|
||||
_md5Pkt.context = _md5Ctx;
|
||||
_sha1Pkt.context = _sha1Ctx;
|
||||
_sha256Pkt.context = _sha256Ctx;
|
||||
_sha384Pkt.context = _sha384Ctx;
|
||||
_sha512Pkt.context = _sha512Ctx;
|
||||
}
|
||||
|
||||
internal void Update(byte[] data)
|
||||
{
|
||||
_crc32Pkt.data = data;
|
||||
_crc32Thread.Start(_crc32Pkt);
|
||||
_md5Pkt.data = data;
|
||||
_md5Thread.Start(_md5Pkt);
|
||||
_sha1Pkt.data = data;
|
||||
_sha1Thread.Start(_sha1Pkt);
|
||||
_sha256Pkt.data = data;
|
||||
_sha256Thread.Start(_sha256Pkt);
|
||||
_sha384Pkt.data = data;
|
||||
_sha384Thread.Start(_sha384Pkt);
|
||||
_sha512Pkt.data = data;
|
||||
_sha512Thread.Start(_sha512Pkt);
|
||||
|
||||
while(_crc32Thread.IsAlive ||
|
||||
_md5Thread.IsAlive ||
|
||||
_sha1Thread.IsAlive ||
|
||||
_sha256Thread.IsAlive ||
|
||||
_sha384Thread.IsAlive ||
|
||||
_sha512Thread.IsAlive) {}
|
||||
|
||||
_crc32Thread = new Thread(UpdateCrc32);
|
||||
_md5Thread = new Thread(UpdateMd5);
|
||||
_sha1Thread = new Thread(UpdateSha1);
|
||||
_sha256Thread = new Thread(UpdateSha256);
|
||||
_sha384Thread = new Thread(UpdateSha384);
|
||||
_sha512Thread = new Thread(UpdateSha512);
|
||||
}
|
||||
|
||||
internal Dictionary<ChecksumType, string> End() => new Dictionary<ChecksumType, string>
|
||||
{
|
||||
[ChecksumType.Crc32] = _crc32Ctx.End(),
|
||||
[ChecksumType.Md5] = _md5Ctx.End(),
|
||||
[ChecksumType.Sha1] = _sha1Ctx.End(),
|
||||
[ChecksumType.Sha256] = _sha256Ctx.End(),
|
||||
[ChecksumType.Sha384] = _sha384Ctx.End(),
|
||||
[ChecksumType.Sha512] = _sha512Ctx.End()
|
||||
};
|
||||
|
||||
#region Threading helpers
|
||||
struct Crc32Packet
|
||||
{
|
||||
public Crc32Context context;
|
||||
public byte[] data;
|
||||
}
|
||||
|
||||
struct Md5Packet
|
||||
{
|
||||
public Md5Context context;
|
||||
public byte[] data;
|
||||
}
|
||||
|
||||
struct Sha1Packet
|
||||
{
|
||||
public Sha1Context context;
|
||||
public byte[] data;
|
||||
}
|
||||
|
||||
struct Sha256Packet
|
||||
{
|
||||
public Sha256Context context;
|
||||
public byte[] data;
|
||||
}
|
||||
|
||||
struct Sha384Packet
|
||||
{
|
||||
public Sha384Context context;
|
||||
public byte[] data;
|
||||
}
|
||||
|
||||
struct Sha512Packet
|
||||
{
|
||||
public Sha512Context context;
|
||||
public byte[] data;
|
||||
}
|
||||
|
||||
static void UpdateCrc32(object packet) => ((Crc32Packet)packet).context.Update(((Crc32Packet)packet).data);
|
||||
|
||||
static void UpdateMd5(object packet) => ((Md5Packet)packet).context.Update(((Md5Packet)packet).data);
|
||||
|
||||
static void UpdateSha1(object packet) => ((Sha1Packet)packet).context.Update(((Sha1Packet)packet).data);
|
||||
|
||||
static void UpdateSha256(object packet) => ((Sha256Packet)packet).context.Update(((Sha256Packet)packet).data);
|
||||
|
||||
static void UpdateSha384(object packet) => ((Sha384Packet)packet).context.Update(((Sha384Packet)packet).data);
|
||||
|
||||
static void UpdateSha512(object packet) => ((Sha512Packet)packet).context.Update(((Sha512Packet)packet).data);
|
||||
#endregion Threading helpers
|
||||
_crc32Thread = new Thread(UpdateCrc32);
|
||||
_md5Thread = new Thread(UpdateMd5);
|
||||
_sha1Thread = new Thread(UpdateSha1);
|
||||
_sha256Thread = new Thread(UpdateSha256);
|
||||
_sha384Thread = new Thread(UpdateSha384);
|
||||
_sha512Thread = new Thread(UpdateSha512);
|
||||
}
|
||||
|
||||
internal Dictionary<ChecksumType, string> End() => new()
|
||||
{
|
||||
[ChecksumType.Crc32] = _crc32Ctx.End(),
|
||||
[ChecksumType.Md5] = _md5Ctx.End(),
|
||||
[ChecksumType.Sha1] = _sha1Ctx.End(),
|
||||
[ChecksumType.Sha256] = _sha256Ctx.End(),
|
||||
[ChecksumType.Sha384] = _sha384Ctx.End(),
|
||||
[ChecksumType.Sha512] = _sha512Ctx.End()
|
||||
};
|
||||
|
||||
#region Threading helpers
|
||||
|
||||
struct Crc32Packet
|
||||
{
|
||||
public Crc32Context context;
|
||||
public byte[] data;
|
||||
}
|
||||
|
||||
struct Md5Packet
|
||||
{
|
||||
public Md5Context context;
|
||||
public byte[] data;
|
||||
}
|
||||
|
||||
struct Sha1Packet
|
||||
{
|
||||
public Sha1Context context;
|
||||
public byte[] data;
|
||||
}
|
||||
|
||||
struct Sha256Packet
|
||||
{
|
||||
public Sha256Context context;
|
||||
public byte[] data;
|
||||
}
|
||||
|
||||
struct Sha384Packet
|
||||
{
|
||||
public Sha384Context context;
|
||||
public byte[] data;
|
||||
}
|
||||
|
||||
struct Sha512Packet
|
||||
{
|
||||
public Sha512Context context;
|
||||
public byte[] data;
|
||||
}
|
||||
|
||||
static void UpdateCrc32(object packet) => ((Crc32Packet)packet).context.Update(((Crc32Packet)packet).data);
|
||||
|
||||
static void UpdateMd5(object packet) => ((Md5Packet)packet).context.Update(((Md5Packet)packet).data);
|
||||
|
||||
static void UpdateSha1(object packet) => ((Sha1Packet)packet).context.Update(((Sha1Packet)packet).data);
|
||||
|
||||
static void UpdateSha256(object packet) => ((Sha256Packet)packet).context.Update(((Sha256Packet)packet).data);
|
||||
|
||||
static void UpdateSha384(object packet) => ((Sha384Packet)packet).context.Update(((Sha384Packet)packet).data);
|
||||
|
||||
static void UpdateSha512(object packet) => ((Sha512Packet)packet).context.Update(((Sha512Packet)packet).data);
|
||||
|
||||
#endregion Threading helpers
|
||||
}
|
||||
@@ -32,207 +32,217 @@ using SharpCompress.Compressors;
|
||||
using SharpCompress.Compressors.LZMA;
|
||||
using ErrorEventArgs = RomRepoMgr.Core.EventArgs.ErrorEventArgs;
|
||||
|
||||
namespace RomRepoMgr.Core.Workers
|
||||
namespace RomRepoMgr.Core.Workers;
|
||||
|
||||
public sealed class Compression
|
||||
{
|
||||
public sealed class Compression
|
||||
const long BUFFER_SIZE = 131072;
|
||||
|
||||
public event EventHandler<ProgressBoundsEventArgs> SetProgressBounds;
|
||||
public event EventHandler<ProgressEventArgs> SetProgress;
|
||||
public event EventHandler<MessageEventArgs> FinishedWithText;
|
||||
public event EventHandler<ErrorEventArgs> FailedWithText;
|
||||
|
||||
public void CompressFile(string source, string destination)
|
||||
{
|
||||
const long BUFFER_SIZE = 131072;
|
||||
var inFs = new FileStream(source, FileMode.Open, FileAccess.Read);
|
||||
var outFs = new FileStream(destination, FileMode.CreateNew, FileAccess.Write);
|
||||
Stream zStream = new LZipStream(outFs, CompressionMode.Compress);
|
||||
|
||||
public event EventHandler<ProgressBoundsEventArgs> SetProgressBounds;
|
||||
public event EventHandler<ProgressEventArgs> SetProgress;
|
||||
public event EventHandler<MessageEventArgs> FinishedWithText;
|
||||
public event EventHandler<ErrorEventArgs> FailedWithText;
|
||||
var buffer = new byte[BUFFER_SIZE];
|
||||
|
||||
public void CompressFile(string source, string destination)
|
||||
SetProgressBounds?.Invoke(this,
|
||||
new ProgressBoundsEventArgs
|
||||
{
|
||||
Minimum = 0,
|
||||
Maximum = inFs.Length
|
||||
});
|
||||
|
||||
while(inFs.Position + BUFFER_SIZE <= inFs.Length)
|
||||
{
|
||||
var inFs = new FileStream(source, FileMode.Open, FileAccess.Read);
|
||||
var outFs = new FileStream(destination, FileMode.CreateNew, FileAccess.Write);
|
||||
Stream zStream = new LZipStream(outFs, CompressionMode.Compress);
|
||||
|
||||
byte[] buffer = new byte[BUFFER_SIZE];
|
||||
|
||||
SetProgressBounds?.Invoke(this, new ProgressBoundsEventArgs
|
||||
{
|
||||
Minimum = 0,
|
||||
Maximum = inFs.Length
|
||||
});
|
||||
|
||||
while(inFs.Position + BUFFER_SIZE <= inFs.Length)
|
||||
{
|
||||
SetProgress?.Invoke(this, new ProgressEventArgs
|
||||
{
|
||||
Value = inFs.Position
|
||||
});
|
||||
|
||||
inFs.Read(buffer, 0, buffer.Length);
|
||||
zStream.Write(buffer, 0, buffer.Length);
|
||||
}
|
||||
|
||||
buffer = new byte[inFs.Length - inFs.Position];
|
||||
|
||||
SetProgressBounds?.Invoke(this, new ProgressBoundsEventArgs
|
||||
{
|
||||
Minimum = 0,
|
||||
Maximum = inFs.Length
|
||||
});
|
||||
SetProgress?.Invoke(this,
|
||||
new ProgressEventArgs
|
||||
{
|
||||
Value = inFs.Position
|
||||
});
|
||||
|
||||
inFs.Read(buffer, 0, buffer.Length);
|
||||
zStream.Write(buffer, 0, buffer.Length);
|
||||
|
||||
inFs.Close();
|
||||
zStream.Close();
|
||||
outFs.Dispose();
|
||||
}
|
||||
|
||||
public void DecompressFile(string source, string destination)
|
||||
buffer = new byte[inFs.Length - inFs.Position];
|
||||
|
||||
SetProgressBounds?.Invoke(this,
|
||||
new ProgressBoundsEventArgs
|
||||
{
|
||||
Minimum = 0,
|
||||
Maximum = inFs.Length
|
||||
});
|
||||
|
||||
inFs.Read(buffer, 0, buffer.Length);
|
||||
zStream.Write(buffer, 0, buffer.Length);
|
||||
|
||||
inFs.Close();
|
||||
zStream.Close();
|
||||
outFs.Dispose();
|
||||
}
|
||||
|
||||
public void DecompressFile(string source, string destination)
|
||||
{
|
||||
var inFs = new FileStream(source, FileMode.Open, FileAccess.Read);
|
||||
var outFs = new FileStream(destination, FileMode.Create, FileAccess.Write);
|
||||
Stream zStream = new LZipStream(inFs, CompressionMode.Decompress);
|
||||
|
||||
zStream.CopyTo(outFs);
|
||||
|
||||
outFs.Close();
|
||||
zStream.Close();
|
||||
inFs.Close();
|
||||
}
|
||||
|
||||
public bool CheckUnAr(string unArPath)
|
||||
{
|
||||
if(string.IsNullOrWhiteSpace(unArPath))
|
||||
{
|
||||
var inFs = new FileStream(source, FileMode.Open, FileAccess.Read);
|
||||
var outFs = new FileStream(destination, FileMode.Create, FileAccess.Write);
|
||||
Stream zStream = new LZipStream(inFs, CompressionMode.Decompress);
|
||||
FailedWithText?.Invoke(this,
|
||||
new ErrorEventArgs
|
||||
{
|
||||
Message = Localization.UnArPathNotSet
|
||||
});
|
||||
|
||||
zStream.CopyTo(outFs);
|
||||
|
||||
outFs.Close();
|
||||
zStream.Close();
|
||||
inFs.Close();
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool CheckUnAr(string unArPath)
|
||||
string unarFolder = Path.GetDirectoryName(unArPath);
|
||||
string extension = Path.GetExtension(unArPath);
|
||||
string unarfilename = Path.GetFileNameWithoutExtension(unArPath);
|
||||
string lsarfilename = unarfilename.Replace("unar", "lsar");
|
||||
string unarPath = Path.Combine(unarFolder, unarfilename + extension);
|
||||
string lsarPath = Path.Combine(unarFolder, lsarfilename + extension);
|
||||
|
||||
if(!File.Exists(unarPath))
|
||||
{
|
||||
if(string.IsNullOrWhiteSpace(unArPath))
|
||||
{
|
||||
FailedWithText?.Invoke(this, new ErrorEventArgs
|
||||
{
|
||||
Message = Localization.UnArPathNotSet
|
||||
});
|
||||
FailedWithText?.Invoke(this,
|
||||
new ErrorEventArgs
|
||||
{
|
||||
Message = string.Format(Localization.CannotFindUnArAtPath, unarPath)
|
||||
});
|
||||
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
string unarFolder = Path.GetDirectoryName(unArPath);
|
||||
string extension = Path.GetExtension(unArPath);
|
||||
string unarfilename = Path.GetFileNameWithoutExtension(unArPath);
|
||||
string lsarfilename = unarfilename.Replace("unar", "lsar");
|
||||
string unarPath = Path.Combine(unarFolder, unarfilename + extension);
|
||||
string lsarPath = Path.Combine(unarFolder, lsarfilename + extension);
|
||||
if(!File.Exists(lsarPath))
|
||||
{
|
||||
FailedWithText?.Invoke(this,
|
||||
new ErrorEventArgs
|
||||
{
|
||||
Message = Localization.CannotFindLsAr
|
||||
});
|
||||
|
||||
if(!File.Exists(unarPath))
|
||||
{
|
||||
FailedWithText?.Invoke(this, new ErrorEventArgs
|
||||
{
|
||||
Message = string.Format(Localization.CannotFindUnArAtPath, unarPath)
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
string unarOut, lsarOut;
|
||||
|
||||
if(!File.Exists(lsarPath))
|
||||
{
|
||||
FailedWithText?.Invoke(this, new ErrorEventArgs
|
||||
{
|
||||
Message = Localization.CannotFindLsAr
|
||||
});
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
string unarOut, lsarOut;
|
||||
|
||||
try
|
||||
{
|
||||
var unarProcess = new Process
|
||||
{
|
||||
StartInfo =
|
||||
{
|
||||
FileName = unarPath,
|
||||
CreateNoWindow = true,
|
||||
RedirectStandardOutput = true,
|
||||
UseShellExecute = false
|
||||
}
|
||||
};
|
||||
|
||||
unarProcess.Start();
|
||||
unarProcess.WaitForExit();
|
||||
unarOut = unarProcess.StandardOutput.ReadToEnd();
|
||||
}
|
||||
catch
|
||||
{
|
||||
FailedWithText?.Invoke(this, new ErrorEventArgs
|
||||
{
|
||||
Message = Localization.CannotRunUnAr
|
||||
});
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var lsarProcess = new Process
|
||||
{
|
||||
StartInfo =
|
||||
{
|
||||
FileName = lsarPath,
|
||||
CreateNoWindow = true,
|
||||
RedirectStandardOutput = true,
|
||||
UseShellExecute = false
|
||||
}
|
||||
};
|
||||
|
||||
lsarProcess.Start();
|
||||
lsarProcess.WaitForExit();
|
||||
lsarOut = lsarProcess.StandardOutput.ReadToEnd();
|
||||
}
|
||||
catch
|
||||
{
|
||||
FailedWithText?.Invoke(this, new ErrorEventArgs
|
||||
{
|
||||
Message = Localization.CannotRunLsAr
|
||||
});
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!unarOut.StartsWith("unar ", StringComparison.CurrentCulture))
|
||||
{
|
||||
FailedWithText?.Invoke(this, new ErrorEventArgs
|
||||
{
|
||||
Message = Localization.NotCorrectUnAr
|
||||
});
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!lsarOut.StartsWith("lsar ", StringComparison.CurrentCulture))
|
||||
{
|
||||
FailedWithText?.Invoke(this, new ErrorEventArgs
|
||||
{
|
||||
Message = Localization.NotCorrectLsAr
|
||||
});
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
var versionProcess = new Process
|
||||
try
|
||||
{
|
||||
var unarProcess = new Process
|
||||
{
|
||||
StartInfo =
|
||||
{
|
||||
FileName = unarPath,
|
||||
CreateNoWindow = true,
|
||||
RedirectStandardOutput = true,
|
||||
UseShellExecute = false,
|
||||
Arguments = "-v"
|
||||
UseShellExecute = false
|
||||
}
|
||||
};
|
||||
|
||||
versionProcess.Start();
|
||||
versionProcess.WaitForExit();
|
||||
|
||||
FinishedWithText?.Invoke(this, new MessageEventArgs
|
||||
{
|
||||
Message = versionProcess.StandardOutput.ReadToEnd().TrimEnd('\n')
|
||||
});
|
||||
|
||||
return true;
|
||||
unarProcess.Start();
|
||||
unarProcess.WaitForExit();
|
||||
unarOut = unarProcess.StandardOutput.ReadToEnd();
|
||||
}
|
||||
catch
|
||||
{
|
||||
FailedWithText?.Invoke(this,
|
||||
new ErrorEventArgs
|
||||
{
|
||||
Message = Localization.CannotRunUnAr
|
||||
});
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var lsarProcess = new Process
|
||||
{
|
||||
StartInfo =
|
||||
{
|
||||
FileName = lsarPath,
|
||||
CreateNoWindow = true,
|
||||
RedirectStandardOutput = true,
|
||||
UseShellExecute = false
|
||||
}
|
||||
};
|
||||
|
||||
lsarProcess.Start();
|
||||
lsarProcess.WaitForExit();
|
||||
lsarOut = lsarProcess.StandardOutput.ReadToEnd();
|
||||
}
|
||||
catch
|
||||
{
|
||||
FailedWithText?.Invoke(this,
|
||||
new ErrorEventArgs
|
||||
{
|
||||
Message = Localization.CannotRunLsAr
|
||||
});
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!unarOut.StartsWith("unar ", StringComparison.CurrentCulture))
|
||||
{
|
||||
FailedWithText?.Invoke(this,
|
||||
new ErrorEventArgs
|
||||
{
|
||||
Message = Localization.NotCorrectUnAr
|
||||
});
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!lsarOut.StartsWith("lsar ", StringComparison.CurrentCulture))
|
||||
{
|
||||
FailedWithText?.Invoke(this,
|
||||
new ErrorEventArgs
|
||||
{
|
||||
Message = Localization.NotCorrectLsAr
|
||||
});
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
var versionProcess = new Process
|
||||
{
|
||||
StartInfo =
|
||||
{
|
||||
FileName = unarPath,
|
||||
CreateNoWindow = true,
|
||||
RedirectStandardOutput = true,
|
||||
UseShellExecute = false,
|
||||
Arguments = "-v"
|
||||
}
|
||||
};
|
||||
|
||||
versionProcess.Start();
|
||||
versionProcess.WaitForExit();
|
||||
|
||||
FinishedWithText?.Invoke(this,
|
||||
new MessageEventArgs
|
||||
{
|
||||
Message = versionProcess.StandardOutput.ReadToEnd().TrimEnd('\n')
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -27,181 +27,177 @@ using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using RomRepoMgr.Database.Models;
|
||||
|
||||
namespace RomRepoMgr.Database
|
||||
namespace RomRepoMgr.Database;
|
||||
|
||||
public sealed class Context : DbContext
|
||||
{
|
||||
public sealed class Context : DbContext
|
||||
public Context(DbContextOptions options) : base(options) {}
|
||||
|
||||
public DbSet<DbFile> Files { get; set; }
|
||||
public DbSet<RomSet> RomSets { get; set; }
|
||||
public DbSet<Machine> Machines { get; set; }
|
||||
public DbSet<FileByMachine> FilesByMachines { get; set; }
|
||||
public DbSet<DbDisk> Disks { get; set; }
|
||||
public DbSet<DiskByMachine> DisksByMachines { get; set; }
|
||||
public DbSet<DbMedia> Medias { get; set; }
|
||||
public DbSet<MediaByMachine> MediasByMachines { get; set; }
|
||||
public DbSet<RomSetStat> RomSetStats { get; set; }
|
||||
|
||||
public static Context Create(string dbPath)
|
||||
{
|
||||
public Context(DbContextOptions options) : base(options) {}
|
||||
var optionsBuilder = new DbContextOptionsBuilder();
|
||||
|
||||
public DbSet<DbFile> Files { get; set; }
|
||||
public DbSet<RomSet> RomSets { get; set; }
|
||||
public DbSet<Machine> Machines { get; set; }
|
||||
public DbSet<FileByMachine> FilesByMachines { get; set; }
|
||||
public DbSet<DbDisk> Disks { get; set; }
|
||||
public DbSet<DiskByMachine> DisksByMachines { get; set; }
|
||||
public DbSet<DbMedia> Medias { get; set; }
|
||||
public DbSet<MediaByMachine> MediasByMachines { get; set; }
|
||||
public DbSet<RomSetStat> RomSetStats { get; set; }
|
||||
optionsBuilder.UseLazyLoadingProxies()
|
||||
#if DEBUG
|
||||
.UseLoggerFactory(LoggerFactory.Create(builder => builder.AddConsole()))
|
||||
#endif
|
||||
.UseSqlite($"Data Source={dbPath}");
|
||||
|
||||
public static Context Create(string dbPath)
|
||||
return new Context(optionsBuilder.Options);
|
||||
}
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
base.OnModelCreating(modelBuilder);
|
||||
|
||||
modelBuilder.Entity<DbFile>(entity =>
|
||||
{
|
||||
var optionsBuilder = new DbContextOptionsBuilder();
|
||||
entity.HasIndex(e => e.Crc32);
|
||||
|
||||
optionsBuilder.UseLazyLoadingProxies()
|
||||
#if DEBUG
|
||||
.UseLoggerFactory(LoggerFactory.Create(builder => builder.AddConsole()))
|
||||
#endif
|
||||
.UseSqlite($"Data Source={dbPath}");
|
||||
entity.HasIndex(e => e.Md5);
|
||||
|
||||
return new Context(optionsBuilder.Options);
|
||||
}
|
||||
entity.HasIndex(e => e.Sha1);
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
entity.HasIndex(e => e.Sha256);
|
||||
|
||||
entity.HasIndex(e => e.Sha384);
|
||||
|
||||
entity.HasIndex(e => e.Sha512);
|
||||
|
||||
entity.HasIndex(e => e.Size);
|
||||
|
||||
entity.HasIndex(e => e.IsInRepo);
|
||||
|
||||
entity.HasIndex(e => new
|
||||
{
|
||||
e.Crc32,
|
||||
e.Size
|
||||
});
|
||||
|
||||
entity.HasIndex(e => new
|
||||
{
|
||||
e.Md5,
|
||||
e.Size
|
||||
});
|
||||
|
||||
entity.HasIndex(e => new
|
||||
{
|
||||
e.Sha1,
|
||||
e.Size
|
||||
});
|
||||
|
||||
entity.HasIndex(e => new
|
||||
{
|
||||
e.Sha256,
|
||||
e.Size
|
||||
});
|
||||
|
||||
entity.HasIndex(e => new
|
||||
{
|
||||
e.Sha384,
|
||||
e.Size
|
||||
});
|
||||
|
||||
entity.HasIndex(e => new
|
||||
{
|
||||
e.Sha512,
|
||||
e.Size
|
||||
});
|
||||
});
|
||||
|
||||
modelBuilder.Entity<RomSet>(entity =>
|
||||
{
|
||||
base.OnModelCreating(modelBuilder);
|
||||
entity.HasIndex(e => e.Author);
|
||||
|
||||
modelBuilder.Entity<DbFile>(entity =>
|
||||
{
|
||||
entity.HasIndex(e => e.Crc32);
|
||||
entity.HasIndex(e => e.Comment);
|
||||
|
||||
entity.HasIndex(e => e.Md5);
|
||||
entity.HasIndex(e => e.Date);
|
||||
|
||||
entity.HasIndex(e => e.Sha1);
|
||||
entity.HasIndex(e => e.Description);
|
||||
|
||||
entity.HasIndex(e => e.Sha256);
|
||||
entity.HasIndex(e => e.Homepage);
|
||||
|
||||
entity.HasIndex(e => e.Sha384);
|
||||
entity.HasIndex(e => e.Name);
|
||||
|
||||
entity.HasIndex(e => e.Sha512);
|
||||
entity.HasIndex(e => e.Version);
|
||||
|
||||
entity.HasIndex(e => e.Size);
|
||||
entity.HasIndex(e => e.Filename);
|
||||
|
||||
entity.HasIndex(e => e.IsInRepo);
|
||||
entity.HasIndex(e => e.Sha384);
|
||||
|
||||
entity.HasIndex(e => new
|
||||
{
|
||||
e.Crc32,
|
||||
e.Size
|
||||
});
|
||||
entity.HasIndex(e => e.Category);
|
||||
});
|
||||
|
||||
entity.HasIndex(e => new
|
||||
{
|
||||
e.Md5,
|
||||
e.Size
|
||||
});
|
||||
modelBuilder.Entity<Machine>(entity =>
|
||||
{
|
||||
entity.HasIndex(e => e.Name);
|
||||
|
||||
entity.HasIndex(e => new
|
||||
{
|
||||
e.Sha1,
|
||||
e.Size
|
||||
});
|
||||
entity.HasOne(e => e.RomSet).WithMany(e => e.Machines).OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
entity.HasIndex(e => new
|
||||
{
|
||||
e.Sha256,
|
||||
e.Size
|
||||
});
|
||||
modelBuilder.Entity<FileByMachine>(entity =>
|
||||
{
|
||||
entity.HasIndex(e => e.Name);
|
||||
|
||||
entity.HasIndex(e => new
|
||||
{
|
||||
e.Sha384,
|
||||
e.Size
|
||||
});
|
||||
entity.HasOne(e => e.Machine).WithMany(e => e.Files).OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
entity.HasIndex(e => new
|
||||
{
|
||||
e.Sha512,
|
||||
e.Size
|
||||
});
|
||||
});
|
||||
entity.HasOne(e => e.File).WithMany(e => e.Machines).OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity<RomSet>(entity =>
|
||||
{
|
||||
entity.HasIndex(e => e.Author);
|
||||
modelBuilder.Entity<DbDisk>(entity =>
|
||||
{
|
||||
entity.HasIndex(e => e.Md5);
|
||||
|
||||
entity.HasIndex(e => e.Comment);
|
||||
entity.HasIndex(e => e.Sha1);
|
||||
|
||||
entity.HasIndex(e => e.Date);
|
||||
entity.HasIndex(e => e.Size);
|
||||
|
||||
entity.HasIndex(e => e.Description);
|
||||
entity.HasIndex(e => e.IsInRepo);
|
||||
});
|
||||
|
||||
entity.HasIndex(e => e.Homepage);
|
||||
modelBuilder.Entity<DiskByMachine>(entity =>
|
||||
{
|
||||
entity.HasIndex(e => e.Name);
|
||||
|
||||
entity.HasIndex(e => e.Name);
|
||||
entity.HasOne(e => e.Machine).WithMany(e => e.Disks).OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
entity.HasIndex(e => e.Version);
|
||||
entity.HasOne(e => e.Disk).WithMany(e => e.Machines).OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
entity.HasIndex(e => e.Filename);
|
||||
modelBuilder.Entity<DbMedia>(entity =>
|
||||
{
|
||||
entity.HasIndex(e => e.Md5);
|
||||
|
||||
entity.HasIndex(e => e.Sha384);
|
||||
entity.HasIndex(e => e.Sha1);
|
||||
|
||||
entity.HasIndex(e => e.Category);
|
||||
});
|
||||
entity.HasIndex(e => e.Sha256);
|
||||
|
||||
modelBuilder.Entity<Machine>(entity =>
|
||||
{
|
||||
entity.HasIndex(e => e.Name);
|
||||
entity.HasIndex(e => e.SpamSum);
|
||||
|
||||
entity.HasOne(e => e.RomSet).WithMany(e => e.Machines).OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
entity.HasIndex(e => e.Size);
|
||||
|
||||
modelBuilder.Entity<FileByMachine>(entity =>
|
||||
{
|
||||
entity.HasIndex(e => e.Name);
|
||||
entity.HasIndex(e => e.IsInRepo);
|
||||
});
|
||||
|
||||
entity.HasOne(e => e.Machine).WithMany(e => e.Files).OnDelete(DeleteBehavior.Cascade);
|
||||
modelBuilder.Entity<MediaByMachine>(entity =>
|
||||
{
|
||||
entity.HasIndex(e => e.Name);
|
||||
|
||||
entity.HasOne(e => e.File).WithMany(e => e.Machines).OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
entity.HasOne(e => e.Machine).WithMany(e => e.Medias).OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
modelBuilder.Entity<DbDisk>(entity =>
|
||||
{
|
||||
entity.HasIndex(e => e.Md5);
|
||||
entity.HasOne(e => e.Media).WithMany(e => e.Machines).OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
entity.HasIndex(e => e.Sha1);
|
||||
|
||||
entity.HasIndex(e => e.Size);
|
||||
|
||||
entity.HasIndex(e => e.IsInRepo);
|
||||
});
|
||||
|
||||
modelBuilder.Entity<DiskByMachine>(entity =>
|
||||
{
|
||||
entity.HasIndex(e => e.Name);
|
||||
|
||||
entity.HasOne(e => e.Machine).WithMany(e => e.Disks).OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
entity.HasOne(e => e.Disk).WithMany(e => e.Machines).OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity<DbMedia>(entity =>
|
||||
{
|
||||
entity.HasIndex(e => e.Md5);
|
||||
|
||||
entity.HasIndex(e => e.Sha1);
|
||||
|
||||
entity.HasIndex(e => e.Sha256);
|
||||
|
||||
entity.HasIndex(e => e.SpamSum);
|
||||
|
||||
entity.HasIndex(e => e.Size);
|
||||
|
||||
entity.HasIndex(e => e.IsInRepo);
|
||||
});
|
||||
|
||||
modelBuilder.Entity<MediaByMachine>(entity =>
|
||||
{
|
||||
entity.HasIndex(e => e.Name);
|
||||
|
||||
entity.HasOne(e => e.Machine).WithMany(e => e.Medias).OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
entity.HasOne(e => e.Media).WithMany(e => e.Machines).OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity<RomSetStat>(entity =>
|
||||
{
|
||||
entity.HasOne(e => e.RomSet).WithOne(e => e.Statistics);
|
||||
});
|
||||
}
|
||||
modelBuilder.Entity<RomSetStat>(entity => { entity.HasOne(e => e.RomSet).WithOne(e => e.Statistics); });
|
||||
}
|
||||
}
|
||||
@@ -25,10 +25,9 @@
|
||||
|
||||
using Microsoft.EntityFrameworkCore.Design;
|
||||
|
||||
namespace RomRepoMgr.Database
|
||||
namespace RomRepoMgr.Database;
|
||||
|
||||
public class ContextFactory : IDesignTimeDbContextFactory<Context>
|
||||
{
|
||||
public class ContextFactory : IDesignTimeDbContextFactory<Context>
|
||||
{
|
||||
public Context CreateDbContext(string[] args) => Context.Create("romrepo.db");
|
||||
}
|
||||
public Context CreateDbContext(string[] args) => Context.Create("romrepo.db");
|
||||
}
|
||||
@@ -25,13 +25,12 @@
|
||||
|
||||
using System;
|
||||
|
||||
namespace RomRepoMgr.Database.Models
|
||||
{
|
||||
public abstract class BaseModel<TKey>
|
||||
{
|
||||
public TKey Id { get; set; }
|
||||
namespace RomRepoMgr.Database.Models;
|
||||
|
||||
public DateTime CreatedOn { get; set; }
|
||||
public DateTime UpdatedOn { get; set; }
|
||||
}
|
||||
public abstract class BaseModel<TKey>
|
||||
{
|
||||
public TKey Id { get; set; }
|
||||
|
||||
public DateTime CreatedOn { get; set; }
|
||||
public DateTime UpdatedOn { get; set; }
|
||||
}
|
||||
@@ -27,18 +27,17 @@ using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace RomRepoMgr.Database.Models
|
||||
namespace RomRepoMgr.Database.Models;
|
||||
|
||||
public class DbDisk : BaseModel<ulong>
|
||||
{
|
||||
public class DbDisk : BaseModel<ulong>
|
||||
{
|
||||
public ulong? Size { get; set; }
|
||||
[StringLength(32, MinimumLength = 32)]
|
||||
public string Md5 { get; set; }
|
||||
[StringLength(40, MinimumLength = 40)]
|
||||
public string Sha1 { get; set; }
|
||||
[DefaultValue(false)]
|
||||
public bool IsInRepo { get; set; }
|
||||
public string OriginalFileName { get; set; }
|
||||
public virtual ICollection<DiskByMachine> Machines { get; set; }
|
||||
}
|
||||
public ulong? Size { get; set; }
|
||||
[StringLength(32, MinimumLength = 32)]
|
||||
public string Md5 { get; set; }
|
||||
[StringLength(40, MinimumLength = 40)]
|
||||
public string Sha1 { get; set; }
|
||||
[DefaultValue(false)]
|
||||
public bool IsInRepo { get; set; }
|
||||
public string OriginalFileName { get; set; }
|
||||
public virtual ICollection<DiskByMachine> Machines { get; set; }
|
||||
}
|
||||
@@ -27,27 +27,26 @@ using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace RomRepoMgr.Database.Models
|
||||
namespace RomRepoMgr.Database.Models;
|
||||
|
||||
public class DbFile : BaseModel<ulong>
|
||||
{
|
||||
public class DbFile : BaseModel<ulong>
|
||||
{
|
||||
[Required]
|
||||
public ulong Size { get; set; }
|
||||
[StringLength(8, MinimumLength = 8)]
|
||||
public string Crc32 { get; set; }
|
||||
[StringLength(32, MinimumLength = 32)]
|
||||
public string Md5 { get; set; }
|
||||
[StringLength(40, MinimumLength = 40)]
|
||||
public string Sha1 { get; set; }
|
||||
[StringLength(64, MinimumLength = 64)]
|
||||
public string Sha256 { get; set; }
|
||||
[StringLength(96, MinimumLength = 96)]
|
||||
public string Sha384 { get; set; }
|
||||
[StringLength(128, MinimumLength = 128)]
|
||||
public string Sha512 { get; set; }
|
||||
[DefaultValue(false)]
|
||||
public bool IsInRepo { get; set; }
|
||||
public string OriginalFileName { get; set; }
|
||||
public virtual ICollection<FileByMachine> Machines { get; set; }
|
||||
}
|
||||
[Required]
|
||||
public ulong Size { get; set; }
|
||||
[StringLength(8, MinimumLength = 8)]
|
||||
public string Crc32 { get; set; }
|
||||
[StringLength(32, MinimumLength = 32)]
|
||||
public string Md5 { get; set; }
|
||||
[StringLength(40, MinimumLength = 40)]
|
||||
public string Sha1 { get; set; }
|
||||
[StringLength(64, MinimumLength = 64)]
|
||||
public string Sha256 { get; set; }
|
||||
[StringLength(96, MinimumLength = 96)]
|
||||
public string Sha384 { get; set; }
|
||||
[StringLength(128, MinimumLength = 128)]
|
||||
public string Sha512 { get; set; }
|
||||
[DefaultValue(false)]
|
||||
public bool IsInRepo { get; set; }
|
||||
public string OriginalFileName { get; set; }
|
||||
public virtual ICollection<FileByMachine> Machines { get; set; }
|
||||
}
|
||||
@@ -27,21 +27,20 @@ using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace RomRepoMgr.Database.Models
|
||||
namespace RomRepoMgr.Database.Models;
|
||||
|
||||
public class DbMedia : BaseModel<ulong>
|
||||
{
|
||||
public class DbMedia : BaseModel<ulong>
|
||||
{
|
||||
public ulong? Size { get; set; }
|
||||
[StringLength(32, MinimumLength = 32)]
|
||||
public string Md5 { get; set; }
|
||||
[StringLength(40, MinimumLength = 40)]
|
||||
public string Sha1 { get; set; }
|
||||
[StringLength(64, MinimumLength = 64)]
|
||||
public string Sha256 { get; set; }
|
||||
public string SpamSum { get; set; }
|
||||
[DefaultValue(false)]
|
||||
public bool IsInRepo { get; set; }
|
||||
public string OriginalFileName { get; set; }
|
||||
public virtual IEnumerable<MediaByMachine> Machines { get; set; }
|
||||
}
|
||||
public ulong? Size { get; set; }
|
||||
[StringLength(32, MinimumLength = 32)]
|
||||
public string Md5 { get; set; }
|
||||
[StringLength(40, MinimumLength = 40)]
|
||||
public string Sha1 { get; set; }
|
||||
[StringLength(64, MinimumLength = 64)]
|
||||
public string Sha256 { get; set; }
|
||||
public string SpamSum { get; set; }
|
||||
[DefaultValue(false)]
|
||||
public bool IsInRepo { get; set; }
|
||||
public string OriginalFileName { get; set; }
|
||||
public virtual IEnumerable<MediaByMachine> Machines { get; set; }
|
||||
}
|
||||
@@ -25,19 +25,18 @@
|
||||
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace RomRepoMgr.Database.Models
|
||||
namespace RomRepoMgr.Database.Models;
|
||||
|
||||
public class DiskByMachine
|
||||
{
|
||||
public class DiskByMachine
|
||||
{
|
||||
[Key]
|
||||
public ulong Id { get; set; }
|
||||
[Required]
|
||||
public virtual DbDisk Disk { get; set; }
|
||||
[Required]
|
||||
public virtual Machine Machine { get; set; }
|
||||
[Required]
|
||||
public string Name { get; set; }
|
||||
public ulong DiskId { get; set; }
|
||||
public ulong MachineId { get; set; }
|
||||
}
|
||||
[Key]
|
||||
public ulong Id { get; set; }
|
||||
[Required]
|
||||
public virtual DbDisk Disk { get; set; }
|
||||
[Required]
|
||||
public virtual Machine Machine { get; set; }
|
||||
[Required]
|
||||
public string Name { get; set; }
|
||||
public ulong DiskId { get; set; }
|
||||
public ulong MachineId { get; set; }
|
||||
}
|
||||
@@ -26,22 +26,21 @@
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace RomRepoMgr.Database.Models
|
||||
namespace RomRepoMgr.Database.Models;
|
||||
|
||||
public class FileByMachine
|
||||
{
|
||||
public class FileByMachine
|
||||
{
|
||||
[Key]
|
||||
public ulong Id { get; set; }
|
||||
[Required]
|
||||
public virtual DbFile File { get; set; }
|
||||
[Required]
|
||||
public virtual Machine Machine { get; set; }
|
||||
[Required]
|
||||
public string Name { get; set; }
|
||||
public ulong FileId { get; set; }
|
||||
public ulong MachineId { get; set; }
|
||||
public DateTime? FileLastModification { get; set; }
|
||||
[StringLength(4096)]
|
||||
public string Path { get; set; }
|
||||
}
|
||||
[Key]
|
||||
public ulong Id { get; set; }
|
||||
[Required]
|
||||
public virtual DbFile File { get; set; }
|
||||
[Required]
|
||||
public virtual Machine Machine { get; set; }
|
||||
[Required]
|
||||
public string Name { get; set; }
|
||||
public ulong FileId { get; set; }
|
||||
public ulong MachineId { get; set; }
|
||||
public DateTime? FileLastModification { get; set; }
|
||||
[StringLength(4096)]
|
||||
public string Path { get; set; }
|
||||
}
|
||||
@@ -26,17 +26,16 @@
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace RomRepoMgr.Database.Models
|
||||
namespace RomRepoMgr.Database.Models;
|
||||
|
||||
public class Machine : BaseModel<ulong>
|
||||
{
|
||||
public class Machine : BaseModel<ulong>
|
||||
{
|
||||
[Required]
|
||||
public string Name { get; set; }
|
||||
[Required]
|
||||
public virtual RomSet RomSet { get; set; }
|
||||
public virtual ICollection<FileByMachine> Files { get; set; }
|
||||
public virtual ICollection<DiskByMachine> Disks { get; set; }
|
||||
public virtual ICollection<MediaByMachine> Medias { get; set; }
|
||||
public long RomSetId { get; set; }
|
||||
}
|
||||
[Required]
|
||||
public string Name { get; set; }
|
||||
[Required]
|
||||
public virtual RomSet RomSet { get; set; }
|
||||
public virtual ICollection<FileByMachine> Files { get; set; }
|
||||
public virtual ICollection<DiskByMachine> Disks { get; set; }
|
||||
public virtual ICollection<MediaByMachine> Medias { get; set; }
|
||||
public long RomSetId { get; set; }
|
||||
}
|
||||
@@ -25,19 +25,18 @@
|
||||
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace RomRepoMgr.Database.Models
|
||||
namespace RomRepoMgr.Database.Models;
|
||||
|
||||
public class MediaByMachine
|
||||
{
|
||||
public class MediaByMachine
|
||||
{
|
||||
[Key]
|
||||
public ulong Id { get; set; }
|
||||
[Required]
|
||||
public virtual DbMedia Media { get; set; }
|
||||
[Required]
|
||||
public virtual Machine Machine { get; set; }
|
||||
[Required]
|
||||
public string Name { get; set; }
|
||||
public ulong MediaId { get; set; }
|
||||
public ulong MachineId { get; set; }
|
||||
}
|
||||
[Key]
|
||||
public ulong Id { get; set; }
|
||||
[Required]
|
||||
public virtual DbMedia Media { get; set; }
|
||||
[Required]
|
||||
public virtual Machine Machine { get; set; }
|
||||
[Required]
|
||||
public string Name { get; set; }
|
||||
public ulong MediaId { get; set; }
|
||||
public ulong MachineId { get; set; }
|
||||
}
|
||||
@@ -26,24 +26,24 @@
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace RomRepoMgr.Database.Models
|
||||
{
|
||||
public class RomSet : BaseModel<long>
|
||||
{
|
||||
public string Author { get; set; }
|
||||
public string Comment { get; set; }
|
||||
public string Date { get; set; }
|
||||
public string Description { get; set; }
|
||||
public string Homepage { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string Version { get; set; }
|
||||
[Required]
|
||||
public string Filename { get; set; }
|
||||
[Required, StringLength(96, MinimumLength = 96)]
|
||||
public string Sha384 { get; set; }
|
||||
public string Category { get; set; }
|
||||
public virtual RomSetStat Statistics { get; set; }
|
||||
namespace RomRepoMgr.Database.Models;
|
||||
|
||||
public virtual ICollection<Machine> Machines { get; set; }
|
||||
}
|
||||
public class RomSet : BaseModel<long>
|
||||
{
|
||||
public string Author { get; set; }
|
||||
public string Comment { get; set; }
|
||||
public string Date { get; set; }
|
||||
public string Description { get; set; }
|
||||
public string Homepage { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string Version { get; set; }
|
||||
[Required]
|
||||
public string Filename { get; set; }
|
||||
[Required]
|
||||
[StringLength(96, MinimumLength = 96)]
|
||||
public string Sha384 { get; set; }
|
||||
public string Category { get; set; }
|
||||
public virtual RomSetStat Statistics { get; set; }
|
||||
|
||||
public virtual ICollection<Machine> Machines { get; set; }
|
||||
}
|
||||
@@ -1,17 +1,16 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace RomRepoMgr.Database.Models
|
||||
namespace RomRepoMgr.Database.Models;
|
||||
|
||||
public class RomSetStat
|
||||
{
|
||||
public class RomSetStat
|
||||
{
|
||||
public long TotalMachines { get; set; }
|
||||
public long CompleteMachines { get; set; }
|
||||
public long IncompleteMachines { get; set; }
|
||||
public long TotalRoms { get; set; }
|
||||
public long HaveRoms { get; set; }
|
||||
public long MissRoms { get; set; }
|
||||
public virtual RomSet RomSet { get; set; }
|
||||
[Key]
|
||||
public long RomSetId { get; set; }
|
||||
}
|
||||
public long TotalMachines { get; set; }
|
||||
public long CompleteMachines { get; set; }
|
||||
public long IncompleteMachines { get; set; }
|
||||
public long TotalRoms { get; set; }
|
||||
public long HaveRoms { get; set; }
|
||||
public long MissRoms { get; set; }
|
||||
public virtual RomSet RomSet { get; set; }
|
||||
[Key]
|
||||
public long RomSetId { get; set; }
|
||||
}
|
||||
@@ -11,32 +11,46 @@ namespace RomRepoMgr.Database.Resources {
|
||||
using System;
|
||||
|
||||
|
||||
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
|
||||
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
/// <summary>
|
||||
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||
/// </summary>
|
||||
// This class was auto-generated by the StronglyTypedResourceBuilder
|
||||
// class via a tool like ResGen or Visual Studio.
|
||||
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||
// with the /str option, or rebuild your VS project.
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class Localization {
|
||||
|
||||
private static System.Resources.ResourceManager resourceMan;
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static System.Globalization.CultureInfo resourceCulture;
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal Localization() {
|
||||
}
|
||||
|
||||
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static System.Resources.ResourceManager ResourceManager {
|
||||
/// <summary>
|
||||
/// Returns the cached ResourceManager instance used by this class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if (object.Equals(null, resourceMan)) {
|
||||
System.Resources.ResourceManager temp = new System.Resources.ResourceManager("RomRepoMgr.Database.Resources.Localization", typeof(Localization).Assembly);
|
||||
if (object.ReferenceEquals(resourceMan, null)) {
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("RomRepoMgr.Database.Resources.Localization", typeof(Localization).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static System.Globalization.CultureInfo Culture {
|
||||
/// <summary>
|
||||
/// Overrides the current thread's CurrentUICulture property for all
|
||||
/// resource lookups using this strongly typed resource class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Globalization.CultureInfo Culture {
|
||||
get {
|
||||
return resourceCulture;
|
||||
}
|
||||
@@ -45,6 +59,9 @@ namespace RomRepoMgr.Database.Resources {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Settings are not initialized!.
|
||||
/// </summary>
|
||||
internal static string Settings_not_initialized {
|
||||
get {
|
||||
return ResourceManager.GetString("Settings_not_initialized", resourceCulture);
|
||||
|
||||
@@ -1,17 +1,21 @@
|
||||
<root>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>1.3</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="Settings_not_initialized" xml:space="preserve">
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>1.3</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<data name="Settings_not_initialized" xml:space="preserve">
|
||||
<value>¡Las preferencias no están inicializadas!</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -1,22 +1,27 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
|
||||
<root>
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:element name="root" msdata:IsDataSet="true"></xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>1.3</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="Settings_not_initialized" xml:space="preserve">
|
||||
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" id="root"
|
||||
xmlns="">
|
||||
<xsd:element name="root" msdata:IsDataSet="true"></xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>1.3</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<data name="Settings_not_initialized" xml:space="preserve">
|
||||
<value>Settings are not initialized!</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -1,42 +1,42 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<LangVersion>default</LangVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<LangVersion>default</LangVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.0-rc.2.24474.1">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Proxies" Version="9.0.0-rc.2.24474.1" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="9.0.0-rc.2.24474.1" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Design" Version="2.0.0-preview1-final" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="9.0.0-rc.2.24473.5" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.0-rc.2.24474.1">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Proxies" Version="9.0.0-rc.2.24474.1"/>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="9.0.0-rc.2.24474.1"/>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Design" Version="2.0.0-preview1-final"/>
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="9.0.0-rc.2.24473.5"/>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Migrations" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Migrations"/>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\RomRepoMgr.Settings\RomRepoMgr.Settings.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\RomRepoMgr.Settings\RomRepoMgr.Settings.csproj"/>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Update="Resources\Localization.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Localization.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Update="Resources\Localization.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Localization.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Update="Resources\Localization.Designer.cs">
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Language.resx</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Update="Resources\Localization.Designer.cs">
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Language.resx</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -43,344 +43,380 @@ using System.Runtime.InteropServices;
|
||||
using System.Security.Principal;
|
||||
using RomRepoMgr.Settings.Resources;
|
||||
|
||||
namespace Aaru.CommonTypes.Interop
|
||||
namespace Aaru.CommonTypes.Interop;
|
||||
|
||||
public static class DetectOS
|
||||
{
|
||||
public static class DetectOS
|
||||
public static readonly bool IsMono =
|
||||
RuntimeInformation.FrameworkDescription.StartsWith("Mono", StringComparison.Ordinal);
|
||||
public static readonly bool IsNetFramework =
|
||||
RuntimeInformation.FrameworkDescription.StartsWith(".NET Framework", StringComparison.Ordinal);
|
||||
public static readonly bool IsNetCore =
|
||||
RuntimeInformation.FrameworkDescription.StartsWith(".NET Core", StringComparison.Ordinal);
|
||||
public static readonly bool IsNetNative =
|
||||
RuntimeInformation.FrameworkDescription.StartsWith(".NET Native", StringComparison.Ordinal);
|
||||
|
||||
/// <summary>Checks if the underlying runtime runs in 64-bit mode</summary>
|
||||
public static readonly bool Is64Bit = IntPtr.Size == 8;
|
||||
|
||||
/// <summary>Checks if the underlying runtime runs in 32-bit mode</summary>
|
||||
public static readonly bool Is32Bit = IntPtr.Size == 4;
|
||||
|
||||
public static bool IsWindows => GetRealPlatformID() == PlatformID.Win32NT ||
|
||||
GetRealPlatformID() == PlatformID.Win32S ||
|
||||
GetRealPlatformID() == PlatformID.Win32Windows ||
|
||||
GetRealPlatformID() == PlatformID.WinCE ||
|
||||
GetRealPlatformID() == PlatformID.WindowsPhone ||
|
||||
GetRealPlatformID() == PlatformID.Xbox;
|
||||
|
||||
public static bool IsAdmin
|
||||
{
|
||||
public static readonly bool IsMono =
|
||||
RuntimeInformation.FrameworkDescription.StartsWith("Mono", StringComparison.Ordinal);
|
||||
public static readonly bool IsNetFramework =
|
||||
RuntimeInformation.FrameworkDescription.StartsWith(".NET Framework", StringComparison.Ordinal);
|
||||
public static readonly bool IsNetCore =
|
||||
RuntimeInformation.FrameworkDescription.StartsWith(".NET Core", StringComparison.Ordinal);
|
||||
public static readonly bool IsNetNative =
|
||||
RuntimeInformation.FrameworkDescription.StartsWith(".NET Native", StringComparison.Ordinal);
|
||||
|
||||
/// <summary>Checks if the underlying runtime runs in 64-bit mode</summary>
|
||||
public static readonly bool Is64Bit = IntPtr.Size == 8;
|
||||
|
||||
/// <summary>Checks if the underlying runtime runs in 32-bit mode</summary>
|
||||
public static readonly bool Is32Bit = IntPtr.Size == 4;
|
||||
|
||||
public static bool IsWindows => GetRealPlatformID() == PlatformID.Win32NT ||
|
||||
GetRealPlatformID() == PlatformID.Win32S ||
|
||||
GetRealPlatformID() == PlatformID.Win32Windows ||
|
||||
GetRealPlatformID() == PlatformID.WinCE ||
|
||||
GetRealPlatformID() == PlatformID.WindowsPhone ||
|
||||
GetRealPlatformID() == PlatformID.Xbox;
|
||||
|
||||
public static bool IsAdmin
|
||||
get
|
||||
{
|
||||
get
|
||||
if(!OperatingSystem.IsWindows()) return Environment.UserName == "root";
|
||||
|
||||
bool isAdmin;
|
||||
WindowsIdentity user = null;
|
||||
|
||||
try
|
||||
{
|
||||
if(!OperatingSystem.IsWindows())
|
||||
return Environment.UserName == "root";
|
||||
|
||||
bool isAdmin;
|
||||
WindowsIdentity user = null;
|
||||
|
||||
try
|
||||
{
|
||||
user = WindowsIdentity.GetCurrent();
|
||||
var principal = new WindowsPrincipal(user);
|
||||
isAdmin = principal.IsInRole(WindowsBuiltInRole.Administrator);
|
||||
}
|
||||
catch(UnauthorizedAccessException)
|
||||
{
|
||||
isAdmin = false;
|
||||
}
|
||||
catch(Exception)
|
||||
{
|
||||
isAdmin = false;
|
||||
}
|
||||
finally
|
||||
{
|
||||
user?.Dispose();
|
||||
}
|
||||
|
||||
return isAdmin;
|
||||
user = WindowsIdentity.GetCurrent();
|
||||
var principal = new WindowsPrincipal(user);
|
||||
isAdmin = principal.IsInRole(WindowsBuiltInRole.Administrator);
|
||||
}
|
||||
}
|
||||
|
||||
[DllImport("libc", SetLastError = true)]
|
||||
static extern int uname(out utsname name);
|
||||
|
||||
[DllImport("libc", SetLastError = true, EntryPoint = "sysctlbyname", CharSet = CharSet.Ansi)]
|
||||
static extern int OSX_sysctlbyname(string name, IntPtr oldp, IntPtr oldlenp, IntPtr newp, uint newlen);
|
||||
|
||||
/// <summary>Gets the real platform ID, not the incomplete .NET framework one</summary>
|
||||
/// <returns>Platform ID</returns>
|
||||
/// <exception cref="Exception">Unhandled exception</exception>
|
||||
public static PlatformID GetRealPlatformID()
|
||||
{
|
||||
if((int)Environment.OSVersion.Platform < 4 ||
|
||||
(int)Environment.OSVersion.Platform == 5)
|
||||
return (PlatformID)(int)Environment.OSVersion.Platform;
|
||||
|
||||
int error = uname(out utsname unixname);
|
||||
|
||||
if(error != 0)
|
||||
throw new Exception(string.Format(Localization.Unhandled_exception_uname, Marshal.GetLastWin32Error()));
|
||||
|
||||
switch(unixname.sysname)
|
||||
catch(UnauthorizedAccessException)
|
||||
{
|
||||
// TODO: Differentiate Linux, Android, Tizen
|
||||
case "Linux":
|
||||
{
|
||||
#if __ANDROID__
|
||||
isAdmin = false;
|
||||
}
|
||||
catch(Exception)
|
||||
{
|
||||
isAdmin = false;
|
||||
}
|
||||
finally
|
||||
{
|
||||
user?.Dispose();
|
||||
}
|
||||
|
||||
return isAdmin;
|
||||
}
|
||||
}
|
||||
|
||||
[DllImport("libc", SetLastError = true)]
|
||||
static extern int uname(out utsname name);
|
||||
|
||||
[DllImport("libc", SetLastError = true, EntryPoint = "sysctlbyname", CharSet = CharSet.Ansi)]
|
||||
static extern int OSX_sysctlbyname(string name, IntPtr oldp, IntPtr oldlenp, IntPtr newp, uint newlen);
|
||||
|
||||
/// <summary>Gets the real platform ID, not the incomplete .NET framework one</summary>
|
||||
/// <returns>Platform ID</returns>
|
||||
/// <exception cref="Exception">Unhandled exception</exception>
|
||||
public static PlatformID GetRealPlatformID()
|
||||
{
|
||||
if((int)Environment.OSVersion.Platform < 4 || (int)Environment.OSVersion.Platform == 5)
|
||||
return (PlatformID)(int)Environment.OSVersion.Platform;
|
||||
|
||||
int error = uname(out utsname unixname);
|
||||
|
||||
if(error != 0)
|
||||
throw new Exception(string.Format(Localization.Unhandled_exception_uname, Marshal.GetLastWin32Error()));
|
||||
|
||||
switch(unixname.sysname)
|
||||
{
|
||||
// TODO: Differentiate Linux, Android, Tizen
|
||||
case "Linux":
|
||||
{
|
||||
#if __ANDROID__
|
||||
return PlatformID.Android;
|
||||
#else
|
||||
return PlatformID.Linux;
|
||||
#endif
|
||||
#else
|
||||
return PlatformID.Linux;
|
||||
#endif
|
||||
}
|
||||
|
||||
case "Darwin":
|
||||
{
|
||||
IntPtr pLen = Marshal.AllocHGlobal(sizeof(int));
|
||||
int osxError = OSX_sysctlbyname("hw.machine", IntPtr.Zero, pLen, IntPtr.Zero, 0);
|
||||
|
||||
if(osxError != 0)
|
||||
{
|
||||
Marshal.FreeHGlobal(pLen);
|
||||
|
||||
throw new Exception(string.Format(Localization.Unhandled_exception_uname,
|
||||
Marshal.GetLastWin32Error()));
|
||||
}
|
||||
|
||||
case "Darwin":
|
||||
int length = Marshal.ReadInt32(pLen);
|
||||
IntPtr pStr = Marshal.AllocHGlobal(length);
|
||||
osxError = OSX_sysctlbyname("hw.machine", pStr, pLen, IntPtr.Zero, 0);
|
||||
|
||||
if(osxError != 0)
|
||||
{
|
||||
IntPtr pLen = Marshal.AllocHGlobal(sizeof(int));
|
||||
int osxError = OSX_sysctlbyname("hw.machine", IntPtr.Zero, pLen, IntPtr.Zero, 0);
|
||||
|
||||
if(osxError != 0)
|
||||
{
|
||||
Marshal.FreeHGlobal(pLen);
|
||||
|
||||
throw new Exception(string.Format(Localization.Unhandled_exception_uname,
|
||||
Marshal.GetLastWin32Error()));
|
||||
}
|
||||
|
||||
int length = Marshal.ReadInt32(pLen);
|
||||
IntPtr pStr = Marshal.AllocHGlobal(length);
|
||||
osxError = OSX_sysctlbyname("hw.machine", pStr, pLen, IntPtr.Zero, 0);
|
||||
|
||||
if(osxError != 0)
|
||||
{
|
||||
Marshal.FreeHGlobal(pStr);
|
||||
Marshal.FreeHGlobal(pLen);
|
||||
|
||||
throw new Exception(string.Format(Localization.Unhandled_exception_uname,
|
||||
Marshal.GetLastWin32Error()));
|
||||
}
|
||||
|
||||
string machine = Marshal.PtrToStringAnsi(pStr);
|
||||
|
||||
Marshal.FreeHGlobal(pStr);
|
||||
Marshal.FreeHGlobal(pLen);
|
||||
|
||||
if(machine != null &&
|
||||
(machine.StartsWith("iPad", StringComparison.Ordinal) ||
|
||||
machine.StartsWith("iPod", StringComparison.Ordinal) ||
|
||||
machine.StartsWith("iPhone", StringComparison.Ordinal)))
|
||||
return PlatformID.iOS;
|
||||
|
||||
return PlatformID.MacOSX;
|
||||
throw new Exception(string.Format(Localization.Unhandled_exception_uname,
|
||||
Marshal.GetLastWin32Error()));
|
||||
}
|
||||
|
||||
case "GNU": return PlatformID.Hurd;
|
||||
case "FreeBSD":
|
||||
case "GNU/kFreeBSD": return PlatformID.FreeBSD;
|
||||
case "DragonFly": return PlatformID.DragonFly;
|
||||
case "Haiku": return PlatformID.Haiku;
|
||||
case "HP-UX": return PlatformID.HPUX;
|
||||
case "AIX": return PlatformID.AIX;
|
||||
case "OS400": return PlatformID.OS400;
|
||||
case "IRIX":
|
||||
case "IRIX64": return PlatformID.IRIX;
|
||||
case "Minix": return PlatformID.Minix;
|
||||
case "NetBSD": return PlatformID.NetBSD;
|
||||
case "NONSTOP_KERNEL": return PlatformID.NonStop;
|
||||
case "OpenBSD": return PlatformID.OpenBSD;
|
||||
case "QNX": return PlatformID.QNX;
|
||||
case "SINIX-Y": return PlatformID.SINIX;
|
||||
case "SunOS": return PlatformID.Solaris;
|
||||
case "OSF1": return PlatformID.Tru64;
|
||||
case "ULTRIX": return PlatformID.Ultrix;
|
||||
case "SCO_SV": return PlatformID.OpenServer;
|
||||
case "UnixWare": return PlatformID.UnixWare;
|
||||
case "Interix":
|
||||
case "UWIN-W7": return PlatformID.Win32NT;
|
||||
default:
|
||||
{
|
||||
if(unixname.sysname.StartsWith("CYGWIN_NT", StringComparison.Ordinal) ||
|
||||
unixname.sysname.StartsWith("MINGW32_NT", StringComparison.Ordinal) ||
|
||||
unixname.sysname.StartsWith("MSYS_NT", StringComparison.Ordinal) ||
|
||||
unixname.sysname.StartsWith("UWIN", StringComparison.Ordinal))
|
||||
return PlatformID.Win32NT;
|
||||
string machine = Marshal.PtrToStringAnsi(pStr);
|
||||
|
||||
return PlatformID.Unknown;
|
||||
}
|
||||
Marshal.FreeHGlobal(pStr);
|
||||
Marshal.FreeHGlobal(pLen);
|
||||
|
||||
if(machine != null &&
|
||||
(machine.StartsWith("iPad", StringComparison.Ordinal) ||
|
||||
machine.StartsWith("iPod", StringComparison.Ordinal) ||
|
||||
machine.StartsWith("iPhone", StringComparison.Ordinal)))
|
||||
return PlatformID.iOS;
|
||||
|
||||
return PlatformID.MacOSX;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Gets a string for the current operating system REAL version (handles Darwin 1.4 and Windows 10 falsifying)</summary>
|
||||
/// <returns>Current operating system version</returns>
|
||||
public static string GetVersion()
|
||||
{
|
||||
string environ = Environment.OSVersion.Version.ToString();
|
||||
|
||||
switch(GetRealPlatformID())
|
||||
case "GNU":
|
||||
return PlatformID.Hurd;
|
||||
case "FreeBSD":
|
||||
case "GNU/kFreeBSD":
|
||||
return PlatformID.FreeBSD;
|
||||
case "DragonFly":
|
||||
return PlatformID.DragonFly;
|
||||
case "Haiku":
|
||||
return PlatformID.Haiku;
|
||||
case "HP-UX":
|
||||
return PlatformID.HPUX;
|
||||
case "AIX":
|
||||
return PlatformID.AIX;
|
||||
case "OS400":
|
||||
return PlatformID.OS400;
|
||||
case "IRIX":
|
||||
case "IRIX64":
|
||||
return PlatformID.IRIX;
|
||||
case "Minix":
|
||||
return PlatformID.Minix;
|
||||
case "NetBSD":
|
||||
return PlatformID.NetBSD;
|
||||
case "NONSTOP_KERNEL":
|
||||
return PlatformID.NonStop;
|
||||
case "OpenBSD":
|
||||
return PlatformID.OpenBSD;
|
||||
case "QNX":
|
||||
return PlatformID.QNX;
|
||||
case "SINIX-Y":
|
||||
return PlatformID.SINIX;
|
||||
case "SunOS":
|
||||
return PlatformID.Solaris;
|
||||
case "OSF1":
|
||||
return PlatformID.Tru64;
|
||||
case "ULTRIX":
|
||||
return PlatformID.Ultrix;
|
||||
case "SCO_SV":
|
||||
return PlatformID.OpenServer;
|
||||
case "UnixWare":
|
||||
return PlatformID.UnixWare;
|
||||
case "Interix":
|
||||
case "UWIN-W7":
|
||||
return PlatformID.Win32NT;
|
||||
default:
|
||||
{
|
||||
case PlatformID.MacOSX:
|
||||
if(Environment.OSVersion.Version.Major != 1)
|
||||
return $"10.{Environment.OSVersion.Version.Major - 4}.{Environment.OSVersion.Version.Minor}";
|
||||
if(unixname.sysname.StartsWith("CYGWIN_NT", StringComparison.Ordinal) ||
|
||||
unixname.sysname.StartsWith("MINGW32_NT", StringComparison.Ordinal) ||
|
||||
unixname.sysname.StartsWith("MSYS_NT", StringComparison.Ordinal) ||
|
||||
unixname.sysname.StartsWith("UWIN", StringComparison.Ordinal))
|
||||
return PlatformID.Win32NT;
|
||||
|
||||
switch(Environment.OSVersion.Version.Minor)
|
||||
{
|
||||
case 3: return "10.0";
|
||||
case 4: return "10.1";
|
||||
}
|
||||
|
||||
goto default;
|
||||
case PlatformID.Win32NT:
|
||||
// From Windows 8.1 the reported version is simply falsified...
|
||||
if((Environment.OSVersion.Version.Major == 6 && Environment.OSVersion.Version.Major >= 2) ||
|
||||
Environment.OSVersion.Version.Major > 6)
|
||||
return FileVersionInfo.
|
||||
GetVersionInfo(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System),
|
||||
"KERNEL32.DLL")).ProductVersion;
|
||||
|
||||
return environ;
|
||||
default: return environ;
|
||||
return PlatformID.Unknown;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>From a platform ID and version returns a human-readable version</summary>
|
||||
/// <param name="id">Platform ID</param>
|
||||
/// <param name="version">Version number</param>
|
||||
/// <returns>Operating system name</returns>
|
||||
public static string GetPlatformName(PlatformID id, string version = null)
|
||||
{
|
||||
switch(id)
|
||||
{
|
||||
case PlatformID.AIX: return "AIX";
|
||||
case PlatformID.Android: return "Android";
|
||||
case PlatformID.DragonFly: return "DragonFly BSD";
|
||||
case PlatformID.FreeBSD: return "FreeBSD";
|
||||
case PlatformID.Haiku: return "Haiku";
|
||||
case PlatformID.HPUX: return "HP/UX";
|
||||
case PlatformID.Hurd: return "Hurd";
|
||||
case PlatformID.iOS: return "iOS";
|
||||
case PlatformID.IRIX: return "IRIX";
|
||||
case PlatformID.Linux:
|
||||
if(!File.Exists("/proc/version"))
|
||||
return "Linux";
|
||||
|
||||
string s = File.ReadAllText("/proc/version");
|
||||
|
||||
return s.Contains("Microsoft") || s.Contains("WSL") ? "Windows Subsystem for Linux" : "Linux";
|
||||
|
||||
case PlatformID.MacOSX:
|
||||
if(string.IsNullOrEmpty(version))
|
||||
return "macOS";
|
||||
|
||||
string[] pieces = version.Split('.');
|
||||
|
||||
if(pieces.Length < 2 ||
|
||||
!int.TryParse(pieces[1], out int minor))
|
||||
return "macOS";
|
||||
|
||||
if(minor >= 12)
|
||||
return "macOS";
|
||||
|
||||
if(minor >= 8)
|
||||
return "OS X";
|
||||
|
||||
return "Mac OS X";
|
||||
|
||||
case PlatformID.Minix: return "MINIX";
|
||||
case PlatformID.NetBSD: return "NetBSD";
|
||||
case PlatformID.NonStop: return "NonStop OS";
|
||||
case PlatformID.OpenBSD: return "OpenBSD";
|
||||
case PlatformID.OpenServer: return "SCO OpenServer";
|
||||
case PlatformID.OS400: return "OS/400";
|
||||
case PlatformID.PlayStation3: return "Sony CellOS";
|
||||
case PlatformID.PlayStation4: return "Sony Orbis OS";
|
||||
case PlatformID.QNX: return "QNX";
|
||||
case PlatformID.SINIX: return "SINIX";
|
||||
case PlatformID.Solaris: return "Sun Solaris";
|
||||
case PlatformID.Tizen: return "Samsung Tizen";
|
||||
case PlatformID.Tru64: return "Tru64 UNIX";
|
||||
case PlatformID.Ultrix: return "Ultrix";
|
||||
case PlatformID.Unix: return "UNIX";
|
||||
case PlatformID.UnixWare: return "SCO UnixWare";
|
||||
case PlatformID.Wii: return "Nintendo Wii";
|
||||
case PlatformID.WiiU: return "Nintendo Wii U";
|
||||
case PlatformID.Win32NT:
|
||||
if(string.IsNullOrEmpty(version))
|
||||
return "Windows NT/2000/XP/Vista/7/10";
|
||||
|
||||
if(version.StartsWith("3.", StringComparison.Ordinal) ||
|
||||
version.StartsWith("4.", StringComparison.Ordinal))
|
||||
return "Windows NT";
|
||||
|
||||
if(version.StartsWith("5.0", StringComparison.Ordinal))
|
||||
return "Windows 2000";
|
||||
|
||||
if(version.StartsWith("5.1", StringComparison.Ordinal))
|
||||
return "Windows XP";
|
||||
|
||||
if(version.StartsWith("5.2", StringComparison.Ordinal))
|
||||
return "Windows 2003";
|
||||
|
||||
if(version.StartsWith("6.0", StringComparison.Ordinal))
|
||||
return "Windows Vista";
|
||||
|
||||
if(version.StartsWith("6.1", StringComparison.Ordinal))
|
||||
return "Windows 7";
|
||||
|
||||
if(version.StartsWith("6.2", StringComparison.Ordinal))
|
||||
return "Windows 8";
|
||||
|
||||
if(version.StartsWith("6.3", StringComparison.Ordinal))
|
||||
return "Windows 8.1";
|
||||
|
||||
if(version.StartsWith("10.0", StringComparison.Ordinal))
|
||||
return "Windows 10";
|
||||
|
||||
return "Windows NT/2000/XP/Vista/7/10";
|
||||
case PlatformID.Win32S: return "Windows 3.x with win32s";
|
||||
case PlatformID.Win32Windows:
|
||||
if(string.IsNullOrEmpty(version))
|
||||
return "Windows 9x/Me";
|
||||
|
||||
if(version.StartsWith("4.0", StringComparison.Ordinal))
|
||||
return "Windows 95";
|
||||
|
||||
if(version.StartsWith("4.10.2222", StringComparison.Ordinal))
|
||||
return "Windows 98 SE";
|
||||
|
||||
if(version.StartsWith("4.1", StringComparison.Ordinal))
|
||||
return "Windows 98";
|
||||
|
||||
if(version.StartsWith("4.9", StringComparison.Ordinal))
|
||||
return "Windows Me";
|
||||
|
||||
return "Windows 9x/Me";
|
||||
case PlatformID.WinCE: return "Windows CE/Mobile";
|
||||
case PlatformID.WindowsPhone: return "Windows Phone";
|
||||
case PlatformID.Xbox: return "Xbox OS";
|
||||
case PlatformID.zOS: return "z/OS";
|
||||
default: return id.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>POSIX uname structure, size from OSX, big enough to handle extra fields</summary>
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
|
||||
struct utsname
|
||||
{
|
||||
/// <summary>System name</summary>
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
|
||||
public readonly string sysname;
|
||||
/// <summary>Node name</summary>
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
|
||||
public readonly string nodename;
|
||||
/// <summary>Release level</summary>
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
|
||||
public readonly string release;
|
||||
/// <summary>Version level</summary>
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
|
||||
public readonly string version;
|
||||
/// <summary>Hardware level</summary>
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
|
||||
public readonly string machine;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Gets a string for the current operating system REAL version (handles Darwin 1.4 and Windows 10 falsifying)</summary>
|
||||
/// <returns>Current operating system version</returns>
|
||||
public static string GetVersion()
|
||||
{
|
||||
var environ = Environment.OSVersion.Version.ToString();
|
||||
|
||||
switch(GetRealPlatformID())
|
||||
{
|
||||
case PlatformID.MacOSX:
|
||||
if(Environment.OSVersion.Version.Major != 1)
|
||||
return $"10.{Environment.OSVersion.Version.Major - 4}.{Environment.OSVersion.Version.Minor}";
|
||||
|
||||
switch(Environment.OSVersion.Version.Minor)
|
||||
{
|
||||
case 3:
|
||||
return "10.0";
|
||||
case 4:
|
||||
return "10.1";
|
||||
}
|
||||
|
||||
goto default;
|
||||
case PlatformID.Win32NT:
|
||||
// From Windows 8.1 the reported version is simply falsified...
|
||||
if(Environment.OSVersion.Version.Major == 6 && Environment.OSVersion.Version.Major >= 2 ||
|
||||
Environment.OSVersion.Version.Major > 6)
|
||||
{
|
||||
return FileVersionInfo
|
||||
.GetVersionInfo(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System),
|
||||
"KERNEL32.DLL"))
|
||||
.ProductVersion;
|
||||
}
|
||||
|
||||
return environ;
|
||||
default:
|
||||
return environ;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>From a platform ID and version returns a human-readable version</summary>
|
||||
/// <param name="id">Platform ID</param>
|
||||
/// <param name="version">Version number</param>
|
||||
/// <returns>Operating system name</returns>
|
||||
public static string GetPlatformName(PlatformID id, string version = null)
|
||||
{
|
||||
switch(id)
|
||||
{
|
||||
case PlatformID.AIX:
|
||||
return "AIX";
|
||||
case PlatformID.Android:
|
||||
return "Android";
|
||||
case PlatformID.DragonFly:
|
||||
return "DragonFly BSD";
|
||||
case PlatformID.FreeBSD:
|
||||
return "FreeBSD";
|
||||
case PlatformID.Haiku:
|
||||
return "Haiku";
|
||||
case PlatformID.HPUX:
|
||||
return "HP/UX";
|
||||
case PlatformID.Hurd:
|
||||
return "Hurd";
|
||||
case PlatformID.iOS:
|
||||
return "iOS";
|
||||
case PlatformID.IRIX:
|
||||
return "IRIX";
|
||||
case PlatformID.Linux:
|
||||
if(!File.Exists("/proc/version")) return "Linux";
|
||||
|
||||
string s = File.ReadAllText("/proc/version");
|
||||
|
||||
return s.Contains("Microsoft") || s.Contains("WSL") ? "Windows Subsystem for Linux" : "Linux";
|
||||
|
||||
case PlatformID.MacOSX:
|
||||
if(string.IsNullOrEmpty(version)) return "macOS";
|
||||
|
||||
string[] pieces = version.Split('.');
|
||||
|
||||
if(pieces.Length < 2 || !int.TryParse(pieces[1], out int minor)) return "macOS";
|
||||
|
||||
if(minor >= 12) return "macOS";
|
||||
|
||||
if(minor >= 8) return "OS X";
|
||||
|
||||
return "Mac OS X";
|
||||
|
||||
case PlatformID.Minix:
|
||||
return "MINIX";
|
||||
case PlatformID.NetBSD:
|
||||
return "NetBSD";
|
||||
case PlatformID.NonStop:
|
||||
return "NonStop OS";
|
||||
case PlatformID.OpenBSD:
|
||||
return "OpenBSD";
|
||||
case PlatformID.OpenServer:
|
||||
return "SCO OpenServer";
|
||||
case PlatformID.OS400:
|
||||
return "OS/400";
|
||||
case PlatformID.PlayStation3:
|
||||
return "Sony CellOS";
|
||||
case PlatformID.PlayStation4:
|
||||
return "Sony Orbis OS";
|
||||
case PlatformID.QNX:
|
||||
return "QNX";
|
||||
case PlatformID.SINIX:
|
||||
return "SINIX";
|
||||
case PlatformID.Solaris:
|
||||
return "Sun Solaris";
|
||||
case PlatformID.Tizen:
|
||||
return "Samsung Tizen";
|
||||
case PlatformID.Tru64:
|
||||
return "Tru64 UNIX";
|
||||
case PlatformID.Ultrix:
|
||||
return "Ultrix";
|
||||
case PlatformID.Unix:
|
||||
return "UNIX";
|
||||
case PlatformID.UnixWare:
|
||||
return "SCO UnixWare";
|
||||
case PlatformID.Wii:
|
||||
return "Nintendo Wii";
|
||||
case PlatformID.WiiU:
|
||||
return "Nintendo Wii U";
|
||||
case PlatformID.Win32NT:
|
||||
if(string.IsNullOrEmpty(version)) return "Windows NT/2000/XP/Vista/7/10";
|
||||
|
||||
if(version.StartsWith("3.", StringComparison.Ordinal) ||
|
||||
version.StartsWith("4.", StringComparison.Ordinal))
|
||||
return "Windows NT";
|
||||
|
||||
if(version.StartsWith("5.0", StringComparison.Ordinal)) return "Windows 2000";
|
||||
|
||||
if(version.StartsWith("5.1", StringComparison.Ordinal)) return "Windows XP";
|
||||
|
||||
if(version.StartsWith("5.2", StringComparison.Ordinal)) return "Windows 2003";
|
||||
|
||||
if(version.StartsWith("6.0", StringComparison.Ordinal)) return "Windows Vista";
|
||||
|
||||
if(version.StartsWith("6.1", StringComparison.Ordinal)) return "Windows 7";
|
||||
|
||||
if(version.StartsWith("6.2", StringComparison.Ordinal)) return "Windows 8";
|
||||
|
||||
if(version.StartsWith("6.3", StringComparison.Ordinal)) return "Windows 8.1";
|
||||
|
||||
if(version.StartsWith("10.0", StringComparison.Ordinal)) return "Windows 10";
|
||||
|
||||
return "Windows NT/2000/XP/Vista/7/10";
|
||||
case PlatformID.Win32S:
|
||||
return "Windows 3.x with win32s";
|
||||
case PlatformID.Win32Windows:
|
||||
if(string.IsNullOrEmpty(version)) return "Windows 9x/Me";
|
||||
|
||||
if(version.StartsWith("4.0", StringComparison.Ordinal)) return "Windows 95";
|
||||
|
||||
if(version.StartsWith("4.10.2222", StringComparison.Ordinal)) return "Windows 98 SE";
|
||||
|
||||
if(version.StartsWith("4.1", StringComparison.Ordinal)) return "Windows 98";
|
||||
|
||||
if(version.StartsWith("4.9", StringComparison.Ordinal)) return "Windows Me";
|
||||
|
||||
return "Windows 9x/Me";
|
||||
case PlatformID.WinCE:
|
||||
return "Windows CE/Mobile";
|
||||
case PlatformID.WindowsPhone:
|
||||
return "Windows Phone";
|
||||
case PlatformID.Xbox:
|
||||
return "Xbox OS";
|
||||
case PlatformID.zOS:
|
||||
return "z/OS";
|
||||
default:
|
||||
return id.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>POSIX uname structure, size from OSX, big enough to handle extra fields</summary>
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
|
||||
struct utsname
|
||||
{
|
||||
/// <summary>System name</summary>
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
|
||||
public readonly string sysname;
|
||||
/// <summary>Node name</summary>
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
|
||||
public readonly string nodename;
|
||||
/// <summary>Release level</summary>
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
|
||||
public readonly string release;
|
||||
/// <summary>Version level</summary>
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
|
||||
public readonly string version;
|
||||
/// <summary>Hardware level</summary>
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
|
||||
public readonly string machine;
|
||||
}
|
||||
}
|
||||
@@ -38,83 +38,83 @@
|
||||
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace Aaru.CommonTypes.Interop
|
||||
namespace Aaru.CommonTypes.Interop;
|
||||
|
||||
/// <summary>Contains an arbitrary list of OSes, even if .NET does not run on them</summary>
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
public enum PlatformID
|
||||
{
|
||||
/// <summary>Contains an arbitrary list of OSes, even if .NET does not run on them</summary>
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
public enum PlatformID
|
||||
{
|
||||
/// <summary>Win32s</summary>
|
||||
Win32S = 0,
|
||||
/// <summary>Win32 (Windows 9x)</summary>
|
||||
Win32Windows = 1,
|
||||
/// <summary>Windows NT</summary>
|
||||
Win32NT = 2,
|
||||
/// <summary>Windows Mobile</summary>
|
||||
WinCE = 3,
|
||||
/// <summary>UNIX (do not use, too generic)</summary>
|
||||
Unix = 4,
|
||||
/// <summary>Xbox 360</summary>
|
||||
Xbox = 5,
|
||||
/// <summary>OS X</summary>
|
||||
MacOSX = 6,
|
||||
/// <summary>iOS is not OS X</summary>
|
||||
iOS = 7,
|
||||
/// <summary>Linux</summary>
|
||||
Linux = 8,
|
||||
/// <summary>Sun Solaris</summary>
|
||||
Solaris = 9,
|
||||
/// <summary>NetBSD</summary>
|
||||
NetBSD = 10,
|
||||
/// <summary>OpenBSD</summary>
|
||||
OpenBSD = 11,
|
||||
/// <summary>FreeBSD</summary>
|
||||
FreeBSD = 12,
|
||||
/// <summary>DragonFly BSD</summary>
|
||||
DragonFly = 13,
|
||||
/// <summary>Nintendo Wii</summary>
|
||||
Wii = 14,
|
||||
/// <summary>Nintendo Wii U</summary>
|
||||
WiiU = 15,
|
||||
/// <summary>Sony PlayStation 3</summary>
|
||||
PlayStation3 = 16,
|
||||
/// <summary>Sony Playstation 4</summary>
|
||||
PlayStation4 = 17,
|
||||
/// <summary>Google Android</summary>
|
||||
Android = 18,
|
||||
/// <summary>Samsung Tizen</summary>
|
||||
Tizen = 19,
|
||||
/// <summary>Windows Phone</summary>
|
||||
WindowsPhone = 20,
|
||||
/// <summary>GNU/Hurd</summary>
|
||||
Hurd = 21,
|
||||
/// <summary>Haiku</summary>
|
||||
Haiku = 22,
|
||||
/// <summary>HP-UX</summary>
|
||||
HPUX = 23,
|
||||
/// <summary>AIX</summary>
|
||||
AIX = 24,
|
||||
/// <summary>OS/400</summary>
|
||||
OS400 = 25,
|
||||
/// <summary>IRIX</summary>
|
||||
IRIX = 26,
|
||||
/// <summary>Minix</summary>
|
||||
Minix = 27,
|
||||
/// <summary>NonStop</summary>
|
||||
NonStop = 28,
|
||||
/// <summary>QNX</summary>
|
||||
QNX = 29,
|
||||
/// <summary>SINIX</summary>
|
||||
SINIX = 30,
|
||||
/// <summary>Tru64 UNIX</summary>
|
||||
Tru64 = 31,
|
||||
/// <summary>Ultrix</summary>
|
||||
Ultrix = 32,
|
||||
/// <summary>SCO OpenServer / SCO UNIX</summary>
|
||||
OpenServer = 33,
|
||||
/// <summary>SCO UnixWare</summary>
|
||||
UnixWare = 34,
|
||||
/// <summary>IBM z/OS</summary>
|
||||
zOS = 35, Unknown = -1
|
||||
}
|
||||
/// <summary>Win32s</summary>
|
||||
Win32S = 0,
|
||||
/// <summary>Win32 (Windows 9x)</summary>
|
||||
Win32Windows = 1,
|
||||
/// <summary>Windows NT</summary>
|
||||
Win32NT = 2,
|
||||
/// <summary>Windows Mobile</summary>
|
||||
WinCE = 3,
|
||||
/// <summary>UNIX (do not use, too generic)</summary>
|
||||
Unix = 4,
|
||||
/// <summary>Xbox 360</summary>
|
||||
Xbox = 5,
|
||||
/// <summary>OS X</summary>
|
||||
MacOSX = 6,
|
||||
/// <summary>iOS is not OS X</summary>
|
||||
iOS = 7,
|
||||
/// <summary>Linux</summary>
|
||||
Linux = 8,
|
||||
/// <summary>Sun Solaris</summary>
|
||||
Solaris = 9,
|
||||
/// <summary>NetBSD</summary>
|
||||
NetBSD = 10,
|
||||
/// <summary>OpenBSD</summary>
|
||||
OpenBSD = 11,
|
||||
/// <summary>FreeBSD</summary>
|
||||
FreeBSD = 12,
|
||||
/// <summary>DragonFly BSD</summary>
|
||||
DragonFly = 13,
|
||||
/// <summary>Nintendo Wii</summary>
|
||||
Wii = 14,
|
||||
/// <summary>Nintendo Wii U</summary>
|
||||
WiiU = 15,
|
||||
/// <summary>Sony PlayStation 3</summary>
|
||||
PlayStation3 = 16,
|
||||
/// <summary>Sony Playstation 4</summary>
|
||||
PlayStation4 = 17,
|
||||
/// <summary>Google Android</summary>
|
||||
Android = 18,
|
||||
/// <summary>Samsung Tizen</summary>
|
||||
Tizen = 19,
|
||||
/// <summary>Windows Phone</summary>
|
||||
WindowsPhone = 20,
|
||||
/// <summary>GNU/Hurd</summary>
|
||||
Hurd = 21,
|
||||
/// <summary>Haiku</summary>
|
||||
Haiku = 22,
|
||||
/// <summary>HP-UX</summary>
|
||||
HPUX = 23,
|
||||
/// <summary>AIX</summary>
|
||||
AIX = 24,
|
||||
/// <summary>OS/400</summary>
|
||||
OS400 = 25,
|
||||
/// <summary>IRIX</summary>
|
||||
IRIX = 26,
|
||||
/// <summary>Minix</summary>
|
||||
Minix = 27,
|
||||
/// <summary>NonStop</summary>
|
||||
NonStop = 28,
|
||||
/// <summary>QNX</summary>
|
||||
QNX = 29,
|
||||
/// <summary>SINIX</summary>
|
||||
SINIX = 30,
|
||||
/// <summary>Tru64 UNIX</summary>
|
||||
Tru64 = 31,
|
||||
/// <summary>Ultrix</summary>
|
||||
Ultrix = 32,
|
||||
/// <summary>SCO OpenServer / SCO UNIX</summary>
|
||||
OpenServer = 33,
|
||||
/// <summary>SCO UnixWare</summary>
|
||||
UnixWare = 34,
|
||||
/// <summary>IBM z/OS</summary>
|
||||
zOS = 35,
|
||||
Unknown = -1
|
||||
}
|
||||
@@ -40,44 +40,40 @@ using System;
|
||||
using System.Reflection;
|
||||
using System.Runtime;
|
||||
|
||||
namespace Aaru.CommonTypes.Interop
|
||||
namespace Aaru.CommonTypes.Interop;
|
||||
|
||||
public static class Version
|
||||
{
|
||||
public static class Version
|
||||
/// <summary>Gets version string</summary>
|
||||
/// <returns>Version</returns>
|
||||
public static string GetVersion() => typeof(Version).Assembly.GetName().Version?.ToString();
|
||||
|
||||
public static string GetNetCoreVersion()
|
||||
{
|
||||
/// <summary>Gets version string</summary>
|
||||
/// <returns>Version</returns>
|
||||
public static string GetVersion() => typeof(Version).Assembly.GetName().Version?.ToString();
|
||||
Assembly assembly = typeof(GCSettings).Assembly;
|
||||
|
||||
public static string GetNetCoreVersion()
|
||||
{
|
||||
Assembly assembly = typeof(GCSettings).Assembly;
|
||||
string[] assemblyPath = assembly.Location.Split(new[]
|
||||
{
|
||||
'/', '\\'
|
||||
},
|
||||
StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
string[] assemblyPath = assembly.Location.Split(new[]
|
||||
{
|
||||
'/', '\\'
|
||||
}, StringSplitOptions.RemoveEmptyEntries);
|
||||
int netCoreAppIndex = Array.IndexOf(assemblyPath, "Microsoft.NETCore.App");
|
||||
|
||||
int netCoreAppIndex = Array.IndexOf(assemblyPath, "Microsoft.NETCore.App");
|
||||
if(netCoreAppIndex > 0 && netCoreAppIndex < assemblyPath.Length - 2) return assemblyPath[netCoreAppIndex + 1];
|
||||
|
||||
if(netCoreAppIndex > 0 &&
|
||||
netCoreAppIndex < assemblyPath.Length - 2)
|
||||
return assemblyPath[netCoreAppIndex + 1];
|
||||
return null;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
public static string GetMonoVersion()
|
||||
{
|
||||
if(!DetectOS.IsMono) return null;
|
||||
|
||||
public static string GetMonoVersion()
|
||||
{
|
||||
if(!DetectOS.IsMono)
|
||||
return null;
|
||||
MethodInfo monoDisplayName = Type.GetType("Mono.Runtime")
|
||||
?.GetMethod("GetDisplayName", BindingFlags.NonPublic | BindingFlags.Static);
|
||||
|
||||
MethodInfo monoDisplayName = Type.GetType("Mono.Runtime")?.
|
||||
GetMethod("GetDisplayName", BindingFlags.NonPublic | BindingFlags.Static);
|
||||
if(monoDisplayName != null) return (string)monoDisplayName.Invoke(null, null);
|
||||
|
||||
if(monoDisplayName != null)
|
||||
return (string)monoDisplayName.Invoke(null, null);
|
||||
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -11,32 +11,46 @@ namespace RomRepoMgr.Settings.Resources {
|
||||
using System;
|
||||
|
||||
|
||||
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
|
||||
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
/// <summary>
|
||||
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||
/// </summary>
|
||||
// This class was auto-generated by the StronglyTypedResourceBuilder
|
||||
// class via a tool like ResGen or Visual Studio.
|
||||
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||
// with the /str option, or rebuild your VS project.
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class Localization {
|
||||
|
||||
private static System.Resources.ResourceManager resourceMan;
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static System.Globalization.CultureInfo resourceCulture;
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal Localization() {
|
||||
}
|
||||
|
||||
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static System.Resources.ResourceManager ResourceManager {
|
||||
/// <summary>
|
||||
/// Returns the cached ResourceManager instance used by this class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if (object.Equals(null, resourceMan)) {
|
||||
System.Resources.ResourceManager temp = new System.Resources.ResourceManager("RomRepoMgr.Settings.Resources.Localization", typeof(Localization).Assembly);
|
||||
if (object.ReferenceEquals(resourceMan, null)) {
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("RomRepoMgr.Settings.Resources.Localization", typeof(Localization).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static System.Globalization.CultureInfo Culture {
|
||||
/// <summary>
|
||||
/// Overrides the current thread's CurrentUICulture property for all
|
||||
/// resource lookups using this strongly typed resource class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Globalization.CultureInfo Culture {
|
||||
get {
|
||||
return resourceCulture;
|
||||
}
|
||||
@@ -45,6 +59,9 @@ namespace RomRepoMgr.Settings.Resources {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Unhandled exception calling uname: {0}.
|
||||
/// </summary>
|
||||
internal static string Unhandled_exception_uname {
|
||||
get {
|
||||
return ResourceManager.GetString("Unhandled_exception_uname", resourceCulture);
|
||||
|
||||
@@ -1,17 +1,21 @@
|
||||
<root>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>1.3</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="Unhandled_exception_uname" xml:space="preserve">
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>1.3</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<data name="Unhandled_exception_uname" xml:space="preserve">
|
||||
<value>Excepción no controlada llamando a uname: {0}</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -1,22 +1,27 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
|
||||
<root>
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:element name="root" msdata:IsDataSet="true"></xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>1.3</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="Unhandled_exception_uname" xml:space="preserve">
|
||||
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" id="root"
|
||||
xmlns="">
|
||||
<xsd:element name="root" msdata:IsDataSet="true"></xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>1.3</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<data name="Unhandled_exception_uname" xml:space="preserve">
|
||||
<value>Unhandled exception calling uname: {0}</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -1,28 +1,28 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<LangVersion>default</LangVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<LangVersion>default</LangVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Win32.Registry" Version="5.0.0" />
|
||||
<PackageReference Include="plist-cil" Version="2.1.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Win32.Registry" Version="5.0.0"/>
|
||||
<PackageReference Include="plist-cil" Version="2.1.0"/>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Update="Resources\Localization.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Localization.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Update="Resources\Localization.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Localization.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Update="Resources\Localization.Designer.cs">
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Localization.resx</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Update="Resources\Localization.Designer.cs">
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Localization.resx</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -31,280 +31,285 @@ using Claunia.PropertyList;
|
||||
using Microsoft.Win32;
|
||||
using PlatformID = Aaru.CommonTypes.Interop.PlatformID;
|
||||
|
||||
namespace RomRepoMgr.Settings
|
||||
namespace RomRepoMgr.Settings;
|
||||
|
||||
public sealed class SetSettings
|
||||
{
|
||||
public sealed class SetSettings
|
||||
public string DatabasePath { get; set; }
|
||||
public string RepositoryPath { get; set; }
|
||||
public string TemporaryFolder { get; set; }
|
||||
public string UnArchiverPath { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>Manages statistics</summary>
|
||||
public static class Settings
|
||||
{
|
||||
const string XDG_CONFIG_HOME = "XDG_CONFIG_HOME";
|
||||
const string XDG_CONFIG_HOME_RESOLVED = ".config";
|
||||
/// <summary>Current statistics</summary>
|
||||
public static SetSettings Current;
|
||||
public static bool UnArUsable { get; set; }
|
||||
|
||||
/// <summary>Loads settings</summary>
|
||||
public static void LoadSettings()
|
||||
{
|
||||
public string DatabasePath { get; set; }
|
||||
public string RepositoryPath { get; set; }
|
||||
public string TemporaryFolder { get; set; }
|
||||
public string UnArchiverPath { get; set; }
|
||||
Current = new SetSettings();
|
||||
PlatformID ptId = DetectOS.GetRealPlatformID();
|
||||
string homePath = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
|
||||
|
||||
FileStream prefsFs = null;
|
||||
StreamReader prefsSr = null;
|
||||
|
||||
try
|
||||
{
|
||||
switch(ptId)
|
||||
{
|
||||
// In case of macOS or iOS settings will be saved in ~/Library/Preferences/com.claunia.romrepomgr.plist
|
||||
case PlatformID.MacOSX:
|
||||
case PlatformID.iOS:
|
||||
{
|
||||
string preferencesPath =
|
||||
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile),
|
||||
"Library",
|
||||
"Preferences");
|
||||
|
||||
string preferencesFilePath = Path.Combine(preferencesPath, "com.claunia.romrepomgr.plist");
|
||||
|
||||
if(!File.Exists(preferencesFilePath))
|
||||
{
|
||||
SetDefaultSettings();
|
||||
SaveSettings();
|
||||
}
|
||||
|
||||
prefsFs = new FileStream(preferencesFilePath, FileMode.Open, FileAccess.Read);
|
||||
|
||||
var parsedPreferences = (NSDictionary)BinaryPropertyListParser.Parse(prefsFs);
|
||||
|
||||
if(parsedPreferences != null)
|
||||
{
|
||||
NSObject obj;
|
||||
|
||||
Current.DatabasePath = parsedPreferences.TryGetValue("DatabasePath", out obj)
|
||||
? ((NSString)obj).ToString()
|
||||
: null;
|
||||
|
||||
Current.RepositoryPath = parsedPreferences.TryGetValue("RepositoryPath", out obj)
|
||||
? ((NSString)obj).ToString()
|
||||
: null;
|
||||
|
||||
Current.TemporaryFolder = parsedPreferences.TryGetValue("TemporaryFolder", out obj)
|
||||
? ((NSString)obj).ToString()
|
||||
: null;
|
||||
|
||||
Current.UnArchiverPath = parsedPreferences.TryGetValue("UnArchiverPath", out obj)
|
||||
? ((NSString)obj).ToString()
|
||||
: null;
|
||||
|
||||
prefsFs.Close();
|
||||
}
|
||||
else
|
||||
{
|
||||
prefsFs.Close();
|
||||
|
||||
SetDefaultSettings();
|
||||
SaveSettings();
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
#if !NETSTANDARD2_0
|
||||
|
||||
// In case of Windows settings will be saved in the registry: HKLM/SOFTWARE/Claunia.com/RomRepoMgr
|
||||
case PlatformID.Win32NT when OperatingSystem.IsWindows():
|
||||
case PlatformID.Win32S when OperatingSystem.IsWindows():
|
||||
case PlatformID.Win32Windows when OperatingSystem.IsWindows():
|
||||
case PlatformID.WinCE when OperatingSystem.IsWindows():
|
||||
case PlatformID.WindowsPhone when OperatingSystem.IsWindows():
|
||||
{
|
||||
RegistryKey parentKey = Registry.CurrentUser.OpenSubKey("SOFTWARE")?.OpenSubKey("Claunia.com");
|
||||
|
||||
if(parentKey == null)
|
||||
{
|
||||
SetDefaultSettings();
|
||||
SaveSettings();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
RegistryKey key = parentKey.OpenSubKey("RomRepoMgr");
|
||||
|
||||
if(key == null)
|
||||
{
|
||||
SetDefaultSettings();
|
||||
SaveSettings();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Current.DatabasePath = key.GetValue("DatabasePath") as string;
|
||||
Current.RepositoryPath = key.GetValue("RepositoryPath") as string;
|
||||
Current.TemporaryFolder = key.GetValue("TemporaryFolder") as string;
|
||||
Current.UnArchiverPath = key.GetValue("UnArchiverPath") as string;
|
||||
}
|
||||
|
||||
break;
|
||||
#endif
|
||||
|
||||
// Otherwise, settings will be saved in ~/.config/RomRepoMgr.json
|
||||
default:
|
||||
{
|
||||
string xdgConfigPath = Path.Combine(homePath,
|
||||
Environment.GetEnvironmentVariable(XDG_CONFIG_HOME) ??
|
||||
XDG_CONFIG_HOME_RESOLVED);
|
||||
|
||||
string settingsPath = Path.Combine(xdgConfigPath, "RomRepoMgr.json");
|
||||
|
||||
if(!File.Exists(settingsPath))
|
||||
{
|
||||
SetDefaultSettings();
|
||||
SaveSettings();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
prefsSr = new StreamReader(settingsPath);
|
||||
|
||||
Current = JsonSerializer.Deserialize<SetSettings>(prefsSr.ReadToEnd(),
|
||||
new JsonSerializerOptions
|
||||
{
|
||||
AllowTrailingCommas = true,
|
||||
PropertyNameCaseInsensitive = true,
|
||||
ReadCommentHandling =
|
||||
JsonCommentHandling.Skip,
|
||||
WriteIndented = true
|
||||
});
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
prefsFs?.Close();
|
||||
prefsSr?.Close();
|
||||
SetDefaultSettings();
|
||||
SaveSettings();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Manages statistics</summary>
|
||||
public static class Settings
|
||||
public static void SaveSettings()
|
||||
{
|
||||
const string XDG_CONFIG_HOME = "XDG_CONFIG_HOME";
|
||||
const string XDG_CONFIG_HOME_RESOLVED = ".config";
|
||||
/// <summary>Current statistics</summary>
|
||||
public static SetSettings Current;
|
||||
public static bool UnArUsable { get; set; }
|
||||
|
||||
/// <summary>Loads settings</summary>
|
||||
public static void LoadSettings()
|
||||
try
|
||||
{
|
||||
Current = new SetSettings();
|
||||
PlatformID ptId = DetectOS.GetRealPlatformID();
|
||||
string homePath = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
|
||||
PlatformID ptId = DetectOS.GetRealPlatformID();
|
||||
|
||||
FileStream prefsFs = null;
|
||||
StreamReader prefsSr = null;
|
||||
|
||||
try
|
||||
switch(ptId)
|
||||
{
|
||||
switch(ptId)
|
||||
// In case of macOS or iOS settings will be saved in ~/Library/Preferences/com.claunia.romrepomgr.plist
|
||||
case PlatformID.MacOSX:
|
||||
case PlatformID.iOS:
|
||||
{
|
||||
// In case of macOS or iOS settings will be saved in ~/Library/Preferences/com.claunia.romrepomgr.plist
|
||||
case PlatformID.MacOSX:
|
||||
case PlatformID.iOS:
|
||||
var root = new NSDictionary
|
||||
{
|
||||
string preferencesPath =
|
||||
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "Library",
|
||||
"Preferences");
|
||||
|
||||
string preferencesFilePath = Path.Combine(preferencesPath, "com.claunia.romrepomgr.plist");
|
||||
|
||||
if(!File.Exists(preferencesFilePath))
|
||||
{
|
||||
SetDefaultSettings();
|
||||
SaveSettings();
|
||||
"DatabasePath", Current.DatabasePath
|
||||
},
|
||||
{
|
||||
"RepositoryPath", Current.RepositoryPath
|
||||
},
|
||||
{
|
||||
"TemporaryFolder", Current.TemporaryFolder
|
||||
},
|
||||
{
|
||||
"UnArchiverPath", Current.UnArchiverPath
|
||||
}
|
||||
};
|
||||
|
||||
prefsFs = new FileStream(preferencesFilePath, FileMode.Open, FileAccess.Read);
|
||||
string preferencesPath =
|
||||
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile),
|
||||
"Library",
|
||||
"Preferences");
|
||||
|
||||
var parsedPreferences = (NSDictionary)BinaryPropertyListParser.Parse(prefsFs);
|
||||
string preferencesFilePath = Path.Combine(preferencesPath, "com.claunia.romrepomgr.plist");
|
||||
|
||||
if(parsedPreferences != null)
|
||||
{
|
||||
NSObject obj;
|
||||
|
||||
Current.DatabasePath = parsedPreferences.TryGetValue("DatabasePath", out obj)
|
||||
? ((NSString)obj).ToString() : null;
|
||||
|
||||
Current.RepositoryPath = parsedPreferences.TryGetValue("RepositoryPath", out obj)
|
||||
? ((NSString)obj).ToString() : null;
|
||||
|
||||
Current.TemporaryFolder = parsedPreferences.TryGetValue("TemporaryFolder", out obj)
|
||||
? ((NSString)obj).ToString() : null;
|
||||
|
||||
Current.UnArchiverPath = parsedPreferences.TryGetValue("UnArchiverPath", out obj)
|
||||
? ((NSString)obj).ToString() : null;
|
||||
|
||||
prefsFs.Close();
|
||||
}
|
||||
else
|
||||
{
|
||||
prefsFs.Close();
|
||||
|
||||
SetDefaultSettings();
|
||||
SaveSettings();
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
#if !NETSTANDARD2_0
|
||||
|
||||
// In case of Windows settings will be saved in the registry: HKLM/SOFTWARE/Claunia.com/RomRepoMgr
|
||||
case PlatformID.Win32NT when OperatingSystem.IsWindows():
|
||||
case PlatformID.Win32S when OperatingSystem.IsWindows():
|
||||
case PlatformID.Win32Windows when OperatingSystem.IsWindows():
|
||||
case PlatformID.WinCE when OperatingSystem.IsWindows():
|
||||
case PlatformID.WindowsPhone when OperatingSystem.IsWindows():
|
||||
{
|
||||
RegistryKey parentKey = Registry.CurrentUser.OpenSubKey("SOFTWARE")?.OpenSubKey("Claunia.com");
|
||||
|
||||
if(parentKey == null)
|
||||
{
|
||||
SetDefaultSettings();
|
||||
SaveSettings();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
RegistryKey key = parentKey.OpenSubKey("RomRepoMgr");
|
||||
|
||||
if(key == null)
|
||||
{
|
||||
SetDefaultSettings();
|
||||
SaveSettings();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Current.DatabasePath = key.GetValue("DatabasePath") as string;
|
||||
Current.RepositoryPath = key.GetValue("RepositoryPath") as string;
|
||||
Current.TemporaryFolder = key.GetValue("TemporaryFolder") as string;
|
||||
Current.UnArchiverPath = key.GetValue("UnArchiverPath") as string;
|
||||
}
|
||||
|
||||
break;
|
||||
#endif
|
||||
|
||||
// Otherwise, settings will be saved in ~/.config/RomRepoMgr.json
|
||||
default:
|
||||
{
|
||||
string xdgConfigPath =
|
||||
Path.Combine(homePath,
|
||||
Environment.GetEnvironmentVariable(XDG_CONFIG_HOME) ??
|
||||
XDG_CONFIG_HOME_RESOLVED);
|
||||
|
||||
string settingsPath = Path.Combine(xdgConfigPath, "RomRepoMgr.json");
|
||||
|
||||
if(!File.Exists(settingsPath))
|
||||
{
|
||||
SetDefaultSettings();
|
||||
SaveSettings();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
prefsSr = new StreamReader(settingsPath);
|
||||
|
||||
Current = JsonSerializer.Deserialize<SetSettings>(prefsSr.ReadToEnd(), new JsonSerializerOptions
|
||||
{
|
||||
AllowTrailingCommas = true,
|
||||
PropertyNameCaseInsensitive = true,
|
||||
ReadCommentHandling = JsonCommentHandling.Skip,
|
||||
WriteIndented = true
|
||||
});
|
||||
}
|
||||
|
||||
break;
|
||||
var fs = new FileStream(preferencesFilePath, FileMode.Create);
|
||||
BinaryPropertyListWriter.Write(fs, root);
|
||||
fs.Close();
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
prefsFs?.Close();
|
||||
prefsSr?.Close();
|
||||
SetDefaultSettings();
|
||||
SaveSettings();
|
||||
}
|
||||
}
|
||||
|
||||
public static void SaveSettings()
|
||||
{
|
||||
try
|
||||
{
|
||||
PlatformID ptId = DetectOS.GetRealPlatformID();
|
||||
break;
|
||||
#if !NETSTANDARD2_0
|
||||
|
||||
switch(ptId)
|
||||
// In case of Windows settings will be saved in the registry: HKLM/SOFTWARE/Claunia.com/RomRepoMgr
|
||||
case PlatformID.Win32NT when OperatingSystem.IsWindows():
|
||||
case PlatformID.Win32S when OperatingSystem.IsWindows():
|
||||
case PlatformID.Win32Windows when OperatingSystem.IsWindows():
|
||||
case PlatformID.WinCE when OperatingSystem.IsWindows():
|
||||
case PlatformID.WindowsPhone when OperatingSystem.IsWindows():
|
||||
{
|
||||
// In case of macOS or iOS settings will be saved in ~/Library/Preferences/com.claunia.romrepomgr.plist
|
||||
case PlatformID.MacOSX:
|
||||
case PlatformID.iOS:
|
||||
{
|
||||
var root = new NSDictionary
|
||||
{
|
||||
{
|
||||
"DatabasePath", Current.DatabasePath
|
||||
},
|
||||
{
|
||||
"RepositoryPath", Current.RepositoryPath
|
||||
},
|
||||
{
|
||||
"TemporaryFolder", Current.TemporaryFolder
|
||||
},
|
||||
{
|
||||
"UnArchiverPath", Current.UnArchiverPath
|
||||
}
|
||||
};
|
||||
RegistryKey parentKey =
|
||||
Registry.CurrentUser.OpenSubKey("SOFTWARE", true)?.CreateSubKey("Claunia.com");
|
||||
|
||||
string preferencesPath =
|
||||
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "Library",
|
||||
"Preferences");
|
||||
RegistryKey key = parentKey?.CreateSubKey("RomRepoMgr");
|
||||
|
||||
string preferencesFilePath = Path.Combine(preferencesPath, "com.claunia.romrepomgr.plist");
|
||||
|
||||
var fs = new FileStream(preferencesFilePath, FileMode.Create);
|
||||
BinaryPropertyListWriter.Write(fs, root);
|
||||
fs.Close();
|
||||
}
|
||||
|
||||
break;
|
||||
#if !NETSTANDARD2_0
|
||||
|
||||
// In case of Windows settings will be saved in the registry: HKLM/SOFTWARE/Claunia.com/RomRepoMgr
|
||||
case PlatformID.Win32NT when OperatingSystem.IsWindows():
|
||||
case PlatformID.Win32S when OperatingSystem.IsWindows():
|
||||
case PlatformID.Win32Windows when OperatingSystem.IsWindows():
|
||||
case PlatformID.WinCE when OperatingSystem.IsWindows():
|
||||
case PlatformID.WindowsPhone when OperatingSystem.IsWindows():
|
||||
{
|
||||
RegistryKey parentKey = Registry.CurrentUser.OpenSubKey("SOFTWARE", true)?.
|
||||
CreateSubKey("Claunia.com");
|
||||
|
||||
RegistryKey key = parentKey?.CreateSubKey("RomRepoMgr");
|
||||
|
||||
key?.SetValue("DatabasePath", Current.DatabasePath);
|
||||
key?.SetValue("RepositoryPath", Current.RepositoryPath);
|
||||
key?.SetValue("TemporaryFolder", Current.TemporaryFolder);
|
||||
key?.SetValue("UnArchiverPath", Current.UnArchiverPath);
|
||||
}
|
||||
|
||||
break;
|
||||
#endif
|
||||
|
||||
// Otherwise, settings will be saved in ~/.config/RomRepoMgr.json
|
||||
default:
|
||||
{
|
||||
string homePath = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
|
||||
|
||||
string xdgConfigPath =
|
||||
Path.Combine(homePath,
|
||||
Environment.GetEnvironmentVariable(XDG_CONFIG_HOME) ??
|
||||
XDG_CONFIG_HOME_RESOLVED);
|
||||
|
||||
string settingsPath = Path.Combine(xdgConfigPath, "RomRepoMgr.json");
|
||||
|
||||
if(!Directory.Exists(xdgConfigPath))
|
||||
Directory.CreateDirectory(xdgConfigPath);
|
||||
|
||||
var prefsSr = new StreamWriter(settingsPath);
|
||||
|
||||
prefsSr.Write(JsonSerializer.Serialize(Current, new JsonSerializerOptions
|
||||
{
|
||||
AllowTrailingCommas = true,
|
||||
PropertyNameCaseInsensitive = true,
|
||||
ReadCommentHandling = JsonCommentHandling.Skip,
|
||||
WriteIndented = true
|
||||
}));
|
||||
|
||||
prefsSr.Close();
|
||||
}
|
||||
|
||||
break;
|
||||
key?.SetValue("DatabasePath", Current.DatabasePath);
|
||||
key?.SetValue("RepositoryPath", Current.RepositoryPath);
|
||||
key?.SetValue("TemporaryFolder", Current.TemporaryFolder);
|
||||
key?.SetValue("UnArchiverPath", Current.UnArchiverPath);
|
||||
}
|
||||
}
|
||||
#pragma warning disable RECS0022 // A catch clause that catches System.Exception and has an empty body
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
#pragma warning restore RECS0022 // A catch clause that catches System.Exception and has an empty body
|
||||
}
|
||||
|
||||
/// <summary>Sets default settings as all statistics, share everything</summary>
|
||||
static void SetDefaultSettings()
|
||||
break;
|
||||
#endif
|
||||
|
||||
// Otherwise, settings will be saved in ~/.config/RomRepoMgr.json
|
||||
default:
|
||||
{
|
||||
string homePath = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
|
||||
|
||||
string xdgConfigPath = Path.Combine(homePath,
|
||||
Environment.GetEnvironmentVariable(XDG_CONFIG_HOME) ??
|
||||
XDG_CONFIG_HOME_RESOLVED);
|
||||
|
||||
string settingsPath = Path.Combine(xdgConfigPath, "RomRepoMgr.json");
|
||||
|
||||
if(!Directory.Exists(xdgConfigPath)) Directory.CreateDirectory(xdgConfigPath);
|
||||
|
||||
var prefsSr = new StreamWriter(settingsPath);
|
||||
|
||||
prefsSr.Write(JsonSerializer.Serialize(Current,
|
||||
new JsonSerializerOptions
|
||||
{
|
||||
AllowTrailingCommas = true,
|
||||
PropertyNameCaseInsensitive = true,
|
||||
ReadCommentHandling = JsonCommentHandling.Skip,
|
||||
WriteIndented = true
|
||||
}));
|
||||
|
||||
prefsSr.Close();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
#pragma warning disable RECS0022 // A catch clause that catches System.Exception and has an empty body
|
||||
catch
|
||||
{
|
||||
string docsPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
|
||||
string dataPath = Path.Combine(docsPath, "RomRepoMgr");
|
||||
|
||||
Current = new SetSettings
|
||||
{
|
||||
DatabasePath = Path.Combine(dataPath, "romrepo.db"),
|
||||
RepositoryPath = Path.Combine(dataPath, "repo"),
|
||||
TemporaryFolder = Path.GetTempPath()
|
||||
};
|
||||
// ignored
|
||||
}
|
||||
#pragma warning restore RECS0022 // A catch clause that catches System.Exception and has an empty body
|
||||
}
|
||||
|
||||
/// <summary>Sets default settings as all statistics, share everything</summary>
|
||||
static void SetDefaultSettings()
|
||||
{
|
||||
string docsPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
|
||||
string dataPath = Path.Combine(docsPath, "RomRepoMgr");
|
||||
|
||||
Current = new SetSettings
|
||||
{
|
||||
DatabasePath = Path.Combine(dataPath, "romrepo.db"),
|
||||
RepositoryPath = Path.Combine(dataPath, "repo"),
|
||||
TemporaryFolder = Path.GetTempPath()
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
<Application xmlns="https://github.com/avaloniaui" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:RomRepoMgr" x:Class="RomRepoMgr.App">
|
||||
<Application xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:RomRepoMgr"
|
||||
x:Class="RomRepoMgr.App">
|
||||
<Application.DataTemplates>
|
||||
<local:ViewLocator />
|
||||
</Application.DataTemplates>
|
||||
@@ -10,9 +12,12 @@
|
||||
</Application.Styles>
|
||||
<NativeMenu.Menu>
|
||||
<NativeMenu>
|
||||
<NativeMenuItem Header="_About" Clicked="OnAboutClicked" />
|
||||
<NativeMenuItem Header="_Preferences" Clicked="OnPreferencesClicked" />
|
||||
<NativeMenuItem Header="_Quit" Clicked="OnQuitClicked" />
|
||||
<NativeMenuItem Header="_About"
|
||||
Clicked="OnAboutClicked" />
|
||||
<NativeMenuItem Header="_Preferences"
|
||||
Clicked="OnPreferencesClicked" />
|
||||
<NativeMenuItem Header="_Quit"
|
||||
Clicked="OnQuitClicked" />
|
||||
</NativeMenu>
|
||||
</NativeMenu.Menu>
|
||||
</Application>
|
||||
@@ -34,79 +34,77 @@ using RomRepoMgr.Core.Models;
|
||||
using RomRepoMgr.ViewModels;
|
||||
using RomRepoMgr.Views;
|
||||
|
||||
namespace RomRepoMgr
|
||||
namespace RomRepoMgr;
|
||||
|
||||
public class App : Application
|
||||
{
|
||||
public class App : Application
|
||||
List<RomSetModel> _romSets;
|
||||
|
||||
public override void Initialize() => AvaloniaXamlLoader.Load(this);
|
||||
|
||||
public override void OnFrameworkInitializationCompleted()
|
||||
{
|
||||
List<RomSetModel> _romSets;
|
||||
|
||||
public override void Initialize() => AvaloniaXamlLoader.Load(this);
|
||||
|
||||
public override void OnFrameworkInitializationCompleted()
|
||||
if(ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
|
||||
{
|
||||
if(ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
|
||||
{
|
||||
var splashWindow = new SplashWindow();
|
||||
var swvm = new SplashWindowViewModel();
|
||||
swvm.WorkFinished += OnSplashFinished;
|
||||
swvm.GotRomSets += OnGotRomSets;
|
||||
splashWindow.DataContext = swvm;
|
||||
desktop.MainWindow = splashWindow;
|
||||
}
|
||||
|
||||
base.OnFrameworkInitializationCompleted();
|
||||
var splashWindow = new SplashWindow();
|
||||
var swvm = new SplashWindowViewModel();
|
||||
swvm.WorkFinished += OnSplashFinished;
|
||||
swvm.GotRomSets += OnGotRomSets;
|
||||
splashWindow.DataContext = swvm;
|
||||
desktop.MainWindow = splashWindow;
|
||||
}
|
||||
|
||||
void OnGotRomSets(object sender, RomSetsEventArgs e) => _romSets = e.RomSets;
|
||||
base.OnFrameworkInitializationCompleted();
|
||||
}
|
||||
|
||||
void OnSplashFinished(object sender, EventArgs e)
|
||||
{
|
||||
if(!(ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop))
|
||||
return;
|
||||
void OnGotRomSets(object sender, RomSetsEventArgs e) => _romSets = e.RomSets;
|
||||
|
||||
// Ensure not exit
|
||||
desktop.ShutdownMode = ShutdownMode.OnExplicitShutdown;
|
||||
void OnSplashFinished(object sender, EventArgs e)
|
||||
{
|
||||
if(!(ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)) return;
|
||||
|
||||
// Close splash window
|
||||
desktop.MainWindow.Close();
|
||||
// Ensure not exit
|
||||
desktop.ShutdownMode = ShutdownMode.OnExplicitShutdown;
|
||||
|
||||
// Create and show main window
|
||||
desktop.MainWindow = new MainWindow();
|
||||
desktop.MainWindow.DataContext = new MainWindowViewModel(desktop.MainWindow as MainWindow, _romSets);
|
||||
desktop.MainWindow.Show();
|
||||
// Close splash window
|
||||
desktop.MainWindow.Close();
|
||||
|
||||
// Now can close when all windows are closed
|
||||
desktop.ShutdownMode = ShutdownMode.OnLastWindowClose;
|
||||
}
|
||||
// Create and show main window
|
||||
desktop.MainWindow = new MainWindow();
|
||||
desktop.MainWindow.DataContext = new MainWindowViewModel(desktop.MainWindow as MainWindow, _romSets);
|
||||
desktop.MainWindow.Show();
|
||||
|
||||
void OnAboutClicked(object sender, EventArgs args)
|
||||
{
|
||||
if(!(ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) ||
|
||||
!(desktop.MainWindow is MainWindow mainWindow) ||
|
||||
!(mainWindow.DataContext is MainWindowViewModel mainWindowViewModel))
|
||||
return;
|
||||
// Now can close when all windows are closed
|
||||
desktop.ShutdownMode = ShutdownMode.OnLastWindowClose;
|
||||
}
|
||||
|
||||
mainWindowViewModel.ExecuteAboutCommand();
|
||||
}
|
||||
void OnAboutClicked(object sender, EventArgs args)
|
||||
{
|
||||
if(!(ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) ||
|
||||
!(desktop.MainWindow is MainWindow mainWindow) ||
|
||||
!(mainWindow.DataContext is MainWindowViewModel mainWindowViewModel))
|
||||
return;
|
||||
|
||||
void OnQuitClicked(object sender, EventArgs args)
|
||||
{
|
||||
if(!(ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) ||
|
||||
!(desktop.MainWindow is MainWindow mainWindow) ||
|
||||
!(mainWindow.DataContext is MainWindowViewModel mainWindowViewModel))
|
||||
return;
|
||||
mainWindowViewModel.ExecuteAboutCommand();
|
||||
}
|
||||
|
||||
mainWindowViewModel.ExecuteExitCommand();
|
||||
}
|
||||
void OnQuitClicked(object sender, EventArgs args)
|
||||
{
|
||||
if(!(ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) ||
|
||||
!(desktop.MainWindow is MainWindow mainWindow) ||
|
||||
!(mainWindow.DataContext is MainWindowViewModel mainWindowViewModel))
|
||||
return;
|
||||
|
||||
void OnPreferencesClicked(object sender, EventArgs args)
|
||||
{
|
||||
if(!(ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) ||
|
||||
!(desktop.MainWindow is MainWindow mainWindow) ||
|
||||
!(mainWindow.DataContext is MainWindowViewModel mainWindowViewModel))
|
||||
return;
|
||||
mainWindowViewModel.ExecuteExitCommand();
|
||||
}
|
||||
|
||||
mainWindowViewModel.ExecuteSettingsCommand();
|
||||
}
|
||||
void OnPreferencesClicked(object sender, EventArgs args)
|
||||
{
|
||||
if(!(ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) ||
|
||||
!(desktop.MainWindow is MainWindow mainWindow) ||
|
||||
!(mainWindow.DataContext is MainWindowViewModel mainWindowViewModel))
|
||||
return;
|
||||
|
||||
mainWindowViewModel.ExecuteSettingsCommand();
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,12 @@
|
||||
<svg viewBox="0 0 8 8" xmlns="http://www.w3.org/2000/svg">
|
||||
<style
|
||||
type="text/css"
|
||||
id="current-color-scheme">
|
||||
.ColorScheme-PositiveText {
|
||||
color:#27ae60;
|
||||
}
|
||||
</style>
|
||||
<rect style="fill:currentColor;fill-opacity:1;stroke:none" class="ColorScheme-PositiveText" height="8" rx="1" width="8"/>
|
||||
<path d="M6 2L3 5 1.5 3.5l-1 1L3 7l4-4z" fill="#fff"/>
|
||||
<style
|
||||
type="text/css"
|
||||
id="current-color-scheme">
|
||||
.ColorScheme-PositiveText {
|
||||
color:#27ae60;
|
||||
}
|
||||
</style>
|
||||
<rect style="fill:currentColor;fill-opacity:1;stroke:none" class="ColorScheme-PositiveText" height="8" rx="1"
|
||||
width="8"/>
|
||||
<path d="M6 2L3 5 1.5 3.5l-1 1L3 7l4-4z" fill="#fff"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 407 B After Width: | Height: | Size: 387 B |
@@ -1,11 +1,12 @@
|
||||
<svg viewBox="0 0 8 8" xmlns="http://www.w3.org/2000/svg">
|
||||
<style
|
||||
type="text/css"
|
||||
id="current-color-scheme">
|
||||
.ColorScheme-NegativeText {
|
||||
color:#da4453;
|
||||
}
|
||||
</style>
|
||||
<path style="fill:currentColor;fill-opacity:1;stroke:none" class="ColorScheme-NegativeText" d="M1 0C.446 0 0 .446 0 1v6c0 .554.446 1 1 1h6c.554 0 1-.446 1-1V1c0-.554-.446-1-1-1z"/>
|
||||
<path d="M2 1L1 2l2 2-2 2 1 1 2-2 2 2 1-1-2-2 2-2-1-1-2 2z" fill="#fff"/>
|
||||
<style
|
||||
type="text/css"
|
||||
id="current-color-scheme">
|
||||
.ColorScheme-NegativeText {
|
||||
color:#da4453;
|
||||
}
|
||||
</style>
|
||||
<path style="fill:currentColor;fill-opacity:1;stroke:none" class="ColorScheme-NegativeText"
|
||||
d="M1 0C.446 0 0 .446 0 1v6c0 .554.446 1 1 1h6c.554 0 1-.446 1-1V1c0-.554-.446-1-1-1z"/>
|
||||
<path d="M2 1L1 2l2 2-2 2 1 1 2-2 2 2 1-1-2-2 2-2-1-1-2 2z" fill="#fff"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 485 B After Width: | Height: | Size: 465 B |
@@ -1,4 +1,6 @@
|
||||
<svg viewBox="0 0 8 8" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect fill="#9b59b6" height="8" rx="1" width="8"/>
|
||||
<path d="M4 1a2 2 0 0 0-2 2h1a1 1 0 0 1 1-1 1 1 0 0 1 1 1 1 1 0 0 1-1 1H3v2h1V5a2 2 0 0 0 2-2 2 2 0 0 0-2-2zM3 7h1v1H3z" fill="#fff"/>
|
||||
<rect fill="#9b59b6" height="8" rx="1" width="8"/>
|
||||
<path
|
||||
d="M4 1a2 2 0 0 0-2 2h1a1 1 0 0 1 1-1 1 1 0 0 1 1 1 1 1 0 0 1-1 1H3v2h1V5a2 2 0 0 0 2-2 2 2 0 0 0-2-2zM3 7h1v1H3z"
|
||||
fill="#fff"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 260 B After Width: | Height: | Size: 268 B |
@@ -26,17 +26,16 @@
|
||||
using Avalonia;
|
||||
using Avalonia.ReactiveUI;
|
||||
|
||||
namespace RomRepoMgr
|
||||
{
|
||||
internal class Program
|
||||
{
|
||||
// Initialization code. Don't use any Avalonia, third-party APIs or any
|
||||
// SynchronizationContext-reliant code before AppMain is called: things aren't initialized
|
||||
// yet and stuff might break.
|
||||
public static void Main(string[] args) => BuildAvaloniaApp().StartWithClassicDesktopLifetime(args);
|
||||
namespace RomRepoMgr;
|
||||
|
||||
// Avalonia configuration, don't remove; also used by visual designer.
|
||||
public static AppBuilder BuildAvaloniaApp() =>
|
||||
AppBuilder.Configure<App>().UsePlatformDetect().LogToDebug().UseReactiveUI();
|
||||
}
|
||||
internal class Program
|
||||
{
|
||||
// Initialization code. Don't use any Avalonia, third-party APIs or any
|
||||
// SynchronizationContext-reliant code before AppMain is called: things aren't initialized
|
||||
// yet and stuff might break.
|
||||
public static void Main(string[] args) => BuildAvaloniaApp().StartWithClassicDesktopLifetime(args);
|
||||
|
||||
// Avalonia configuration, don't remove; also used by visual designer.
|
||||
public static AppBuilder BuildAvaloniaApp() =>
|
||||
AppBuilder.Configure<App>().UsePlatformDetect().LogToDebug().UseReactiveUI();
|
||||
}
|
||||
@@ -1,371 +1,375 @@
|
||||
<root>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>1.3</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="AboutLabel" xml:space="preserve">
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>1.3</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<data name="AboutLabel" xml:space="preserve">
|
||||
<value>Acerca de</value>
|
||||
</data>
|
||||
<data name="AboutTitle" xml:space="preserve">
|
||||
<data name="AboutTitle" xml:space="preserve">
|
||||
<value>Acerda de ROM Repository Manager</value>
|
||||
</data>
|
||||
<data name="AllFilesDialogLabel" xml:space="preserve">
|
||||
<data name="AllFilesDialogLabel" xml:space="preserve">
|
||||
<value>Todos los archivos</value>
|
||||
</data>
|
||||
<data name="AllFilesLabel" xml:space="preserve">
|
||||
<data name="AllFilesLabel" xml:space="preserve">
|
||||
<value>Comprobar todos los archivos.</value>
|
||||
</data>
|
||||
<data name="AssembliesLibraryText" xml:space="preserve">
|
||||
<data name="AssembliesLibraryText" xml:space="preserve">
|
||||
<value>Librería</value>
|
||||
</data>
|
||||
<data name="AssembliesVersionText" xml:space="preserve">
|
||||
<data name="AssembliesVersionText" xml:space="preserve">
|
||||
<value>Versión</value>
|
||||
</data>
|
||||
<data name="AuthorsLabel" xml:space="preserve">
|
||||
<data name="AuthorsLabel" xml:space="preserve">
|
||||
<value>Autores</value>
|
||||
</data>
|
||||
<data name="AuthorsText" xml:space="preserve">
|
||||
<data name="AuthorsText" xml:space="preserve">
|
||||
<value>Desarrolladores:
|
||||
Natalia Portillo</value>
|
||||
</data>
|
||||
<data name="CancelLabel" xml:space="preserve">
|
||||
<data name="CancelLabel" xml:space="preserve">
|
||||
<value>Cancelar</value>
|
||||
</data>
|
||||
<data name="CheckingUnArText" xml:space="preserve">
|
||||
<data name="CheckingUnArText" xml:space="preserve">
|
||||
<value>Comprobando The Unarchiver...</value>
|
||||
</data>
|
||||
<data name="ChooseDatabaseFile" xml:space="preserve">
|
||||
<data name="ChooseDatabaseFile" xml:space="preserve">
|
||||
<value>Elegir base de datos a abrir o crear</value>
|
||||
</data>
|
||||
<data name="ChooseLabel" xml:space="preserve">
|
||||
<data name="ChooseLabel" xml:space="preserve">
|
||||
<value>Elegir...</value>
|
||||
</data>
|
||||
<data name="ChooseRepositoryFolder" xml:space="preserve">
|
||||
<data name="ChooseRepositoryFolder" xml:space="preserve">
|
||||
<value>Elegir carpeta del repositorio</value>
|
||||
</data>
|
||||
<data name="ChooseTemporaryFolder" xml:space="preserve">
|
||||
<data name="ChooseTemporaryFolder" xml:space="preserve">
|
||||
<value>Elegir carpeta temporal</value>
|
||||
</data>
|
||||
<data name="ChooseUnArExecutable" xml:space="preserve">
|
||||
<data name="ChooseUnArExecutable" xml:space="preserve">
|
||||
<value>Elegir ejecutable de UnArchiver</value>
|
||||
</data>
|
||||
<data name="CloseLabel" xml:space="preserve">
|
||||
<data name="CloseLabel" xml:space="preserve">
|
||||
<value>Cerrar</value>
|
||||
</data>
|
||||
<data name="CompleteMachinesLabel" xml:space="preserve">
|
||||
<data name="CompleteMachinesLabel" xml:space="preserve">
|
||||
<value>Juegos completos</value>
|
||||
</data>
|
||||
<data name="DatabaseFileCannotDeleteCaption" xml:space="preserve">
|
||||
<data name="DatabaseFileCannotDeleteCaption" xml:space="preserve">
|
||||
<value>Ocurrió un error al eliminar el archivo elegido.</value>
|
||||
</data>
|
||||
<data name="DatabaseFileCannotDeleteTitle" xml:space="preserve">
|
||||
<data name="DatabaseFileCannotDeleteTitle" xml:space="preserve">
|
||||
<value>No se pudo eliminar el archivo.</value>
|
||||
</data>
|
||||
<data name="DatabaseFileDeleteCaption" xml:space="preserve">
|
||||
<data name="DatabaseFileDeleteCaption" xml:space="preserve">
|
||||
<value>¿Quieres eliminar el archivo?</value>
|
||||
</data>
|
||||
<data name="DatabaseFileExistsMsgBoxTitle" xml:space="preserve">
|
||||
<data name="DatabaseFileExistsMsgBoxTitle" xml:space="preserve">
|
||||
<value>El archivo existe</value>
|
||||
</data>
|
||||
<data name="DatabaseFileLabel" xml:space="preserve">
|
||||
<data name="DatabaseFileLabel" xml:space="preserve">
|
||||
<value>Archivo de base de datos</value>
|
||||
</data>
|
||||
<data name="DatabaseFileMsgBoxTryOpen" xml:space="preserve">
|
||||
<data name="DatabaseFileMsgBoxTryOpen" xml:space="preserve">
|
||||
<value>¿Quieres intentar abrir el archivo existente como una base de datos?</value>
|
||||
</data>
|
||||
<data name="DatabaseFileTryOpenCaption" xml:space="preserve">
|
||||
<data name="DatabaseFileTryOpenCaption" xml:space="preserve">
|
||||
<value>¿Quieres intentar abrir el archivo existente como una base de datos?</value>
|
||||
</data>
|
||||
<data name="DatabaseFileUnusableDeleteMsgBoxCaption" xml:space="preserve">
|
||||
<data name="DatabaseFileUnusableDeleteMsgBoxCaption" xml:space="preserve">
|
||||
<value>Ocurrió un error al tratar de usar el archivo seleccionado como una base de datos.
|
||||
¿Quieres eliminarlo?</value>
|
||||
</data>
|
||||
<data name="DatabaseFileUnusableMsgBoxCaption" xml:space="preserve">
|
||||
<data name="DatabaseFileUnusableMsgBoxCaption" xml:space="preserve">
|
||||
<value>Ocurrió un error al tratar de usar el archivo seleccionado como una base de datos.</value>
|
||||
</data>
|
||||
<data name="DatabaseFileUnusableMsgBoxTitle" xml:space="preserve">
|
||||
<data name="DatabaseFileUnusableMsgBoxTitle" xml:space="preserve">
|
||||
<value>No se puede usar la base de datos.</value>
|
||||
</data>
|
||||
<data name="DatFilesDialogLabel" xml:space="preserve">
|
||||
<data name="DatFilesDialogLabel" xml:space="preserve">
|
||||
<value>Archivos DAT</value>
|
||||
</data>
|
||||
<data name="DecompressingDat" xml:space="preserve">
|
||||
<data name="DecompressingDat" xml:space="preserve">
|
||||
<value>Descomprimiendo archivo DAT...</value>
|
||||
</data>
|
||||
<data name="DeleteRomSetMsgBoxCaption" xml:space="preserve">
|
||||
<data name="DeleteRomSetMsgBoxCaption" xml:space="preserve">
|
||||
<value>¿Estás seguro de eliminar el set de ROMs {0}?</value>
|
||||
</data>
|
||||
<data name="DeleteRomSetMsgBoxTitle" xml:space="preserve">
|
||||
<data name="DeleteRomSetMsgBoxTitle" xml:space="preserve">
|
||||
<value>Eliminar set de ROMs</value>
|
||||
</data>
|
||||
<data name="EditDatTitle" xml:space="preserve">
|
||||
<data name="EditDatTitle" xml:space="preserve">
|
||||
<value>Editar DAT</value>
|
||||
</data>
|
||||
<data name="Error" xml:space="preserve">
|
||||
<data name="Error" xml:space="preserve">
|
||||
<value>Error</value>
|
||||
</data>
|
||||
<data name="ExitButtonText" xml:space="preserve">
|
||||
<data name="ExitButtonText" xml:space="preserve">
|
||||
<value>Salir</value>
|
||||
</data>
|
||||
<data name="ExportDatTitle" xml:space="preserve">
|
||||
<data name="ExportDatTitle" xml:space="preserve">
|
||||
<value>Exportando archivo DAT...</value>
|
||||
</data>
|
||||
<data name="ExportRomsDialogTitle" xml:space="preserve">
|
||||
<data name="ExportRomsDialogTitle" xml:space="preserve">
|
||||
<value>Exportar ROMs a carpeta...</value>
|
||||
</data>
|
||||
<data name="ExportRomsTitle" xml:space="preserve">
|
||||
<data name="ExportRomsTitle" xml:space="preserve">
|
||||
<value>Exportando ROMs a carpeta...</value>
|
||||
</data>
|
||||
<data name="FileMenuExitText" xml:space="preserve">
|
||||
<data name="FileMenuExitText" xml:space="preserve">
|
||||
<value>_Salir</value>
|
||||
</data>
|
||||
<data name="FileMenuImportDatFileText" xml:space="preserve">
|
||||
<data name="FileMenuImportDatFileText" xml:space="preserve">
|
||||
<value>Importar _archivo DAT</value>
|
||||
</data>
|
||||
<data name="FileMenuImportDatFolderText" xml:space="preserve">
|
||||
<data name="FileMenuImportDatFolderText" xml:space="preserve">
|
||||
<value>Importar _carpeta de DATs</value>
|
||||
</data>
|
||||
<data name="FileMenuSettingsText" xml:space="preserve">
|
||||
<data name="FileMenuSettingsText" xml:space="preserve">
|
||||
<value>_Preferencias</value>
|
||||
</data>
|
||||
<data name="FileMenuText" xml:space="preserve">
|
||||
<data name="FileMenuText" xml:space="preserve">
|
||||
<value>_Archivo</value>
|
||||
</data>
|
||||
<data name="FilesystemMenuMountText" xml:space="preserve">
|
||||
<data name="FilesystemMenuMountText" xml:space="preserve">
|
||||
<value>_Montar</value>
|
||||
</data>
|
||||
<data name="FilesystemMenuText" xml:space="preserve">
|
||||
<data name="FilesystemMenuText" xml:space="preserve">
|
||||
<value>_Sistema de ficheros</value>
|
||||
</data>
|
||||
<data name="Finished" xml:space="preserve">
|
||||
<data name="Finished" xml:space="preserve">
|
||||
<value>Terminado</value>
|
||||
</data>
|
||||
<data name="FoundFiles" xml:space="preserve">
|
||||
<data name="FoundFiles" xml:space="preserve">
|
||||
<value>Encontrados {0} archivos...</value>
|
||||
</data>
|
||||
<data name="HaveRomsLabel" xml:space="preserve">
|
||||
<data name="HaveRomsLabel" xml:space="preserve">
|
||||
<value>ROMs presentes</value>
|
||||
</data>
|
||||
<data name="HelpMenuAboutText" xml:space="preserve">
|
||||
<data name="HelpMenuAboutText" xml:space="preserve">
|
||||
<value>_Acerca de</value>
|
||||
</data>
|
||||
<data name="HelpMenuText" xml:space="preserve">
|
||||
<data name="HelpMenuText" xml:space="preserve">
|
||||
<value>_Ayuda</value>
|
||||
</data>
|
||||
<data name="HomepageLabel" xml:space="preserve">
|
||||
<data name="HomepageLabel" xml:space="preserve">
|
||||
<value>Página web</value>
|
||||
</data>
|
||||
<data name="ImportDatFileDialogTitle" xml:space="preserve">
|
||||
<data name="ImportDatFileDialogTitle" xml:space="preserve">
|
||||
<value>Importar archivo DAT...</value>
|
||||
</data>
|
||||
<data name="ImportDatFolderDialogTitle" xml:space="preserve">
|
||||
<data name="ImportDatFolderDialogTitle" xml:space="preserve">
|
||||
<value>Importar DATs en carpeta...</value>
|
||||
</data>
|
||||
<data name="ImportDatFolderTitle" xml:space="preserve">
|
||||
<data name="ImportDatFolderTitle" xml:space="preserve">
|
||||
<value>Importar archivos DAT de carpeta...</value>
|
||||
</data>
|
||||
<data name="ImportDatTitle" xml:space="preserve">
|
||||
<data name="ImportDatTitle" xml:space="preserve">
|
||||
<value>Importando archivo DAT...</value>
|
||||
</data>
|
||||
<data name="ImportingItem" xml:space="preserve">
|
||||
<data name="ImportingItem" xml:space="preserve">
|
||||
<value>Importando {0}...</value>
|
||||
</data>
|
||||
<data name="ImportRomFolderTitle" xml:space="preserve">
|
||||
<data name="ImportRomFolderTitle" xml:space="preserve">
|
||||
<value>Importar ROMs de carpeta...</value>
|
||||
</data>
|
||||
<data name="ImportRomsFolderDialogTitle" xml:space="preserve">
|
||||
<data name="ImportRomsFolderDialogTitle" xml:space="preserve">
|
||||
<value>IImportar ROMs de carpeta...</value>
|
||||
</data>
|
||||
<data name="IncompleteMachinesLabel" xml:space="preserve">
|
||||
<data name="IncompleteMachinesLabel" xml:space="preserve">
|
||||
<value>Juegos incompletos</value>
|
||||
</data>
|
||||
<data name="KnownOnlyLabel" xml:space="preserve">
|
||||
<data name="KnownOnlyLabel" xml:space="preserve">
|
||||
<value>Importar solo archivos conocidos.</value>
|
||||
</data>
|
||||
<data name="LibrariesLabel" xml:space="preserve">
|
||||
<data name="LibrariesLabel" xml:space="preserve">
|
||||
<value>Librerías</value>
|
||||
</data>
|
||||
<data name="LicenseLabel" xml:space="preserve">
|
||||
<data name="LicenseLabel" xml:space="preserve">
|
||||
<value>Licencia: Licencia Pública General GNU Versión 3</value>
|
||||
</data>
|
||||
<data name="LoadingDatabaseText" xml:space="preserve">
|
||||
<data name="LoadingDatabaseText" xml:space="preserve">
|
||||
<value>Cargando base de datos...</value>
|
||||
</data>
|
||||
<data name="LoadingRomSetsText" xml:space="preserve">
|
||||
<data name="LoadingRomSetsText" xml:space="preserve">
|
||||
<value>Cargando sets de ROMs...</value>
|
||||
</data>
|
||||
<data name="LoadingSettingsText" xml:space="preserve">
|
||||
<data name="LoadingSettingsText" xml:space="preserve">
|
||||
<value>Cargando preferencias...</value>
|
||||
</data>
|
||||
<data name="MigratingDatabaseText" xml:space="preserve">
|
||||
<data name="MigratingDatabaseText" xml:space="preserve">
|
||||
<value>Migrando base de datos...</value>
|
||||
</data>
|
||||
<data name="MissRomsLabel" xml:space="preserve">
|
||||
<data name="MissRomsLabel" xml:space="preserve">
|
||||
<value>ROMs faltantes</value>
|
||||
</data>
|
||||
<data name="OK" xml:space="preserve">
|
||||
<data name="OK" xml:space="preserve">
|
||||
<value>OK</value>
|
||||
</data>
|
||||
<data name="PathLabel" xml:space="preserve">
|
||||
<data name="PathLabel" xml:space="preserve">
|
||||
<value>Ruta:</value>
|
||||
</data>
|
||||
<data name="RecurseArchivesLabel" xml:space="preserve">
|
||||
<data name="RecurseArchivesLabel" xml:space="preserve">
|
||||
<value>Intentar detectar archivos comprimiedos e importar su contenido.</value>
|
||||
</data>
|
||||
<data name="RecursiveLabel" xml:space="preserve">
|
||||
<data name="RecursiveLabel" xml:space="preserve">
|
||||
<value>Recorrer subcarpetas.</value>
|
||||
</data>
|
||||
<data name="RemoveDatTitle" xml:space="preserve">
|
||||
<data name="RemoveDatTitle" xml:space="preserve">
|
||||
<value>Eliminando set de ROM...</value>
|
||||
</data>
|
||||
<data name="RemoveFilesLabel" xml:space="preserve">
|
||||
<data name="RemoveFilesLabel" xml:space="preserve">
|
||||
<value>Eliminar archivos después de importar satisfactoriamente.</value>
|
||||
</data>
|
||||
<data name="RemovingDatFileFromRepo" xml:space="preserve">
|
||||
<data name="RemovingDatFileFromRepo" xml:space="preserve">
|
||||
<value>Eliminando archivo DAT del repositorio...</value>
|
||||
</data>
|
||||
<data name="RemovingRomSetFromDatabase" xml:space="preserve">
|
||||
<data name="RemovingRomSetFromDatabase" xml:space="preserve">
|
||||
<value>Elimiando set de ROMs de la base de datos...</value>
|
||||
</data>
|
||||
<data name="RepositoryFolderLabel" xml:space="preserve">
|
||||
<data name="RepositoryFolderLabel" xml:space="preserve">
|
||||
<value>Carpeta del repositorio</value>
|
||||
</data>
|
||||
<data name="ResultFilenameLabel" xml:space="preserve">
|
||||
<data name="ResultFilenameLabel" xml:space="preserve">
|
||||
<value>Nombre de archivo</value>
|
||||
</data>
|
||||
<data name="ResultStatusLabel" xml:space="preserve">
|
||||
<data name="ResultStatusLabel" xml:space="preserve">
|
||||
<value>Estado</value>
|
||||
</data>
|
||||
<data name="RetrievingRomSetFromDatabase" xml:space="preserve">
|
||||
<data name="RetrievingRomSetFromDatabase" xml:space="preserve">
|
||||
<value>Recuperando set de ROMs de la base de datos...</value>
|
||||
</data>
|
||||
<data name="RomSetAuthorLabel" xml:space="preserve">
|
||||
<data name="RomSetAuthorLabel" xml:space="preserve">
|
||||
<value>Autor</value>
|
||||
</data>
|
||||
<data name="RomSetCommentLabel" xml:space="preserve">
|
||||
<data name="RomSetCommentLabel" xml:space="preserve">
|
||||
<value>Comentario</value>
|
||||
</data>
|
||||
<data name="RomSetCompleteMachinesLabel" xml:space="preserve">
|
||||
<data name="RomSetCompleteMachinesLabel" xml:space="preserve">
|
||||
<value>Completos</value>
|
||||
</data>
|
||||
<data name="RomSetDateLabel" xml:space="preserve">
|
||||
<data name="RomSetDateLabel" xml:space="preserve">
|
||||
<value>Fecha</value>
|
||||
</data>
|
||||
<data name="RomSetDescriptionLabel" xml:space="preserve">
|
||||
<data name="RomSetDescriptionLabel" xml:space="preserve">
|
||||
<value>Descripción</value>
|
||||
</data>
|
||||
<data name="RomSetHaveRomsLabel" xml:space="preserve">
|
||||
<data name="RomSetHaveRomsLabel" xml:space="preserve">
|
||||
<value>Presentes</value>
|
||||
</data>
|
||||
<data name="RomSetIncompleteMachinesLabel" xml:space="preserve">
|
||||
<data name="RomSetIncompleteMachinesLabel" xml:space="preserve">
|
||||
<value>Incompletos</value>
|
||||
</data>
|
||||
<data name="RomSetMissRomsLabel" xml:space="preserve">
|
||||
<data name="RomSetMissRomsLabel" xml:space="preserve">
|
||||
<value>Faltantes</value>
|
||||
</data>
|
||||
<data name="RomSetNameLabel" xml:space="preserve">
|
||||
<data name="RomSetNameLabel" xml:space="preserve">
|
||||
<value>Nombre</value>
|
||||
</data>
|
||||
<data name="RomSets" xml:space="preserve">
|
||||
<data name="RomSets" xml:space="preserve">
|
||||
<value>Sets de ROMs</value>
|
||||
</data>
|
||||
<data name="RomSetsMenuDeleteText" xml:space="preserve">
|
||||
<data name="RomSetsMenuDeleteText" xml:space="preserve">
|
||||
<value>Elimina_r</value>
|
||||
</data>
|
||||
<data name="RomSetsMenuEditText" xml:space="preserve">
|
||||
<data name="RomSetsMenuEditText" xml:space="preserve">
|
||||
<value>_Editar</value>
|
||||
</data>
|
||||
<data name="RomSetsMenuSaveDatText" xml:space="preserve">
|
||||
<data name="RomSetsMenuSaveDatText" xml:space="preserve">
|
||||
<value>_Guardar archivo DAT</value>
|
||||
</data>
|
||||
<data name="RomSetsMenuSaveRomsText" xml:space="preserve">
|
||||
<data name="RomSetsMenuSaveRomsText" xml:space="preserve">
|
||||
<value>Guardar ROMs en _carpeta</value>
|
||||
</data>
|
||||
<data name="RomSetsMenuText" xml:space="preserve">
|
||||
<data name="RomSetsMenuText" xml:space="preserve">
|
||||
<value>Sets de _ROMs</value>
|
||||
</data>
|
||||
<data name="RomSetTotalMachinesLabel" xml:space="preserve">
|
||||
<data name="RomSetTotalMachinesLabel" xml:space="preserve">
|
||||
<value>Juegos</value>
|
||||
</data>
|
||||
<data name="RomSetTotalRomsLabel" xml:space="preserve">
|
||||
<data name="RomSetTotalRomsLabel" xml:space="preserve">
|
||||
<value>ROMs</value>
|
||||
</data>
|
||||
<data name="RomSetVersionLabel" xml:space="preserve">
|
||||
<data name="RomSetVersionLabel" xml:space="preserve">
|
||||
<value>Versión</value>
|
||||
</data>
|
||||
<data name="RomsMenuImportText" xml:space="preserve">
|
||||
<data name="RomsMenuImportText" xml:space="preserve">
|
||||
<value>Importar _carpeta</value>
|
||||
</data>
|
||||
<data name="RomsMenuText" xml:space="preserve">
|
||||
<data name="RomsMenuText" xml:space="preserve">
|
||||
<value>_ROMs</value>
|
||||
</data>
|
||||
<data name="SaveLabel" xml:space="preserve">
|
||||
<data name="SaveLabel" xml:space="preserve">
|
||||
<value>Guardar</value>
|
||||
</data>
|
||||
<data name="SavingChangesToDatabase" xml:space="preserve">
|
||||
<data name="SavingChangesToDatabase" xml:space="preserve">
|
||||
<value>Guardando cambios en la base de datos...</value>
|
||||
</data>
|
||||
<data name="SearchingForFiles" xml:space="preserve">
|
||||
<data name="SearchingForFiles" xml:space="preserve">
|
||||
<value>Buscando archivos...</value>
|
||||
</data>
|
||||
<data name="SelectMountPointDialogTitle" xml:space="preserve">
|
||||
<data name="SelectMountPointDialogTitle" xml:space="preserve">
|
||||
<value>Elegir punto de montaje...</value>
|
||||
</data>
|
||||
<data name="SettingsTitle" xml:space="preserve">
|
||||
<data name="SettingsTitle" xml:space="preserve">
|
||||
<value>Preferencias</value>
|
||||
</data>
|
||||
<data name="StartLabel" xml:space="preserve">
|
||||
<data name="StartLabel" xml:space="preserve">
|
||||
<value>Comenzar</value>
|
||||
</data>
|
||||
<data name="TemporaryFolderLabel" xml:space="preserve">
|
||||
<data name="TemporaryFolderLabel" xml:space="preserve">
|
||||
<value>Carpeta temporal</value>
|
||||
</data>
|
||||
<data name="TheUnarchiverVersionLabel" xml:space="preserve">
|
||||
<data name="TheUnarchiverVersionLabel" xml:space="preserve">
|
||||
<value>The Unarchiver versión {0}</value>
|
||||
</data>
|
||||
<data name="TotalMachinesLabel" xml:space="preserve">
|
||||
<data name="TotalMachinesLabel" xml:space="preserve">
|
||||
<value>Total de juegos</value>
|
||||
</data>
|
||||
<data name="TotalRomsLabel" xml:space="preserve">
|
||||
<data name="TotalRomsLabel" xml:space="preserve">
|
||||
<value>Total de ROMs</value>
|
||||
</data>
|
||||
<data name="UnArPathLabel" xml:space="preserve">
|
||||
<data name="UnArPathLabel" xml:space="preserve">
|
||||
<value>Ruta a UnAr</value>
|
||||
</data>
|
||||
<data name="FilesystemMenuUmountText" xml:space="preserve">
|
||||
<data name="FilesystemMenuUmountText" xml:space="preserve">
|
||||
<value>_Desmontar</value>
|
||||
</data>
|
||||
<data name="RomSetCategoryLabel" xml:space="preserve">
|
||||
<data name="RomSetCategoryLabel" xml:space="preserve">
|
||||
<value>Categoría</value>
|
||||
</data>
|
||||
<data name="RetrievingRomSetsFromDatabase" xml:space="preserve">
|
||||
<data name="RetrievingRomSetsFromDatabase" xml:space="preserve">
|
||||
<value>Recuperando sets de ROMs de la base de datos...</value>
|
||||
</data>
|
||||
<data name="RemovingOldStatistics" xml:space="preserve">
|
||||
<data name="RemovingOldStatistics" xml:space="preserve">
|
||||
<value>Eliminando estadísticas antiguas</value>
|
||||
</data>
|
||||
<data name="CalculatingStatisticsForRomSet" xml:space="preserve">
|
||||
<data name="CalculatingStatisticsForRomSet" xml:space="preserve">
|
||||
<value>Calculando estadísticas para {0} - {1} ({2})</value>
|
||||
</data>
|
||||
<data name="DatabaseMenuText" xml:space="preserve">
|
||||
<data name="DatabaseMenuText" xml:space="preserve">
|
||||
<value>Base de datos</value>
|
||||
</data>
|
||||
<data name="DatabaseMenuUpdateStatsText" xml:space="preserve">
|
||||
<data name="DatabaseMenuUpdateStatsText" xml:space="preserve">
|
||||
<value>Actualizar estadísticas</value>
|
||||
</data>
|
||||
<data name="UpdateStatsConfirmationDialogText" xml:space="preserve">
|
||||
<data name="UpdateStatsConfirmationDialogText" xml:space="preserve">
|
||||
<value>¿Quieres actualizar las estadísticas de los sets de ROMs en la base de datos?
|
||||
Tardará mucho tiempo...</value>
|
||||
</data>
|
||||
<data name="UpdateStatsTitle" xml:space="preserve">
|
||||
<data name="UpdateStatsTitle" xml:space="preserve">
|
||||
<value>Actualizando estadísticas de sets de ROMs</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -1,377 +1,382 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
|
||||
<root>
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:element name="root" msdata:IsDataSet="true"></xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>1.3</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="FileMenuText" xml:space="preserve">
|
||||
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" id="root"
|
||||
xmlns="">
|
||||
<xsd:element name="root" msdata:IsDataSet="true"></xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>1.3</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<data name="FileMenuText" xml:space="preserve">
|
||||
<value>_File</value>
|
||||
</data>
|
||||
<data name="RomSets" xml:space="preserve">
|
||||
<data name="RomSets" xml:space="preserve">
|
||||
<value>ROM sets</value>
|
||||
</data>
|
||||
<data name="RomSetNameLabel" xml:space="preserve">
|
||||
<data name="RomSetNameLabel" xml:space="preserve">
|
||||
<value>Name</value>
|
||||
</data>
|
||||
<data name="RomSetVersionLabel" xml:space="preserve">
|
||||
<data name="RomSetVersionLabel" xml:space="preserve">
|
||||
<value>Version</value>
|
||||
</data>
|
||||
<data name="RomSetAuthorLabel" xml:space="preserve">
|
||||
<data name="RomSetAuthorLabel" xml:space="preserve">
|
||||
<value>Author</value>
|
||||
</data>
|
||||
<data name="RomSetDateLabel" xml:space="preserve">
|
||||
<data name="RomSetDateLabel" xml:space="preserve">
|
||||
<value>Date</value>
|
||||
</data>
|
||||
<data name="RomSetDescriptionLabel" xml:space="preserve">
|
||||
<data name="RomSetDescriptionLabel" xml:space="preserve">
|
||||
<value>Description</value>
|
||||
</data>
|
||||
<data name="RomSetCommentLabel" xml:space="preserve">
|
||||
<data name="RomSetCommentLabel" xml:space="preserve">
|
||||
<value>Comment</value>
|
||||
</data>
|
||||
<data name="RomSetTotalMachinesLabel" xml:space="preserve">
|
||||
<data name="RomSetTotalMachinesLabel" xml:space="preserve">
|
||||
<value>Games</value>
|
||||
</data>
|
||||
<data name="RomSetCompleteMachinesLabel" xml:space="preserve">
|
||||
<data name="RomSetCompleteMachinesLabel" xml:space="preserve">
|
||||
<value>Complete</value>
|
||||
</data>
|
||||
<data name="RomSetIncompleteMachinesLabel" xml:space="preserve">
|
||||
<data name="RomSetIncompleteMachinesLabel" xml:space="preserve">
|
||||
<value>Incomplete</value>
|
||||
</data>
|
||||
<data name="RomSetTotalRomsLabel" xml:space="preserve">
|
||||
<data name="RomSetTotalRomsLabel" xml:space="preserve">
|
||||
<value>ROMs</value>
|
||||
</data>
|
||||
<data name="RomSetHaveRomsLabel" xml:space="preserve">
|
||||
<data name="RomSetHaveRomsLabel" xml:space="preserve">
|
||||
<value>Have</value>
|
||||
</data>
|
||||
<data name="RomSetMissRomsLabel" xml:space="preserve">
|
||||
<data name="RomSetMissRomsLabel" xml:space="preserve">
|
||||
<value>Miss</value>
|
||||
</data>
|
||||
<data name="FileMenuImportDatFileText" xml:space="preserve">
|
||||
<data name="FileMenuImportDatFileText" xml:space="preserve">
|
||||
<value>Import DAT _file</value>
|
||||
</data>
|
||||
<data name="FileMenuImportDatFolderText" xml:space="preserve">
|
||||
<data name="FileMenuImportDatFolderText" xml:space="preserve">
|
||||
<value>Import DAT f_older</value>
|
||||
</data>
|
||||
<data name="FileMenuSettingsText" xml:space="preserve">
|
||||
<data name="FileMenuSettingsText" xml:space="preserve">
|
||||
<value>_Settings</value>
|
||||
</data>
|
||||
<data name="FileMenuExitText" xml:space="preserve">
|
||||
<data name="FileMenuExitText" xml:space="preserve">
|
||||
<value>E_xit</value>
|
||||
</data>
|
||||
<data name="FilesystemMenuText" xml:space="preserve">
|
||||
<data name="FilesystemMenuText" xml:space="preserve">
|
||||
<value>File_system</value>
|
||||
</data>
|
||||
<data name="FilesystemMenuMountText" xml:space="preserve">
|
||||
<data name="FilesystemMenuMountText" xml:space="preserve">
|
||||
<value>_Mount</value>
|
||||
</data>
|
||||
<data name="RomsMenuText" xml:space="preserve">
|
||||
<data name="RomsMenuText" xml:space="preserve">
|
||||
<value>_ROMs</value>
|
||||
</data>
|
||||
<data name="RomsMenuImportText" xml:space="preserve">
|
||||
<data name="RomsMenuImportText" xml:space="preserve">
|
||||
<value>_Import folder</value>
|
||||
</data>
|
||||
<data name="RomSetsMenuText" xml:space="preserve">
|
||||
<data name="RomSetsMenuText" xml:space="preserve">
|
||||
<value>ROM _sets</value>
|
||||
</data>
|
||||
<data name="RomSetsMenuSaveRomsText" xml:space="preserve">
|
||||
<data name="RomSetsMenuSaveRomsText" xml:space="preserve">
|
||||
<value>_Save ROMs to folder</value>
|
||||
</data>
|
||||
<data name="RomSetsMenuSaveDatText" xml:space="preserve">
|
||||
<data name="RomSetsMenuSaveDatText" xml:space="preserve">
|
||||
<value>Save DAT _file</value>
|
||||
</data>
|
||||
<data name="RomSetsMenuEditText" xml:space="preserve">
|
||||
<data name="RomSetsMenuEditText" xml:space="preserve">
|
||||
<value>_Edit</value>
|
||||
</data>
|
||||
<data name="RomSetsMenuDeleteText" xml:space="preserve">
|
||||
<data name="RomSetsMenuDeleteText" xml:space="preserve">
|
||||
<value>_Delete</value>
|
||||
</data>
|
||||
<data name="HelpMenuText" xml:space="preserve">
|
||||
<data name="HelpMenuText" xml:space="preserve">
|
||||
<value>_Help</value>
|
||||
</data>
|
||||
<data name="HelpMenuAboutText" xml:space="preserve">
|
||||
<data name="HelpMenuAboutText" xml:space="preserve">
|
||||
<value>_About</value>
|
||||
</data>
|
||||
<data name="AboutLabel" xml:space="preserve">
|
||||
<data name="AboutLabel" xml:space="preserve">
|
||||
<value>About</value>
|
||||
</data>
|
||||
<data name="LibrariesLabel" xml:space="preserve">
|
||||
<data name="LibrariesLabel" xml:space="preserve">
|
||||
<value>Libraries</value>
|
||||
</data>
|
||||
<data name="AuthorsLabel" xml:space="preserve">
|
||||
<data name="AuthorsLabel" xml:space="preserve">
|
||||
<value>Authors</value>
|
||||
</data>
|
||||
<data name="AboutTitle" xml:space="preserve">
|
||||
<data name="AboutTitle" xml:space="preserve">
|
||||
<value>About ROM Repository Manager</value>
|
||||
</data>
|
||||
<data name="LicenseLabel" xml:space="preserve">
|
||||
<data name="LicenseLabel" xml:space="preserve">
|
||||
<value>License: GNU General Public License Version 3</value>
|
||||
</data>
|
||||
<data name="CloseLabel" xml:space="preserve">
|
||||
<data name="CloseLabel" xml:space="preserve">
|
||||
<value>Close</value>
|
||||
</data>
|
||||
<data name="AssembliesLibraryText" xml:space="preserve">
|
||||
<data name="AssembliesLibraryText" xml:space="preserve">
|
||||
<value>Library</value>
|
||||
</data>
|
||||
<data name="AssembliesVersionText" xml:space="preserve">
|
||||
<data name="AssembliesVersionText" xml:space="preserve">
|
||||
<value>Version</value>
|
||||
</data>
|
||||
<data name="AuthorsText" xml:space="preserve">
|
||||
<data name="AuthorsText" xml:space="preserve">
|
||||
<value>Developers:
|
||||
Natalia Portillo
|
||||
</value>
|
||||
</data>
|
||||
<data name="HomepageLabel" xml:space="preserve">
|
||||
<data name="HomepageLabel" xml:space="preserve">
|
||||
<value>Homepage</value>
|
||||
</data>
|
||||
<data name="TotalMachinesLabel" xml:space="preserve">
|
||||
<data name="TotalMachinesLabel" xml:space="preserve">
|
||||
<value>Total games</value>
|
||||
</data>
|
||||
<data name="CompleteMachinesLabel" xml:space="preserve">
|
||||
<data name="CompleteMachinesLabel" xml:space="preserve">
|
||||
<value>Complete games</value>
|
||||
</data>
|
||||
<data name="IncompleteMachinesLabel" xml:space="preserve">
|
||||
<data name="IncompleteMachinesLabel" xml:space="preserve">
|
||||
<value>Incomplete games</value>
|
||||
</data>
|
||||
<data name="TotalRomsLabel" xml:space="preserve">
|
||||
<data name="TotalRomsLabel" xml:space="preserve">
|
||||
<value>Total ROMs</value>
|
||||
</data>
|
||||
<data name="HaveRomsLabel" xml:space="preserve">
|
||||
<data name="HaveRomsLabel" xml:space="preserve">
|
||||
<value>Have ROMs</value>
|
||||
</data>
|
||||
<data name="MissRomsLabel" xml:space="preserve">
|
||||
<data name="MissRomsLabel" xml:space="preserve">
|
||||
<value>Missing ROMs</value>
|
||||
</data>
|
||||
<data name="EditDatTitle" xml:space="preserve">
|
||||
<data name="EditDatTitle" xml:space="preserve">
|
||||
<value>Edit DAT</value>
|
||||
</data>
|
||||
<data name="SaveLabel" xml:space="preserve">
|
||||
<data name="SaveLabel" xml:space="preserve">
|
||||
<value>Save</value>
|
||||
</data>
|
||||
<data name="CancelLabel" xml:space="preserve">
|
||||
<data name="CancelLabel" xml:space="preserve">
|
||||
<value>Cancel</value>
|
||||
</data>
|
||||
<data name="ExportDatTitle" xml:space="preserve">
|
||||
<data name="ExportDatTitle" xml:space="preserve">
|
||||
<value>Exporting DAT file...</value>
|
||||
</data>
|
||||
<data name="DecompressingDat" xml:space="preserve">
|
||||
<data name="DecompressingDat" xml:space="preserve">
|
||||
<value>Decompressing DAT file...</value>
|
||||
</data>
|
||||
<data name="Finished" xml:space="preserve">
|
||||
<data name="Finished" xml:space="preserve">
|
||||
<value>Finished</value>
|
||||
</data>
|
||||
<data name="ExportRomsTitle" xml:space="preserve">
|
||||
<data name="ExportRomsTitle" xml:space="preserve">
|
||||
<value>Exporting ROM files to folder...</value>
|
||||
</data>
|
||||
<data name="PathLabel" xml:space="preserve">
|
||||
<data name="PathLabel" xml:space="preserve">
|
||||
<value>Path:</value>
|
||||
</data>
|
||||
<data name="AllFilesLabel" xml:space="preserve">
|
||||
<data name="AllFilesLabel" xml:space="preserve">
|
||||
<value>Check all files.</value>
|
||||
</data>
|
||||
<data name="RecursiveLabel" xml:space="preserve">
|
||||
<data name="RecursiveLabel" xml:space="preserve">
|
||||
<value>Recurse subfolders.</value>
|
||||
</data>
|
||||
<data name="ImportDatFolderTitle" xml:space="preserve">
|
||||
<data name="ImportDatFolderTitle" xml:space="preserve">
|
||||
<value>Import DAT files from folder...</value>
|
||||
</data>
|
||||
<data name="ResultFilenameLabel" xml:space="preserve">
|
||||
<data name="ResultFilenameLabel" xml:space="preserve">
|
||||
<value>Filename</value>
|
||||
</data>
|
||||
<data name="ResultStatusLabel" xml:space="preserve">
|
||||
<data name="ResultStatusLabel" xml:space="preserve">
|
||||
<value>Status</value>
|
||||
</data>
|
||||
<data name="StartLabel" xml:space="preserve">
|
||||
<data name="StartLabel" xml:space="preserve">
|
||||
<value>Start</value>
|
||||
</data>
|
||||
<data name="SearchingForFiles" xml:space="preserve">
|
||||
<data name="SearchingForFiles" xml:space="preserve">
|
||||
<value>Searching for files...</value>
|
||||
</data>
|
||||
<data name="FoundFiles" xml:space="preserve">
|
||||
<data name="FoundFiles" xml:space="preserve">
|
||||
<value>Found {0} files...</value>
|
||||
</data>
|
||||
<data name="ImportingItem" xml:space="preserve">
|
||||
<data name="ImportingItem" xml:space="preserve">
|
||||
<value>Importing {0}...</value>
|
||||
</data>
|
||||
<data name="OK" xml:space="preserve">
|
||||
<data name="OK" xml:space="preserve">
|
||||
<value>OK</value>
|
||||
</data>
|
||||
<data name="ImportDatTitle" xml:space="preserve">
|
||||
<data name="ImportDatTitle" xml:space="preserve">
|
||||
<value>Importing DAT file...</value>
|
||||
</data>
|
||||
<data name="RemoveFilesLabel" xml:space="preserve">
|
||||
<data name="RemoveFilesLabel" xml:space="preserve">
|
||||
<value>Remove files after import successful.</value>
|
||||
</data>
|
||||
<data name="KnownOnlyLabel" xml:space="preserve">
|
||||
<data name="KnownOnlyLabel" xml:space="preserve">
|
||||
<value>Only import known files.</value>
|
||||
</data>
|
||||
<data name="RecurseArchivesLabel" xml:space="preserve">
|
||||
<data name="RecurseArchivesLabel" xml:space="preserve">
|
||||
<value>Try to detect archives and import their contents.</value>
|
||||
</data>
|
||||
<data name="ImportRomFolderTitle" xml:space="preserve">
|
||||
<data name="ImportRomFolderTitle" xml:space="preserve">
|
||||
<value>Import ROM files from folder...</value>
|
||||
</data>
|
||||
<data name="RemoveDatTitle" xml:space="preserve">
|
||||
<data name="RemoveDatTitle" xml:space="preserve">
|
||||
<value>Removing ROM set...</value>
|
||||
</data>
|
||||
<data name="RetrievingRomSetFromDatabase" xml:space="preserve">
|
||||
<data name="RetrievingRomSetFromDatabase" xml:space="preserve">
|
||||
<value>Retrieving ROM set from database...</value>
|
||||
</data>
|
||||
<data name="RemovingRomSetFromDatabase" xml:space="preserve">
|
||||
<data name="RemovingRomSetFromDatabase" xml:space="preserve">
|
||||
<value>Removing ROM set from database...</value>
|
||||
</data>
|
||||
<data name="SavingChangesToDatabase" xml:space="preserve">
|
||||
<data name="SavingChangesToDatabase" xml:space="preserve">
|
||||
<value>Saving changes to database...</value>
|
||||
</data>
|
||||
<data name="RemovingDatFileFromRepo" xml:space="preserve">
|
||||
<data name="RemovingDatFileFromRepo" xml:space="preserve">
|
||||
<value>Removing DAT file from repo...</value>
|
||||
</data>
|
||||
<data name="ChooseLabel" xml:space="preserve">
|
||||
<data name="ChooseLabel" xml:space="preserve">
|
||||
<value>Choose...</value>
|
||||
</data>
|
||||
<data name="SettingsTitle" xml:space="preserve">
|
||||
<data name="SettingsTitle" xml:space="preserve">
|
||||
<value>Settings</value>
|
||||
</data>
|
||||
<data name="DatabaseFileLabel" xml:space="preserve">
|
||||
<data name="DatabaseFileLabel" xml:space="preserve">
|
||||
<value>Database file</value>
|
||||
</data>
|
||||
<data name="RepositoryFolderLabel" xml:space="preserve">
|
||||
<data name="RepositoryFolderLabel" xml:space="preserve">
|
||||
<value>Repository folder</value>
|
||||
</data>
|
||||
<data name="TemporaryFolderLabel" xml:space="preserve">
|
||||
<data name="TemporaryFolderLabel" xml:space="preserve">
|
||||
<value>Temporary folder</value>
|
||||
</data>
|
||||
<data name="UnArPathLabel" xml:space="preserve">
|
||||
<data name="UnArPathLabel" xml:space="preserve">
|
||||
<value>Path to UnAr</value>
|
||||
</data>
|
||||
<data name="Error" xml:space="preserve">
|
||||
<data name="Error" xml:space="preserve">
|
||||
<value>Error</value>
|
||||
</data>
|
||||
<data name="TheUnarchiverVersionLabel" xml:space="preserve">
|
||||
<data name="TheUnarchiverVersionLabel" xml:space="preserve">
|
||||
<value>The Unarchiver version {0}</value>
|
||||
</data>
|
||||
<data name="ChooseUnArExecutable" xml:space="preserve">
|
||||
<data name="ChooseUnArExecutable" xml:space="preserve">
|
||||
<value>Choose UnArchiver executable</value>
|
||||
</data>
|
||||
<data name="ChooseTemporaryFolder" xml:space="preserve">
|
||||
<data name="ChooseTemporaryFolder" xml:space="preserve">
|
||||
<value>Choose temporary folder</value>
|
||||
</data>
|
||||
<data name="ChooseRepositoryFolder" xml:space="preserve">
|
||||
<data name="ChooseRepositoryFolder" xml:space="preserve">
|
||||
<value>Choose repository folder</value>
|
||||
</data>
|
||||
<data name="ChooseDatabaseFile" xml:space="preserve">
|
||||
<data name="ChooseDatabaseFile" xml:space="preserve">
|
||||
<value>Choose database to open / create</value>
|
||||
</data>
|
||||
<data name="DatabaseFileMsgBoxTryOpen" xml:space="preserve">
|
||||
<data name="DatabaseFileMsgBoxTryOpen" xml:space="preserve">
|
||||
<value>Do you want to try to open the existing file as a database?</value>
|
||||
</data>
|
||||
<data name="DatabaseFileTryOpenCaption" xml:space="preserve">
|
||||
<data name="DatabaseFileTryOpenCaption" xml:space="preserve">
|
||||
<value>Do you want to try to open the existing file as a database?</value>
|
||||
</data>
|
||||
<data name="DatabaseFileExistsMsgBoxTitle" xml:space="preserve">
|
||||
<data name="DatabaseFileExistsMsgBoxTitle" xml:space="preserve">
|
||||
<value>File exists</value>
|
||||
</data>
|
||||
<data name="DatabaseFileUnusableMsgBoxTitle" xml:space="preserve">
|
||||
<data name="DatabaseFileUnusableMsgBoxTitle" xml:space="preserve">
|
||||
<value>Could not use database</value>
|
||||
</data>
|
||||
<data name="DatabaseFileUnusableDeleteMsgBoxCaption" xml:space="preserve">
|
||||
<data name="DatabaseFileUnusableDeleteMsgBoxCaption" xml:space="preserve">
|
||||
<value>An error occurred trying to use the chosen file as a database.
|
||||
Do you want to delete the file?</value>
|
||||
</data>
|
||||
<data name="DatabaseFileUnusableMsgBoxCaption" xml:space="preserve">
|
||||
<data name="DatabaseFileUnusableMsgBoxCaption" xml:space="preserve">
|
||||
<value>An error occurred trying to use the chosen file as a database.</value>
|
||||
</data>
|
||||
<data name="DatabaseFileDeleteCaption" xml:space="preserve">
|
||||
<data name="DatabaseFileDeleteCaption" xml:space="preserve">
|
||||
<value>Do you want to delete the file?</value>
|
||||
</data>
|
||||
<data name="DatabaseFileCannotDeleteTitle" xml:space="preserve">
|
||||
<data name="DatabaseFileCannotDeleteTitle" xml:space="preserve">
|
||||
<value>Could not delete file</value>
|
||||
</data>
|
||||
<data name="DatabaseFileCannotDeleteCaption" xml:space="preserve">
|
||||
<data name="DatabaseFileCannotDeleteCaption" xml:space="preserve">
|
||||
<value>An error occurred trying to delete the chosen file.</value>
|
||||
</data>
|
||||
<data name="ImportDatFileDialogTitle" xml:space="preserve">
|
||||
<data name="ImportDatFileDialogTitle" xml:space="preserve">
|
||||
<value>Import DAT file...</value>
|
||||
</data>
|
||||
<data name="DatFilesDialogLabel" xml:space="preserve">
|
||||
<data name="DatFilesDialogLabel" xml:space="preserve">
|
||||
<value>DAT files</value>
|
||||
</data>
|
||||
<data name="AllFilesDialogLabel" xml:space="preserve">
|
||||
<data name="AllFilesDialogLabel" xml:space="preserve">
|
||||
<value>All files</value>
|
||||
</data>
|
||||
<data name="ImportDatFolderDialogTitle" xml:space="preserve">
|
||||
<data name="ImportDatFolderDialogTitle" xml:space="preserve">
|
||||
<value>Import DATs from folder...</value>
|
||||
</data>
|
||||
<data name="ImportRomsFolderDialogTitle" xml:space="preserve">
|
||||
<data name="ImportRomsFolderDialogTitle" xml:space="preserve">
|
||||
<value>Import ROMs from folder...</value>
|
||||
</data>
|
||||
<data name="DeleteRomSetMsgBoxTitle" xml:space="preserve">
|
||||
<data name="DeleteRomSetMsgBoxTitle" xml:space="preserve">
|
||||
<value>Delete ROM set</value>
|
||||
</data>
|
||||
<data name="DeleteRomSetMsgBoxCaption" xml:space="preserve">
|
||||
<data name="DeleteRomSetMsgBoxCaption" xml:space="preserve">
|
||||
<value>Are you sure you want to delete the ROM set {0}?</value>
|
||||
</data>
|
||||
<data name="ExportRomsDialogTitle" xml:space="preserve">
|
||||
<data name="ExportRomsDialogTitle" xml:space="preserve">
|
||||
<value>Export ROMs to folder...</value>
|
||||
</data>
|
||||
<data name="SelectMountPointDialogTitle" xml:space="preserve">
|
||||
<data name="SelectMountPointDialogTitle" xml:space="preserve">
|
||||
<value>Select mount point...</value>
|
||||
</data>
|
||||
<data name="LoadingSettingsText" xml:space="preserve">
|
||||
<data name="LoadingSettingsText" xml:space="preserve">
|
||||
<value>Loading settings...</value>
|
||||
</data>
|
||||
<data name="CheckingUnArText" xml:space="preserve">
|
||||
<data name="CheckingUnArText" xml:space="preserve">
|
||||
<value>Checking The Unarchiver...</value>
|
||||
</data>
|
||||
<data name="LoadingDatabaseText" xml:space="preserve">
|
||||
<data name="LoadingDatabaseText" xml:space="preserve">
|
||||
<value>Loading database...</value>
|
||||
</data>
|
||||
<data name="MigratingDatabaseText" xml:space="preserve">
|
||||
<data name="MigratingDatabaseText" xml:space="preserve">
|
||||
<value>Migrating database...</value>
|
||||
</data>
|
||||
<data name="LoadingRomSetsText" xml:space="preserve">
|
||||
<data name="LoadingRomSetsText" xml:space="preserve">
|
||||
<value>Loading ROM sets...</value>
|
||||
</data>
|
||||
<data name="ExitButtonText" xml:space="preserve">
|
||||
<data name="ExitButtonText" xml:space="preserve">
|
||||
<value>Exit</value>
|
||||
</data>
|
||||
<data name="FilesystemMenuUmountText" xml:space="preserve">
|
||||
<data name="FilesystemMenuUmountText" xml:space="preserve">
|
||||
<value>_Umount</value>
|
||||
</data>
|
||||
<data name="RomSetCategoryLabel" xml:space="preserve">
|
||||
<data name="RomSetCategoryLabel" xml:space="preserve">
|
||||
<value>Category</value>
|
||||
</data>
|
||||
<data name="DatabaseMenuText" xml:space="preserve">
|
||||
<data name="DatabaseMenuText" xml:space="preserve">
|
||||
<value>Database</value>
|
||||
</data>
|
||||
<data name="DatabaseMenuUpdateStatsText" xml:space="preserve">
|
||||
<data name="DatabaseMenuUpdateStatsText" xml:space="preserve">
|
||||
<value>Update statistics</value>
|
||||
</data>
|
||||
<data name="UpdateStatsConfirmationDialogText" xml:space="preserve">
|
||||
<data name="UpdateStatsConfirmationDialogText" xml:space="preserve">
|
||||
<value>Do you want to update ROM set statistics in database?
|
||||
This will take a long time...</value>
|
||||
</data>
|
||||
<data name="UpdateStatsTitle" xml:space="preserve">
|
||||
<data name="UpdateStatsTitle" xml:space="preserve">
|
||||
<value>Updating ROM sets statistics</value>
|
||||
</data>
|
||||
<data name="CalculatingStatisticsForRomSet" xml:space="preserve">
|
||||
<data name="CalculatingStatisticsForRomSet" xml:space="preserve">
|
||||
<value>Calculating statistics for {0} - {1} ({2})</value>
|
||||
</data>
|
||||
<data name="RemovingOldStatistics" xml:space="preserve">
|
||||
<data name="RemovingOldStatistics" xml:space="preserve">
|
||||
<value>Removing old statistics</value>
|
||||
</data>
|
||||
<data name="RetrievingRomSetsFromDatabase" xml:space="preserve">
|
||||
<data name="RetrievingRomSetsFromDatabase" xml:space="preserve">
|
||||
<value>Retrieving ROM sets from database...</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -1,44 +1,44 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<LangVersion>default</LangVersion>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Update="**\*.xaml.cs">
|
||||
<DependentUpon>%(Filename)</DependentUpon>
|
||||
</Compile>
|
||||
<AvaloniaResource Include="**\*.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
</AvaloniaResource>
|
||||
<AvaloniaResource Include="Assets\**" />
|
||||
<Compile Update="Resources\Localization.Designer.cs">
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Localization.resx</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Avalonia" Version="0.10.0-rc1" />
|
||||
<PackageReference Include="Avalonia.Controls.DataGrid" Version="0.10.0-rc1" />
|
||||
<PackageReference Include="Avalonia.Desktop" Version="0.10.0-rc1" />
|
||||
<PackageReference Include="Avalonia.Diagnostics" Version="0.10.0-rc1" />
|
||||
<PackageReference Include="Avalonia.ReactiveUI" Version="0.10.0-rc1" />
|
||||
<PackageReference Include="MessageBox.Avalonia" Version="0.10.7-rc1" />
|
||||
<PackageReference Include="Svg.Skia.Avalonia" Version="0.10.0-preview7" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\RomRepoMgr.Database\RomRepoMgr.Database.csproj" />
|
||||
<ProjectReference Include="..\RomRepoMgr.Settings\RomRepoMgr.Settings.csproj" />
|
||||
<ProjectReference Include="..\RomRepoMgr.Core\RomRepoMgr.Core.csproj" />
|
||||
<ProjectReference Include="..\SabreTools\SabreTools.DatFiles\SabreTools.DatFiles.csproj" />
|
||||
<ProjectReference Include="..\SabreTools\SabreTools.DatItems\SabreTools.DatItems.csproj" />
|
||||
<ProjectReference Include="..\SabreTools\SabreTools.IO\SabreTools.IO.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Update="Resources\Localization.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Localization.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<LangVersion>default</LangVersion>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Update="**\*.xaml.cs">
|
||||
<DependentUpon>%(Filename)</DependentUpon>
|
||||
</Compile>
|
||||
<AvaloniaResource Include="**\*.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
</AvaloniaResource>
|
||||
<AvaloniaResource Include="Assets\**"/>
|
||||
<Compile Update="Resources\Localization.Designer.cs">
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Localization.resx</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Avalonia" Version="0.10.0-rc1"/>
|
||||
<PackageReference Include="Avalonia.Controls.DataGrid" Version="0.10.0-rc1"/>
|
||||
<PackageReference Include="Avalonia.Desktop" Version="0.10.0-rc1"/>
|
||||
<PackageReference Include="Avalonia.Diagnostics" Version="0.10.0-rc1"/>
|
||||
<PackageReference Include="Avalonia.ReactiveUI" Version="0.10.0-rc1"/>
|
||||
<PackageReference Include="MessageBox.Avalonia" Version="0.10.7-rc1"/>
|
||||
<PackageReference Include="Svg.Skia.Avalonia" Version="0.10.0-preview7"/>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\RomRepoMgr.Database\RomRepoMgr.Database.csproj"/>
|
||||
<ProjectReference Include="..\RomRepoMgr.Settings\RomRepoMgr.Settings.csproj"/>
|
||||
<ProjectReference Include="..\RomRepoMgr.Core\RomRepoMgr.Core.csproj"/>
|
||||
<ProjectReference Include="..\SabreTools\SabreTools.DatFiles\SabreTools.DatFiles.csproj"/>
|
||||
<ProjectReference Include="..\SabreTools\SabreTools.DatItems\SabreTools.DatItems.csproj"/>
|
||||
<ProjectReference Include="..\SabreTools\SabreTools.IO\SabreTools.IO.csproj"/>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Update="Resources\Localization.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Localization.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
@@ -6,23 +6,24 @@ using Avalonia.Controls;
|
||||
using Avalonia.Controls.Templates;
|
||||
using RomRepoMgr.ViewModels;
|
||||
|
||||
namespace RomRepoMgr
|
||||
namespace RomRepoMgr;
|
||||
|
||||
public class ViewLocator : IDataTemplate
|
||||
{
|
||||
public class ViewLocator : IDataTemplate
|
||||
public bool SupportsRecycling => false;
|
||||
|
||||
public IControl Build(object data)
|
||||
{
|
||||
public bool SupportsRecycling => false;
|
||||
string name = data.GetType().FullName?.Replace("ViewModel", "View");
|
||||
Type type = name is null ? null : Type.GetType(name);
|
||||
|
||||
public IControl Build(object data)
|
||||
{
|
||||
string name = data.GetType().FullName?.Replace("ViewModel", "View");
|
||||
Type type = name is null ? null : Type.GetType(name);
|
||||
|
||||
return type is null ? new TextBlock
|
||||
{
|
||||
Text = "Not Found: " + name
|
||||
} : (Control)Activator.CreateInstance(type);
|
||||
}
|
||||
|
||||
public bool Match(object data) => data is ViewModelBase;
|
||||
return type is null
|
||||
? new TextBlock
|
||||
{
|
||||
Text = "Not Found: " + name
|
||||
}
|
||||
: (Control)Activator.CreateInstance(type);
|
||||
}
|
||||
|
||||
public bool Match(object data) => data is ViewModelBase;
|
||||
}
|
||||
@@ -31,136 +31,130 @@ using System.Reactive;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading.Tasks;
|
||||
using Avalonia.Platform;
|
||||
using JetBrains.Annotations;
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.DotNet.PlatformAbstractions;
|
||||
using ReactiveUI;
|
||||
using RomRepoMgr.Core.Models;
|
||||
using RomRepoMgr.Resources;
|
||||
using RomRepoMgr.Views;
|
||||
|
||||
namespace RomRepoMgr.ViewModels
|
||||
namespace RomRepoMgr.ViewModels;
|
||||
|
||||
public sealed class AboutViewModel : ViewModelBase
|
||||
{
|
||||
public sealed class AboutViewModel : ViewModelBase
|
||||
readonly About _view;
|
||||
string _versionText;
|
||||
|
||||
public AboutViewModel(About view)
|
||||
{
|
||||
readonly About _view;
|
||||
string _versionText;
|
||||
_view = view;
|
||||
|
||||
public AboutViewModel(About view)
|
||||
VersionText =
|
||||
(Attribute.GetCustomAttribute(typeof(App).Assembly, typeof(AssemblyInformationalVersionAttribute)) as
|
||||
AssemblyInformationalVersionAttribute)?.InformationalVersion;
|
||||
|
||||
WebsiteCommand = ReactiveCommand.Create(ExecuteWebsiteCommand);
|
||||
LicenseCommand = ReactiveCommand.Create(ExecuteLicenseCommand);
|
||||
CloseCommand = ReactiveCommand.Create(ExecuteCloseCommand);
|
||||
|
||||
Assemblies = new ObservableCollection<AssemblyModel>();
|
||||
|
||||
// TODO: They do not load in time
|
||||
Task.Run(() =>
|
||||
{
|
||||
_view = view;
|
||||
|
||||
VersionText =
|
||||
(Attribute.GetCustomAttribute(typeof(App).Assembly, typeof(AssemblyInformationalVersionAttribute)) as
|
||||
AssemblyInformationalVersionAttribute)?.InformationalVersion;
|
||||
|
||||
WebsiteCommand = ReactiveCommand.Create(ExecuteWebsiteCommand);
|
||||
LicenseCommand = ReactiveCommand.Create(ExecuteLicenseCommand);
|
||||
CloseCommand = ReactiveCommand.Create(ExecuteCloseCommand);
|
||||
|
||||
Assemblies = new ObservableCollection<AssemblyModel>();
|
||||
|
||||
// TODO: They do not load in time
|
||||
Task.Run(() =>
|
||||
foreach(Assembly assembly in AppDomain.CurrentDomain.GetAssemblies().OrderBy(a => a.FullName))
|
||||
{
|
||||
foreach(Assembly assembly in AppDomain.CurrentDomain.GetAssemblies().OrderBy(a => a.FullName))
|
||||
string name = assembly.GetName().Name;
|
||||
|
||||
string version =
|
||||
(Attribute.GetCustomAttribute(assembly, typeof(AssemblyInformationalVersionAttribute)) as
|
||||
AssemblyInformationalVersionAttribute)?.InformationalVersion;
|
||||
|
||||
if(name is null || version is null) continue;
|
||||
|
||||
Assemblies.Add(new AssemblyModel
|
||||
{
|
||||
string name = assembly.GetName().Name;
|
||||
|
||||
string version =
|
||||
(Attribute.GetCustomAttribute(assembly, typeof(AssemblyInformationalVersionAttribute)) as
|
||||
AssemblyInformationalVersionAttribute)?.InformationalVersion;
|
||||
|
||||
if(name is null ||
|
||||
version is null)
|
||||
continue;
|
||||
|
||||
Assemblies.Add(new AssemblyModel
|
||||
{
|
||||
Name = name,
|
||||
Version = version
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
[NotNull]
|
||||
public string AboutLabel => Localization.AboutLabel;
|
||||
[NotNull]
|
||||
public string LibrariesLabel => Localization.LibrariesLabel;
|
||||
[NotNull]
|
||||
public string AuthorsLabel => Localization.AuthorsLabel;
|
||||
[NotNull]
|
||||
public string Title => Localization.AboutTitle;
|
||||
[NotNull]
|
||||
public string SoftwareName => "RomRepoMgr";
|
||||
[NotNull]
|
||||
public string SuiteName => "ROM Repository Manager";
|
||||
[NotNull]
|
||||
public string Copyright => "© 2020-2024 Natalia Portillo";
|
||||
[NotNull]
|
||||
public string Website => "https://www.claunia.com";
|
||||
[NotNull]
|
||||
public string License => Localization.LicenseLabel;
|
||||
[NotNull]
|
||||
public string CloseLabel => Localization.CloseLabel;
|
||||
[NotNull]
|
||||
public string AssembliesLibraryText => Localization.AssembliesLibraryText;
|
||||
[NotNull]
|
||||
public string AssembliesVersionText => Localization.AssembliesVersionText;
|
||||
[NotNull]
|
||||
public string Authors => Localization.AuthorsText;
|
||||
public ReactiveCommand<Unit, Unit> WebsiteCommand { get; }
|
||||
public ReactiveCommand<Unit, Unit> LicenseCommand { get; }
|
||||
public ReactiveCommand<Unit, Unit> CloseCommand { get; }
|
||||
public ObservableCollection<AssemblyModel> Assemblies { get; }
|
||||
|
||||
public string VersionText
|
||||
{
|
||||
get => _versionText;
|
||||
set => this.RaiseAndSetIfChanged(ref _versionText, value);
|
||||
}
|
||||
|
||||
void ExecuteWebsiteCommand()
|
||||
{
|
||||
var process = new Process
|
||||
{
|
||||
StartInfo =
|
||||
{
|
||||
UseShellExecute = false,
|
||||
CreateNoWindow = true,
|
||||
Arguments = "https://www.claunia.com"
|
||||
}
|
||||
};
|
||||
|
||||
if(RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
{
|
||||
process.StartInfo.FileName = "cmd";
|
||||
process.StartInfo.Arguments = $"/c start {process.StartInfo.Arguments.Replace("&", "^&")}";
|
||||
Name = name,
|
||||
Version = version
|
||||
});
|
||||
}
|
||||
else if(RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ||
|
||||
RuntimeInformation.IsOSPlatform(OSPlatform.FreeBSD))
|
||||
process.StartInfo.FileName = "xdg-open";
|
||||
else if(RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
|
||||
process.StartInfo.FileName = "open";
|
||||
else
|
||||
{
|
||||
if(Debugger.IsAttached) throw new ArgumentOutOfRangeException();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
process.Start();
|
||||
}
|
||||
|
||||
void ExecuteLicenseCommand()
|
||||
{
|
||||
/* var dialog = new LicenseDialog();
|
||||
dialog.DataContext = new LicenseViewModel(dialog);
|
||||
dialog.ShowDialog(_view);*/
|
||||
}
|
||||
|
||||
void ExecuteCloseCommand() => _view.Close();
|
||||
});
|
||||
}
|
||||
|
||||
[NotNull]
|
||||
public string AboutLabel => Localization.AboutLabel;
|
||||
[NotNull]
|
||||
public string LibrariesLabel => Localization.LibrariesLabel;
|
||||
[NotNull]
|
||||
public string AuthorsLabel => Localization.AuthorsLabel;
|
||||
[NotNull]
|
||||
public string Title => Localization.AboutTitle;
|
||||
[NotNull]
|
||||
public string SoftwareName => "RomRepoMgr";
|
||||
[NotNull]
|
||||
public string SuiteName => "ROM Repository Manager";
|
||||
[NotNull]
|
||||
public string Copyright => "© 2020-2024 Natalia Portillo";
|
||||
[NotNull]
|
||||
public string Website => "https://www.claunia.com";
|
||||
[NotNull]
|
||||
public string License => Localization.LicenseLabel;
|
||||
[NotNull]
|
||||
public string CloseLabel => Localization.CloseLabel;
|
||||
[NotNull]
|
||||
public string AssembliesLibraryText => Localization.AssembliesLibraryText;
|
||||
[NotNull]
|
||||
public string AssembliesVersionText => Localization.AssembliesVersionText;
|
||||
[NotNull]
|
||||
public string Authors => Localization.AuthorsText;
|
||||
public ReactiveCommand<Unit, Unit> WebsiteCommand { get; }
|
||||
public ReactiveCommand<Unit, Unit> LicenseCommand { get; }
|
||||
public ReactiveCommand<Unit, Unit> CloseCommand { get; }
|
||||
public ObservableCollection<AssemblyModel> Assemblies { get; }
|
||||
|
||||
public string VersionText
|
||||
{
|
||||
get => _versionText;
|
||||
set => this.RaiseAndSetIfChanged(ref _versionText, value);
|
||||
}
|
||||
|
||||
void ExecuteWebsiteCommand()
|
||||
{
|
||||
var process = new Process
|
||||
{
|
||||
StartInfo =
|
||||
{
|
||||
UseShellExecute = false,
|
||||
CreateNoWindow = true,
|
||||
Arguments = "https://www.claunia.com"
|
||||
}
|
||||
};
|
||||
|
||||
if(RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
{
|
||||
process.StartInfo.FileName = "cmd";
|
||||
process.StartInfo.Arguments = $"/c start {process.StartInfo.Arguments.Replace("&", "^&")}";
|
||||
}
|
||||
else if(RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ||
|
||||
RuntimeInformation.IsOSPlatform(OSPlatform.FreeBSD))
|
||||
process.StartInfo.FileName = "xdg-open";
|
||||
else if(RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
|
||||
process.StartInfo.FileName = "open";
|
||||
else
|
||||
{
|
||||
if(Debugger.IsAttached) throw new ArgumentOutOfRangeException();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
process.Start();
|
||||
}
|
||||
|
||||
void ExecuteLicenseCommand()
|
||||
{
|
||||
/* var dialog = new LicenseDialog();
|
||||
dialog.DataContext = new LicenseViewModel(dialog);
|
||||
dialog.ShowDialog(_view);*/
|
||||
}
|
||||
|
||||
void ExecuteCloseCommand() => _view.Close();
|
||||
}
|
||||
@@ -33,220 +33,211 @@ using RomRepoMgr.Database.Models;
|
||||
using RomRepoMgr.Resources;
|
||||
using RomRepoMgr.Views;
|
||||
|
||||
namespace RomRepoMgr.ViewModels
|
||||
namespace RomRepoMgr.ViewModels;
|
||||
|
||||
public class EditDatViewModel : ViewModelBase
|
||||
{
|
||||
public class EditDatViewModel : ViewModelBase
|
||||
readonly RomSetModel _romSet;
|
||||
readonly EditDat _view;
|
||||
string _author;
|
||||
string _category;
|
||||
string _comment;
|
||||
string _date;
|
||||
string _description;
|
||||
string _homepage;
|
||||
bool _modified;
|
||||
string _name;
|
||||
string _version;
|
||||
|
||||
public EditDatViewModel(EditDat view, RomSetModel romSet)
|
||||
{
|
||||
readonly RomSetModel _romSet;
|
||||
readonly EditDat _view;
|
||||
string _author;
|
||||
string _category;
|
||||
string _comment;
|
||||
string _date;
|
||||
string _description;
|
||||
string _homepage;
|
||||
bool _modified;
|
||||
string _name;
|
||||
string _version;
|
||||
_view = view;
|
||||
_romSet = romSet;
|
||||
_name = romSet.Name;
|
||||
_version = romSet.Version;
|
||||
_author = romSet.Author;
|
||||
_comment = romSet.Comment;
|
||||
_category = romSet.Category;
|
||||
_date = romSet.Date;
|
||||
_description = romSet.Description;
|
||||
_homepage = romSet.Homepage;
|
||||
SaveCommand = ReactiveCommand.Create(ExecuteSaveCommand);
|
||||
CancelCommand = ReactiveCommand.Create(ExecuteCloseCommand);
|
||||
CloseCommand = ReactiveCommand.Create(ExecuteCloseCommand);
|
||||
}
|
||||
|
||||
public EditDatViewModel(EditDat view, RomSetModel romSet)
|
||||
public string NameLabel => Localization.RomSetNameLabel;
|
||||
public string VersionLabel => Localization.RomSetVersionLabel;
|
||||
public string AuthorLabel => Localization.RomSetAuthorLabel;
|
||||
public string CategoryLabel => Localization.RomSetCategoryLabel;
|
||||
public string CommentLabel => Localization.RomSetCommentLabel;
|
||||
public string DateLabel => Localization.RomSetDateLabel;
|
||||
public string DescriptionLabel => Localization.RomSetDescriptionLabel;
|
||||
public string HomepageLabel => Localization.HomepageLabel;
|
||||
public string TotalMachinesLabel => Localization.TotalMachinesLabel;
|
||||
public string CompleteMachinesLabel => Localization.CompleteMachinesLabel;
|
||||
public string IncompleteMachinesLabel => Localization.IncompleteMachinesLabel;
|
||||
public string TotalRomsLabel => Localization.TotalRomsLabel;
|
||||
public string HaveRomsLabel => Localization.HaveRomsLabel;
|
||||
public string MissRomsLabel => Localization.MissRomsLabel;
|
||||
public string Title => Localization.EditDatTitle;
|
||||
public string SaveLabel => Localization.SaveLabel;
|
||||
public string CancelLabel => Localization.CancelLabel;
|
||||
public string CloseLabel => Localization.CloseLabel;
|
||||
|
||||
public ReactiveCommand<Unit, Unit> SaveCommand { get; }
|
||||
public ReactiveCommand<Unit, Unit> CancelCommand { get; }
|
||||
public ReactiveCommand<Unit, Unit> CloseCommand { get; }
|
||||
public long TotalMachines => _romSet.TotalMachines;
|
||||
public long CompleteMachines => _romSet.CompleteMachines;
|
||||
public long IncompleteMachines => _romSet.IncompleteMachines;
|
||||
public long TotalRoms => _romSet.TotalRoms;
|
||||
public long HaveRoms => _romSet.HaveRoms;
|
||||
public long MissRoms => _romSet.MissRoms;
|
||||
|
||||
public bool Modified
|
||||
{
|
||||
get => _modified;
|
||||
set => this.RaiseAndSetIfChanged(ref _modified, value);
|
||||
}
|
||||
|
||||
public string Name
|
||||
{
|
||||
get => _name;
|
||||
set
|
||||
{
|
||||
_view = view;
|
||||
_romSet = romSet;
|
||||
_name = romSet.Name;
|
||||
_version = romSet.Version;
|
||||
_author = romSet.Author;
|
||||
_comment = romSet.Comment;
|
||||
_category = romSet.Category;
|
||||
_date = romSet.Date;
|
||||
_description = romSet.Description;
|
||||
_homepage = romSet.Homepage;
|
||||
SaveCommand = ReactiveCommand.Create(ExecuteSaveCommand);
|
||||
CancelCommand = ReactiveCommand.Create(ExecuteCloseCommand);
|
||||
CloseCommand = ReactiveCommand.Create(ExecuteCloseCommand);
|
||||
}
|
||||
if(value != _name) Modified = true;
|
||||
|
||||
public string NameLabel => Localization.RomSetNameLabel;
|
||||
public string VersionLabel => Localization.RomSetVersionLabel;
|
||||
public string AuthorLabel => Localization.RomSetAuthorLabel;
|
||||
public string CategoryLabel => Localization.RomSetCategoryLabel;
|
||||
public string CommentLabel => Localization.RomSetCommentLabel;
|
||||
public string DateLabel => Localization.RomSetDateLabel;
|
||||
public string DescriptionLabel => Localization.RomSetDescriptionLabel;
|
||||
public string HomepageLabel => Localization.HomepageLabel;
|
||||
public string TotalMachinesLabel => Localization.TotalMachinesLabel;
|
||||
public string CompleteMachinesLabel => Localization.CompleteMachinesLabel;
|
||||
public string IncompleteMachinesLabel => Localization.IncompleteMachinesLabel;
|
||||
public string TotalRomsLabel => Localization.TotalRomsLabel;
|
||||
public string HaveRomsLabel => Localization.HaveRomsLabel;
|
||||
public string MissRomsLabel => Localization.MissRomsLabel;
|
||||
public string Title => Localization.EditDatTitle;
|
||||
public string SaveLabel => Localization.SaveLabel;
|
||||
public string CancelLabel => Localization.CancelLabel;
|
||||
public string CloseLabel => Localization.CloseLabel;
|
||||
|
||||
public ReactiveCommand<Unit, Unit> SaveCommand { get; }
|
||||
public ReactiveCommand<Unit, Unit> CancelCommand { get; }
|
||||
public ReactiveCommand<Unit, Unit> CloseCommand { get; }
|
||||
public long TotalMachines => _romSet.TotalMachines;
|
||||
public long CompleteMachines => _romSet.CompleteMachines;
|
||||
public long IncompleteMachines => _romSet.IncompleteMachines;
|
||||
public long TotalRoms => _romSet.TotalRoms;
|
||||
public long HaveRoms => _romSet.HaveRoms;
|
||||
public long MissRoms => _romSet.MissRoms;
|
||||
|
||||
public bool Modified
|
||||
{
|
||||
get => _modified;
|
||||
set => this.RaiseAndSetIfChanged(ref _modified, value);
|
||||
}
|
||||
|
||||
public string Name
|
||||
{
|
||||
get => _name;
|
||||
set
|
||||
{
|
||||
if(value != _name)
|
||||
Modified = true;
|
||||
|
||||
this.RaiseAndSetIfChanged(ref _name, value);
|
||||
}
|
||||
}
|
||||
|
||||
public string Version
|
||||
{
|
||||
get => _version;
|
||||
set
|
||||
{
|
||||
if(value != _version)
|
||||
Modified = true;
|
||||
|
||||
this.RaiseAndSetIfChanged(ref _version, value);
|
||||
}
|
||||
}
|
||||
|
||||
public string Author
|
||||
{
|
||||
get => _author;
|
||||
set
|
||||
{
|
||||
if(value != _author)
|
||||
Modified = true;
|
||||
|
||||
this.RaiseAndSetIfChanged(ref _author, value);
|
||||
}
|
||||
}
|
||||
|
||||
public string Comment
|
||||
{
|
||||
get => _comment;
|
||||
set
|
||||
{
|
||||
if(value != _comment)
|
||||
Modified = true;
|
||||
|
||||
this.RaiseAndSetIfChanged(ref _comment, value);
|
||||
}
|
||||
}
|
||||
|
||||
public string Category
|
||||
{
|
||||
get => _category;
|
||||
set
|
||||
{
|
||||
if(value != _category)
|
||||
Modified = true;
|
||||
|
||||
this.RaiseAndSetIfChanged(ref _category, value);
|
||||
}
|
||||
}
|
||||
|
||||
public string Date
|
||||
{
|
||||
get => _date;
|
||||
set
|
||||
{
|
||||
if(value != _date)
|
||||
Modified = true;
|
||||
|
||||
this.RaiseAndSetIfChanged(ref _date, value);
|
||||
}
|
||||
}
|
||||
|
||||
public string Description
|
||||
{
|
||||
get => _description;
|
||||
set
|
||||
{
|
||||
if(value != _description)
|
||||
Modified = true;
|
||||
|
||||
this.RaiseAndSetIfChanged(ref _description, value);
|
||||
}
|
||||
}
|
||||
|
||||
public string Homepage
|
||||
{
|
||||
get => _homepage;
|
||||
set
|
||||
{
|
||||
if(value != _homepage)
|
||||
Modified = true;
|
||||
|
||||
this.RaiseAndSetIfChanged(ref _homepage, value);
|
||||
}
|
||||
}
|
||||
|
||||
public EventHandler<RomSetEventArgs> RomSetModified { get; set; }
|
||||
|
||||
void ExecuteCloseCommand() => _view.Close();
|
||||
|
||||
async void ExecuteSaveCommand()
|
||||
{
|
||||
using var ctx = Context.Create(Settings.Settings.Current.DatabasePath);
|
||||
|
||||
RomSet romSetDb = await ctx.RomSets.FindAsync(_romSet.Id);
|
||||
|
||||
if(romSetDb == null)
|
||||
return;
|
||||
|
||||
romSetDb.Author = Author;
|
||||
romSetDb.Comment = Comment;
|
||||
romSetDb.Category = Category;
|
||||
romSetDb.Date = Date;
|
||||
romSetDb.Description = Description;
|
||||
romSetDb.Homepage = Homepage;
|
||||
romSetDb.Name = Name;
|
||||
romSetDb.Version = Version;
|
||||
romSetDb.UpdatedOn = DateTime.UtcNow;
|
||||
|
||||
await ctx.SaveChangesAsync();
|
||||
|
||||
RomSetModified?.Invoke(this, new RomSetEventArgs
|
||||
{
|
||||
RomSet = new RomSetModel
|
||||
{
|
||||
Author = Author,
|
||||
Comment = Comment,
|
||||
Category = Category,
|
||||
Date = Date,
|
||||
Description = Description,
|
||||
Homepage = Homepage,
|
||||
Name = Name,
|
||||
Version = Version,
|
||||
Filename = _romSet.Filename,
|
||||
Sha384 = _romSet.Sha384,
|
||||
TotalMachines = _romSet.TotalMachines,
|
||||
CompleteMachines = _romSet.CompleteMachines,
|
||||
IncompleteMachines = _romSet.IncompleteMachines,
|
||||
TotalRoms = _romSet.TotalRoms,
|
||||
HaveRoms = _romSet.HaveRoms,
|
||||
MissRoms = _romSet.MissRoms,
|
||||
Id = _romSet.Id
|
||||
}
|
||||
});
|
||||
|
||||
Modified = false;
|
||||
this.RaiseAndSetIfChanged(ref _name, value);
|
||||
}
|
||||
}
|
||||
|
||||
public string Version
|
||||
{
|
||||
get => _version;
|
||||
set
|
||||
{
|
||||
if(value != _version) Modified = true;
|
||||
|
||||
this.RaiseAndSetIfChanged(ref _version, value);
|
||||
}
|
||||
}
|
||||
|
||||
public string Author
|
||||
{
|
||||
get => _author;
|
||||
set
|
||||
{
|
||||
if(value != _author) Modified = true;
|
||||
|
||||
this.RaiseAndSetIfChanged(ref _author, value);
|
||||
}
|
||||
}
|
||||
|
||||
public string Comment
|
||||
{
|
||||
get => _comment;
|
||||
set
|
||||
{
|
||||
if(value != _comment) Modified = true;
|
||||
|
||||
this.RaiseAndSetIfChanged(ref _comment, value);
|
||||
}
|
||||
}
|
||||
|
||||
public string Category
|
||||
{
|
||||
get => _category;
|
||||
set
|
||||
{
|
||||
if(value != _category) Modified = true;
|
||||
|
||||
this.RaiseAndSetIfChanged(ref _category, value);
|
||||
}
|
||||
}
|
||||
|
||||
public string Date
|
||||
{
|
||||
get => _date;
|
||||
set
|
||||
{
|
||||
if(value != _date) Modified = true;
|
||||
|
||||
this.RaiseAndSetIfChanged(ref _date, value);
|
||||
}
|
||||
}
|
||||
|
||||
public string Description
|
||||
{
|
||||
get => _description;
|
||||
set
|
||||
{
|
||||
if(value != _description) Modified = true;
|
||||
|
||||
this.RaiseAndSetIfChanged(ref _description, value);
|
||||
}
|
||||
}
|
||||
|
||||
public string Homepage
|
||||
{
|
||||
get => _homepage;
|
||||
set
|
||||
{
|
||||
if(value != _homepage) Modified = true;
|
||||
|
||||
this.RaiseAndSetIfChanged(ref _homepage, value);
|
||||
}
|
||||
}
|
||||
|
||||
public EventHandler<RomSetEventArgs> RomSetModified { get; set; }
|
||||
|
||||
void ExecuteCloseCommand() => _view.Close();
|
||||
|
||||
async void ExecuteSaveCommand()
|
||||
{
|
||||
using var ctx = Context.Create(Settings.Settings.Current.DatabasePath);
|
||||
|
||||
RomSet romSetDb = await ctx.RomSets.FindAsync(_romSet.Id);
|
||||
|
||||
if(romSetDb == null) return;
|
||||
|
||||
romSetDb.Author = Author;
|
||||
romSetDb.Comment = Comment;
|
||||
romSetDb.Category = Category;
|
||||
romSetDb.Date = Date;
|
||||
romSetDb.Description = Description;
|
||||
romSetDb.Homepage = Homepage;
|
||||
romSetDb.Name = Name;
|
||||
romSetDb.Version = Version;
|
||||
romSetDb.UpdatedOn = DateTime.UtcNow;
|
||||
|
||||
await ctx.SaveChangesAsync();
|
||||
|
||||
RomSetModified?.Invoke(this,
|
||||
new RomSetEventArgs
|
||||
{
|
||||
RomSet = new RomSetModel
|
||||
{
|
||||
Author = Author,
|
||||
Comment = Comment,
|
||||
Category = Category,
|
||||
Date = Date,
|
||||
Description = Description,
|
||||
Homepage = Homepage,
|
||||
Name = Name,
|
||||
Version = Version,
|
||||
Filename = _romSet.Filename,
|
||||
Sha384 = _romSet.Sha384,
|
||||
TotalMachines = _romSet.TotalMachines,
|
||||
CompleteMachines = _romSet.CompleteMachines,
|
||||
IncompleteMachines = _romSet.IncompleteMachines,
|
||||
TotalRoms = _romSet.TotalRoms,
|
||||
HaveRoms = _romSet.HaveRoms,
|
||||
MissRoms = _romSet.MissRoms,
|
||||
Id = _romSet.Id
|
||||
}
|
||||
});
|
||||
|
||||
Modified = false;
|
||||
}
|
||||
}
|
||||
@@ -36,125 +36,117 @@ using RomRepoMgr.Resources;
|
||||
using RomRepoMgr.Views;
|
||||
using ErrorEventArgs = RomRepoMgr.Core.EventArgs.ErrorEventArgs;
|
||||
|
||||
namespace RomRepoMgr.ViewModels
|
||||
namespace RomRepoMgr.ViewModels;
|
||||
|
||||
public sealed class ExportDatViewModel : ViewModelBase
|
||||
{
|
||||
public sealed class ExportDatViewModel : ViewModelBase
|
||||
readonly string _datHash;
|
||||
readonly string _outPath;
|
||||
readonly ExportDat _view;
|
||||
readonly Compression _worker;
|
||||
bool _canClose;
|
||||
string _errorMessage;
|
||||
bool _errorVisible;
|
||||
bool _progressVisible;
|
||||
string _statusMessage;
|
||||
|
||||
public ExportDatViewModel(ExportDat view, string datHash, string outPath)
|
||||
{
|
||||
readonly string _datHash;
|
||||
readonly string _outPath;
|
||||
readonly ExportDat _view;
|
||||
readonly Compression _worker;
|
||||
bool _canClose;
|
||||
string _errorMessage;
|
||||
bool _errorVisible;
|
||||
bool _progressVisible;
|
||||
string _statusMessage;
|
||||
_view = view;
|
||||
_datHash = datHash;
|
||||
_outPath = outPath;
|
||||
CloseCommand = ReactiveCommand.Create(ExecuteCloseCommand);
|
||||
ProgressVisible = false;
|
||||
ErrorVisible = false;
|
||||
_worker = new Compression();
|
||||
_worker.FinishedWithText += OnWorkerOnFinishedWithText;
|
||||
_worker.FailedWithText += OnWorkerOnFailedWithText;
|
||||
}
|
||||
|
||||
public ExportDatViewModel(ExportDat view, string datHash, string outPath)
|
||||
[NotNull]
|
||||
public string Title => Localization.ExportDatTitle;
|
||||
|
||||
public string StatusMessage
|
||||
{
|
||||
get => _statusMessage;
|
||||
set => this.RaiseAndSetIfChanged(ref _statusMessage, 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 => Localization.CloseLabel;
|
||||
public ReactiveCommand<Unit, Unit> CloseCommand { get; }
|
||||
|
||||
void OnWorkerOnFinishedWithText(object sender, MessageEventArgs args) => Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
StatusMessage = Localization.Finished;
|
||||
ProgressVisible = false;
|
||||
CanClose = true;
|
||||
});
|
||||
|
||||
void OnWorkerOnFailedWithText(object sender, ErrorEventArgs args) => Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
ErrorMessage = args.Message;
|
||||
ProgressVisible = false;
|
||||
ErrorVisible = true;
|
||||
CanClose = true;
|
||||
});
|
||||
|
||||
void ExecuteCloseCommand() => _view.Close();
|
||||
|
||||
internal void OnOpened()
|
||||
{
|
||||
ProgressVisible = true;
|
||||
StatusMessage = Localization.DecompressingDat;
|
||||
|
||||
var sha384Bytes = new byte[48];
|
||||
string sha384 = _datHash;
|
||||
|
||||
for(var i = 0; i < 48; i++)
|
||||
{
|
||||
_view = view;
|
||||
_datHash = datHash;
|
||||
_outPath = outPath;
|
||||
CloseCommand = ReactiveCommand.Create(ExecuteCloseCommand);
|
||||
ProgressVisible = false;
|
||||
ErrorVisible = false;
|
||||
_worker = new Compression();
|
||||
_worker.FinishedWithText += OnWorkerOnFinishedWithText;
|
||||
_worker.FailedWithText += OnWorkerOnFailedWithText;
|
||||
if(sha384[i * 2] >= 0x30 && sha384[i * 2] <= 0x39)
|
||||
sha384Bytes[i] = (byte)((sha384[i * 2] - 0x30) * 0x10);
|
||||
else if(sha384[i * 2] >= 0x41 && sha384[i * 2] <= 0x46)
|
||||
sha384Bytes[i] = (byte)((sha384[i * 2] - 0x37) * 0x10);
|
||||
else if(sha384[i * 2] >= 0x61 && sha384[i * 2] <= 0x66)
|
||||
sha384Bytes[i] = (byte)((sha384[i * 2] - 0x57) * 0x10);
|
||||
|
||||
if(sha384[i * 2 + 1] >= 0x30 && sha384[i * 2 + 1] <= 0x39)
|
||||
sha384Bytes[i] += (byte)(sha384[i * 2 + 1] - 0x30);
|
||||
else if(sha384[i * 2 + 1] >= 0x41 && sha384[i * 2 + 1] <= 0x46)
|
||||
sha384Bytes[i] += (byte)(sha384[i * 2 + 1] - 0x37);
|
||||
else if(sha384[i * 2 + 1] >= 0x61 && sha384[i * 2 + 1] <= 0x66)
|
||||
sha384Bytes[i] += (byte)(sha384[i * 2 + 1] - 0x57);
|
||||
}
|
||||
|
||||
[NotNull]
|
||||
public string Title => Localization.ExportDatTitle;
|
||||
string datHash32 = Base32.ToBase32String(sha384Bytes);
|
||||
string datFilesPath = Path.Combine(Settings.Settings.Current.RepositoryPath, "datfiles");
|
||||
string compressedDatPath = Path.Combine(datFilesPath, datHash32 + ".lz");
|
||||
|
||||
public string StatusMessage
|
||||
{
|
||||
get => _statusMessage;
|
||||
set => this.RaiseAndSetIfChanged(ref _statusMessage, value);
|
||||
}
|
||||
if(!File.Exists(compressedDatPath)) _view.Close();
|
||||
|
||||
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 => Localization.CloseLabel;
|
||||
public ReactiveCommand<Unit, Unit> CloseCommand { get; }
|
||||
|
||||
void OnWorkerOnFinishedWithText(object sender, MessageEventArgs args) => Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
StatusMessage = Localization.Finished;
|
||||
ProgressVisible = false;
|
||||
CanClose = true;
|
||||
});
|
||||
|
||||
void OnWorkerOnFailedWithText(object sender, ErrorEventArgs args) => Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
ErrorMessage = args.Message;
|
||||
ProgressVisible = false;
|
||||
ErrorVisible = true;
|
||||
CanClose = true;
|
||||
});
|
||||
|
||||
void ExecuteCloseCommand() => _view.Close();
|
||||
|
||||
internal void OnOpened()
|
||||
{
|
||||
ProgressVisible = true;
|
||||
StatusMessage = Localization.DecompressingDat;
|
||||
|
||||
byte[] sha384Bytes = new byte[48];
|
||||
string sha384 = _datHash;
|
||||
|
||||
for(int i = 0; i < 48; i++)
|
||||
{
|
||||
if(sha384[i * 2] >= 0x30 &&
|
||||
sha384[i * 2] <= 0x39)
|
||||
sha384Bytes[i] = (byte)((sha384[i * 2] - 0x30) * 0x10);
|
||||
else if(sha384[i * 2] >= 0x41 &&
|
||||
sha384[i * 2] <= 0x46)
|
||||
sha384Bytes[i] = (byte)((sha384[i * 2] - 0x37) * 0x10);
|
||||
else if(sha384[i * 2] >= 0x61 &&
|
||||
sha384[i * 2] <= 0x66)
|
||||
sha384Bytes[i] = (byte)((sha384[i * 2] - 0x57) * 0x10);
|
||||
|
||||
if(sha384[(i * 2) + 1] >= 0x30 &&
|
||||
sha384[(i * 2) + 1] <= 0x39)
|
||||
sha384Bytes[i] += (byte)(sha384[(i * 2) + 1] - 0x30);
|
||||
else if(sha384[(i * 2) + 1] >= 0x41 &&
|
||||
sha384[(i * 2) + 1] <= 0x46)
|
||||
sha384Bytes[i] += (byte)(sha384[(i * 2) + 1] - 0x37);
|
||||
else if(sha384[(i * 2) + 1] >= 0x61 &&
|
||||
sha384[(i * 2) + 1] <= 0x66)
|
||||
sha384Bytes[i] += (byte)(sha384[(i * 2) + 1] - 0x57);
|
||||
}
|
||||
|
||||
string datHash32 = Base32.ToBase32String(sha384Bytes);
|
||||
string datFilesPath = Path.Combine(Settings.Settings.Current.RepositoryPath, "datfiles");
|
||||
string compressedDatPath = Path.Combine(datFilesPath, datHash32 + ".lz");
|
||||
|
||||
if(!File.Exists(compressedDatPath))
|
||||
_view.Close();
|
||||
|
||||
Task.Run(() => _worker.DecompressFile(compressedDatPath, _outPath));
|
||||
}
|
||||
Task.Run(() => _worker.DecompressFile(compressedDatPath, _outPath));
|
||||
}
|
||||
}
|
||||
@@ -34,237 +34,236 @@ using RomRepoMgr.Core.Workers;
|
||||
using RomRepoMgr.Resources;
|
||||
using RomRepoMgr.Views;
|
||||
|
||||
namespace RomRepoMgr.ViewModels
|
||||
namespace RomRepoMgr.ViewModels;
|
||||
|
||||
public sealed class ExportRomsViewModel : ViewModelBase
|
||||
{
|
||||
public sealed class ExportRomsViewModel : ViewModelBase
|
||||
readonly long _romSetId;
|
||||
readonly ExportRoms _view;
|
||||
bool _canClose;
|
||||
bool _progress2IsIndeterminate;
|
||||
double _progress2Maximum;
|
||||
double _progress2Minimum;
|
||||
double _progress2Value;
|
||||
bool _progress2Visible;
|
||||
bool _progress3IsIndeterminate;
|
||||
double _progress3Maximum;
|
||||
double _progress3Minimum;
|
||||
double _progress3Value;
|
||||
bool _progress3Visible;
|
||||
bool _progressIsIndeterminate;
|
||||
double _progressMaximum;
|
||||
double _progressMinimum;
|
||||
double _progressValue;
|
||||
bool _progressVisible;
|
||||
string _status2Message;
|
||||
string _status3Message;
|
||||
string _statusMessage;
|
||||
|
||||
public ExportRomsViewModel(ExportRoms view, string folderPath, long romSetId)
|
||||
{
|
||||
readonly long _romSetId;
|
||||
readonly ExportRoms _view;
|
||||
bool _canClose;
|
||||
bool _progress2IsIndeterminate;
|
||||
double _progress2Maximum;
|
||||
double _progress2Minimum;
|
||||
double _progress2Value;
|
||||
bool _progress2Visible;
|
||||
bool _progress3IsIndeterminate;
|
||||
double _progress3Maximum;
|
||||
double _progress3Minimum;
|
||||
double _progress3Value;
|
||||
bool _progress3Visible;
|
||||
bool _progressIsIndeterminate;
|
||||
double _progressMaximum;
|
||||
double _progressMinimum;
|
||||
double _progressValue;
|
||||
bool _progressVisible;
|
||||
string _status2Message;
|
||||
string _status3Message;
|
||||
string _statusMessage;
|
||||
_view = view;
|
||||
_romSetId = romSetId;
|
||||
FolderPath = folderPath;
|
||||
CloseCommand = ReactiveCommand.Create(ExecuteCloseCommand);
|
||||
CanClose = false;
|
||||
}
|
||||
|
||||
public ExportRomsViewModel(ExportRoms view, string folderPath, long romSetId)
|
||||
{
|
||||
_view = view;
|
||||
_romSetId = romSetId;
|
||||
FolderPath = folderPath;
|
||||
CloseCommand = ReactiveCommand.Create(ExecuteCloseCommand);
|
||||
CanClose = false;
|
||||
}
|
||||
[NotNull]
|
||||
public string PathLabel => Localization.PathLabel;
|
||||
public string FolderPath { get; }
|
||||
|
||||
[NotNull]
|
||||
public string PathLabel => Localization.PathLabel;
|
||||
public string FolderPath { get; }
|
||||
public bool ProgressVisible
|
||||
{
|
||||
get => _progressVisible;
|
||||
set => this.RaiseAndSetIfChanged(ref _progressVisible, value);
|
||||
}
|
||||
|
||||
public bool ProgressVisible
|
||||
{
|
||||
get => _progressVisible;
|
||||
set => this.RaiseAndSetIfChanged(ref _progressVisible, value);
|
||||
}
|
||||
public string StatusMessage
|
||||
{
|
||||
get => _statusMessage;
|
||||
set => this.RaiseAndSetIfChanged(ref _statusMessage, value);
|
||||
}
|
||||
|
||||
public string StatusMessage
|
||||
{
|
||||
get => _statusMessage;
|
||||
set => this.RaiseAndSetIfChanged(ref _statusMessage, value);
|
||||
}
|
||||
public double ProgressMinimum
|
||||
{
|
||||
get => _progressMinimum;
|
||||
set => this.RaiseAndSetIfChanged(ref _progressMinimum, value);
|
||||
}
|
||||
|
||||
public double ProgressMinimum
|
||||
{
|
||||
get => _progressMinimum;
|
||||
set => this.RaiseAndSetIfChanged(ref _progressMinimum, value);
|
||||
}
|
||||
public double ProgressMaximum
|
||||
{
|
||||
get => _progressMaximum;
|
||||
set => this.RaiseAndSetIfChanged(ref _progressMaximum, value);
|
||||
}
|
||||
|
||||
public double ProgressMaximum
|
||||
{
|
||||
get => _progressMaximum;
|
||||
set => this.RaiseAndSetIfChanged(ref _progressMaximum, value);
|
||||
}
|
||||
public double ProgressValue
|
||||
{
|
||||
get => _progressValue;
|
||||
set => this.RaiseAndSetIfChanged(ref _progressValue, value);
|
||||
}
|
||||
|
||||
public double ProgressValue
|
||||
{
|
||||
get => _progressValue;
|
||||
set => this.RaiseAndSetIfChanged(ref _progressValue, value);
|
||||
}
|
||||
public bool ProgressIsIndeterminate
|
||||
{
|
||||
get => _progressIsIndeterminate;
|
||||
set => this.RaiseAndSetIfChanged(ref _progressIsIndeterminate, value);
|
||||
}
|
||||
|
||||
public bool ProgressIsIndeterminate
|
||||
{
|
||||
get => _progressIsIndeterminate;
|
||||
set => this.RaiseAndSetIfChanged(ref _progressIsIndeterminate, value);
|
||||
}
|
||||
public bool Progress2Visible
|
||||
{
|
||||
get => _progress2Visible;
|
||||
set => this.RaiseAndSetIfChanged(ref _progress2Visible, value);
|
||||
}
|
||||
|
||||
public bool Progress2Visible
|
||||
{
|
||||
get => _progress2Visible;
|
||||
set => this.RaiseAndSetIfChanged(ref _progress2Visible, value);
|
||||
}
|
||||
public string Status2Message
|
||||
{
|
||||
get => _status2Message;
|
||||
set => this.RaiseAndSetIfChanged(ref _status2Message, value);
|
||||
}
|
||||
|
||||
public string Status2Message
|
||||
{
|
||||
get => _status2Message;
|
||||
set => this.RaiseAndSetIfChanged(ref _status2Message, value);
|
||||
}
|
||||
public double Progress2Minimum
|
||||
{
|
||||
get => _progress2Minimum;
|
||||
set => this.RaiseAndSetIfChanged(ref _progress2Minimum, value);
|
||||
}
|
||||
|
||||
public double Progress2Minimum
|
||||
{
|
||||
get => _progress2Minimum;
|
||||
set => this.RaiseAndSetIfChanged(ref _progress2Minimum, value);
|
||||
}
|
||||
public double Progress2Maximum
|
||||
{
|
||||
get => _progress2Maximum;
|
||||
set => this.RaiseAndSetIfChanged(ref _progress2Maximum, value);
|
||||
}
|
||||
|
||||
public double Progress2Maximum
|
||||
{
|
||||
get => _progress2Maximum;
|
||||
set => this.RaiseAndSetIfChanged(ref _progress2Maximum, value);
|
||||
}
|
||||
public double Progress2Value
|
||||
{
|
||||
get => _progress2Value;
|
||||
set => this.RaiseAndSetIfChanged(ref _progress2Value, value);
|
||||
}
|
||||
|
||||
public double Progress2Value
|
||||
{
|
||||
get => _progress2Value;
|
||||
set => this.RaiseAndSetIfChanged(ref _progress2Value, value);
|
||||
}
|
||||
public bool Progress2IsIndeterminate
|
||||
{
|
||||
get => _progress2IsIndeterminate;
|
||||
set => this.RaiseAndSetIfChanged(ref _progress2IsIndeterminate, value);
|
||||
}
|
||||
|
||||
public bool Progress2IsIndeterminate
|
||||
{
|
||||
get => _progress2IsIndeterminate;
|
||||
set => this.RaiseAndSetIfChanged(ref _progress2IsIndeterminate, value);
|
||||
}
|
||||
public bool Progress3Visible
|
||||
{
|
||||
get => _progress3Visible;
|
||||
set => this.RaiseAndSetIfChanged(ref _progress3Visible, value);
|
||||
}
|
||||
|
||||
public bool Progress3Visible
|
||||
{
|
||||
get => _progress3Visible;
|
||||
set => this.RaiseAndSetIfChanged(ref _progress3Visible, value);
|
||||
}
|
||||
public string Status3Message
|
||||
{
|
||||
get => _status3Message;
|
||||
set => this.RaiseAndSetIfChanged(ref _status3Message, value);
|
||||
}
|
||||
|
||||
public string Status3Message
|
||||
{
|
||||
get => _status3Message;
|
||||
set => this.RaiseAndSetIfChanged(ref _status3Message, value);
|
||||
}
|
||||
public double Progress3Minimum
|
||||
{
|
||||
get => _progress3Minimum;
|
||||
set => this.RaiseAndSetIfChanged(ref _progress3Minimum, value);
|
||||
}
|
||||
|
||||
public double Progress3Minimum
|
||||
{
|
||||
get => _progress3Minimum;
|
||||
set => this.RaiseAndSetIfChanged(ref _progress3Minimum, value);
|
||||
}
|
||||
public double Progress3Maximum
|
||||
{
|
||||
get => _progress3Maximum;
|
||||
set => this.RaiseAndSetIfChanged(ref _progress3Maximum, value);
|
||||
}
|
||||
|
||||
public double Progress3Maximum
|
||||
{
|
||||
get => _progress3Maximum;
|
||||
set => this.RaiseAndSetIfChanged(ref _progress3Maximum, value);
|
||||
}
|
||||
public double Progress3Value
|
||||
{
|
||||
get => _progress3Value;
|
||||
set => this.RaiseAndSetIfChanged(ref _progress3Value, value);
|
||||
}
|
||||
|
||||
public double Progress3Value
|
||||
{
|
||||
get => _progress3Value;
|
||||
set => this.RaiseAndSetIfChanged(ref _progress3Value, value);
|
||||
}
|
||||
public bool Progress3IsIndeterminate
|
||||
{
|
||||
get => _progress3IsIndeterminate;
|
||||
set => this.RaiseAndSetIfChanged(ref _progress3IsIndeterminate, value);
|
||||
}
|
||||
|
||||
public bool Progress3IsIndeterminate
|
||||
{
|
||||
get => _progress3IsIndeterminate;
|
||||
set => this.RaiseAndSetIfChanged(ref _progress3IsIndeterminate, value);
|
||||
}
|
||||
[NotNull]
|
||||
public string Title => Localization.ExportRomsTitle;
|
||||
[NotNull]
|
||||
public string CloseLabel => Localization.CloseLabel;
|
||||
|
||||
[NotNull]
|
||||
public string Title => Localization.ExportRomsTitle;
|
||||
[NotNull]
|
||||
public string CloseLabel => Localization.CloseLabel;
|
||||
public bool CanClose
|
||||
{
|
||||
get => _canClose;
|
||||
set => this.RaiseAndSetIfChanged(ref _canClose, value);
|
||||
}
|
||||
|
||||
public bool CanClose
|
||||
{
|
||||
get => _canClose;
|
||||
set => this.RaiseAndSetIfChanged(ref _canClose, value);
|
||||
}
|
||||
public ReactiveCommand<Unit, Unit> CloseCommand { get; }
|
||||
|
||||
public ReactiveCommand<Unit, Unit> CloseCommand { get; }
|
||||
void ExecuteCloseCommand() => _view.Close();
|
||||
|
||||
void ExecuteCloseCommand() => _view.Close();
|
||||
void OnWorkerOnFinished(object sender, EventArgs args) => Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
ProgressVisible = false;
|
||||
CanClose = true;
|
||||
Progress2Visible = false;
|
||||
Progress3Visible = false;
|
||||
});
|
||||
|
||||
void OnWorkerOnFinished(object sender, EventArgs args) => Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
ProgressVisible = false;
|
||||
CanClose = true;
|
||||
Progress2Visible = false;
|
||||
Progress3Visible = false;
|
||||
});
|
||||
void OnWorkerOnSetProgressBounds(object sender, ProgressBoundsEventArgs args) => Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
ProgressIsIndeterminate = false;
|
||||
ProgressMaximum = args.Maximum;
|
||||
ProgressMinimum = args.Minimum;
|
||||
});
|
||||
|
||||
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 OnWorkerOnSetProgress(object sender, ProgressEventArgs args) =>
|
||||
Dispatcher.UIThread.Post(() => ProgressValue = args.Value);
|
||||
void OnWorkerOnSetMessage(object sender, MessageEventArgs args) =>
|
||||
Dispatcher.UIThread.Post(() => StatusMessage = args.Message);
|
||||
|
||||
void OnWorkerOnSetMessage(object sender, MessageEventArgs args) =>
|
||||
Dispatcher.UIThread.Post(() => StatusMessage = args.Message);
|
||||
void OnWorkerOnSetIndeterminateProgress(object sender, EventArgs args) =>
|
||||
Dispatcher.UIThread.Post(() => ProgressIsIndeterminate = true);
|
||||
|
||||
void OnWorkerOnSetIndeterminateProgress(object sender, EventArgs args) =>
|
||||
Dispatcher.UIThread.Post(() => ProgressIsIndeterminate = true);
|
||||
void OnWorkerOnSetProgressBounds2(object sender, ProgressBoundsEventArgs args) => Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
Progress2Visible = true;
|
||||
Progress2IsIndeterminate = false;
|
||||
Progress2Maximum = args.Maximum;
|
||||
Progress2Minimum = args.Minimum;
|
||||
});
|
||||
|
||||
void OnWorkerOnSetProgressBounds2(object sender, ProgressBoundsEventArgs args) => Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
Progress2Visible = true;
|
||||
Progress2IsIndeterminate = false;
|
||||
Progress2Maximum = args.Maximum;
|
||||
Progress2Minimum = args.Minimum;
|
||||
});
|
||||
void OnWorkerOnSetProgress2(object sender, ProgressEventArgs args) =>
|
||||
Dispatcher.UIThread.Post(() => Progress2Value = args.Value);
|
||||
|
||||
void OnWorkerOnSetProgress2(object sender, ProgressEventArgs args) =>
|
||||
Dispatcher.UIThread.Post(() => Progress2Value = args.Value);
|
||||
void OnWorkerOnSetMessage2(object sender, MessageEventArgs args) =>
|
||||
Dispatcher.UIThread.Post(() => Status2Message = args.Message);
|
||||
|
||||
void OnWorkerOnSetMessage2(object sender, MessageEventArgs args) =>
|
||||
Dispatcher.UIThread.Post(() => Status2Message = args.Message);
|
||||
void OnWorkerOnSetProgressBounds3(object sender, ProgressBoundsEventArgs args) => Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
Progress3Visible = true;
|
||||
Progress3IsIndeterminate = false;
|
||||
Progress3Maximum = args.Maximum;
|
||||
Progress3Minimum = args.Minimum;
|
||||
});
|
||||
|
||||
void OnWorkerOnSetProgressBounds3(object sender, ProgressBoundsEventArgs args) => Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
Progress3Visible = true;
|
||||
Progress3IsIndeterminate = false;
|
||||
Progress3Maximum = args.Maximum;
|
||||
Progress3Minimum = args.Minimum;
|
||||
});
|
||||
void OnWorkerOnSetProgress3(object sender, ProgressEventArgs args) =>
|
||||
Dispatcher.UIThread.Post(() => Progress3Value = args.Value);
|
||||
|
||||
void OnWorkerOnSetProgress3(object sender, ProgressEventArgs args) =>
|
||||
Dispatcher.UIThread.Post(() => Progress3Value = args.Value);
|
||||
void OnWorkerOnSetMessage3(object sender, MessageEventArgs args) =>
|
||||
Dispatcher.UIThread.Post(() => Status3Message = args.Message);
|
||||
|
||||
void OnWorkerOnSetMessage3(object sender, MessageEventArgs args) =>
|
||||
Dispatcher.UIThread.Post(() => Status3Message = args.Message);
|
||||
public void OnOpened()
|
||||
{
|
||||
var worker = new FileExporter(_romSetId, FolderPath);
|
||||
worker.SetMessage += OnWorkerOnSetMessage;
|
||||
worker.SetProgress += OnWorkerOnSetProgress;
|
||||
worker.SetProgressBounds += OnWorkerOnSetProgressBounds;
|
||||
worker.SetMessage2 += OnWorkerOnSetMessage2;
|
||||
worker.SetProgress2 += OnWorkerOnSetProgress2;
|
||||
worker.SetProgress2Bounds += OnWorkerOnSetProgressBounds2;
|
||||
worker.SetMessage3 += OnWorkerOnSetMessage3;
|
||||
worker.SetProgress3 += OnWorkerOnSetProgress3;
|
||||
worker.SetProgress3Bounds += OnWorkerOnSetProgressBounds3;
|
||||
worker.WorkFinished += OnWorkerOnFinished;
|
||||
|
||||
public void OnOpened()
|
||||
{
|
||||
var worker = new FileExporter(_romSetId, FolderPath);
|
||||
worker.SetMessage += OnWorkerOnSetMessage;
|
||||
worker.SetProgress += OnWorkerOnSetProgress;
|
||||
worker.SetProgressBounds += OnWorkerOnSetProgressBounds;
|
||||
worker.SetMessage2 += OnWorkerOnSetMessage2;
|
||||
worker.SetProgress2 += OnWorkerOnSetProgress2;
|
||||
worker.SetProgress2Bounds += OnWorkerOnSetProgressBounds2;
|
||||
worker.SetMessage3 += OnWorkerOnSetMessage3;
|
||||
worker.SetProgress3 += OnWorkerOnSetProgress3;
|
||||
worker.SetProgress3Bounds += OnWorkerOnSetProgressBounds3;
|
||||
worker.WorkFinished += OnWorkerOnFinished;
|
||||
ProgressVisible = true;
|
||||
|
||||
ProgressVisible = true;
|
||||
|
||||
Task.Run(worker.Export);
|
||||
}
|
||||
Task.Run(worker.Export);
|
||||
}
|
||||
}
|
||||
@@ -38,319 +38,325 @@ using RomRepoMgr.Resources;
|
||||
using RomRepoMgr.Views;
|
||||
using ErrorEventArgs = RomRepoMgr.Core.EventArgs.ErrorEventArgs;
|
||||
|
||||
namespace RomRepoMgr.ViewModels
|
||||
namespace RomRepoMgr.ViewModels;
|
||||
|
||||
public sealed class ImportDatFolderViewModel : ViewModelBase
|
||||
{
|
||||
public sealed class ImportDatFolderViewModel : ViewModelBase
|
||||
readonly ImportDatFolder _view;
|
||||
bool _allFilesChecked;
|
||||
bool _canClose;
|
||||
bool _canStart;
|
||||
string _category;
|
||||
string[] _datFiles;
|
||||
bool _isImporting;
|
||||
bool _isReady;
|
||||
int _listPosition;
|
||||
bool _progress2IsIndeterminate;
|
||||
double _progress2Maximum;
|
||||
double _progress2Minimum;
|
||||
double _progress2Value;
|
||||
bool _progress2Visible;
|
||||
bool _progressIsIndeterminate;
|
||||
double _progressMaximum;
|
||||
double _progressMinimum;
|
||||
double _progressValue;
|
||||
bool _progressVisible;
|
||||
bool _recursiveChecked;
|
||||
string _status2Message;
|
||||
string _statusMessage;
|
||||
|
||||
public ImportDatFolderViewModel(ImportDatFolder view, string folderPath)
|
||||
{
|
||||
readonly ImportDatFolder _view;
|
||||
bool _allFilesChecked;
|
||||
bool _canClose;
|
||||
bool _canStart;
|
||||
string _category;
|
||||
string[] _datFiles;
|
||||
bool _isImporting;
|
||||
bool _isReady;
|
||||
int _listPosition;
|
||||
bool _progress2IsIndeterminate;
|
||||
double _progress2Maximum;
|
||||
double _progress2Minimum;
|
||||
double _progress2Value;
|
||||
bool _progress2Visible;
|
||||
bool _progressIsIndeterminate;
|
||||
double _progressMaximum;
|
||||
double _progressMinimum;
|
||||
double _progressValue;
|
||||
bool _progressVisible;
|
||||
bool _recursiveChecked;
|
||||
string _status2Message;
|
||||
string _statusMessage;
|
||||
_view = view;
|
||||
FolderPath = folderPath;
|
||||
_allFilesChecked = false;
|
||||
_recursiveChecked = true;
|
||||
ImportResults = new ObservableCollection<ImportDatFolderItem>();
|
||||
CloseCommand = ReactiveCommand.Create(ExecuteCloseCommand);
|
||||
StartCommand = ReactiveCommand.Create(ExecuteStartCommand);
|
||||
}
|
||||
|
||||
public ImportDatFolderViewModel(ImportDatFolder view, string folderPath)
|
||||
public string PathLabel => Localization.PathLabel;
|
||||
public string CategoryLabel => Localization.RomSetCategoryLabel;
|
||||
public string FolderPath { get; }
|
||||
public string AllFilesLabel => Localization.AllFilesLabel;
|
||||
public string RecursiveLabel => Localization.RecursiveLabel;
|
||||
|
||||
public bool AllFilesChecked
|
||||
{
|
||||
get => _allFilesChecked;
|
||||
set
|
||||
{
|
||||
_view = view;
|
||||
FolderPath = folderPath;
|
||||
_allFilesChecked = false;
|
||||
_recursiveChecked = true;
|
||||
ImportResults = new ObservableCollection<ImportDatFolderItem>();
|
||||
CloseCommand = ReactiveCommand.Create(ExecuteCloseCommand);
|
||||
StartCommand = ReactiveCommand.Create(ExecuteStartCommand);
|
||||
this.RaiseAndSetIfChanged(ref _allFilesChecked, value);
|
||||
RefreshFiles();
|
||||
}
|
||||
}
|
||||
|
||||
public string PathLabel => Localization.PathLabel;
|
||||
public string CategoryLabel => Localization.RomSetCategoryLabel;
|
||||
public string FolderPath { get; }
|
||||
public string AllFilesLabel => Localization.AllFilesLabel;
|
||||
public string RecursiveLabel => Localization.RecursiveLabel;
|
||||
|
||||
public bool AllFilesChecked
|
||||
public bool RecursiveChecked
|
||||
{
|
||||
get => _recursiveChecked;
|
||||
set
|
||||
{
|
||||
get => _allFilesChecked;
|
||||
set
|
||||
{
|
||||
this.RaiseAndSetIfChanged(ref _allFilesChecked, value);
|
||||
RefreshFiles();
|
||||
}
|
||||
this.RaiseAndSetIfChanged(ref _recursiveChecked, value);
|
||||
RefreshFiles();
|
||||
}
|
||||
}
|
||||
|
||||
public bool RecursiveChecked
|
||||
public bool IsReady
|
||||
{
|
||||
get => _isReady;
|
||||
set => this.RaiseAndSetIfChanged(ref _isReady, value);
|
||||
}
|
||||
|
||||
public bool ProgressVisible
|
||||
{
|
||||
get => _progressVisible;
|
||||
set => this.RaiseAndSetIfChanged(ref _progressVisible, value);
|
||||
}
|
||||
|
||||
public string StatusMessage
|
||||
{
|
||||
get => _statusMessage;
|
||||
set => this.RaiseAndSetIfChanged(ref _statusMessage, value);
|
||||
}
|
||||
|
||||
public double ProgressMinimum
|
||||
{
|
||||
get => _progressMinimum;
|
||||
set => this.RaiseAndSetIfChanged(ref _progressMinimum, value);
|
||||
}
|
||||
|
||||
public double ProgressMaximum
|
||||
{
|
||||
get => _progressMaximum;
|
||||
set => this.RaiseAndSetIfChanged(ref _progressMaximum, value);
|
||||
}
|
||||
|
||||
public double ProgressValue
|
||||
{
|
||||
get => _progressValue;
|
||||
set => this.RaiseAndSetIfChanged(ref _progressValue, value);
|
||||
}
|
||||
|
||||
public bool ProgressIsIndeterminate
|
||||
{
|
||||
get => _progressIsIndeterminate;
|
||||
set => this.RaiseAndSetIfChanged(ref _progressIsIndeterminate, value);
|
||||
}
|
||||
|
||||
public bool Progress2Visible
|
||||
{
|
||||
get => _progress2Visible;
|
||||
set => this.RaiseAndSetIfChanged(ref _progress2Visible, value);
|
||||
}
|
||||
|
||||
public string Status2Message
|
||||
{
|
||||
get => _status2Message;
|
||||
set => this.RaiseAndSetIfChanged(ref _status2Message, value);
|
||||
}
|
||||
|
||||
public double Progress2Minimum
|
||||
{
|
||||
get => _progress2Minimum;
|
||||
set => this.RaiseAndSetIfChanged(ref _progress2Minimum, value);
|
||||
}
|
||||
|
||||
public double Progress2Maximum
|
||||
{
|
||||
get => _progress2Maximum;
|
||||
set => this.RaiseAndSetIfChanged(ref _progress2Maximum, value);
|
||||
}
|
||||
|
||||
public double Progress2Value
|
||||
{
|
||||
get => _progress2Value;
|
||||
set => this.RaiseAndSetIfChanged(ref _progress2Value, value);
|
||||
}
|
||||
|
||||
public bool Progress2IsIndeterminate
|
||||
{
|
||||
get => _progress2IsIndeterminate;
|
||||
set => this.RaiseAndSetIfChanged(ref _progress2IsIndeterminate, value);
|
||||
}
|
||||
|
||||
public bool IsImporting
|
||||
{
|
||||
get => _isImporting;
|
||||
set => this.RaiseAndSetIfChanged(ref _isImporting, value);
|
||||
}
|
||||
|
||||
public string Category
|
||||
{
|
||||
get => _category;
|
||||
set => this.RaiseAndSetIfChanged(ref _category, value);
|
||||
}
|
||||
|
||||
[NotNull]
|
||||
public string Title => Localization.ImportDatFolderTitle;
|
||||
|
||||
public ObservableCollection<ImportDatFolderItem> ImportResults { get; }
|
||||
public string ResultFilenameLabel => Localization.ResultFilenameLabel;
|
||||
public string ResultStatusLabel => Localization.ResultStatusLabel;
|
||||
public string CloseLabel => Localization.CloseLabel;
|
||||
public string StartLabel => Localization.StartLabel;
|
||||
|
||||
public bool CanClose
|
||||
{
|
||||
get => _canClose;
|
||||
set => this.RaiseAndSetIfChanged(ref _canClose, value);
|
||||
}
|
||||
|
||||
public bool CanStart
|
||||
{
|
||||
get => _canStart;
|
||||
set => this.RaiseAndSetIfChanged(ref _canStart, value);
|
||||
}
|
||||
|
||||
public ReactiveCommand<Unit, Unit> CloseCommand { get; }
|
||||
public ReactiveCommand<Unit, Unit> StartCommand { get; }
|
||||
|
||||
internal void OnOpened() => RefreshFiles();
|
||||
|
||||
void RefreshFiles() => Task.Run(() =>
|
||||
{
|
||||
Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
get => _recursiveChecked;
|
||||
set
|
||||
{
|
||||
this.RaiseAndSetIfChanged(ref _recursiveChecked, value);
|
||||
RefreshFiles();
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsReady
|
||||
{
|
||||
get => _isReady;
|
||||
set => this.RaiseAndSetIfChanged(ref _isReady, value);
|
||||
}
|
||||
|
||||
public bool ProgressVisible
|
||||
{
|
||||
get => _progressVisible;
|
||||
set => this.RaiseAndSetIfChanged(ref _progressVisible, value);
|
||||
}
|
||||
|
||||
public string StatusMessage
|
||||
{
|
||||
get => _statusMessage;
|
||||
set => this.RaiseAndSetIfChanged(ref _statusMessage, value);
|
||||
}
|
||||
|
||||
public double ProgressMinimum
|
||||
{
|
||||
get => _progressMinimum;
|
||||
set => this.RaiseAndSetIfChanged(ref _progressMinimum, value);
|
||||
}
|
||||
|
||||
public double ProgressMaximum
|
||||
{
|
||||
get => _progressMaximum;
|
||||
set => this.RaiseAndSetIfChanged(ref _progressMaximum, value);
|
||||
}
|
||||
|
||||
public double ProgressValue
|
||||
{
|
||||
get => _progressValue;
|
||||
set => this.RaiseAndSetIfChanged(ref _progressValue, value);
|
||||
}
|
||||
|
||||
public bool ProgressIsIndeterminate
|
||||
{
|
||||
get => _progressIsIndeterminate;
|
||||
set => this.RaiseAndSetIfChanged(ref _progressIsIndeterminate, value);
|
||||
}
|
||||
|
||||
public bool Progress2Visible
|
||||
{
|
||||
get => _progress2Visible;
|
||||
set => this.RaiseAndSetIfChanged(ref _progress2Visible, value);
|
||||
}
|
||||
|
||||
public string Status2Message
|
||||
{
|
||||
get => _status2Message;
|
||||
set => this.RaiseAndSetIfChanged(ref _status2Message, value);
|
||||
}
|
||||
|
||||
public double Progress2Minimum
|
||||
{
|
||||
get => _progress2Minimum;
|
||||
set => this.RaiseAndSetIfChanged(ref _progress2Minimum, value);
|
||||
}
|
||||
|
||||
public double Progress2Maximum
|
||||
{
|
||||
get => _progress2Maximum;
|
||||
set => this.RaiseAndSetIfChanged(ref _progress2Maximum, value);
|
||||
}
|
||||
|
||||
public double Progress2Value
|
||||
{
|
||||
get => _progress2Value;
|
||||
set => this.RaiseAndSetIfChanged(ref _progress2Value, value);
|
||||
}
|
||||
|
||||
public bool Progress2IsIndeterminate
|
||||
{
|
||||
get => _progress2IsIndeterminate;
|
||||
set => this.RaiseAndSetIfChanged(ref _progress2IsIndeterminate, value);
|
||||
}
|
||||
|
||||
public bool IsImporting
|
||||
{
|
||||
get => _isImporting;
|
||||
set => this.RaiseAndSetIfChanged(ref _isImporting, value);
|
||||
}
|
||||
|
||||
public string Category
|
||||
{
|
||||
get => _category;
|
||||
set => this.RaiseAndSetIfChanged(ref _category, value);
|
||||
}
|
||||
|
||||
[NotNull]
|
||||
public string Title => Localization.ImportDatFolderTitle;
|
||||
|
||||
public ObservableCollection<ImportDatFolderItem> ImportResults { get; }
|
||||
public string ResultFilenameLabel => Localization.ResultFilenameLabel;
|
||||
public string ResultStatusLabel => Localization.ResultStatusLabel;
|
||||
public string CloseLabel => Localization.CloseLabel;
|
||||
public string StartLabel => Localization.StartLabel;
|
||||
|
||||
public bool CanClose
|
||||
{
|
||||
get => _canClose;
|
||||
set => this.RaiseAndSetIfChanged(ref _canClose, value);
|
||||
}
|
||||
|
||||
public bool CanStart
|
||||
{
|
||||
get => _canStart;
|
||||
set => this.RaiseAndSetIfChanged(ref _canStart, value);
|
||||
}
|
||||
|
||||
public ReactiveCommand<Unit, Unit> CloseCommand { get; }
|
||||
public ReactiveCommand<Unit, Unit> StartCommand { get; }
|
||||
|
||||
internal void OnOpened() => RefreshFiles();
|
||||
|
||||
void RefreshFiles() => Task.Run(() =>
|
||||
{
|
||||
Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
IsReady = false;
|
||||
ProgressVisible = true;
|
||||
Progress2Visible = false;
|
||||
ProgressIsIndeterminate = true;
|
||||
StatusMessage = Localization.SearchingForFiles;
|
||||
});
|
||||
|
||||
if(_allFilesChecked)
|
||||
{
|
||||
_datFiles = Directory.GetFiles(FolderPath, "*.*",
|
||||
_recursiveChecked ? SearchOption.AllDirectories
|
||||
: SearchOption.TopDirectoryOnly).OrderBy(f => f).ToArray();
|
||||
}
|
||||
else
|
||||
{
|
||||
string[] dats = Directory.GetFiles(FolderPath, "*.dat",
|
||||
_recursiveChecked ? SearchOption.AllDirectories
|
||||
: SearchOption.TopDirectoryOnly);
|
||||
|
||||
string[] xmls = Directory.GetFiles(FolderPath, "*.xml",
|
||||
_recursiveChecked ? SearchOption.AllDirectories
|
||||
: SearchOption.TopDirectoryOnly);
|
||||
|
||||
_datFiles = dats.Concat(xmls).OrderBy(f => f).ToArray();
|
||||
}
|
||||
|
||||
Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
IsReady = true;
|
||||
ProgressVisible = false;
|
||||
StatusMessage = string.Format(Localization.FoundFiles, _datFiles.Length);
|
||||
CanClose = true;
|
||||
CanStart = true;
|
||||
});
|
||||
});
|
||||
|
||||
void ExecuteCloseCommand() => _view.Close();
|
||||
|
||||
void ExecuteStartCommand()
|
||||
{
|
||||
_listPosition = 0;
|
||||
ProgressMinimum = 0;
|
||||
ProgressMaximum = _datFiles.Length;
|
||||
ProgressValue = 0;
|
||||
ProgressIsIndeterminate = false;
|
||||
ProgressVisible = true;
|
||||
Progress2Visible = true;
|
||||
CanClose = false;
|
||||
CanStart = false;
|
||||
IsReady = false;
|
||||
IsImporting = true;
|
||||
ProgressVisible = true;
|
||||
Progress2Visible = false;
|
||||
ProgressIsIndeterminate = true;
|
||||
StatusMessage = Localization.SearchingForFiles;
|
||||
});
|
||||
|
||||
Import();
|
||||
if(_allFilesChecked)
|
||||
{
|
||||
_datFiles = Directory
|
||||
.GetFiles(FolderPath,
|
||||
"*.*",
|
||||
_recursiveChecked ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly)
|
||||
.OrderBy(f => f)
|
||||
.ToArray();
|
||||
}
|
||||
else
|
||||
{
|
||||
string[] dats = Directory.GetFiles(FolderPath,
|
||||
"*.dat",
|
||||
_recursiveChecked
|
||||
? SearchOption.AllDirectories
|
||||
: SearchOption.TopDirectoryOnly);
|
||||
|
||||
string[] xmls = Directory.GetFiles(FolderPath,
|
||||
"*.xml",
|
||||
_recursiveChecked
|
||||
? SearchOption.AllDirectories
|
||||
: SearchOption.TopDirectoryOnly);
|
||||
|
||||
_datFiles = dats.Concat(xmls).OrderBy(f => f).ToArray();
|
||||
}
|
||||
|
||||
void Import()
|
||||
Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
if(_listPosition >= _datFiles.Length)
|
||||
{
|
||||
Progress2Visible = false;
|
||||
ProgressVisible = false;
|
||||
StatusMessage = Localization.Finished;
|
||||
CanClose = true;
|
||||
CanStart = false;
|
||||
IsReady = true;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
StatusMessage = string.Format(Localization.ImportingItem, Path.GetFileName(_datFiles[_listPosition]));
|
||||
ProgressValue = _listPosition;
|
||||
|
||||
var _worker = new DatImporter(_datFiles[_listPosition], Category);
|
||||
_worker.ErrorOccurred += OnWorkerOnErrorOccurred;
|
||||
_worker.SetIndeterminateProgress += OnWorkerOnSetIndeterminateProgress;
|
||||
_worker.SetMessage += OnWorkerOnSetMessage;
|
||||
_worker.SetProgress += OnWorkerOnSetProgress;
|
||||
_worker.SetProgressBounds += OnWorkerOnSetProgressBounds;
|
||||
_worker.WorkFinished += OnWorkerOnWorkFinished;
|
||||
_worker.RomSetAdded += RomSetAdded;
|
||||
Task.Run(_worker.Import);
|
||||
}
|
||||
|
||||
void OnWorkerOnWorkFinished(object sender, MessageEventArgs args) => Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
ImportResults.Add(new ImportDatFolderItem
|
||||
{
|
||||
Filename = Path.GetFileName(_datFiles[_listPosition]),
|
||||
Status = args.Message
|
||||
});
|
||||
|
||||
_listPosition++;
|
||||
Import();
|
||||
IsReady = true;
|
||||
ProgressVisible = false;
|
||||
StatusMessage = string.Format(Localization.FoundFiles, _datFiles.Length);
|
||||
CanClose = true;
|
||||
CanStart = true;
|
||||
});
|
||||
});
|
||||
|
||||
void OnWorkerOnSetProgressBounds(object sender, ProgressBoundsEventArgs args) => Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
Progress2IsIndeterminate = false;
|
||||
Progress2Maximum = args.Maximum;
|
||||
Progress2Minimum = args.Minimum;
|
||||
});
|
||||
void ExecuteCloseCommand() => _view.Close();
|
||||
|
||||
void OnWorkerOnSetProgress(object sender, ProgressEventArgs args) =>
|
||||
Dispatcher.UIThread.Post(() => Progress2Value = args.Value);
|
||||
|
||||
void OnWorkerOnSetMessage(object sender, MessageEventArgs args) =>
|
||||
Dispatcher.UIThread.Post(() => Status2Message = args.Message);
|
||||
|
||||
void OnWorkerOnSetIndeterminateProgress(object sender, EventArgs args) =>
|
||||
Dispatcher.UIThread.Post(() => Progress2IsIndeterminate = true);
|
||||
|
||||
void OnWorkerOnErrorOccurred(object sender, ErrorEventArgs args) => Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
ImportResults.Add(new ImportDatFolderItem
|
||||
{
|
||||
Filename = Path.GetFileName(_datFiles[_listPosition]),
|
||||
Status = args.Message
|
||||
});
|
||||
|
||||
_listPosition++;
|
||||
Import();
|
||||
});
|
||||
|
||||
public event EventHandler<RomSetEventArgs> RomSetAdded;
|
||||
}
|
||||
|
||||
public sealed class ImportDatFolderItem
|
||||
void ExecuteStartCommand()
|
||||
{
|
||||
public string Filename { get; set; }
|
||||
public string Status { get; set; }
|
||||
_listPosition = 0;
|
||||
ProgressMinimum = 0;
|
||||
ProgressMaximum = _datFiles.Length;
|
||||
ProgressValue = 0;
|
||||
ProgressIsIndeterminate = false;
|
||||
ProgressVisible = true;
|
||||
Progress2Visible = true;
|
||||
CanClose = false;
|
||||
CanStart = false;
|
||||
IsReady = false;
|
||||
IsImporting = true;
|
||||
|
||||
Import();
|
||||
}
|
||||
|
||||
void Import()
|
||||
{
|
||||
if(_listPosition >= _datFiles.Length)
|
||||
{
|
||||
Progress2Visible = false;
|
||||
ProgressVisible = false;
|
||||
StatusMessage = Localization.Finished;
|
||||
CanClose = true;
|
||||
CanStart = false;
|
||||
IsReady = true;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
StatusMessage = string.Format(Localization.ImportingItem, Path.GetFileName(_datFiles[_listPosition]));
|
||||
ProgressValue = _listPosition;
|
||||
|
||||
var _worker = new DatImporter(_datFiles[_listPosition], Category);
|
||||
_worker.ErrorOccurred += OnWorkerOnErrorOccurred;
|
||||
_worker.SetIndeterminateProgress += OnWorkerOnSetIndeterminateProgress;
|
||||
_worker.SetMessage += OnWorkerOnSetMessage;
|
||||
_worker.SetProgress += OnWorkerOnSetProgress;
|
||||
_worker.SetProgressBounds += OnWorkerOnSetProgressBounds;
|
||||
_worker.WorkFinished += OnWorkerOnWorkFinished;
|
||||
_worker.RomSetAdded += RomSetAdded;
|
||||
Task.Run(_worker.Import);
|
||||
}
|
||||
|
||||
void OnWorkerOnWorkFinished(object sender, MessageEventArgs args) => Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
ImportResults.Add(new ImportDatFolderItem
|
||||
{
|
||||
Filename = Path.GetFileName(_datFiles[_listPosition]),
|
||||
Status = args.Message
|
||||
});
|
||||
|
||||
_listPosition++;
|
||||
Import();
|
||||
});
|
||||
|
||||
void OnWorkerOnSetProgressBounds(object sender, ProgressBoundsEventArgs args) => Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
Progress2IsIndeterminate = false;
|
||||
Progress2Maximum = args.Maximum;
|
||||
Progress2Minimum = args.Minimum;
|
||||
});
|
||||
|
||||
void OnWorkerOnSetProgress(object sender, ProgressEventArgs args) =>
|
||||
Dispatcher.UIThread.Post(() => Progress2Value = args.Value);
|
||||
|
||||
void OnWorkerOnSetMessage(object sender, MessageEventArgs args) =>
|
||||
Dispatcher.UIThread.Post(() => Status2Message = args.Message);
|
||||
|
||||
void OnWorkerOnSetIndeterminateProgress(object sender, EventArgs args) =>
|
||||
Dispatcher.UIThread.Post(() => Progress2IsIndeterminate = true);
|
||||
|
||||
void OnWorkerOnErrorOccurred(object sender, ErrorEventArgs args) => Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
ImportResults.Add(new ImportDatFolderItem
|
||||
{
|
||||
Filename = Path.GetFileName(_datFiles[_listPosition]),
|
||||
Status = args.Message
|
||||
});
|
||||
|
||||
_listPosition++;
|
||||
Import();
|
||||
});
|
||||
|
||||
public event EventHandler<RomSetEventArgs> RomSetAdded;
|
||||
}
|
||||
|
||||
public sealed class ImportDatFolderItem
|
||||
{
|
||||
public string Filename { get; set; }
|
||||
public string Status { get; set; }
|
||||
}
|
||||
@@ -34,138 +34,137 @@ using RomRepoMgr.Core.Workers;
|
||||
using RomRepoMgr.Resources;
|
||||
using RomRepoMgr.Views;
|
||||
|
||||
namespace RomRepoMgr.ViewModels
|
||||
namespace RomRepoMgr.ViewModels;
|
||||
|
||||
public sealed class ImportDatViewModel : ViewModelBase
|
||||
{
|
||||
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)
|
||||
{
|
||||
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, null);
|
||||
_worker.ErrorOccurred += OnWorkerOnErrorOccurred;
|
||||
_worker.SetIndeterminateProgress += OnWorkerOnSetIndeterminateProgress;
|
||||
_worker.SetMessage += OnWorkerOnSetMessage;
|
||||
_worker.SetProgress += OnWorkerOnSetProgress;
|
||||
_worker.SetProgressBounds += OnWorkerOnSetProgressBounds;
|
||||
_worker.WorkFinished += OnWorkerOnWorkFinished;
|
||||
}
|
||||
|
||||
[NotNull]
|
||||
public string Title => Localization.ImportDatTitle;
|
||||
|
||||
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 => Localization.CloseLabel;
|
||||
public ReactiveCommand<Unit, Unit> CloseCommand { get; }
|
||||
|
||||
void OnWorkerOnWorkFinished(object sender, MessageEventArgs args) => Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
StatusMessage = args.Message;
|
||||
ProgressVisible = false;
|
||||
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;
|
||||
ProgressVisible = false;
|
||||
ErrorVisible = true;
|
||||
CanClose = true;
|
||||
});
|
||||
|
||||
void ExecuteCloseCommand() => _view.Close();
|
||||
|
||||
internal void OnOpened()
|
||||
{
|
||||
ProgressVisible = true;
|
||||
_worker.RomSetAdded += RomSetAdded;
|
||||
Task.Run(_worker.Import);
|
||||
}
|
||||
|
||||
public event EventHandler<RomSetEventArgs> RomSetAdded;
|
||||
_view = view;
|
||||
CloseCommand = ReactiveCommand.Create(ExecuteCloseCommand);
|
||||
IndeterminateProgress = true;
|
||||
ProgressVisible = false;
|
||||
ErrorVisible = false;
|
||||
_worker = new DatImporter(datPath, null);
|
||||
_worker.ErrorOccurred += OnWorkerOnErrorOccurred;
|
||||
_worker.SetIndeterminateProgress += OnWorkerOnSetIndeterminateProgress;
|
||||
_worker.SetMessage += OnWorkerOnSetMessage;
|
||||
_worker.SetProgress += OnWorkerOnSetProgress;
|
||||
_worker.SetProgressBounds += OnWorkerOnSetProgressBounds;
|
||||
_worker.WorkFinished += OnWorkerOnWorkFinished;
|
||||
}
|
||||
|
||||
[NotNull]
|
||||
public string Title => Localization.ImportDatTitle;
|
||||
|
||||
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 => Localization.CloseLabel;
|
||||
public ReactiveCommand<Unit, Unit> CloseCommand { get; }
|
||||
|
||||
void OnWorkerOnWorkFinished(object sender, MessageEventArgs args) => Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
StatusMessage = args.Message;
|
||||
ProgressVisible = false;
|
||||
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;
|
||||
ProgressVisible = false;
|
||||
ErrorVisible = true;
|
||||
CanClose = true;
|
||||
});
|
||||
|
||||
void ExecuteCloseCommand() => _view.Close();
|
||||
|
||||
internal void OnOpened()
|
||||
{
|
||||
ProgressVisible = true;
|
||||
_worker.RomSetAdded += RomSetAdded;
|
||||
Task.Run(_worker.Import);
|
||||
}
|
||||
|
||||
public event EventHandler<RomSetEventArgs> RomSetAdded;
|
||||
}
|
||||
@@ -36,261 +36,259 @@ using RomRepoMgr.Core.Workers;
|
||||
using RomRepoMgr.Resources;
|
||||
using RomRepoMgr.Views;
|
||||
|
||||
namespace RomRepoMgr.ViewModels
|
||||
namespace RomRepoMgr.ViewModels;
|
||||
|
||||
public sealed class ImportRomFolderViewModel : ViewModelBase
|
||||
{
|
||||
public sealed class ImportRomFolderViewModel : ViewModelBase
|
||||
readonly ImportRomFolder _view;
|
||||
bool _canClose;
|
||||
bool _canStart;
|
||||
bool _isImporting;
|
||||
bool _isReady;
|
||||
bool _knownOnlyChecked;
|
||||
bool _progress2IsIndeterminate;
|
||||
double _progress2Maximum;
|
||||
double _progress2Minimum;
|
||||
double _progress2Value;
|
||||
bool _progress2Visible;
|
||||
bool _progressIsIndeterminate;
|
||||
double _progressMaximum;
|
||||
double _progressMinimum;
|
||||
double _progressValue;
|
||||
bool _progressVisible;
|
||||
bool _recurseArchivesChecked;
|
||||
bool _removeFilesChecked;
|
||||
bool _removeFilesEnabled;
|
||||
string _status2Message;
|
||||
string _statusMessage;
|
||||
|
||||
public ImportRomFolderViewModel(ImportRomFolder view, string folderPath)
|
||||
{
|
||||
readonly ImportRomFolder _view;
|
||||
bool _canClose;
|
||||
bool _canStart;
|
||||
bool _isImporting;
|
||||
bool _isReady;
|
||||
bool _knownOnlyChecked;
|
||||
bool _progress2IsIndeterminate;
|
||||
double _progress2Maximum;
|
||||
double _progress2Minimum;
|
||||
double _progress2Value;
|
||||
bool _progress2Visible;
|
||||
bool _progressIsIndeterminate;
|
||||
double _progressMaximum;
|
||||
double _progressMinimum;
|
||||
double _progressValue;
|
||||
bool _progressVisible;
|
||||
bool _recurseArchivesChecked;
|
||||
bool _removeFilesChecked;
|
||||
bool _removeFilesEnabled;
|
||||
string _status2Message;
|
||||
string _statusMessage;
|
||||
|
||||
public ImportRomFolderViewModel(ImportRomFolder view, string folderPath)
|
||||
{
|
||||
_view = view;
|
||||
FolderPath = folderPath;
|
||||
_removeFilesChecked = false;
|
||||
_knownOnlyChecked = true;
|
||||
_recurseArchivesChecked = Settings.Settings.UnArUsable;
|
||||
ImportResults = new ObservableCollection<ImportRomItem>();
|
||||
CloseCommand = ReactiveCommand.Create(ExecuteCloseCommand);
|
||||
StartCommand = ReactiveCommand.Create(ExecuteStartCommand);
|
||||
IsReady = true;
|
||||
CanStart = true;
|
||||
CanClose = true;
|
||||
_removeFilesEnabled = false;
|
||||
}
|
||||
|
||||
public string PathLabel => Localization.PathLabel;
|
||||
public string FolderPath { get; }
|
||||
public string RemoveFilesLabel => Localization.RemoveFilesLabel;
|
||||
public string KnownOnlyLabel => Localization.KnownOnlyLabel;
|
||||
public string RecurseArchivesLabel => Localization.RecurseArchivesLabel;
|
||||
public bool RecurseArchivesEnabled => Settings.Settings.UnArUsable;
|
||||
|
||||
public bool RemoveFilesChecked
|
||||
{
|
||||
get => _removeFilesChecked;
|
||||
set => this.RaiseAndSetIfChanged(ref _removeFilesChecked, value);
|
||||
}
|
||||
|
||||
public bool KnownOnlyChecked
|
||||
{
|
||||
get => _knownOnlyChecked;
|
||||
set => this.RaiseAndSetIfChanged(ref _knownOnlyChecked, value);
|
||||
}
|
||||
|
||||
public bool RemoveFilesEnabled
|
||||
{
|
||||
get => _removeFilesEnabled;
|
||||
set => this.RaiseAndSetIfChanged(ref _removeFilesEnabled, value);
|
||||
}
|
||||
|
||||
public bool RecurseArchivesChecked
|
||||
{
|
||||
get => _recurseArchivesChecked;
|
||||
set
|
||||
{
|
||||
if(value)
|
||||
RemoveFilesChecked = false;
|
||||
|
||||
RemoveFilesEnabled = !value;
|
||||
this.RaiseAndSetIfChanged(ref _recurseArchivesChecked, value);
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsReady
|
||||
{
|
||||
get => _isReady;
|
||||
set => this.RaiseAndSetIfChanged(ref _isReady, value);
|
||||
}
|
||||
|
||||
public bool ProgressVisible
|
||||
{
|
||||
get => _progressVisible;
|
||||
set => this.RaiseAndSetIfChanged(ref _progressVisible, value);
|
||||
}
|
||||
|
||||
public string StatusMessage
|
||||
{
|
||||
get => _statusMessage;
|
||||
set => this.RaiseAndSetIfChanged(ref _statusMessage, value);
|
||||
}
|
||||
|
||||
public double ProgressMinimum
|
||||
{
|
||||
get => _progressMinimum;
|
||||
set => this.RaiseAndSetIfChanged(ref _progressMinimum, value);
|
||||
}
|
||||
|
||||
public double ProgressMaximum
|
||||
{
|
||||
get => _progressMaximum;
|
||||
set => this.RaiseAndSetIfChanged(ref _progressMaximum, value);
|
||||
}
|
||||
|
||||
public double ProgressValue
|
||||
{
|
||||
get => _progressValue;
|
||||
set => this.RaiseAndSetIfChanged(ref _progressValue, value);
|
||||
}
|
||||
|
||||
public bool ProgressIsIndeterminate
|
||||
{
|
||||
get => _progressIsIndeterminate;
|
||||
set => this.RaiseAndSetIfChanged(ref _progressIsIndeterminate, value);
|
||||
}
|
||||
|
||||
public bool Progress2Visible
|
||||
{
|
||||
get => _progress2Visible;
|
||||
set => this.RaiseAndSetIfChanged(ref _progress2Visible, value);
|
||||
}
|
||||
|
||||
public string Status2Message
|
||||
{
|
||||
get => _status2Message;
|
||||
set => this.RaiseAndSetIfChanged(ref _status2Message, value);
|
||||
}
|
||||
|
||||
public double Progress2Minimum
|
||||
{
|
||||
get => _progress2Minimum;
|
||||
set => this.RaiseAndSetIfChanged(ref _progress2Minimum, value);
|
||||
}
|
||||
|
||||
public double Progress2Maximum
|
||||
{
|
||||
get => _progress2Maximum;
|
||||
set => this.RaiseAndSetIfChanged(ref _progress2Maximum, value);
|
||||
}
|
||||
|
||||
public double Progress2Value
|
||||
{
|
||||
get => _progress2Value;
|
||||
set => this.RaiseAndSetIfChanged(ref _progress2Value, value);
|
||||
}
|
||||
|
||||
public bool Progress2IsIndeterminate
|
||||
{
|
||||
get => _progress2IsIndeterminate;
|
||||
set => this.RaiseAndSetIfChanged(ref _progress2IsIndeterminate, value);
|
||||
}
|
||||
|
||||
public bool IsImporting
|
||||
{
|
||||
get => _isImporting;
|
||||
set => this.RaiseAndSetIfChanged(ref _isImporting, value);
|
||||
}
|
||||
|
||||
[NotNull]
|
||||
public string Title => Localization.ImportRomFolderTitle;
|
||||
|
||||
public ObservableCollection<ImportRomItem> ImportResults { get; }
|
||||
public string ResultFilenameLabel => Localization.ResultFilenameLabel;
|
||||
public string ResultStatusLabel => Localization.ResultStatusLabel;
|
||||
public string CloseLabel => Localization.CloseLabel;
|
||||
public string StartLabel => Localization.StartLabel;
|
||||
|
||||
public bool CanClose
|
||||
{
|
||||
get => _canClose;
|
||||
set => this.RaiseAndSetIfChanged(ref _canClose, value);
|
||||
}
|
||||
|
||||
public bool CanStart
|
||||
{
|
||||
get => _canStart;
|
||||
set => this.RaiseAndSetIfChanged(ref _canStart, value);
|
||||
}
|
||||
|
||||
public ReactiveCommand<Unit, Unit> CloseCommand { get; }
|
||||
public ReactiveCommand<Unit, Unit> StartCommand { get; }
|
||||
|
||||
void ExecuteCloseCommand() => _view.Close();
|
||||
|
||||
void ExecuteStartCommand()
|
||||
{
|
||||
IsReady = false;
|
||||
ProgressVisible = true;
|
||||
IsImporting = true;
|
||||
CanStart = false;
|
||||
CanClose = false;
|
||||
Progress2Visible = true;
|
||||
|
||||
var worker = new FileImporter(KnownOnlyChecked, RemoveFilesChecked);
|
||||
worker.SetIndeterminateProgress += OnWorkerOnSetIndeterminateProgress;
|
||||
worker.SetMessage += OnWorkerOnSetMessage;
|
||||
worker.SetProgress += OnWorkerOnSetProgress;
|
||||
worker.SetProgressBounds += OnWorkerOnSetProgressBounds;
|
||||
worker.SetIndeterminateProgress2 += OnWorkerOnSetIndeterminateProgress2;
|
||||
worker.SetMessage2 += OnWorkerOnSetMessage2;
|
||||
worker.SetProgress2 += OnWorkerOnSetProgress2;
|
||||
worker.SetProgressBounds2 += OnWorkerOnSetProgressBounds2;
|
||||
worker.Finished += OnWorkerOnFinished;
|
||||
worker.ImportedRom += OnWorkerOnImportedRom;
|
||||
|
||||
Task.Run(() => worker.ProcessPath(FolderPath, true, RecurseArchivesChecked));
|
||||
}
|
||||
|
||||
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 = Localization.Finished;
|
||||
CanClose = true;
|
||||
Progress2Visible = false;
|
||||
});
|
||||
|
||||
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;
|
||||
Progress2Maximum = args.Maximum;
|
||||
Progress2Minimum = args.Minimum;
|
||||
});
|
||||
|
||||
void OnWorkerOnSetProgress2(object sender, ProgressEventArgs args) =>
|
||||
Dispatcher.UIThread.Post(() => Progress2Value = args.Value);
|
||||
|
||||
void OnWorkerOnSetMessage2(object sender, MessageEventArgs args) =>
|
||||
Dispatcher.UIThread.Post(() => Status2Message = args.Message);
|
||||
|
||||
void OnWorkerOnSetIndeterminateProgress2(object sender, EventArgs args) =>
|
||||
Dispatcher.UIThread.Post(() => Progress2IsIndeterminate = true);
|
||||
_view = view;
|
||||
FolderPath = folderPath;
|
||||
_removeFilesChecked = false;
|
||||
_knownOnlyChecked = true;
|
||||
_recurseArchivesChecked = Settings.Settings.UnArUsable;
|
||||
ImportResults = new ObservableCollection<ImportRomItem>();
|
||||
CloseCommand = ReactiveCommand.Create(ExecuteCloseCommand);
|
||||
StartCommand = ReactiveCommand.Create(ExecuteStartCommand);
|
||||
IsReady = true;
|
||||
CanStart = true;
|
||||
CanClose = true;
|
||||
_removeFilesEnabled = false;
|
||||
}
|
||||
|
||||
public string PathLabel => Localization.PathLabel;
|
||||
public string FolderPath { get; }
|
||||
public string RemoveFilesLabel => Localization.RemoveFilesLabel;
|
||||
public string KnownOnlyLabel => Localization.KnownOnlyLabel;
|
||||
public string RecurseArchivesLabel => Localization.RecurseArchivesLabel;
|
||||
public bool RecurseArchivesEnabled => Settings.Settings.UnArUsable;
|
||||
|
||||
public bool RemoveFilesChecked
|
||||
{
|
||||
get => _removeFilesChecked;
|
||||
set => this.RaiseAndSetIfChanged(ref _removeFilesChecked, value);
|
||||
}
|
||||
|
||||
public bool KnownOnlyChecked
|
||||
{
|
||||
get => _knownOnlyChecked;
|
||||
set => this.RaiseAndSetIfChanged(ref _knownOnlyChecked, value);
|
||||
}
|
||||
|
||||
public bool RemoveFilesEnabled
|
||||
{
|
||||
get => _removeFilesEnabled;
|
||||
set => this.RaiseAndSetIfChanged(ref _removeFilesEnabled, value);
|
||||
}
|
||||
|
||||
public bool RecurseArchivesChecked
|
||||
{
|
||||
get => _recurseArchivesChecked;
|
||||
set
|
||||
{
|
||||
if(value) RemoveFilesChecked = false;
|
||||
|
||||
RemoveFilesEnabled = !value;
|
||||
this.RaiseAndSetIfChanged(ref _recurseArchivesChecked, value);
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsReady
|
||||
{
|
||||
get => _isReady;
|
||||
set => this.RaiseAndSetIfChanged(ref _isReady, value);
|
||||
}
|
||||
|
||||
public bool ProgressVisible
|
||||
{
|
||||
get => _progressVisible;
|
||||
set => this.RaiseAndSetIfChanged(ref _progressVisible, value);
|
||||
}
|
||||
|
||||
public string StatusMessage
|
||||
{
|
||||
get => _statusMessage;
|
||||
set => this.RaiseAndSetIfChanged(ref _statusMessage, value);
|
||||
}
|
||||
|
||||
public double ProgressMinimum
|
||||
{
|
||||
get => _progressMinimum;
|
||||
set => this.RaiseAndSetIfChanged(ref _progressMinimum, value);
|
||||
}
|
||||
|
||||
public double ProgressMaximum
|
||||
{
|
||||
get => _progressMaximum;
|
||||
set => this.RaiseAndSetIfChanged(ref _progressMaximum, value);
|
||||
}
|
||||
|
||||
public double ProgressValue
|
||||
{
|
||||
get => _progressValue;
|
||||
set => this.RaiseAndSetIfChanged(ref _progressValue, value);
|
||||
}
|
||||
|
||||
public bool ProgressIsIndeterminate
|
||||
{
|
||||
get => _progressIsIndeterminate;
|
||||
set => this.RaiseAndSetIfChanged(ref _progressIsIndeterminate, value);
|
||||
}
|
||||
|
||||
public bool Progress2Visible
|
||||
{
|
||||
get => _progress2Visible;
|
||||
set => this.RaiseAndSetIfChanged(ref _progress2Visible, value);
|
||||
}
|
||||
|
||||
public string Status2Message
|
||||
{
|
||||
get => _status2Message;
|
||||
set => this.RaiseAndSetIfChanged(ref _status2Message, value);
|
||||
}
|
||||
|
||||
public double Progress2Minimum
|
||||
{
|
||||
get => _progress2Minimum;
|
||||
set => this.RaiseAndSetIfChanged(ref _progress2Minimum, value);
|
||||
}
|
||||
|
||||
public double Progress2Maximum
|
||||
{
|
||||
get => _progress2Maximum;
|
||||
set => this.RaiseAndSetIfChanged(ref _progress2Maximum, value);
|
||||
}
|
||||
|
||||
public double Progress2Value
|
||||
{
|
||||
get => _progress2Value;
|
||||
set => this.RaiseAndSetIfChanged(ref _progress2Value, value);
|
||||
}
|
||||
|
||||
public bool Progress2IsIndeterminate
|
||||
{
|
||||
get => _progress2IsIndeterminate;
|
||||
set => this.RaiseAndSetIfChanged(ref _progress2IsIndeterminate, value);
|
||||
}
|
||||
|
||||
public bool IsImporting
|
||||
{
|
||||
get => _isImporting;
|
||||
set => this.RaiseAndSetIfChanged(ref _isImporting, value);
|
||||
}
|
||||
|
||||
[NotNull]
|
||||
public string Title => Localization.ImportRomFolderTitle;
|
||||
|
||||
public ObservableCollection<ImportRomItem> ImportResults { get; }
|
||||
public string ResultFilenameLabel => Localization.ResultFilenameLabel;
|
||||
public string ResultStatusLabel => Localization.ResultStatusLabel;
|
||||
public string CloseLabel => Localization.CloseLabel;
|
||||
public string StartLabel => Localization.StartLabel;
|
||||
|
||||
public bool CanClose
|
||||
{
|
||||
get => _canClose;
|
||||
set => this.RaiseAndSetIfChanged(ref _canClose, value);
|
||||
}
|
||||
|
||||
public bool CanStart
|
||||
{
|
||||
get => _canStart;
|
||||
set => this.RaiseAndSetIfChanged(ref _canStart, value);
|
||||
}
|
||||
|
||||
public ReactiveCommand<Unit, Unit> CloseCommand { get; }
|
||||
public ReactiveCommand<Unit, Unit> StartCommand { get; }
|
||||
|
||||
void ExecuteCloseCommand() => _view.Close();
|
||||
|
||||
void ExecuteStartCommand()
|
||||
{
|
||||
IsReady = false;
|
||||
ProgressVisible = true;
|
||||
IsImporting = true;
|
||||
CanStart = false;
|
||||
CanClose = false;
|
||||
Progress2Visible = true;
|
||||
|
||||
var worker = new FileImporter(KnownOnlyChecked, RemoveFilesChecked);
|
||||
worker.SetIndeterminateProgress += OnWorkerOnSetIndeterminateProgress;
|
||||
worker.SetMessage += OnWorkerOnSetMessage;
|
||||
worker.SetProgress += OnWorkerOnSetProgress;
|
||||
worker.SetProgressBounds += OnWorkerOnSetProgressBounds;
|
||||
worker.SetIndeterminateProgress2 += OnWorkerOnSetIndeterminateProgress2;
|
||||
worker.SetMessage2 += OnWorkerOnSetMessage2;
|
||||
worker.SetProgress2 += OnWorkerOnSetProgress2;
|
||||
worker.SetProgressBounds2 += OnWorkerOnSetProgressBounds2;
|
||||
worker.Finished += OnWorkerOnFinished;
|
||||
worker.ImportedRom += OnWorkerOnImportedRom;
|
||||
|
||||
Task.Run(() => worker.ProcessPath(FolderPath, true, RecurseArchivesChecked));
|
||||
}
|
||||
|
||||
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 = Localization.Finished;
|
||||
CanClose = true;
|
||||
Progress2Visible = false;
|
||||
});
|
||||
|
||||
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;
|
||||
Progress2Maximum = args.Maximum;
|
||||
Progress2Minimum = args.Minimum;
|
||||
});
|
||||
|
||||
void OnWorkerOnSetProgress2(object sender, ProgressEventArgs args) =>
|
||||
Dispatcher.UIThread.Post(() => Progress2Value = args.Value);
|
||||
|
||||
void OnWorkerOnSetMessage2(object sender, MessageEventArgs args) =>
|
||||
Dispatcher.UIThread.Post(() => Status2Message = args.Message);
|
||||
|
||||
void OnWorkerOnSetIndeterminateProgress2(object sender, EventArgs args) =>
|
||||
Dispatcher.UIThread.Post(() => Progress2IsIndeterminate = true);
|
||||
}
|
||||
@@ -42,330 +42,318 @@ using RomRepoMgr.Core.Models;
|
||||
using RomRepoMgr.Resources;
|
||||
using RomRepoMgr.Views;
|
||||
|
||||
namespace RomRepoMgr.ViewModels
|
||||
namespace RomRepoMgr.ViewModels;
|
||||
|
||||
public class MainWindowViewModel : ViewModelBase
|
||||
{
|
||||
public class MainWindowViewModel : ViewModelBase
|
||||
readonly MainWindow _view;
|
||||
RomSetModel _selectedRomSet;
|
||||
Vfs _vfs;
|
||||
|
||||
public MainWindowViewModel(MainWindow view, List<RomSetModel> romSets)
|
||||
{
|
||||
readonly MainWindow _view;
|
||||
RomSetModel _selectedRomSet;
|
||||
Vfs _vfs;
|
||||
_view = view;
|
||||
ExitCommand = ReactiveCommand.Create(ExecuteExitCommand);
|
||||
SettingsCommand = ReactiveCommand.Create(ExecuteSettingsCommand);
|
||||
AboutCommand = ReactiveCommand.Create(ExecuteAboutCommand);
|
||||
ImportDatCommand = ReactiveCommand.Create(ExecuteImportDatCommand);
|
||||
ImportDatFolderCommand = ReactiveCommand.Create(ExecuteImportDatFolderCommand);
|
||||
ImportRomFolderCommand = ReactiveCommand.Create(ExecuteImportRomFolderCommand);
|
||||
DeleteRomSetCommand = ReactiveCommand.Create(ExecuteDeleteRomSetCommand);
|
||||
EditRomSetCommand = ReactiveCommand.Create(ExecuteEditRomSetCommand);
|
||||
ExportDatCommand = ReactiveCommand.Create(ExecuteExportDatCommand);
|
||||
ExportRomsCommand = ReactiveCommand.Create(ExecuteExportRomsCommand);
|
||||
MountCommand = ReactiveCommand.Create(ExecuteMountCommand);
|
||||
UmountCommand = ReactiveCommand.Create(ExecuteUmountCommand);
|
||||
UpdateStatsCommand = ReactiveCommand.Create(ExecuteUpdateStatsCommand);
|
||||
RomSets = new ObservableCollection<RomSetModel>(romSets);
|
||||
}
|
||||
|
||||
public MainWindowViewModel(MainWindow view, List<RomSetModel> romSets)
|
||||
public ObservableCollection<RomSetModel> RomSets { get; }
|
||||
public string RomSetLabel => Localization.RomSets;
|
||||
public string RomSetNameLabel => Localization.RomSetNameLabel;
|
||||
public string RomSetVersionLabel => Localization.RomSetVersionLabel;
|
||||
public string RomSetAuthorLabel => Localization.RomSetAuthorLabel;
|
||||
public string RomSetCategoryLabel => Localization.RomSetCategoryLabel;
|
||||
public string RomSetDateLabel => Localization.RomSetDateLabel;
|
||||
public string RomSetDescriptionLabel => Localization.RomSetDescriptionLabel;
|
||||
public string RomSetCommentLabel => Localization.RomSetCommentLabel;
|
||||
public string RomSetTotalMachinesLabel => Localization.RomSetTotalMachinesLabel;
|
||||
public string RomSetCompleteMachinesLabel => Localization.RomSetCompleteMachinesLabel;
|
||||
public string RomSetIncompleteMachinesLabel => Localization.RomSetIncompleteMachinesLabel;
|
||||
public string RomSetTotalRomsLabel => Localization.RomSetTotalRomsLabel;
|
||||
public string RomSetHaveRomsLabel => Localization.RomSetHaveRomsLabel;
|
||||
public string RomSetMissRomsLabel => Localization.RomSetMissRomsLabel;
|
||||
public bool IsVfsAvailable => Vfs.IsAvailable;
|
||||
public string FileMenuText => Localization.FileMenuText;
|
||||
public string FileMenuImportDatFileText => Localization.FileMenuImportDatFileText;
|
||||
public string FileMenuImportDatFolderText => Localization.FileMenuImportDatFolderText;
|
||||
public string FileMenuSettingsText => Localization.FileMenuSettingsText;
|
||||
public string FileMenuExitText => Localization.FileMenuExitText;
|
||||
public string FilesystemMenuText => Localization.FilesystemMenuText;
|
||||
public string FilesystemMenuMountText => Localization.FilesystemMenuMountText;
|
||||
public string RomsMenuText => Localization.RomsMenuText;
|
||||
public string RomsMenuImportText => Localization.RomsMenuImportText;
|
||||
public string RomSetsMenuText => Localization.RomSetsMenuText;
|
||||
public string RomSetsMenuSaveRomsText => Localization.RomSetsMenuSaveRomsText;
|
||||
public string RomSetsMenuSaveDatText => Localization.RomSetsMenuSaveDatText;
|
||||
public string RomSetsMenuEditText => Localization.RomSetsMenuEditText;
|
||||
public string RomSetsMenuDeleteText => Localization.RomSetsMenuDeleteText;
|
||||
public string HelpMenuText => Localization.HelpMenuText;
|
||||
public string HelpMenuAboutText => Localization.HelpMenuAboutText;
|
||||
public string FilesystemMenuUmountText => Localization.FilesystemMenuUmountText;
|
||||
public string DatabaseMenuText => Localization.DatabaseMenuText;
|
||||
public string DatabaseMenuUpdateStatsText => Localization.DatabaseMenuUpdateStatsText;
|
||||
|
||||
public bool NativeMenuSupported =>
|
||||
NativeMenu.GetIsNativeMenuExported((Application.Current.ApplicationLifetime as
|
||||
IClassicDesktopStyleApplicationLifetime)?.MainWindow);
|
||||
|
||||
public ReactiveCommand<Unit, Unit> AboutCommand { get; }
|
||||
public ReactiveCommand<Unit, Unit> ExitCommand { get; }
|
||||
public ReactiveCommand<Unit, Unit> SettingsCommand { get; }
|
||||
public ReactiveCommand<Unit, Unit> ImportDatCommand { get; }
|
||||
public ReactiveCommand<Unit, Unit> ImportDatFolderCommand { get; }
|
||||
public ReactiveCommand<Unit, Unit> ImportRomFolderCommand { get; }
|
||||
public ReactiveCommand<Unit, Unit> DeleteRomSetCommand { get; }
|
||||
public ReactiveCommand<Unit, Unit> EditRomSetCommand { get; }
|
||||
public ReactiveCommand<Unit, Unit> ExportDatCommand { get; }
|
||||
public ReactiveCommand<Unit, Unit> ExportRomsCommand { get; }
|
||||
public ReactiveCommand<Unit, Unit> MountCommand { get; }
|
||||
public ReactiveCommand<Unit, Unit> UmountCommand { get; }
|
||||
public ReactiveCommand<Unit, Unit> UpdateStatsCommand { get; }
|
||||
|
||||
public Vfs Vfs
|
||||
{
|
||||
get => _vfs;
|
||||
set => this.RaiseAndSetIfChanged(ref _vfs, value);
|
||||
}
|
||||
|
||||
public RomSetModel SelectedRomSet
|
||||
{
|
||||
get => _selectedRomSet;
|
||||
set => this.RaiseAndSetIfChanged(ref _selectedRomSet, value);
|
||||
}
|
||||
|
||||
internal async void ExecuteSettingsCommand()
|
||||
{
|
||||
var dialog = new SettingsDialog();
|
||||
dialog.DataContext = new SettingsViewModel(dialog);
|
||||
await dialog.ShowDialog(_view);
|
||||
}
|
||||
|
||||
internal void ExecuteExitCommand() =>
|
||||
(Application.Current.ApplicationLifetime as ClassicDesktopStyleApplicationLifetime)?.Shutdown();
|
||||
|
||||
internal void ExecuteAboutCommand()
|
||||
{
|
||||
var dialog = new About();
|
||||
dialog.DataContext = new AboutViewModel(dialog);
|
||||
dialog.ShowDialog(_view);
|
||||
}
|
||||
|
||||
async void ExecuteImportDatCommand()
|
||||
{
|
||||
var dlgOpen = new OpenFileDialog
|
||||
{
|
||||
_view = view;
|
||||
ExitCommand = ReactiveCommand.Create(ExecuteExitCommand);
|
||||
SettingsCommand = ReactiveCommand.Create(ExecuteSettingsCommand);
|
||||
AboutCommand = ReactiveCommand.Create(ExecuteAboutCommand);
|
||||
ImportDatCommand = ReactiveCommand.Create(ExecuteImportDatCommand);
|
||||
ImportDatFolderCommand = ReactiveCommand.Create(ExecuteImportDatFolderCommand);
|
||||
ImportRomFolderCommand = ReactiveCommand.Create(ExecuteImportRomFolderCommand);
|
||||
DeleteRomSetCommand = ReactiveCommand.Create(ExecuteDeleteRomSetCommand);
|
||||
EditRomSetCommand = ReactiveCommand.Create(ExecuteEditRomSetCommand);
|
||||
ExportDatCommand = ReactiveCommand.Create(ExecuteExportDatCommand);
|
||||
ExportRomsCommand = ReactiveCommand.Create(ExecuteExportRomsCommand);
|
||||
MountCommand = ReactiveCommand.Create(ExecuteMountCommand);
|
||||
UmountCommand = ReactiveCommand.Create(ExecuteUmountCommand);
|
||||
UpdateStatsCommand = ReactiveCommand.Create(ExecuteUpdateStatsCommand);
|
||||
RomSets = new ObservableCollection<RomSetModel>(romSets);
|
||||
}
|
||||
AllowMultiple = false,
|
||||
Title = Localization.ImportDatFileDialogTitle
|
||||
};
|
||||
|
||||
public ObservableCollection<RomSetModel> RomSets { get; }
|
||||
public string RomSetLabel => Localization.RomSets;
|
||||
public string RomSetNameLabel => Localization.RomSetNameLabel;
|
||||
public string RomSetVersionLabel => Localization.RomSetVersionLabel;
|
||||
public string RomSetAuthorLabel => Localization.RomSetAuthorLabel;
|
||||
public string RomSetCategoryLabel => Localization.RomSetCategoryLabel;
|
||||
public string RomSetDateLabel => Localization.RomSetDateLabel;
|
||||
public string RomSetDescriptionLabel => Localization.RomSetDescriptionLabel;
|
||||
public string RomSetCommentLabel => Localization.RomSetCommentLabel;
|
||||
public string RomSetTotalMachinesLabel => Localization.RomSetTotalMachinesLabel;
|
||||
public string RomSetCompleteMachinesLabel => Localization.RomSetCompleteMachinesLabel;
|
||||
public string RomSetIncompleteMachinesLabel => Localization.RomSetIncompleteMachinesLabel;
|
||||
public string RomSetTotalRomsLabel => Localization.RomSetTotalRomsLabel;
|
||||
public string RomSetHaveRomsLabel => Localization.RomSetHaveRomsLabel;
|
||||
public string RomSetMissRomsLabel => Localization.RomSetMissRomsLabel;
|
||||
public bool IsVfsAvailable => Vfs.IsAvailable;
|
||||
public string FileMenuText => Localization.FileMenuText;
|
||||
public string FileMenuImportDatFileText => Localization.FileMenuImportDatFileText;
|
||||
public string FileMenuImportDatFolderText => Localization.FileMenuImportDatFolderText;
|
||||
public string FileMenuSettingsText => Localization.FileMenuSettingsText;
|
||||
public string FileMenuExitText => Localization.FileMenuExitText;
|
||||
public string FilesystemMenuText => Localization.FilesystemMenuText;
|
||||
public string FilesystemMenuMountText => Localization.FilesystemMenuMountText;
|
||||
public string RomsMenuText => Localization.RomsMenuText;
|
||||
public string RomsMenuImportText => Localization.RomsMenuImportText;
|
||||
public string RomSetsMenuText => Localization.RomSetsMenuText;
|
||||
public string RomSetsMenuSaveRomsText => Localization.RomSetsMenuSaveRomsText;
|
||||
public string RomSetsMenuSaveDatText => Localization.RomSetsMenuSaveDatText;
|
||||
public string RomSetsMenuEditText => Localization.RomSetsMenuEditText;
|
||||
public string RomSetsMenuDeleteText => Localization.RomSetsMenuDeleteText;
|
||||
public string HelpMenuText => Localization.HelpMenuText;
|
||||
public string HelpMenuAboutText => Localization.HelpMenuAboutText;
|
||||
public string FilesystemMenuUmountText => Localization.FilesystemMenuUmountText;
|
||||
public string DatabaseMenuText => Localization.DatabaseMenuText;
|
||||
public string DatabaseMenuUpdateStatsText => Localization.DatabaseMenuUpdateStatsText;
|
||||
|
||||
public bool NativeMenuSupported =>
|
||||
NativeMenu.GetIsNativeMenuExported((Application.Current.ApplicationLifetime as
|
||||
IClassicDesktopStyleApplicationLifetime)?.MainWindow);
|
||||
|
||||
public ReactiveCommand<Unit, Unit> AboutCommand { get; }
|
||||
public ReactiveCommand<Unit, Unit> ExitCommand { get; }
|
||||
public ReactiveCommand<Unit, Unit> SettingsCommand { get; }
|
||||
public ReactiveCommand<Unit, Unit> ImportDatCommand { get; }
|
||||
public ReactiveCommand<Unit, Unit> ImportDatFolderCommand { get; }
|
||||
public ReactiveCommand<Unit, Unit> ImportRomFolderCommand { get; }
|
||||
public ReactiveCommand<Unit, Unit> DeleteRomSetCommand { get; }
|
||||
public ReactiveCommand<Unit, Unit> EditRomSetCommand { get; }
|
||||
public ReactiveCommand<Unit, Unit> ExportDatCommand { get; }
|
||||
public ReactiveCommand<Unit, Unit> ExportRomsCommand { get; }
|
||||
public ReactiveCommand<Unit, Unit> MountCommand { get; }
|
||||
public ReactiveCommand<Unit, Unit> UmountCommand { get; }
|
||||
public ReactiveCommand<Unit, Unit> UpdateStatsCommand { get; }
|
||||
|
||||
public Vfs Vfs
|
||||
dlgOpen.Filters.Add(new FileDialogFilter
|
||||
{
|
||||
get => _vfs;
|
||||
set => this.RaiseAndSetIfChanged(ref _vfs, value);
|
||||
}
|
||||
|
||||
public RomSetModel SelectedRomSet
|
||||
{
|
||||
get => _selectedRomSet;
|
||||
set => this.RaiseAndSetIfChanged(ref _selectedRomSet, value);
|
||||
}
|
||||
|
||||
internal async void ExecuteSettingsCommand()
|
||||
{
|
||||
var dialog = new SettingsDialog();
|
||||
dialog.DataContext = new SettingsViewModel(dialog);
|
||||
await dialog.ShowDialog(_view);
|
||||
}
|
||||
|
||||
internal void ExecuteExitCommand() =>
|
||||
(Application.Current.ApplicationLifetime as ClassicDesktopStyleApplicationLifetime)?.Shutdown();
|
||||
|
||||
internal void ExecuteAboutCommand()
|
||||
{
|
||||
var dialog = new About();
|
||||
dialog.DataContext = new AboutViewModel(dialog);
|
||||
dialog.ShowDialog(_view);
|
||||
}
|
||||
|
||||
async void ExecuteImportDatCommand()
|
||||
{
|
||||
var dlgOpen = new OpenFileDialog
|
||||
Extensions = new List<string>
|
||||
{
|
||||
AllowMultiple = false,
|
||||
Title = Localization.ImportDatFileDialogTitle
|
||||
};
|
||||
"dat",
|
||||
"xml"
|
||||
},
|
||||
Name = Localization.DatFilesDialogLabel
|
||||
});
|
||||
|
||||
dlgOpen.Filters.Add(new FileDialogFilter
|
||||
{
|
||||
Extensions = new List<string>
|
||||
{
|
||||
"dat",
|
||||
"xml"
|
||||
},
|
||||
Name = Localization.DatFilesDialogLabel
|
||||
});
|
||||
|
||||
dlgOpen.Filters.Add(new FileDialogFilter
|
||||
{
|
||||
Extensions = new List<string>
|
||||
{
|
||||
"*"
|
||||
},
|
||||
Name = Localization.AllFilesDialogLabel
|
||||
});
|
||||
|
||||
string[] result = await dlgOpen.ShowAsync(_view);
|
||||
|
||||
if(result?.Length != 1)
|
||||
return;
|
||||
|
||||
var dialog = new ImportDat();
|
||||
var importDatViewModel = new ImportDatViewModel(dialog, result[0]);
|
||||
importDatViewModel.RomSetAdded += ImportDatViewModelOnRomSetAdded;
|
||||
dialog.DataContext = importDatViewModel;
|
||||
await dialog.ShowDialog(_view);
|
||||
}
|
||||
|
||||
void ImportDatViewModelOnRomSetAdded(object sender, RomSetEventArgs e) =>
|
||||
Dispatcher.UIThread.Post(() => RomSets.Add(e.RomSet));
|
||||
|
||||
async void ExecuteImportDatFolderCommand()
|
||||
dlgOpen.Filters.Add(new FileDialogFilter
|
||||
{
|
||||
var dlgOpen = new OpenFolderDialog
|
||||
Extensions = new List<string>
|
||||
{
|
||||
Title = Localization.ImportDatFolderDialogTitle
|
||||
};
|
||||
"*"
|
||||
},
|
||||
Name = Localization.AllFilesDialogLabel
|
||||
});
|
||||
|
||||
string result = await dlgOpen.ShowAsync(_view);
|
||||
string[] result = await dlgOpen.ShowAsync(_view);
|
||||
|
||||
if(result == null)
|
||||
return;
|
||||
if(result?.Length != 1) return;
|
||||
|
||||
var dialog = new ImportDatFolder();
|
||||
var importDatFolderViewModel = new ImportDatFolderViewModel(dialog, result);
|
||||
importDatFolderViewModel.RomSetAdded += ImportDatViewModelOnRomSetAdded;
|
||||
dialog.DataContext = importDatFolderViewModel;
|
||||
await dialog.ShowDialog(_view);
|
||||
}
|
||||
var dialog = new ImportDat();
|
||||
var importDatViewModel = new ImportDatViewModel(dialog, result[0]);
|
||||
importDatViewModel.RomSetAdded += ImportDatViewModelOnRomSetAdded;
|
||||
dialog.DataContext = importDatViewModel;
|
||||
await dialog.ShowDialog(_view);
|
||||
}
|
||||
|
||||
async void ExecuteImportRomFolderCommand()
|
||||
void ImportDatViewModelOnRomSetAdded(object sender, RomSetEventArgs e) =>
|
||||
Dispatcher.UIThread.Post(() => RomSets.Add(e.RomSet));
|
||||
|
||||
async void ExecuteImportDatFolderCommand()
|
||||
{
|
||||
var dlgOpen = new OpenFolderDialog
|
||||
{
|
||||
var dlgOpen = new OpenFolderDialog
|
||||
{
|
||||
Title = Localization.ImportRomsFolderDialogTitle
|
||||
};
|
||||
Title = Localization.ImportDatFolderDialogTitle
|
||||
};
|
||||
|
||||
string result = await dlgOpen.ShowAsync(_view);
|
||||
string result = await dlgOpen.ShowAsync(_view);
|
||||
|
||||
if(result == null)
|
||||
return;
|
||||
if(result == null) return;
|
||||
|
||||
var dialog = new ImportRomFolder();
|
||||
var importRomFolderViewModel = new ImportRomFolderViewModel(dialog, result);
|
||||
dialog.DataContext = importRomFolderViewModel;
|
||||
await dialog.ShowDialog(_view);
|
||||
}
|
||||
var dialog = new ImportDatFolder();
|
||||
var importDatFolderViewModel = new ImportDatFolderViewModel(dialog, result);
|
||||
importDatFolderViewModel.RomSetAdded += ImportDatViewModelOnRomSetAdded;
|
||||
dialog.DataContext = importDatFolderViewModel;
|
||||
await dialog.ShowDialog(_view);
|
||||
}
|
||||
|
||||
async void ExecuteDeleteRomSetCommand()
|
||||
async void ExecuteImportRomFolderCommand()
|
||||
{
|
||||
var dlgOpen = new OpenFolderDialog
|
||||
{
|
||||
if(SelectedRomSet == null)
|
||||
return;
|
||||
Title = Localization.ImportRomsFolderDialogTitle
|
||||
};
|
||||
|
||||
ButtonResult result = await MessageBoxManager.
|
||||
GetMessageBoxStandardWindow(Localization.DeleteRomSetMsgBoxTitle,
|
||||
string.
|
||||
Format(Localization.DeleteRomSetMsgBoxCaption,
|
||||
SelectedRomSet.Name), ButtonEnum.YesNo,
|
||||
Icon.Database).ShowDialog(_view);
|
||||
string result = await dlgOpen.ShowAsync(_view);
|
||||
|
||||
if(result == ButtonResult.No)
|
||||
return;
|
||||
if(result == null) return;
|
||||
|
||||
var dialog = new RemoveDat();
|
||||
var removeDatViewModel = new RemoveDatViewModel(dialog, SelectedRomSet.Id);
|
||||
dialog.DataContext = removeDatViewModel;
|
||||
await dialog.ShowDialog(_view);
|
||||
var dialog = new ImportRomFolder();
|
||||
var importRomFolderViewModel = new ImportRomFolderViewModel(dialog, result);
|
||||
dialog.DataContext = importRomFolderViewModel;
|
||||
await dialog.ShowDialog(_view);
|
||||
}
|
||||
|
||||
RomSets.Remove(SelectedRomSet);
|
||||
SelectedRomSet = null;
|
||||
}
|
||||
async void ExecuteDeleteRomSetCommand()
|
||||
{
|
||||
if(SelectedRomSet == null) return;
|
||||
|
||||
void ExecuteEditRomSetCommand()
|
||||
ButtonResult result = await MessageBoxManager
|
||||
.GetMessageBoxStandardWindow(Localization.DeleteRomSetMsgBoxTitle,
|
||||
string.Format(Localization.DeleteRomSetMsgBoxCaption,
|
||||
SelectedRomSet.Name),
|
||||
ButtonEnum.YesNo,
|
||||
Icon.Database)
|
||||
.ShowDialog(_view);
|
||||
|
||||
if(result == ButtonResult.No) return;
|
||||
|
||||
var dialog = new RemoveDat();
|
||||
var removeDatViewModel = new RemoveDatViewModel(dialog, SelectedRomSet.Id);
|
||||
dialog.DataContext = removeDatViewModel;
|
||||
await dialog.ShowDialog(_view);
|
||||
|
||||
RomSets.Remove(SelectedRomSet);
|
||||
SelectedRomSet = null;
|
||||
}
|
||||
|
||||
void ExecuteEditRomSetCommand()
|
||||
{
|
||||
if(SelectedRomSet == null) return;
|
||||
|
||||
var window = new EditDat();
|
||||
var viewModel = new EditDatViewModel(window, SelectedRomSet);
|
||||
|
||||
viewModel.RomSetModified += (sender, args) =>
|
||||
{
|
||||
if(SelectedRomSet == null)
|
||||
return;
|
||||
RomSetModel old = RomSets.FirstOrDefault(r => r.Id == args.RomSet.Id);
|
||||
|
||||
var window = new EditDat();
|
||||
var viewModel = new EditDatViewModel(window, SelectedRomSet);
|
||||
if(old == null) return;
|
||||
|
||||
viewModel.RomSetModified += (sender, args) =>
|
||||
{
|
||||
RomSetModel old = RomSets.FirstOrDefault(r => r.Id == args.RomSet.Id);
|
||||
RomSets.Remove(old);
|
||||
RomSets.Add(args.RomSet);
|
||||
};
|
||||
|
||||
if(old == null)
|
||||
return;
|
||||
window.DataContext = viewModel;
|
||||
|
||||
RomSets.Remove(old);
|
||||
RomSets.Add(args.RomSet);
|
||||
};
|
||||
window.Show();
|
||||
}
|
||||
|
||||
window.DataContext = viewModel;
|
||||
async void ExecuteExportDatCommand()
|
||||
{
|
||||
if(SelectedRomSet == null) return;
|
||||
|
||||
window.Show();
|
||||
}
|
||||
|
||||
async void ExecuteExportDatCommand()
|
||||
var dlgSave = new SaveFileDialog
|
||||
{
|
||||
if(SelectedRomSet == null)
|
||||
return;
|
||||
InitialFileName = SelectedRomSet.Filename
|
||||
};
|
||||
|
||||
var dlgSave = new SaveFileDialog
|
||||
{
|
||||
InitialFileName = SelectedRomSet.Filename
|
||||
};
|
||||
string result = await dlgSave.ShowAsync(_view);
|
||||
|
||||
string result = await dlgSave.ShowAsync(_view);
|
||||
if(result == null) return;
|
||||
|
||||
if(result == null)
|
||||
return;
|
||||
var dialog = new ExportDat();
|
||||
var viewModel = new ExportDatViewModel(dialog, SelectedRomSet.Sha384, result);
|
||||
dialog.DataContext = viewModel;
|
||||
await dialog.ShowDialog(_view);
|
||||
}
|
||||
|
||||
var dialog = new ExportDat();
|
||||
var viewModel = new ExportDatViewModel(dialog, SelectedRomSet.Sha384, result);
|
||||
dialog.DataContext = viewModel;
|
||||
await dialog.ShowDialog(_view);
|
||||
}
|
||||
|
||||
async void ExecuteExportRomsCommand()
|
||||
async void ExecuteExportRomsCommand()
|
||||
{
|
||||
var dlgOpen = new OpenFolderDialog
|
||||
{
|
||||
var dlgOpen = new OpenFolderDialog
|
||||
{
|
||||
Title = Localization.ExportRomsDialogTitle
|
||||
};
|
||||
Title = Localization.ExportRomsDialogTitle
|
||||
};
|
||||
|
||||
string result = await dlgOpen.ShowAsync(_view);
|
||||
string result = await dlgOpen.ShowAsync(_view);
|
||||
|
||||
if(result == null)
|
||||
return;
|
||||
if(result == null) return;
|
||||
|
||||
var dialog = new ExportRoms();
|
||||
var viewModel = new ExportRomsViewModel(dialog, result, SelectedRomSet.Id);
|
||||
dialog.DataContext = viewModel;
|
||||
await dialog.ShowDialog(_view);
|
||||
}
|
||||
var dialog = new ExportRoms();
|
||||
var viewModel = new ExportRomsViewModel(dialog, result, SelectedRomSet.Id);
|
||||
dialog.DataContext = viewModel;
|
||||
await dialog.ShowDialog(_view);
|
||||
}
|
||||
|
||||
async void ExecuteMountCommand()
|
||||
async void ExecuteMountCommand()
|
||||
{
|
||||
if(Vfs != null) return;
|
||||
|
||||
var dlgOpen = new OpenFolderDialog
|
||||
{
|
||||
if(Vfs != null)
|
||||
return;
|
||||
Title = Localization.SelectMountPointDialogTitle
|
||||
};
|
||||
|
||||
var dlgOpen = new OpenFolderDialog
|
||||
{
|
||||
Title = Localization.SelectMountPointDialogTitle
|
||||
};
|
||||
string result = await dlgOpen.ShowAsync(_view);
|
||||
|
||||
string result = await dlgOpen.ShowAsync(_view);
|
||||
if(result == null) return;
|
||||
|
||||
if(result == null)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
Vfs = new Vfs();
|
||||
Vfs.Umounted += VfsOnUmounted;
|
||||
Vfs.MountTo(result);
|
||||
}
|
||||
catch(Exception)
|
||||
{
|
||||
if(Debugger.IsAttached)
|
||||
throw;
|
||||
|
||||
Vfs = null;
|
||||
}
|
||||
}
|
||||
|
||||
void VfsOnUmounted(object sender, EventArgs e) => Vfs = null;
|
||||
|
||||
void ExecuteUmountCommand() => Vfs?.Umount();
|
||||
|
||||
async void ExecuteUpdateStatsCommand()
|
||||
try
|
||||
{
|
||||
ButtonResult result = await MessageBoxManager.
|
||||
GetMessageBoxStandardWindow(Localization.DatabaseMenuUpdateStatsText,
|
||||
Localization.UpdateStatsConfirmationDialogText,
|
||||
ButtonEnum.YesNo, Icon.Database).ShowDialog(_view);
|
||||
Vfs = new Vfs();
|
||||
Vfs.Umounted += VfsOnUmounted;
|
||||
Vfs.MountTo(result);
|
||||
}
|
||||
catch(Exception)
|
||||
{
|
||||
if(Debugger.IsAttached) throw;
|
||||
|
||||
if(result == ButtonResult.No)
|
||||
return;
|
||||
|
||||
var view = new UpdateStats();
|
||||
var viewModel = new UpdateStatsViewModel(view);
|
||||
view.DataContext = viewModel;
|
||||
await view.ShowDialog(_view);
|
||||
Vfs = null;
|
||||
}
|
||||
}
|
||||
|
||||
void VfsOnUmounted(object sender, EventArgs e) => Vfs = null;
|
||||
|
||||
void ExecuteUmountCommand() => Vfs?.Umount();
|
||||
|
||||
async void ExecuteUpdateStatsCommand()
|
||||
{
|
||||
ButtonResult result = await MessageBoxManager
|
||||
.GetMessageBoxStandardWindow(Localization.DatabaseMenuUpdateStatsText,
|
||||
Localization.UpdateStatsConfirmationDialogText,
|
||||
ButtonEnum.YesNo,
|
||||
Icon.Database)
|
||||
.ShowDialog(_view);
|
||||
|
||||
if(result == ButtonResult.No) return;
|
||||
|
||||
var view = new UpdateStats();
|
||||
var viewModel = new UpdateStatsViewModel(view);
|
||||
view.DataContext = viewModel;
|
||||
await view.ShowDialog(_view);
|
||||
}
|
||||
}
|
||||
@@ -34,84 +34,75 @@ using RomRepoMgr.Database.Models;
|
||||
using RomRepoMgr.Resources;
|
||||
using RomRepoMgr.Views;
|
||||
|
||||
namespace RomRepoMgr.ViewModels
|
||||
namespace RomRepoMgr.ViewModels;
|
||||
|
||||
public sealed class RemoveDatViewModel : ViewModelBase
|
||||
{
|
||||
public sealed class RemoveDatViewModel : ViewModelBase
|
||||
readonly long _romSetId;
|
||||
readonly RemoveDat _view;
|
||||
string _statusMessage;
|
||||
|
||||
public RemoveDatViewModel(RemoveDat view, long romSetId)
|
||||
{
|
||||
readonly long _romSetId;
|
||||
readonly RemoveDat _view;
|
||||
string _statusMessage;
|
||||
|
||||
public RemoveDatViewModel(RemoveDat view, long romSetId)
|
||||
{
|
||||
_view = view;
|
||||
_romSetId = romSetId;
|
||||
}
|
||||
|
||||
[NotNull]
|
||||
public string Title => Localization.RemoveDatTitle;
|
||||
|
||||
public string StatusMessage
|
||||
{
|
||||
get => _statusMessage;
|
||||
set => this.RaiseAndSetIfChanged(ref _statusMessage, value);
|
||||
}
|
||||
|
||||
internal void OnOpened() => Task.Run(() =>
|
||||
{
|
||||
using var ctx = Context.Create(Settings.Settings.Current.DatabasePath);
|
||||
|
||||
Dispatcher.UIThread.Post(() => StatusMessage = Localization.RetrievingRomSetFromDatabase);
|
||||
|
||||
RomSet romSet = ctx.RomSets.Find(_romSetId);
|
||||
|
||||
if(romSet == null)
|
||||
return;
|
||||
|
||||
Dispatcher.UIThread.Post(() => StatusMessage = Localization.RemovingRomSetFromDatabase);
|
||||
|
||||
ctx.RomSets.Remove(romSet);
|
||||
|
||||
Dispatcher.UIThread.Post(() => StatusMessage = Localization.SavingChangesToDatabase);
|
||||
|
||||
ctx.SaveChanges();
|
||||
|
||||
Dispatcher.UIThread.Post(() => StatusMessage = Localization.RemovingDatFileFromRepo);
|
||||
|
||||
byte[] sha384Bytes = new byte[48];
|
||||
string sha384 = romSet.Sha384;
|
||||
|
||||
for(int i = 0; i < 48; i++)
|
||||
{
|
||||
if(sha384[i * 2] >= 0x30 &&
|
||||
sha384[i * 2] <= 0x39)
|
||||
sha384Bytes[i] = (byte)((sha384[i * 2] - 0x30) * 0x10);
|
||||
else if(sha384[i * 2] >= 0x41 &&
|
||||
sha384[i * 2] <= 0x46)
|
||||
sha384Bytes[i] = (byte)((sha384[i * 2] - 0x37) * 0x10);
|
||||
else if(sha384[i * 2] >= 0x61 &&
|
||||
sha384[i * 2] <= 0x66)
|
||||
sha384Bytes[i] = (byte)((sha384[i * 2] - 0x57) * 0x10);
|
||||
|
||||
if(sha384[(i * 2) + 1] >= 0x30 &&
|
||||
sha384[(i * 2) + 1] <= 0x39)
|
||||
sha384Bytes[i] += (byte)(sha384[(i * 2) + 1] - 0x30);
|
||||
else if(sha384[(i * 2) + 1] >= 0x41 &&
|
||||
sha384[(i * 2) + 1] <= 0x46)
|
||||
sha384Bytes[i] += (byte)(sha384[(i * 2) + 1] - 0x37);
|
||||
else if(sha384[(i * 2) + 1] >= 0x61 &&
|
||||
sha384[(i * 2) + 1] <= 0x66)
|
||||
sha384Bytes[i] += (byte)(sha384[(i * 2) + 1] - 0x57);
|
||||
}
|
||||
|
||||
string datHash32 = Base32.ToBase32String(sha384Bytes);
|
||||
string datFilesPath = Path.Combine(Settings.Settings.Current.RepositoryPath, "datfiles");
|
||||
string compressedDatPath = Path.Combine(datFilesPath, datHash32 + ".lz");
|
||||
|
||||
if(File.Exists(compressedDatPath))
|
||||
File.Delete(compressedDatPath);
|
||||
|
||||
Dispatcher.UIThread.Post(_view.Close);
|
||||
});
|
||||
_view = view;
|
||||
_romSetId = romSetId;
|
||||
}
|
||||
|
||||
[NotNull]
|
||||
public string Title => Localization.RemoveDatTitle;
|
||||
|
||||
public string StatusMessage
|
||||
{
|
||||
get => _statusMessage;
|
||||
set => this.RaiseAndSetIfChanged(ref _statusMessage, value);
|
||||
}
|
||||
|
||||
internal void OnOpened() => Task.Run(() =>
|
||||
{
|
||||
using var ctx = Context.Create(Settings.Settings.Current.DatabasePath);
|
||||
|
||||
Dispatcher.UIThread.Post(() => StatusMessage = Localization.RetrievingRomSetFromDatabase);
|
||||
|
||||
RomSet romSet = ctx.RomSets.Find(_romSetId);
|
||||
|
||||
if(romSet == null) return;
|
||||
|
||||
Dispatcher.UIThread.Post(() => StatusMessage = Localization.RemovingRomSetFromDatabase);
|
||||
|
||||
ctx.RomSets.Remove(romSet);
|
||||
|
||||
Dispatcher.UIThread.Post(() => StatusMessage = Localization.SavingChangesToDatabase);
|
||||
|
||||
ctx.SaveChanges();
|
||||
|
||||
Dispatcher.UIThread.Post(() => StatusMessage = Localization.RemovingDatFileFromRepo);
|
||||
|
||||
var sha384Bytes = new byte[48];
|
||||
string sha384 = romSet.Sha384;
|
||||
|
||||
for(var i = 0; i < 48; i++)
|
||||
{
|
||||
if(sha384[i * 2] >= 0x30 && sha384[i * 2] <= 0x39)
|
||||
sha384Bytes[i] = (byte)((sha384[i * 2] - 0x30) * 0x10);
|
||||
else if(sha384[i * 2] >= 0x41 && sha384[i * 2] <= 0x46)
|
||||
sha384Bytes[i] = (byte)((sha384[i * 2] - 0x37) * 0x10);
|
||||
else if(sha384[i * 2] >= 0x61 && sha384[i * 2] <= 0x66)
|
||||
sha384Bytes[i] = (byte)((sha384[i * 2] - 0x57) * 0x10);
|
||||
|
||||
if(sha384[i * 2 + 1] >= 0x30 && sha384[i * 2 + 1] <= 0x39)
|
||||
sha384Bytes[i] += (byte)(sha384[i * 2 + 1] - 0x30);
|
||||
else if(sha384[i * 2 + 1] >= 0x41 && sha384[i * 2 + 1] <= 0x46)
|
||||
sha384Bytes[i] += (byte)(sha384[i * 2 + 1] - 0x37);
|
||||
else if(sha384[i * 2 + 1] >= 0x61 && sha384[i * 2 + 1] <= 0x66)
|
||||
sha384Bytes[i] += (byte)(sha384[i * 2 + 1] - 0x57);
|
||||
}
|
||||
|
||||
string datHash32 = Base32.ToBase32String(sha384Bytes);
|
||||
string datFilesPath = Path.Combine(Settings.Settings.Current.RepositoryPath, "datfiles");
|
||||
string compressedDatPath = Path.Combine(datFilesPath, datHash32 + ".lz");
|
||||
|
||||
if(File.Exists(compressedDatPath)) File.Delete(compressedDatPath);
|
||||
|
||||
Dispatcher.UIThread.Post(_view.Close);
|
||||
});
|
||||
}
|
||||
@@ -41,248 +41,219 @@ using RomRepoMgr.Resources;
|
||||
using RomRepoMgr.Views;
|
||||
using ErrorEventArgs = RomRepoMgr.Core.EventArgs.ErrorEventArgs;
|
||||
|
||||
namespace RomRepoMgr.ViewModels
|
||||
namespace RomRepoMgr.ViewModels;
|
||||
|
||||
public sealed class SettingsViewModel : ViewModelBase
|
||||
{
|
||||
public sealed class SettingsViewModel : ViewModelBase
|
||||
readonly SettingsDialog _view;
|
||||
bool _databaseChanged;
|
||||
string _databasePath;
|
||||
bool _repositoryChanged;
|
||||
string _repositoryPath;
|
||||
bool _temporaryChanged;
|
||||
string _temporaryPath;
|
||||
bool _unArChanged;
|
||||
string _unArPath;
|
||||
string _unArVersion;
|
||||
|
||||
public SettingsViewModel(SettingsDialog view)
|
||||
{
|
||||
readonly SettingsDialog _view;
|
||||
bool _databaseChanged;
|
||||
string _databasePath;
|
||||
bool _repositoryChanged;
|
||||
string _repositoryPath;
|
||||
bool _temporaryChanged;
|
||||
string _temporaryPath;
|
||||
bool _unArChanged;
|
||||
string _unArPath;
|
||||
string _unArVersion;
|
||||
_view = view;
|
||||
_databaseChanged = false;
|
||||
_repositoryChanged = false;
|
||||
_temporaryChanged = false;
|
||||
_unArChanged = false;
|
||||
|
||||
public SettingsViewModel(SettingsDialog view)
|
||||
CloseCommand = ReactiveCommand.Create(ExecuteCloseCommand);
|
||||
UnArCommand = ReactiveCommand.Create(ExecuteUnArCommand);
|
||||
TemporaryCommand = ReactiveCommand.Create(ExecuteTemporaryCommand);
|
||||
RepositoryCommand = ReactiveCommand.Create(ExecuteRepositoryCommand);
|
||||
DatabaseCommand = ReactiveCommand.Create(ExecuteDatabaseCommand);
|
||||
SaveCommand = ReactiveCommand.Create(ExecuteSaveCommand);
|
||||
|
||||
DatabasePath = Settings.Settings.Current.DatabasePath;
|
||||
RepositoryPath = Settings.Settings.Current.RepositoryPath;
|
||||
TemporaryPath = Settings.Settings.Current.TemporaryFolder;
|
||||
UnArPath = Settings.Settings.Current.UnArchiverPath;
|
||||
|
||||
if(!string.IsNullOrWhiteSpace(UnArPath)) CheckUnAr();
|
||||
}
|
||||
|
||||
public string ChooseLabel => Localization.ChooseLabel;
|
||||
public string Title => Localization.SettingsTitle;
|
||||
public string CloseLabel => Localization.CloseLabel;
|
||||
public string DatabaseLabel => Localization.DatabaseFileLabel;
|
||||
public string RepositoryLabel => Localization.RepositoryFolderLabel;
|
||||
public string TemporaryLabel => Localization.TemporaryFolderLabel;
|
||||
public string UnArPathLabel => Localization.UnArPathLabel;
|
||||
|
||||
public ReactiveCommand<Unit, Unit> UnArCommand { get; }
|
||||
public ReactiveCommand<Unit, Unit> TemporaryCommand { get; }
|
||||
public ReactiveCommand<Unit, Unit> RepositoryCommand { get; }
|
||||
public ReactiveCommand<Unit, Unit> DatabaseCommand { get; }
|
||||
public ReactiveCommand<Unit, Unit> CloseCommand { get; }
|
||||
public ReactiveCommand<Unit, Unit> SaveCommand { get; }
|
||||
|
||||
public string DatabasePath
|
||||
{
|
||||
get => _databasePath;
|
||||
set
|
||||
{
|
||||
_view = view;
|
||||
_databaseChanged = false;
|
||||
_repositoryChanged = false;
|
||||
_temporaryChanged = false;
|
||||
_unArChanged = false;
|
||||
|
||||
CloseCommand = ReactiveCommand.Create(ExecuteCloseCommand);
|
||||
UnArCommand = ReactiveCommand.Create(ExecuteUnArCommand);
|
||||
TemporaryCommand = ReactiveCommand.Create(ExecuteTemporaryCommand);
|
||||
RepositoryCommand = ReactiveCommand.Create(ExecuteRepositoryCommand);
|
||||
DatabaseCommand = ReactiveCommand.Create(ExecuteDatabaseCommand);
|
||||
SaveCommand = ReactiveCommand.Create(ExecuteSaveCommand);
|
||||
|
||||
DatabasePath = Settings.Settings.Current.DatabasePath;
|
||||
RepositoryPath = Settings.Settings.Current.RepositoryPath;
|
||||
TemporaryPath = Settings.Settings.Current.TemporaryFolder;
|
||||
UnArPath = Settings.Settings.Current.UnArchiverPath;
|
||||
|
||||
if(!string.IsNullOrWhiteSpace(UnArPath))
|
||||
CheckUnAr();
|
||||
this.RaiseAndSetIfChanged(ref _databasePath, value);
|
||||
_databaseChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
public string ChooseLabel => Localization.ChooseLabel;
|
||||
public string Title => Localization.SettingsTitle;
|
||||
public string CloseLabel => Localization.CloseLabel;
|
||||
public string DatabaseLabel => Localization.DatabaseFileLabel;
|
||||
public string RepositoryLabel => Localization.RepositoryFolderLabel;
|
||||
public string TemporaryLabel => Localization.TemporaryFolderLabel;
|
||||
public string UnArPathLabel => Localization.UnArPathLabel;
|
||||
|
||||
public ReactiveCommand<Unit, Unit> UnArCommand { get; }
|
||||
public ReactiveCommand<Unit, Unit> TemporaryCommand { get; }
|
||||
public ReactiveCommand<Unit, Unit> RepositoryCommand { get; }
|
||||
public ReactiveCommand<Unit, Unit> DatabaseCommand { get; }
|
||||
public ReactiveCommand<Unit, Unit> CloseCommand { get; }
|
||||
public ReactiveCommand<Unit, Unit> SaveCommand { get; }
|
||||
|
||||
public string DatabasePath
|
||||
public string RepositoryPath
|
||||
{
|
||||
get => _repositoryPath;
|
||||
set
|
||||
{
|
||||
get => _databasePath;
|
||||
set
|
||||
this.RaiseAndSetIfChanged(ref _repositoryPath, value);
|
||||
|
||||
// TODO: Refresh repository existing files
|
||||
_repositoryChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
public string TemporaryPath
|
||||
{
|
||||
get => _temporaryPath;
|
||||
set
|
||||
{
|
||||
this.RaiseAndSetIfChanged(ref _temporaryPath, value);
|
||||
_temporaryChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
public string UnArPath
|
||||
{
|
||||
get => _unArPath;
|
||||
set => this.RaiseAndSetIfChanged(ref _unArPath, value);
|
||||
}
|
||||
|
||||
public string UnArVersion
|
||||
{
|
||||
get => _unArVersion;
|
||||
set => this.RaiseAndSetIfChanged(ref _unArVersion, value);
|
||||
}
|
||||
|
||||
public string SaveLabel => Localization.SaveLabel;
|
||||
|
||||
void CheckUnAr()
|
||||
{
|
||||
var worker = new Compression();
|
||||
|
||||
worker.FinishedWithText += CheckUnArFinished;
|
||||
worker.FailedWithText += CheckUnArFailed;
|
||||
|
||||
Task.Run(() => worker.CheckUnAr(UnArPath));
|
||||
}
|
||||
|
||||
async void CheckUnArFailed(object sender, [NotNull] ErrorEventArgs args)
|
||||
{
|
||||
UnArVersion = "";
|
||||
UnArPath = "";
|
||||
|
||||
await MessageBoxManager
|
||||
.GetMessageBoxStandardWindow(Localization.Error, $"{args.Message}", ButtonEnum.Ok, Icon.Error)
|
||||
.ShowDialog(_view);
|
||||
}
|
||||
|
||||
void CheckUnArFinished(object sender, MessageEventArgs args) => Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
UnArVersion = string.Format(Localization.TheUnarchiverVersionLabel, args.Message);
|
||||
_unArChanged = true;
|
||||
});
|
||||
|
||||
void ExecuteCloseCommand() => _view.Close();
|
||||
|
||||
async void ExecuteUnArCommand()
|
||||
{
|
||||
var dlgFile = new OpenFileDialog
|
||||
{
|
||||
Title = Localization.ChooseUnArExecutable,
|
||||
AllowMultiple = false
|
||||
};
|
||||
|
||||
if(!string.IsNullOrWhiteSpace(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles)))
|
||||
dlgFile.Directory = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles);
|
||||
|
||||
string[] result = await dlgFile.ShowAsync(_view);
|
||||
|
||||
if(result?.Length != 1) return;
|
||||
|
||||
UnArPath = result[0];
|
||||
CheckUnAr();
|
||||
}
|
||||
|
||||
async void ExecuteTemporaryCommand()
|
||||
{
|
||||
var dlgFolder = new OpenFolderDialog
|
||||
{
|
||||
Title = Localization.ChooseTemporaryFolder
|
||||
};
|
||||
|
||||
string result = await dlgFolder.ShowAsync(_view);
|
||||
|
||||
if(result == null) return;
|
||||
|
||||
TemporaryPath = result;
|
||||
}
|
||||
|
||||
async void ExecuteRepositoryCommand()
|
||||
{
|
||||
var dlgFolder = new OpenFolderDialog
|
||||
{
|
||||
Title = Localization.ChooseRepositoryFolder
|
||||
};
|
||||
|
||||
string result = await dlgFolder.ShowAsync(_view);
|
||||
|
||||
if(result == null) return;
|
||||
|
||||
RepositoryPath = result;
|
||||
}
|
||||
|
||||
async void ExecuteDatabaseCommand()
|
||||
{
|
||||
var dlgFile = new SaveFileDialog
|
||||
{
|
||||
InitialFileName = "romrepo.db",
|
||||
Directory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
|
||||
Title = Localization.ChooseDatabaseFile
|
||||
};
|
||||
|
||||
string result = await dlgFile.ShowAsync(_view);
|
||||
|
||||
if(result == null) return;
|
||||
|
||||
if(File.Exists(result))
|
||||
{
|
||||
ButtonResult btnResult = await MessageBoxManager
|
||||
.GetMessageBoxStandardWindow(Localization.DatabaseFileExistsMsgBoxTitle,
|
||||
Localization.DatabaseFileTryOpenCaption,
|
||||
ButtonEnum.YesNo,
|
||||
Icon.Database)
|
||||
.ShowDialog(_view);
|
||||
|
||||
if(btnResult == ButtonResult.Yes)
|
||||
{
|
||||
this.RaiseAndSetIfChanged(ref _databasePath, value);
|
||||
_databaseChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
public string RepositoryPath
|
||||
{
|
||||
get => _repositoryPath;
|
||||
set
|
||||
{
|
||||
this.RaiseAndSetIfChanged(ref _repositoryPath, value);
|
||||
|
||||
// TODO: Refresh repository existing files
|
||||
_repositoryChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
public string TemporaryPath
|
||||
{
|
||||
get => _temporaryPath;
|
||||
set
|
||||
{
|
||||
this.RaiseAndSetIfChanged(ref _temporaryPath, value);
|
||||
_temporaryChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
public string UnArPath
|
||||
{
|
||||
get => _unArPath;
|
||||
set => this.RaiseAndSetIfChanged(ref _unArPath, value);
|
||||
}
|
||||
|
||||
public string UnArVersion
|
||||
{
|
||||
get => _unArVersion;
|
||||
set => this.RaiseAndSetIfChanged(ref _unArVersion, value);
|
||||
}
|
||||
|
||||
public string SaveLabel => Localization.SaveLabel;
|
||||
|
||||
void CheckUnAr()
|
||||
{
|
||||
var worker = new Compression();
|
||||
|
||||
worker.FinishedWithText += CheckUnArFinished;
|
||||
worker.FailedWithText += CheckUnArFailed;
|
||||
|
||||
Task.Run(() => worker.CheckUnAr(UnArPath));
|
||||
}
|
||||
|
||||
async void CheckUnArFailed(object sender, [NotNull] ErrorEventArgs args)
|
||||
{
|
||||
UnArVersion = "";
|
||||
UnArPath = "";
|
||||
|
||||
await MessageBoxManager.
|
||||
GetMessageBoxStandardWindow(Localization.Error, $"{args.Message}", ButtonEnum.Ok, Icon.Error).
|
||||
ShowDialog(_view);
|
||||
}
|
||||
|
||||
void CheckUnArFinished(object sender, MessageEventArgs args) => Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
UnArVersion = string.Format(Localization.TheUnarchiverVersionLabel, args.Message);
|
||||
_unArChanged = true;
|
||||
});
|
||||
|
||||
void ExecuteCloseCommand() => _view.Close();
|
||||
|
||||
async void ExecuteUnArCommand()
|
||||
{
|
||||
var dlgFile = new OpenFileDialog
|
||||
{
|
||||
Title = Localization.ChooseUnArExecutable,
|
||||
AllowMultiple = false
|
||||
};
|
||||
|
||||
if(!string.IsNullOrWhiteSpace(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles)))
|
||||
dlgFile.Directory = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles);
|
||||
|
||||
string[] result = await dlgFile.ShowAsync(_view);
|
||||
|
||||
if(result?.Length != 1)
|
||||
return;
|
||||
|
||||
UnArPath = result[0];
|
||||
CheckUnAr();
|
||||
}
|
||||
|
||||
async void ExecuteTemporaryCommand()
|
||||
{
|
||||
var dlgFolder = new OpenFolderDialog
|
||||
{
|
||||
Title = Localization.ChooseTemporaryFolder
|
||||
};
|
||||
|
||||
string result = await dlgFolder.ShowAsync(_view);
|
||||
|
||||
if(result == null)
|
||||
return;
|
||||
|
||||
TemporaryPath = result;
|
||||
}
|
||||
|
||||
async void ExecuteRepositoryCommand()
|
||||
{
|
||||
var dlgFolder = new OpenFolderDialog
|
||||
{
|
||||
Title = Localization.ChooseRepositoryFolder
|
||||
};
|
||||
|
||||
string result = await dlgFolder.ShowAsync(_view);
|
||||
|
||||
if(result == null)
|
||||
return;
|
||||
|
||||
RepositoryPath = result;
|
||||
}
|
||||
|
||||
async void ExecuteDatabaseCommand()
|
||||
{
|
||||
var dlgFile = new SaveFileDialog
|
||||
{
|
||||
InitialFileName = "romrepo.db",
|
||||
Directory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
|
||||
Title = Localization.ChooseDatabaseFile
|
||||
};
|
||||
|
||||
string result = await dlgFile.ShowAsync(_view);
|
||||
|
||||
if(result == null)
|
||||
return;
|
||||
|
||||
if(File.Exists(result))
|
||||
{
|
||||
ButtonResult btnResult = await MessageBoxManager.
|
||||
GetMessageBoxStandardWindow(Localization.DatabaseFileExistsMsgBoxTitle,
|
||||
Localization.DatabaseFileTryOpenCaption,
|
||||
ButtonEnum.YesNo, Icon.Database).
|
||||
ShowDialog(_view);
|
||||
|
||||
if(btnResult == ButtonResult.Yes)
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
var ctx = Context.Create(result);
|
||||
await ctx.Database.MigrateAsync();
|
||||
}
|
||||
catch(Exception)
|
||||
{
|
||||
btnResult = await MessageBoxManager.
|
||||
GetMessageBoxStandardWindow(Localization.DatabaseFileUnusableMsgBoxTitle,
|
||||
Localization.
|
||||
DatabaseFileUnusableDeleteMsgBoxCaption,
|
||||
ButtonEnum.YesNo, Icon.Error).ShowDialog(_view);
|
||||
|
||||
if(btnResult == ButtonResult.No)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
File.Delete(result);
|
||||
}
|
||||
catch(Exception)
|
||||
{
|
||||
await MessageBoxManager.
|
||||
GetMessageBoxStandardWindow(Localization.DatabaseFileCannotDeleteTitle,
|
||||
Localization.DatabaseFileCannotDeleteCaption,
|
||||
ButtonEnum.Ok, Icon.Error).ShowDialog(_view);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
var ctx = Context.Create(result);
|
||||
await ctx.Database.MigrateAsync();
|
||||
}
|
||||
else
|
||||
catch(Exception)
|
||||
{
|
||||
btnResult = await MessageBoxManager.
|
||||
GetMessageBoxStandardWindow(Localization.DatabaseFileExistsMsgBoxTitle,
|
||||
Localization.DatabaseFileDeleteCaption,
|
||||
ButtonEnum.YesNo, Icon.Error).ShowDialog(_view);
|
||||
btnResult = await MessageBoxManager
|
||||
.GetMessageBoxStandardWindow(Localization.DatabaseFileUnusableMsgBoxTitle,
|
||||
Localization.DatabaseFileUnusableDeleteMsgBoxCaption,
|
||||
ButtonEnum.YesNo,
|
||||
Icon.Error)
|
||||
.ShowDialog(_view);
|
||||
|
||||
if(btnResult == ButtonResult.No)
|
||||
return;
|
||||
if(btnResult == ButtonResult.No) return;
|
||||
|
||||
try
|
||||
{
|
||||
@@ -290,58 +261,83 @@ namespace RomRepoMgr.ViewModels
|
||||
}
|
||||
catch(Exception)
|
||||
{
|
||||
await MessageBoxManager.
|
||||
GetMessageBoxStandardWindow(Localization.DatabaseFileCannotDeleteTitle,
|
||||
Localization.DatabaseFileCannotDeleteCaption, ButtonEnum.Ok,
|
||||
Icon.Error).ShowDialog(_view);
|
||||
await MessageBoxManager
|
||||
.GetMessageBoxStandardWindow(Localization.DatabaseFileCannotDeleteTitle,
|
||||
Localization.DatabaseFileCannotDeleteCaption,
|
||||
ButtonEnum.Ok,
|
||||
Icon.Error)
|
||||
.ShowDialog(_view);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
else
|
||||
{
|
||||
var ctx = Context.Create(result);
|
||||
await ctx.Database.MigrateAsync();
|
||||
}
|
||||
catch(Exception)
|
||||
{
|
||||
await MessageBoxManager.
|
||||
GetMessageBoxStandardWindow(Localization.DatabaseFileUnusableMsgBoxTitle,
|
||||
Localization.DatabaseFileUnusableMsgBoxCaption, ButtonEnum.Ok,
|
||||
Icon.Error).ShowDialog(_view);
|
||||
btnResult = await MessageBoxManager
|
||||
.GetMessageBoxStandardWindow(Localization.DatabaseFileExistsMsgBoxTitle,
|
||||
Localization.DatabaseFileDeleteCaption,
|
||||
ButtonEnum.YesNo,
|
||||
Icon.Error)
|
||||
.ShowDialog(_view);
|
||||
|
||||
return;
|
||||
}
|
||||
if(btnResult == ButtonResult.No) return;
|
||||
|
||||
DatabasePath = result;
|
||||
try
|
||||
{
|
||||
File.Delete(result);
|
||||
}
|
||||
catch(Exception)
|
||||
{
|
||||
await MessageBoxManager
|
||||
.GetMessageBoxStandardWindow(Localization.DatabaseFileCannotDeleteTitle,
|
||||
Localization.DatabaseFileCannotDeleteCaption,
|
||||
ButtonEnum.Ok,
|
||||
Icon.Error)
|
||||
.ShowDialog(_view);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ExecuteSaveCommand()
|
||||
try
|
||||
{
|
||||
if(_databaseChanged)
|
||||
Settings.Settings.Current.DatabasePath = DatabasePath;
|
||||
|
||||
if(_repositoryChanged)
|
||||
Settings.Settings.Current.RepositoryPath = RepositoryPath;
|
||||
|
||||
if(_temporaryChanged)
|
||||
Settings.Settings.Current.TemporaryFolder = TemporaryPath;
|
||||
|
||||
if(_unArChanged)
|
||||
{
|
||||
Settings.Settings.Current.UnArchiverPath = UnArPath;
|
||||
Settings.Settings.UnArUsable = true;
|
||||
}
|
||||
|
||||
if(_databaseChanged ||
|
||||
_repositoryChanged ||
|
||||
_temporaryChanged ||
|
||||
_unArChanged)
|
||||
Settings.Settings.SaveSettings();
|
||||
|
||||
_view.Close();
|
||||
var ctx = Context.Create(result);
|
||||
await ctx.Database.MigrateAsync();
|
||||
}
|
||||
catch(Exception)
|
||||
{
|
||||
await MessageBoxManager
|
||||
.GetMessageBoxStandardWindow(Localization.DatabaseFileUnusableMsgBoxTitle,
|
||||
Localization.DatabaseFileUnusableMsgBoxCaption,
|
||||
ButtonEnum.Ok,
|
||||
Icon.Error)
|
||||
.ShowDialog(_view);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
DatabasePath = result;
|
||||
}
|
||||
|
||||
void ExecuteSaveCommand()
|
||||
{
|
||||
if(_databaseChanged) Settings.Settings.Current.DatabasePath = DatabasePath;
|
||||
|
||||
if(_repositoryChanged) Settings.Settings.Current.RepositoryPath = RepositoryPath;
|
||||
|
||||
if(_temporaryChanged) Settings.Settings.Current.TemporaryFolder = TemporaryPath;
|
||||
|
||||
if(_unArChanged)
|
||||
{
|
||||
Settings.Settings.Current.UnArchiverPath = UnArPath;
|
||||
Settings.Settings.UnArUsable = true;
|
||||
}
|
||||
|
||||
if(_databaseChanged || _repositoryChanged || _temporaryChanged || _unArChanged)
|
||||
Settings.Settings.SaveSettings();
|
||||
|
||||
_view.Close();
|
||||
}
|
||||
}
|
||||
@@ -39,335 +39,339 @@ using RomRepoMgr.Core.Workers;
|
||||
using RomRepoMgr.Database;
|
||||
using RomRepoMgr.Resources;
|
||||
|
||||
namespace RomRepoMgr.ViewModels
|
||||
namespace RomRepoMgr.ViewModels;
|
||||
|
||||
public sealed class SplashWindowViewModel : ViewModelBase
|
||||
{
|
||||
public sealed class SplashWindowViewModel : ViewModelBase
|
||||
bool _checkingUnArError;
|
||||
bool _checkingUnArOk;
|
||||
bool _checkingUnArUnknown;
|
||||
bool _exitVisible;
|
||||
bool _loadingDatabaseError;
|
||||
bool _loadingDatabaseOk;
|
||||
bool _loadingDatabaseUnknown;
|
||||
bool _loadingRomSetsError;
|
||||
bool _loadingRomSetsOk;
|
||||
bool _loadingRomSetsUnknown;
|
||||
bool _loadingSettingsError;
|
||||
bool _loadingSettingsOk;
|
||||
bool _loadingSettingsUnknown;
|
||||
bool _migratingDatabaseError;
|
||||
bool _migratingDatabaseOk;
|
||||
bool _migratingDatabaseUnknown;
|
||||
|
||||
public SplashWindowViewModel()
|
||||
{
|
||||
bool _checkingUnArError;
|
||||
bool _checkingUnArOk;
|
||||
bool _checkingUnArUnknown;
|
||||
bool _exitVisible;
|
||||
bool _loadingDatabaseError;
|
||||
bool _loadingDatabaseOk;
|
||||
bool _loadingDatabaseUnknown;
|
||||
bool _loadingRomSetsError;
|
||||
bool _loadingRomSetsOk;
|
||||
bool _loadingRomSetsUnknown;
|
||||
bool _loadingSettingsError;
|
||||
bool _loadingSettingsOk;
|
||||
bool _loadingSettingsUnknown;
|
||||
bool _migratingDatabaseError;
|
||||
bool _migratingDatabaseOk;
|
||||
bool _migratingDatabaseUnknown;
|
||||
ExitCommand = ReactiveCommand.Create(ExecuteExitCommand);
|
||||
|
||||
public SplashWindowViewModel()
|
||||
{
|
||||
ExitCommand = ReactiveCommand.Create(ExecuteExitCommand);
|
||||
|
||||
LoadingSettingsOk = false;
|
||||
LoadingSettingsError = false;
|
||||
LoadingSettingsUnknown = true;
|
||||
CheckingUnArOk = false;
|
||||
CheckingUnArError = false;
|
||||
CheckingUnArUnknown = true;
|
||||
LoadingDatabaseOk = false;
|
||||
LoadingDatabaseError = false;
|
||||
LoadingDatabaseUnknown = true;
|
||||
MigratingDatabaseOk = false;
|
||||
MigratingDatabaseError = false;
|
||||
MigratingDatabaseUnknown = true;
|
||||
LoadingRomSetsOk = false;
|
||||
LoadingRomSetsError = false;
|
||||
LoadingRomSetsUnknown = true;
|
||||
ExitVisible = false;
|
||||
}
|
||||
|
||||
public ReactiveCommand<Unit, Unit> ExitCommand { get; }
|
||||
|
||||
public bool LoadingSettingsOk
|
||||
{
|
||||
get => _loadingSettingsOk;
|
||||
set => this.RaiseAndSetIfChanged(ref _loadingSettingsOk, value);
|
||||
}
|
||||
|
||||
public bool LoadingSettingsError
|
||||
{
|
||||
get => _loadingSettingsError;
|
||||
set => this.RaiseAndSetIfChanged(ref _loadingSettingsError, value);
|
||||
}
|
||||
|
||||
public bool LoadingSettingsUnknown
|
||||
{
|
||||
get => _loadingSettingsUnknown;
|
||||
set => this.RaiseAndSetIfChanged(ref _loadingSettingsUnknown, value);
|
||||
}
|
||||
|
||||
public bool CheckingUnArOk
|
||||
{
|
||||
get => _checkingUnArOk;
|
||||
set => this.RaiseAndSetIfChanged(ref _checkingUnArOk, value);
|
||||
}
|
||||
|
||||
public bool CheckingUnArError
|
||||
{
|
||||
get => _checkingUnArError;
|
||||
set => this.RaiseAndSetIfChanged(ref _checkingUnArError, value);
|
||||
}
|
||||
|
||||
public bool CheckingUnArUnknown
|
||||
{
|
||||
get => _checkingUnArUnknown;
|
||||
set => this.RaiseAndSetIfChanged(ref _checkingUnArUnknown, value);
|
||||
}
|
||||
|
||||
public bool LoadingDatabaseOk
|
||||
{
|
||||
get => _loadingDatabaseOk;
|
||||
set => this.RaiseAndSetIfChanged(ref _loadingDatabaseOk, value);
|
||||
}
|
||||
|
||||
public bool LoadingDatabaseError
|
||||
{
|
||||
get => _loadingDatabaseError;
|
||||
set => this.RaiseAndSetIfChanged(ref _loadingDatabaseError, value);
|
||||
}
|
||||
|
||||
public bool LoadingDatabaseUnknown
|
||||
{
|
||||
get => _loadingDatabaseUnknown;
|
||||
set => this.RaiseAndSetIfChanged(ref _loadingDatabaseUnknown, value);
|
||||
}
|
||||
|
||||
public bool MigratingDatabaseOk
|
||||
{
|
||||
get => _migratingDatabaseOk;
|
||||
set => this.RaiseAndSetIfChanged(ref _migratingDatabaseOk, value);
|
||||
}
|
||||
|
||||
public bool MigratingDatabaseError
|
||||
{
|
||||
get => _migratingDatabaseError;
|
||||
set => this.RaiseAndSetIfChanged(ref _migratingDatabaseError, value);
|
||||
}
|
||||
|
||||
public bool MigratingDatabaseUnknown
|
||||
{
|
||||
get => _migratingDatabaseUnknown;
|
||||
set => this.RaiseAndSetIfChanged(ref _migratingDatabaseUnknown, value);
|
||||
}
|
||||
|
||||
public bool ExitVisible
|
||||
{
|
||||
get => _exitVisible;
|
||||
set => this.RaiseAndSetIfChanged(ref _exitVisible, value);
|
||||
}
|
||||
|
||||
public bool LoadingRomSetsOk
|
||||
{
|
||||
get => _loadingRomSetsOk;
|
||||
set => this.RaiseAndSetIfChanged(ref _loadingRomSetsOk, value);
|
||||
}
|
||||
|
||||
public bool LoadingRomSetsError
|
||||
{
|
||||
get => _loadingRomSetsError;
|
||||
set => this.RaiseAndSetIfChanged(ref _loadingRomSetsError, value);
|
||||
}
|
||||
|
||||
public bool LoadingRomSetsUnknown
|
||||
{
|
||||
get => _loadingRomSetsUnknown;
|
||||
set => this.RaiseAndSetIfChanged(ref _loadingRomSetsUnknown, value);
|
||||
}
|
||||
|
||||
public string LoadingText => "ROM Repository Manager";
|
||||
public string LoadingSettingsText => Localization.LoadingSettingsText;
|
||||
public string CheckingUnArText => Localization.CheckingUnArText;
|
||||
public string LoadingDatabaseText => Localization.LoadingDatabaseText;
|
||||
public string MigratingDatabaseText => Localization.MigratingDatabaseText;
|
||||
public string LoadingRomSetsText => Localization.LoadingRomSetsText;
|
||||
public string ExitButtonText => Localization.ExitButtonText;
|
||||
|
||||
void ExecuteExitCommand() =>
|
||||
(Application.Current.ApplicationLifetime as ClassicDesktopStyleApplicationLifetime)?.Shutdown();
|
||||
|
||||
internal void OnOpened() => Dispatcher.UIThread.Post(LoadSettings);
|
||||
|
||||
void LoadSettings() => Task.Run(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
Settings.Settings.LoadSettings();
|
||||
|
||||
Dispatcher.UIThread.Post(CheckUnAr);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
// TODO: Log error
|
||||
Dispatcher.UIThread.Post(FailedLoadingSettings);
|
||||
}
|
||||
});
|
||||
|
||||
void FailedLoadingSettings()
|
||||
{
|
||||
LoadingSettingsUnknown = false;
|
||||
LoadingSettingsError = true;
|
||||
ExitVisible = true;
|
||||
}
|
||||
|
||||
void CheckUnAr() => Task.Run(() =>
|
||||
{
|
||||
LoadingSettingsUnknown = false;
|
||||
LoadingSettingsOk = true;
|
||||
|
||||
try
|
||||
{
|
||||
var worker = new Compression();
|
||||
Settings.Settings.UnArUsable = worker.CheckUnAr(Settings.Settings.Current.UnArchiverPath);
|
||||
|
||||
Dispatcher.UIThread.Post(LoadDatabase);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
// TODO: Log error
|
||||
Dispatcher.UIThread.Post(FailedCheckUnAr);
|
||||
}
|
||||
});
|
||||
|
||||
void FailedCheckUnAr()
|
||||
{
|
||||
CheckingUnArUnknown = false;
|
||||
CheckingUnArError = true;
|
||||
ExitVisible = true;
|
||||
}
|
||||
|
||||
void LoadDatabase()
|
||||
{
|
||||
CheckingUnArUnknown = false;
|
||||
CheckingUnArOk = true;
|
||||
|
||||
Task.Run(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
string dbPathFolder = Path.GetDirectoryName(Settings.Settings.Current.DatabasePath);
|
||||
|
||||
if(!Directory.Exists(dbPathFolder))
|
||||
Directory.CreateDirectory(dbPathFolder);
|
||||
|
||||
using var ctx = Context.Create(Settings.Settings.Current.DatabasePath);
|
||||
|
||||
Dispatcher.UIThread.Post(MigrateDatabase);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
// TODO: Log error
|
||||
Dispatcher.UIThread.Post(FailedLoadingDatabase);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void FailedLoadingDatabase()
|
||||
{
|
||||
LoadingDatabaseUnknown = false;
|
||||
LoadingDatabaseError = true;
|
||||
ExitVisible = true;
|
||||
}
|
||||
|
||||
void MigrateDatabase()
|
||||
{
|
||||
LoadingDatabaseUnknown = false;
|
||||
LoadingDatabaseOk = true;
|
||||
|
||||
Task.Run(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
using var ctx = Context.Create(Settings.Settings.Current.DatabasePath);
|
||||
|
||||
ctx.Database.Migrate();
|
||||
|
||||
Dispatcher.UIThread.Post(LoadRomSets);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
// TODO: Log error
|
||||
Dispatcher.UIThread.Post(FailedMigratingDatabase);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void FailedMigratingDatabase()
|
||||
{
|
||||
MigratingDatabaseUnknown = false;
|
||||
MigratingDatabaseError = true;
|
||||
ExitVisible = true;
|
||||
}
|
||||
|
||||
void LoadRomSets()
|
||||
{
|
||||
MigratingDatabaseUnknown = false;
|
||||
MigratingDatabaseOk = true;
|
||||
|
||||
Task.Run(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
using var ctx = Context.Create(Settings.Settings.Current.DatabasePath);
|
||||
|
||||
GotRomSets?.Invoke(this, new RomSetsEventArgs
|
||||
{
|
||||
RomSets = ctx.RomSets.OrderBy(r => r.Name).ThenBy(r => r.Version).ThenBy(r => r.Date).
|
||||
ThenBy(r => r.Description).ThenBy(r => r.Comment).ThenBy(r => r.Filename).
|
||||
Select(r => new RomSetModel
|
||||
{
|
||||
Id = r.Id,
|
||||
Author = r.Author,
|
||||
Comment = r.Comment,
|
||||
Date = r.Date,
|
||||
Description = r.Description,
|
||||
Filename = r.Filename,
|
||||
Homepage = r.Homepage,
|
||||
Name = r.Name,
|
||||
Sha384 = r.Sha384,
|
||||
Version = r.Version,
|
||||
TotalMachines = r.Statistics.TotalMachines,
|
||||
CompleteMachines = r.Statistics.CompleteMachines,
|
||||
IncompleteMachines = r.Statistics.IncompleteMachines,
|
||||
TotalRoms = r.Statistics.TotalRoms,
|
||||
HaveRoms = r.Statistics.HaveRoms,
|
||||
MissRoms = r.Statistics.MissRoms,
|
||||
Category = r.Category
|
||||
}).ToList()
|
||||
});
|
||||
|
||||
Dispatcher.UIThread.Post(LoadMainWindow);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
// TODO: Log error
|
||||
Dispatcher.UIThread.Post(FailedLoadingRomSets);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void FailedLoadingRomSets()
|
||||
{
|
||||
LoadingRomSetsUnknown = false;
|
||||
LoadingRomSetsError = true;
|
||||
ExitVisible = true;
|
||||
}
|
||||
|
||||
void LoadMainWindow()
|
||||
{
|
||||
LoadingRomSetsUnknown = false;
|
||||
LoadingRomSetsOk = true;
|
||||
|
||||
WorkFinished?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
internal event EventHandler WorkFinished;
|
||||
|
||||
internal event EventHandler<RomSetsEventArgs> GotRomSets;
|
||||
LoadingSettingsOk = false;
|
||||
LoadingSettingsError = false;
|
||||
LoadingSettingsUnknown = true;
|
||||
CheckingUnArOk = false;
|
||||
CheckingUnArError = false;
|
||||
CheckingUnArUnknown = true;
|
||||
LoadingDatabaseOk = false;
|
||||
LoadingDatabaseError = false;
|
||||
LoadingDatabaseUnknown = true;
|
||||
MigratingDatabaseOk = false;
|
||||
MigratingDatabaseError = false;
|
||||
MigratingDatabaseUnknown = true;
|
||||
LoadingRomSetsOk = false;
|
||||
LoadingRomSetsError = false;
|
||||
LoadingRomSetsUnknown = true;
|
||||
ExitVisible = false;
|
||||
}
|
||||
|
||||
public ReactiveCommand<Unit, Unit> ExitCommand { get; }
|
||||
|
||||
public bool LoadingSettingsOk
|
||||
{
|
||||
get => _loadingSettingsOk;
|
||||
set => this.RaiseAndSetIfChanged(ref _loadingSettingsOk, value);
|
||||
}
|
||||
|
||||
public bool LoadingSettingsError
|
||||
{
|
||||
get => _loadingSettingsError;
|
||||
set => this.RaiseAndSetIfChanged(ref _loadingSettingsError, value);
|
||||
}
|
||||
|
||||
public bool LoadingSettingsUnknown
|
||||
{
|
||||
get => _loadingSettingsUnknown;
|
||||
set => this.RaiseAndSetIfChanged(ref _loadingSettingsUnknown, value);
|
||||
}
|
||||
|
||||
public bool CheckingUnArOk
|
||||
{
|
||||
get => _checkingUnArOk;
|
||||
set => this.RaiseAndSetIfChanged(ref _checkingUnArOk, value);
|
||||
}
|
||||
|
||||
public bool CheckingUnArError
|
||||
{
|
||||
get => _checkingUnArError;
|
||||
set => this.RaiseAndSetIfChanged(ref _checkingUnArError, value);
|
||||
}
|
||||
|
||||
public bool CheckingUnArUnknown
|
||||
{
|
||||
get => _checkingUnArUnknown;
|
||||
set => this.RaiseAndSetIfChanged(ref _checkingUnArUnknown, value);
|
||||
}
|
||||
|
||||
public bool LoadingDatabaseOk
|
||||
{
|
||||
get => _loadingDatabaseOk;
|
||||
set => this.RaiseAndSetIfChanged(ref _loadingDatabaseOk, value);
|
||||
}
|
||||
|
||||
public bool LoadingDatabaseError
|
||||
{
|
||||
get => _loadingDatabaseError;
|
||||
set => this.RaiseAndSetIfChanged(ref _loadingDatabaseError, value);
|
||||
}
|
||||
|
||||
public bool LoadingDatabaseUnknown
|
||||
{
|
||||
get => _loadingDatabaseUnknown;
|
||||
set => this.RaiseAndSetIfChanged(ref _loadingDatabaseUnknown, value);
|
||||
}
|
||||
|
||||
public bool MigratingDatabaseOk
|
||||
{
|
||||
get => _migratingDatabaseOk;
|
||||
set => this.RaiseAndSetIfChanged(ref _migratingDatabaseOk, value);
|
||||
}
|
||||
|
||||
public bool MigratingDatabaseError
|
||||
{
|
||||
get => _migratingDatabaseError;
|
||||
set => this.RaiseAndSetIfChanged(ref _migratingDatabaseError, value);
|
||||
}
|
||||
|
||||
public bool MigratingDatabaseUnknown
|
||||
{
|
||||
get => _migratingDatabaseUnknown;
|
||||
set => this.RaiseAndSetIfChanged(ref _migratingDatabaseUnknown, value);
|
||||
}
|
||||
|
||||
public bool ExitVisible
|
||||
{
|
||||
get => _exitVisible;
|
||||
set => this.RaiseAndSetIfChanged(ref _exitVisible, value);
|
||||
}
|
||||
|
||||
public bool LoadingRomSetsOk
|
||||
{
|
||||
get => _loadingRomSetsOk;
|
||||
set => this.RaiseAndSetIfChanged(ref _loadingRomSetsOk, value);
|
||||
}
|
||||
|
||||
public bool LoadingRomSetsError
|
||||
{
|
||||
get => _loadingRomSetsError;
|
||||
set => this.RaiseAndSetIfChanged(ref _loadingRomSetsError, value);
|
||||
}
|
||||
|
||||
public bool LoadingRomSetsUnknown
|
||||
{
|
||||
get => _loadingRomSetsUnknown;
|
||||
set => this.RaiseAndSetIfChanged(ref _loadingRomSetsUnknown, value);
|
||||
}
|
||||
|
||||
public string LoadingText => "ROM Repository Manager";
|
||||
public string LoadingSettingsText => Localization.LoadingSettingsText;
|
||||
public string CheckingUnArText => Localization.CheckingUnArText;
|
||||
public string LoadingDatabaseText => Localization.LoadingDatabaseText;
|
||||
public string MigratingDatabaseText => Localization.MigratingDatabaseText;
|
||||
public string LoadingRomSetsText => Localization.LoadingRomSetsText;
|
||||
public string ExitButtonText => Localization.ExitButtonText;
|
||||
|
||||
void ExecuteExitCommand() =>
|
||||
(Application.Current.ApplicationLifetime as ClassicDesktopStyleApplicationLifetime)?.Shutdown();
|
||||
|
||||
internal void OnOpened() => Dispatcher.UIThread.Post(LoadSettings);
|
||||
|
||||
void LoadSettings() => Task.Run(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
Settings.Settings.LoadSettings();
|
||||
|
||||
Dispatcher.UIThread.Post(CheckUnAr);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
// TODO: Log error
|
||||
Dispatcher.UIThread.Post(FailedLoadingSettings);
|
||||
}
|
||||
});
|
||||
|
||||
void FailedLoadingSettings()
|
||||
{
|
||||
LoadingSettingsUnknown = false;
|
||||
LoadingSettingsError = true;
|
||||
ExitVisible = true;
|
||||
}
|
||||
|
||||
void CheckUnAr() => Task.Run(() =>
|
||||
{
|
||||
LoadingSettingsUnknown = false;
|
||||
LoadingSettingsOk = true;
|
||||
|
||||
try
|
||||
{
|
||||
var worker = new Compression();
|
||||
Settings.Settings.UnArUsable = worker.CheckUnAr(Settings.Settings.Current.UnArchiverPath);
|
||||
|
||||
Dispatcher.UIThread.Post(LoadDatabase);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
// TODO: Log error
|
||||
Dispatcher.UIThread.Post(FailedCheckUnAr);
|
||||
}
|
||||
});
|
||||
|
||||
void FailedCheckUnAr()
|
||||
{
|
||||
CheckingUnArUnknown = false;
|
||||
CheckingUnArError = true;
|
||||
ExitVisible = true;
|
||||
}
|
||||
|
||||
void LoadDatabase()
|
||||
{
|
||||
CheckingUnArUnknown = false;
|
||||
CheckingUnArOk = true;
|
||||
|
||||
Task.Run(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
string dbPathFolder = Path.GetDirectoryName(Settings.Settings.Current.DatabasePath);
|
||||
|
||||
if(!Directory.Exists(dbPathFolder)) Directory.CreateDirectory(dbPathFolder);
|
||||
|
||||
using var ctx = Context.Create(Settings.Settings.Current.DatabasePath);
|
||||
|
||||
Dispatcher.UIThread.Post(MigrateDatabase);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
// TODO: Log error
|
||||
Dispatcher.UIThread.Post(FailedLoadingDatabase);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void FailedLoadingDatabase()
|
||||
{
|
||||
LoadingDatabaseUnknown = false;
|
||||
LoadingDatabaseError = true;
|
||||
ExitVisible = true;
|
||||
}
|
||||
|
||||
void MigrateDatabase()
|
||||
{
|
||||
LoadingDatabaseUnknown = false;
|
||||
LoadingDatabaseOk = true;
|
||||
|
||||
Task.Run(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
using var ctx = Context.Create(Settings.Settings.Current.DatabasePath);
|
||||
|
||||
ctx.Database.Migrate();
|
||||
|
||||
Dispatcher.UIThread.Post(LoadRomSets);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
// TODO: Log error
|
||||
Dispatcher.UIThread.Post(FailedMigratingDatabase);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void FailedMigratingDatabase()
|
||||
{
|
||||
MigratingDatabaseUnknown = false;
|
||||
MigratingDatabaseError = true;
|
||||
ExitVisible = true;
|
||||
}
|
||||
|
||||
void LoadRomSets()
|
||||
{
|
||||
MigratingDatabaseUnknown = false;
|
||||
MigratingDatabaseOk = true;
|
||||
|
||||
Task.Run(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
using var ctx = Context.Create(Settings.Settings.Current.DatabasePath);
|
||||
|
||||
GotRomSets?.Invoke(this,
|
||||
new RomSetsEventArgs
|
||||
{
|
||||
RomSets = ctx.RomSets.OrderBy(r => r.Name)
|
||||
.ThenBy(r => r.Version)
|
||||
.ThenBy(r => r.Date)
|
||||
.ThenBy(r => r.Description)
|
||||
.ThenBy(r => r.Comment)
|
||||
.ThenBy(r => r.Filename)
|
||||
.Select(r => new RomSetModel
|
||||
{
|
||||
Id = r.Id,
|
||||
Author = r.Author,
|
||||
Comment = r.Comment,
|
||||
Date = r.Date,
|
||||
Description = r.Description,
|
||||
Filename = r.Filename,
|
||||
Homepage = r.Homepage,
|
||||
Name = r.Name,
|
||||
Sha384 = r.Sha384,
|
||||
Version = r.Version,
|
||||
TotalMachines = r.Statistics.TotalMachines,
|
||||
CompleteMachines = r.Statistics.CompleteMachines,
|
||||
IncompleteMachines = r.Statistics.IncompleteMachines,
|
||||
TotalRoms = r.Statistics.TotalRoms,
|
||||
HaveRoms = r.Statistics.HaveRoms,
|
||||
MissRoms = r.Statistics.MissRoms,
|
||||
Category = r.Category
|
||||
})
|
||||
.ToList()
|
||||
});
|
||||
|
||||
Dispatcher.UIThread.Post(LoadMainWindow);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
// TODO: Log error
|
||||
Dispatcher.UIThread.Post(FailedLoadingRomSets);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void FailedLoadingRomSets()
|
||||
{
|
||||
LoadingRomSetsUnknown = false;
|
||||
LoadingRomSetsError = true;
|
||||
ExitVisible = true;
|
||||
}
|
||||
|
||||
void LoadMainWindow()
|
||||
{
|
||||
LoadingRomSetsUnknown = false;
|
||||
LoadingRomSetsOk = true;
|
||||
|
||||
WorkFinished?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
internal event EventHandler WorkFinished;
|
||||
|
||||
internal event EventHandler<RomSetsEventArgs> GotRomSets;
|
||||
}
|
||||
@@ -38,223 +38,231 @@ using RomRepoMgr.Database.Models;
|
||||
using RomRepoMgr.Resources;
|
||||
using RomRepoMgr.Views;
|
||||
|
||||
namespace RomRepoMgr.ViewModels
|
||||
namespace RomRepoMgr.ViewModels;
|
||||
|
||||
public sealed class UpdateStatsViewModel : ViewModelBase
|
||||
{
|
||||
public sealed class UpdateStatsViewModel : ViewModelBase
|
||||
readonly UpdateStats _view;
|
||||
bool _canClose;
|
||||
double _currentValue;
|
||||
bool _indeterminateProgress;
|
||||
double _maximumValue;
|
||||
double _minimumValue;
|
||||
bool _progressVisible;
|
||||
RomSetModel _selectedRomSet;
|
||||
string _statusMessage;
|
||||
|
||||
public UpdateStatsViewModel(UpdateStats view)
|
||||
{
|
||||
readonly UpdateStats _view;
|
||||
bool _canClose;
|
||||
double _currentValue;
|
||||
bool _indeterminateProgress;
|
||||
double _maximumValue;
|
||||
double _minimumValue;
|
||||
bool _progressVisible;
|
||||
RomSetModel _selectedRomSet;
|
||||
string _statusMessage;
|
||||
_view = view;
|
||||
CloseCommand = ReactiveCommand.Create(ExecuteCloseCommand);
|
||||
IndeterminateProgress = true;
|
||||
ProgressVisible = false;
|
||||
RomSets = new ObservableCollection<RomSetModel>();
|
||||
}
|
||||
|
||||
public UpdateStatsViewModel(UpdateStats view)
|
||||
[NotNull]
|
||||
public string Title => Localization.UpdateStatsTitle;
|
||||
public string RomSetNameLabel => Localization.RomSetNameLabel;
|
||||
public string RomSetVersionLabel => Localization.RomSetVersionLabel;
|
||||
public string RomSetAuthorLabel => Localization.RomSetAuthorLabel;
|
||||
public string RomSetCategoryLabel => Localization.RomSetCategoryLabel;
|
||||
public string RomSetDateLabel => Localization.RomSetDateLabel;
|
||||
public string RomSetDescriptionLabel => Localization.RomSetDescriptionLabel;
|
||||
public string RomSetCommentLabel => Localization.RomSetCommentLabel;
|
||||
public string RomSetTotalMachinesLabel => Localization.RomSetTotalMachinesLabel;
|
||||
public string RomSetCompleteMachinesLabel => Localization.RomSetCompleteMachinesLabel;
|
||||
public string RomSetIncompleteMachinesLabel => Localization.RomSetIncompleteMachinesLabel;
|
||||
public string RomSetTotalRomsLabel => Localization.RomSetTotalRomsLabel;
|
||||
public string RomSetHaveRomsLabel => Localization.RomSetHaveRomsLabel;
|
||||
public string RomSetMissRomsLabel => Localization.RomSetMissRomsLabel;
|
||||
|
||||
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 RomSetModel SelectedRomSet
|
||||
{
|
||||
get => _selectedRomSet;
|
||||
set => this.RaiseAndSetIfChanged(ref _selectedRomSet, value);
|
||||
}
|
||||
|
||||
public bool CanClose
|
||||
{
|
||||
get => _canClose;
|
||||
set => this.RaiseAndSetIfChanged(ref _canClose, value);
|
||||
}
|
||||
|
||||
public ObservableCollection<RomSetModel> RomSets { get; }
|
||||
|
||||
public string CloseLabel => Localization.CloseLabel;
|
||||
public ReactiveCommand<Unit, Unit> CloseCommand { get; }
|
||||
|
||||
internal void OnOpened() => Task.Run(() =>
|
||||
{
|
||||
using var ctx = Context.Create(Settings.Settings.Current.DatabasePath);
|
||||
|
||||
Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
_view = view;
|
||||
CloseCommand = ReactiveCommand.Create(ExecuteCloseCommand);
|
||||
StatusMessage = Localization.RetrievingRomSetsFromDatabase;
|
||||
ProgressVisible = true;
|
||||
IndeterminateProgress = true;
|
||||
ProgressVisible = false;
|
||||
RomSets = new ObservableCollection<RomSetModel>();
|
||||
}
|
||||
});
|
||||
|
||||
[NotNull]
|
||||
public string Title => Localization.UpdateStatsTitle;
|
||||
public string RomSetNameLabel => Localization.RomSetNameLabel;
|
||||
public string RomSetVersionLabel => Localization.RomSetVersionLabel;
|
||||
public string RomSetAuthorLabel => Localization.RomSetAuthorLabel;
|
||||
public string RomSetCategoryLabel => Localization.RomSetCategoryLabel;
|
||||
public string RomSetDateLabel => Localization.RomSetDateLabel;
|
||||
public string RomSetDescriptionLabel => Localization.RomSetDescriptionLabel;
|
||||
public string RomSetCommentLabel => Localization.RomSetCommentLabel;
|
||||
public string RomSetTotalMachinesLabel => Localization.RomSetTotalMachinesLabel;
|
||||
public string RomSetCompleteMachinesLabel => Localization.RomSetCompleteMachinesLabel;
|
||||
public string RomSetIncompleteMachinesLabel => Localization.RomSetIncompleteMachinesLabel;
|
||||
public string RomSetTotalRomsLabel => Localization.RomSetTotalRomsLabel;
|
||||
public string RomSetHaveRomsLabel => Localization.RomSetHaveRomsLabel;
|
||||
public string RomSetMissRomsLabel => Localization.RomSetMissRomsLabel;
|
||||
long romSetCount = ctx.RomSets.LongCount();
|
||||
|
||||
public string StatusMessage
|
||||
Dispatcher.UIThread.Post(() => { StatusMessage = Localization.RemovingOldStatistics; });
|
||||
|
||||
ctx.Database.ExecuteSqlRaw("DELETE FROM \"RomSetStats\"");
|
||||
|
||||
Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
get => _statusMessage;
|
||||
set => this.RaiseAndSetIfChanged(ref _statusMessage, value);
|
||||
}
|
||||
IndeterminateProgress = false;
|
||||
MinimumValue = 0;
|
||||
MaximumValue = romSetCount;
|
||||
CurrentValue = 0;
|
||||
});
|
||||
|
||||
public bool IndeterminateProgress
|
||||
long pos = 0;
|
||||
|
||||
foreach(RomSet romSet in ctx.RomSets)
|
||||
{
|
||||
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 RomSetModel SelectedRomSet
|
||||
{
|
||||
get => _selectedRomSet;
|
||||
set => this.RaiseAndSetIfChanged(ref _selectedRomSet, value);
|
||||
}
|
||||
|
||||
public bool CanClose
|
||||
{
|
||||
get => _canClose;
|
||||
set => this.RaiseAndSetIfChanged(ref _canClose, value);
|
||||
}
|
||||
|
||||
public ObservableCollection<RomSetModel> RomSets { get; }
|
||||
|
||||
public string CloseLabel => Localization.CloseLabel;
|
||||
public ReactiveCommand<Unit, Unit> CloseCommand { get; }
|
||||
|
||||
internal void OnOpened() => Task.Run(() =>
|
||||
{
|
||||
using var ctx = Context.Create(Settings.Settings.Current.DatabasePath);
|
||||
long currentPos = pos;
|
||||
|
||||
Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
StatusMessage = Localization.RetrievingRomSetsFromDatabase;
|
||||
ProgressVisible = true;
|
||||
IndeterminateProgress = true;
|
||||
StatusMessage = string.Format(Localization.CalculatingStatisticsForRomSet,
|
||||
romSet.Name,
|
||||
romSet.Version,
|
||||
romSet.Description);
|
||||
|
||||
CurrentValue = currentPos;
|
||||
});
|
||||
|
||||
long romSetCount = ctx.RomSets.LongCount();
|
||||
|
||||
Dispatcher.UIThread.Post(() =>
|
||||
try
|
||||
{
|
||||
StatusMessage = Localization.RemovingOldStatistics;
|
||||
});
|
||||
RomSetStat stats = ctx.RomSets.Where(r => r.Id == romSet.Id)
|
||||
.Select(r => new RomSetStat
|
||||
{
|
||||
RomSetId = r.Id,
|
||||
TotalMachines = r.Machines.Count,
|
||||
CompleteMachines =
|
||||
r.Machines.Count(m => m.Files.Count > 0 &&
|
||||
m.Disks.Count == 0 &&
|
||||
m.Files.All(f => f.File.IsInRepo)) +
|
||||
r.Machines.Count(m => m.Disks.Count > 0 &&
|
||||
m.Files.Count == 0 &&
|
||||
m.Disks.All(f => f.Disk.IsInRepo)) +
|
||||
r.Machines.Count(m => m.Files.Count > 0 &&
|
||||
m.Disks.Count > 0 &&
|
||||
m.Files.All(f => f.File.IsInRepo) &&
|
||||
m.Disks.All(f => f.Disk.IsInRepo)),
|
||||
IncompleteMachines =
|
||||
r.Machines.Count(m => m.Files.Count > 0 &&
|
||||
m.Disks.Count == 0 &&
|
||||
m.Files.Any(f => !f.File.IsInRepo)) +
|
||||
r.Machines.Count(m => m.Disks.Count > 0 &&
|
||||
m.Files.Count == 0 &&
|
||||
m.Disks.Any(f => !f.Disk.IsInRepo)) +
|
||||
r.Machines.Count(m => m.Files.Count > 0 &&
|
||||
m.Disks.Count > 0 &&
|
||||
(m.Files.Any(f => !f.File.IsInRepo) ||
|
||||
m.Disks.Any(f => !f.Disk.IsInRepo))),
|
||||
TotalRoms =
|
||||
r.Machines.Sum(m => m.Files.Count) +
|
||||
r.Machines.Sum(m => m.Disks.Count) +
|
||||
r.Machines.Sum(m => m.Medias.Count),
|
||||
HaveRoms = r.Machines.Sum(m => m.Files.Count(f => f.File.IsInRepo)) +
|
||||
r.Machines.Sum(m => m.Disks.Count(f => f.Disk.IsInRepo)) +
|
||||
r.Machines.Sum(m => m.Medias.Count(f => f.Media.IsInRepo)),
|
||||
MissRoms = r.Machines.Sum(m => m.Files.Count(f => !f.File.IsInRepo)) +
|
||||
r.Machines.Sum(m => m.Disks.Count(f => !f.Disk.IsInRepo)) +
|
||||
r.Machines.Sum(m => m.Medias.Count(f => !f.Media.IsInRepo))
|
||||
})
|
||||
.FirstOrDefault();
|
||||
|
||||
ctx.Database.ExecuteSqlRaw("DELETE FROM \"RomSetStats\"");
|
||||
|
||||
Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
IndeterminateProgress = false;
|
||||
MinimumValue = 0;
|
||||
MaximumValue = romSetCount;
|
||||
CurrentValue = 0;
|
||||
});
|
||||
|
||||
long pos = 0;
|
||||
|
||||
foreach(RomSet romSet in ctx.RomSets)
|
||||
{
|
||||
long currentPos = pos;
|
||||
ctx.RomSetStats.Add(stats);
|
||||
|
||||
Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
StatusMessage = string.Format(Localization.CalculatingStatisticsForRomSet, romSet.Name,
|
||||
romSet.Version, romSet.Description);
|
||||
|
||||
CurrentValue = currentPos;
|
||||
});
|
||||
|
||||
try
|
||||
{
|
||||
RomSetStat stats = ctx.RomSets.Where(r => r.Id == romSet.Id).Select(r => new RomSetStat
|
||||
RomSets.Add(new RomSetModel
|
||||
{
|
||||
RomSetId = r.Id,
|
||||
TotalMachines = r.Machines.Count,
|
||||
CompleteMachines =
|
||||
r.Machines.Count(m => m.Files.Count > 0 && m.Disks.Count == 0 &&
|
||||
m.Files.All(f => f.File.IsInRepo)) +
|
||||
r.Machines.Count(m => m.Disks.Count > 0 && m.Files.Count == 0 &&
|
||||
m.Disks.All(f => f.Disk.IsInRepo)) +
|
||||
r.Machines.Count(m => m.Files.Count > 0 && m.Disks.Count > 0 &&
|
||||
m.Files.All(f => f.File.IsInRepo) &&
|
||||
m.Disks.All(f => f.Disk.IsInRepo)),
|
||||
IncompleteMachines =
|
||||
r.Machines.Count(m => m.Files.Count > 0 && m.Disks.Count == 0 &&
|
||||
m.Files.Any(f => !f.File.IsInRepo)) +
|
||||
r.Machines.Count(m => m.Disks.Count > 0 && m.Files.Count == 0 &&
|
||||
m.Disks.Any(f => !f.Disk.IsInRepo)) +
|
||||
r.Machines.Count(m => m.Files.Count > 0 && m.Disks.Count > 0 &&
|
||||
(m.Files.Any(f => !f.File.IsInRepo) ||
|
||||
m.Disks.Any(f => !f.Disk.IsInRepo))),
|
||||
TotalRoms = r.Machines.Sum(m => m.Files.Count) + r.Machines.Sum(m => m.Disks.Count) +
|
||||
r.Machines.Sum(m => m.Medias.Count),
|
||||
HaveRoms = r.Machines.Sum(m => m.Files.Count(f => f.File.IsInRepo)) +
|
||||
r.Machines.Sum(m => m.Disks.Count(f => f.Disk.IsInRepo)) +
|
||||
r.Machines.Sum(m => m.Medias.Count(f => f.Media.IsInRepo)),
|
||||
MissRoms = r.Machines.Sum(m => m.Files.Count(f => !f.File.IsInRepo)) +
|
||||
r.Machines.Sum(m => m.Disks.Count(f => !f.Disk.IsInRepo)) +
|
||||
r.Machines.Sum(m => m.Medias.Count(f => !f.Media.IsInRepo))
|
||||
}).FirstOrDefault();
|
||||
|
||||
ctx.RomSetStats.Add(stats);
|
||||
|
||||
Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
RomSets.Add(new RomSetModel
|
||||
{
|
||||
Id = romSet.Id,
|
||||
Author = romSet.Author,
|
||||
Comment = romSet.Comment,
|
||||
Date = romSet.Date,
|
||||
Description = romSet.Description,
|
||||
Filename = romSet.Filename,
|
||||
Homepage = romSet.Homepage,
|
||||
Name = romSet.Name,
|
||||
Sha384 = romSet.Sha384,
|
||||
Version = romSet.Version,
|
||||
TotalMachines = stats.TotalMachines,
|
||||
CompleteMachines = stats.CompleteMachines,
|
||||
IncompleteMachines = stats.IncompleteMachines,
|
||||
TotalRoms = stats.TotalRoms,
|
||||
HaveRoms = stats.HaveRoms,
|
||||
MissRoms = stats.MissRoms,
|
||||
Category = romSet.Category
|
||||
});
|
||||
Id = romSet.Id,
|
||||
Author = romSet.Author,
|
||||
Comment = romSet.Comment,
|
||||
Date = romSet.Date,
|
||||
Description = romSet.Description,
|
||||
Filename = romSet.Filename,
|
||||
Homepage = romSet.Homepage,
|
||||
Name = romSet.Name,
|
||||
Sha384 = romSet.Sha384,
|
||||
Version = romSet.Version,
|
||||
TotalMachines = stats.TotalMachines,
|
||||
CompleteMachines = stats.CompleteMachines,
|
||||
IncompleteMachines = stats.IncompleteMachines,
|
||||
TotalRoms = stats.TotalRoms,
|
||||
HaveRoms = stats.HaveRoms,
|
||||
MissRoms = stats.MissRoms,
|
||||
Category = romSet.Category
|
||||
});
|
||||
}
|
||||
catch(Exception)
|
||||
{
|
||||
// Ignored
|
||||
}
|
||||
|
||||
pos++;
|
||||
});
|
||||
}
|
||||
catch(Exception)
|
||||
{
|
||||
// Ignored
|
||||
}
|
||||
|
||||
Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
StatusMessage = Localization.SavingChangesToDatabase;
|
||||
ProgressVisible = true;
|
||||
IndeterminateProgress = true;
|
||||
});
|
||||
pos++;
|
||||
}
|
||||
|
||||
ctx.SaveChanges();
|
||||
|
||||
Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
StatusMessage = Localization.Finished;
|
||||
ProgressVisible = false;
|
||||
CanClose = true;
|
||||
});
|
||||
Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
StatusMessage = Localization.SavingChangesToDatabase;
|
||||
ProgressVisible = true;
|
||||
IndeterminateProgress = true;
|
||||
});
|
||||
|
||||
void ExecuteCloseCommand() => _view.Close();
|
||||
}
|
||||
ctx.SaveChanges();
|
||||
|
||||
Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
StatusMessage = Localization.Finished;
|
||||
ProgressVisible = false;
|
||||
CanClose = true;
|
||||
});
|
||||
});
|
||||
|
||||
void ExecuteCloseCommand() => _view.Close();
|
||||
}
|
||||
@@ -25,7 +25,6 @@
|
||||
|
||||
using ReactiveUI;
|
||||
|
||||
namespace RomRepoMgr.ViewModels
|
||||
{
|
||||
public class ViewModelBase : ReactiveObject {}
|
||||
}
|
||||
namespace RomRepoMgr.ViewModels;
|
||||
|
||||
public class ViewModelBase : ReactiveObject {}
|
||||
@@ -24,12 +24,20 @@
|
||||
// Copyright © 2020-2024 Natalia Portillo
|
||||
// ****************************************************************************/
|
||||
-->
|
||||
<Window xmlns="https://github.com/avaloniaui" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
<Window xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:vm="clr-namespace:RomRepoMgr.ViewModels;assembly=RomRepoMgr" mc:Ignorable="d" d:DesignWidth="800"
|
||||
d:DesignHeight="450" Width="480" Height="320" x:Class="RomRepoMgr.Views.About" Icon="/Assets/avalonia-logo.ico"
|
||||
CanResize="False" Title="{Binding Title}">
|
||||
xmlns:vm="clr-namespace:RomRepoMgr.ViewModels;assembly=RomRepoMgr"
|
||||
mc:Ignorable="d"
|
||||
d:DesignWidth="800"
|
||||
d:DesignHeight="450"
|
||||
Width="480"
|
||||
Height="320"
|
||||
x:Class="RomRepoMgr.Views.About"
|
||||
Icon="/Assets/avalonia-logo.ico"
|
||||
CanResize="False"
|
||||
Title="{Binding Title}">
|
||||
<Design.DataContext>
|
||||
<vm:AboutViewModel />
|
||||
</Design.DataContext>
|
||||
@@ -42,20 +50,33 @@
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" /> <ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Border Grid.Column="0" BorderThickness="5">
|
||||
<Image Source="/Assets/avalonia-logo.ico" Width="48" Height="48" />
|
||||
<Border Grid.Column="0"
|
||||
BorderThickness="5">
|
||||
<Image Source="/Assets/avalonia-logo.ico"
|
||||
Width="48"
|
||||
Height="48" />
|
||||
</Border>
|
||||
<Grid Grid.Column="1" HorizontalAlignment="Left" VerticalAlignment="Center">
|
||||
<Grid Grid.Column="1"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<TextBlock Grid.Row="0" Text="{Binding SoftwareName}" HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center" FontSize="16" FontWeight="Bold" />
|
||||
<TextBlock Grid.Row="1" Text="{Binding VersionText}" HorizontalAlignment="Left"
|
||||
<TextBlock Grid.Row="0"
|
||||
Text="{Binding SoftwareName}"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="16"
|
||||
FontWeight="Bold" />
|
||||
<TextBlock Grid.Row="1"
|
||||
Text="{Binding VersionText}"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
<TabControl Grid.Row="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
|
||||
<TabControl Grid.Row="1"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch">
|
||||
<TabItem>
|
||||
<TabItem.Header>
|
||||
<TextBlock Text="{Binding AboutLabel}" />
|
||||
@@ -67,17 +88,31 @@
|
||||
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<TextBlock Grid.Row="0" Text="{Binding SuiteName}" />
|
||||
<TextBlock Grid.Row="2" Text="{Binding Copyright}" />
|
||||
<Button Grid.Row="4" BorderThickness="0" Background="Transparent" HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center" Padding="0" Command="{Binding WebsiteCommand}">
|
||||
<TextBlock Grid.Row="0"
|
||||
Text="{Binding SuiteName}" />
|
||||
<TextBlock Grid.Row="2"
|
||||
Text="{Binding Copyright}" />
|
||||
<Button Grid.Row="4"
|
||||
BorderThickness="0"
|
||||
Background="Transparent"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
Padding="0"
|
||||
Command="{Binding WebsiteCommand}">
|
||||
<!-- TODO: TextDecorations="Underline" in next Avalonia UI version -->
|
||||
<TextBlock Text="{Binding Website}" Foreground="Blue" />
|
||||
<TextBlock Text="{Binding Website}"
|
||||
Foreground="Blue" />
|
||||
</Button>
|
||||
<Button Grid.Row="5" BorderThickness="0" Background="Transparent" HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center" Padding="0" Command="{Binding LicenseCommand}">
|
||||
<Button Grid.Row="5"
|
||||
BorderThickness="0"
|
||||
Background="Transparent"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
Padding="0"
|
||||
Command="{Binding LicenseCommand}">
|
||||
<!-- TODO: TextDecorations="Underline" in next Avalonia UI version -->
|
||||
<TextBlock Text="{Binding License}" Foreground="Blue" />
|
||||
<TextBlock Text="{Binding License}"
|
||||
Foreground="Blue" />
|
||||
</Button>
|
||||
</Grid>
|
||||
</TabItem>
|
||||
@@ -85,14 +120,19 @@
|
||||
<TabItem.Header>
|
||||
<TextBlock Text="{Binding LibrariesLabel}" />
|
||||
</TabItem.Header>
|
||||
<DataGrid Items="{Binding Assemblies}" HorizontalScrollBarVisibility="Visible">
|
||||
<DataGrid Items="{Binding Assemblies}"
|
||||
HorizontalScrollBarVisibility="Visible">
|
||||
<DataGrid.Columns>
|
||||
<DataGridTextColumn Binding="{Binding Name}" Width="Auto" IsReadOnly="True">
|
||||
<DataGridTextColumn Binding="{Binding Name}"
|
||||
Width="Auto"
|
||||
IsReadOnly="True">
|
||||
<DataGridTextColumn.Header>
|
||||
<TextBlock Text="{Binding AssembliesLibraryText}" />
|
||||
</DataGridTextColumn.Header>
|
||||
</DataGridTextColumn>
|
||||
<DataGridTextColumn Binding="{Binding Version}" Width="Auto" IsReadOnly="True">
|
||||
<DataGridTextColumn Binding="{Binding Version}"
|
||||
Width="Auto"
|
||||
IsReadOnly="True">
|
||||
<DataGridTextColumn.Header>
|
||||
<TextBlock Text="{Binding AssembliesVersionText}" />
|
||||
</DataGridTextColumn.Header>
|
||||
@@ -104,10 +144,13 @@
|
||||
<TabItem.Header>
|
||||
<TextBlock Text="{Binding AuthorsLabel}" />
|
||||
</TabItem.Header>
|
||||
<TextBox IsReadOnly="True" Text="{Binding Authors}" />
|
||||
<TextBox IsReadOnly="True"
|
||||
Text="{Binding Authors}" />
|
||||
</TabItem>
|
||||
</TabControl>
|
||||
<Button Grid.Row="2" HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||
<Button Grid.Row="2"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Center"
|
||||
Command="{Binding CloseCommand}">
|
||||
<TextBlock Text="{Binding CloseLabel}" />
|
||||
</Button>
|
||||
|
||||
@@ -26,12 +26,11 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
|
||||
namespace RomRepoMgr.Views
|
||||
{
|
||||
public sealed class About : Window
|
||||
{
|
||||
public About() => InitializeComponent();
|
||||
namespace RomRepoMgr.Views;
|
||||
|
||||
void InitializeComponent() => AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
public sealed class About : Window
|
||||
{
|
||||
public About() => InitializeComponent();
|
||||
|
||||
void InitializeComponent() => AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
@@ -24,12 +24,21 @@
|
||||
// Copyright © 2020-2024 Natalia Portillo
|
||||
// ****************************************************************************/
|
||||
-->
|
||||
<Window xmlns="https://github.com/avaloniaui" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
<Window xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:vm="clr-namespace:RomRepoMgr.ViewModels;assembly=RomRepoMgr" mc:Ignorable="d" d:DesignWidth="800"
|
||||
d:DesignHeight="450" Width="720" Height="480" x:Class="RomRepoMgr.Views.EditDat"
|
||||
Icon="/Assets/avalonia-logo.ico" CanResize="False" Title="{Binding Title}" WindowStartupLocation="CenterScreen">
|
||||
xmlns:vm="clr-namespace:RomRepoMgr.ViewModels;assembly=RomRepoMgr"
|
||||
mc:Ignorable="d"
|
||||
d:DesignWidth="800"
|
||||
d:DesignHeight="450"
|
||||
Width="720"
|
||||
Height="480"
|
||||
x:Class="RomRepoMgr.Views.EditDat"
|
||||
Icon="/Assets/avalonia-logo.ico"
|
||||
CanResize="False"
|
||||
Title="{Binding Title}"
|
||||
WindowStartupLocation="CenterScreen">
|
||||
<Design.DataContext>
|
||||
<vm:EditDatViewModel />
|
||||
</Design.DataContext>
|
||||
@@ -46,138 +55,244 @@
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="140" /> <ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Grid.Column="0" HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||
Text="{Binding NameLabel}" FontWeight="Bold" Padding="5" />
|
||||
<TextBox Grid.Column="1" HorizontalAlignment="Stretch" VerticalAlignment="Center" Text="{Binding Name}"
|
||||
<TextBlock Grid.Column="0"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Center"
|
||||
Text="{Binding NameLabel}"
|
||||
FontWeight="Bold"
|
||||
Padding="5" />
|
||||
<TextBox Grid.Column="1"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Center"
|
||||
Text="{Binding Name}"
|
||||
Padding="5" />
|
||||
</Grid>
|
||||
<Grid Grid.Row="1">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="140" /> <ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Grid.Column="0" HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||
Text="{Binding VersionLabel}" FontWeight="Bold" Padding="5" />
|
||||
<TextBox Grid.Column="1" HorizontalAlignment="Stretch" VerticalAlignment="Center"
|
||||
Text="{Binding Version}" Padding="5" />
|
||||
<TextBlock Grid.Column="0"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Center"
|
||||
Text="{Binding VersionLabel}"
|
||||
FontWeight="Bold"
|
||||
Padding="5" />
|
||||
<TextBox Grid.Column="1"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Center"
|
||||
Text="{Binding Version}"
|
||||
Padding="5" />
|
||||
</Grid>
|
||||
<Grid Grid.Row="2">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="140" /> <ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Grid.Column="0" HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||
Text="{Binding AuthorLabel}" FontWeight="Bold" Padding="5" />
|
||||
<TextBox Grid.Column="1" HorizontalAlignment="Stretch" VerticalAlignment="Center"
|
||||
Text="{Binding Author}" Padding="5" />
|
||||
<TextBlock Grid.Column="0"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Center"
|
||||
Text="{Binding AuthorLabel}"
|
||||
FontWeight="Bold"
|
||||
Padding="5" />
|
||||
<TextBox Grid.Column="1"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Center"
|
||||
Text="{Binding Author}"
|
||||
Padding="5" />
|
||||
</Grid>
|
||||
<Grid Grid.Row="3">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="140" /> <ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Grid.Column="0" HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||
Text="{Binding CategoryLabel}" FontWeight="Bold" Padding="5" />
|
||||
<TextBox Grid.Column="1" HorizontalAlignment="Stretch" VerticalAlignment="Center"
|
||||
Text="{Binding Category}" Padding="5" />
|
||||
<TextBlock Grid.Column="0"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Center"
|
||||
Text="{Binding CategoryLabel}"
|
||||
FontWeight="Bold"
|
||||
Padding="5" />
|
||||
<TextBox Grid.Column="1"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Center"
|
||||
Text="{Binding Category}"
|
||||
Padding="5" />
|
||||
</Grid>
|
||||
<Grid Grid.Row="4">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="140" /> <ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Grid.Column="0" HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||
Text="{Binding CommentLabel}" FontWeight="Bold" Padding="5" />
|
||||
<TextBox Grid.Column="1" HorizontalAlignment="Stretch" VerticalAlignment="Center"
|
||||
Text="{Binding Comment}" Padding="5" />
|
||||
<TextBlock Grid.Column="0"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Center"
|
||||
Text="{Binding CommentLabel}"
|
||||
FontWeight="Bold"
|
||||
Padding="5" />
|
||||
<TextBox Grid.Column="1"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Center"
|
||||
Text="{Binding Comment}"
|
||||
Padding="5" />
|
||||
</Grid>
|
||||
<Grid Grid.Row="5">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="140" /> <ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Grid.Column="0" HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||
Text="{Binding DateLabel}" FontWeight="Bold" Padding="5" />
|
||||
<TextBox Grid.Column="1" HorizontalAlignment="Stretch" VerticalAlignment="Center" Text="{Binding Date}"
|
||||
<TextBlock Grid.Column="0"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Center"
|
||||
Text="{Binding DateLabel}"
|
||||
FontWeight="Bold"
|
||||
Padding="5" />
|
||||
<TextBox Grid.Column="1"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Center"
|
||||
Text="{Binding Date}"
|
||||
Padding="5" />
|
||||
</Grid>
|
||||
<Grid Grid.Row="6">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="140" /> <ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Grid.Column="0" HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||
Text="{Binding DescriptionLabel}" FontWeight="Bold" Padding="5" />
|
||||
<TextBox Grid.Column="1" HorizontalAlignment="Stretch" VerticalAlignment="Center"
|
||||
Text="{Binding Description}" Padding="5" />
|
||||
<TextBlock Grid.Column="0"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Center"
|
||||
Text="{Binding DescriptionLabel}"
|
||||
FontWeight="Bold"
|
||||
Padding="5" />
|
||||
<TextBox Grid.Column="1"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Center"
|
||||
Text="{Binding Description}"
|
||||
Padding="5" />
|
||||
</Grid>
|
||||
<Grid Grid.Row="7">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="140" /> <ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Grid.Column="0" HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||
Text="{Binding HomepageLabel}" FontWeight="Bold" Padding="5" />
|
||||
<TextBox Grid.Column="1" HorizontalAlignment="Stretch" VerticalAlignment="Center"
|
||||
Text="{Binding Homepage}" Padding="5" />
|
||||
<TextBlock Grid.Column="0"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Center"
|
||||
Text="{Binding HomepageLabel}"
|
||||
FontWeight="Bold"
|
||||
Padding="5" />
|
||||
<TextBox Grid.Column="1"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Center"
|
||||
Text="{Binding Homepage}"
|
||||
Padding="5" />
|
||||
</Grid>
|
||||
<Grid Grid.Row="8">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="140" /> <ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Grid.Column="0" HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||
Text="{Binding TotalMachinesLabel}" FontWeight="Bold" Padding="5" />
|
||||
<TextBlock Grid.Column="1" HorizontalAlignment="Left" VerticalAlignment="Center"
|
||||
Text="{Binding TotalMachines}" Padding="5" />
|
||||
<TextBlock Grid.Column="0"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Center"
|
||||
Text="{Binding TotalMachinesLabel}"
|
||||
FontWeight="Bold"
|
||||
Padding="5" />
|
||||
<TextBlock Grid.Column="1"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
Text="{Binding TotalMachines}"
|
||||
Padding="5" />
|
||||
</Grid>
|
||||
<Grid Grid.Row="9">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="140" /> <ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Grid.Column="0" HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||
Text="{Binding CompleteMachinesLabel}" FontWeight="Bold" Padding="5" />
|
||||
<TextBlock Grid.Column="1" HorizontalAlignment="Left" VerticalAlignment="Center"
|
||||
Text="{Binding CompleteMachines}" Padding="5" />
|
||||
<TextBlock Grid.Column="0"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Center"
|
||||
Text="{Binding CompleteMachinesLabel}"
|
||||
FontWeight="Bold"
|
||||
Padding="5" />
|
||||
<TextBlock Grid.Column="1"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
Text="{Binding CompleteMachines}"
|
||||
Padding="5" />
|
||||
</Grid>
|
||||
<Grid Grid.Row="10">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="140" /> <ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Grid.Column="0" HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||
Text="{Binding IncompleteMachinesLabel}" FontWeight="Bold" Padding="5" />
|
||||
<TextBlock Grid.Column="1" HorizontalAlignment="Left" VerticalAlignment="Center"
|
||||
Text="{Binding IncompleteMachines}" Padding="5" />
|
||||
<TextBlock Grid.Column="0"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Center"
|
||||
Text="{Binding IncompleteMachinesLabel}"
|
||||
FontWeight="Bold"
|
||||
Padding="5" />
|
||||
<TextBlock Grid.Column="1"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
Text="{Binding IncompleteMachines}"
|
||||
Padding="5" />
|
||||
</Grid>
|
||||
<Grid Grid.Row="11">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="140" /> <ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Grid.Column="0" HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||
Text="{Binding TotalRomsLabel}" FontWeight="Bold" Padding="5" />
|
||||
<TextBlock Grid.Column="1" HorizontalAlignment="Left" VerticalAlignment="Center"
|
||||
Text="{Binding TotalRoms}" Padding="5" />
|
||||
<TextBlock Grid.Column="0"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Center"
|
||||
Text="{Binding TotalRomsLabel}"
|
||||
FontWeight="Bold"
|
||||
Padding="5" />
|
||||
<TextBlock Grid.Column="1"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
Text="{Binding TotalRoms}"
|
||||
Padding="5" />
|
||||
</Grid>
|
||||
<Grid Grid.Row="12">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="140" /> <ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Grid.Column="0" HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||
Text="{Binding HaveRomsLabel}" FontWeight="Bold" Padding="5" />
|
||||
<TextBlock Grid.Column="1" HorizontalAlignment="Left" VerticalAlignment="Center"
|
||||
Text="{Binding HaveRoms}" Padding="5" />
|
||||
<TextBlock Grid.Column="0"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Center"
|
||||
Text="{Binding HaveRomsLabel}"
|
||||
FontWeight="Bold"
|
||||
Padding="5" />
|
||||
<TextBlock Grid.Column="1"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
Text="{Binding HaveRoms}"
|
||||
Padding="5" />
|
||||
</Grid>
|
||||
<Grid Grid.Row="13">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="140" /> <ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Grid.Column="0" HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||
Text="{Binding MissRomsLabel}" FontWeight="Bold" Padding="5" />
|
||||
<TextBlock Grid.Column="1" HorizontalAlignment="Left" VerticalAlignment="Center"
|
||||
Text="{Binding MissRoms}" Padding="5" />
|
||||
<TextBlock Grid.Column="0"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Center"
|
||||
Text="{Binding MissRomsLabel}"
|
||||
FontWeight="Bold"
|
||||
Padding="5" />
|
||||
<TextBlock Grid.Column="1"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
Text="{Binding MissRoms}"
|
||||
Padding="5" />
|
||||
</Grid>
|
||||
<StackPanel Grid.Row="14" Orientation="Horizontal" HorizontalAlignment="Right">
|
||||
<Button HorizontalAlignment="Right" VerticalAlignment="Center" Command="{Binding SaveCommand}"
|
||||
<StackPanel Grid.Row="14"
|
||||
Orientation="Horizontal"
|
||||
HorizontalAlignment="Right">
|
||||
<Button HorizontalAlignment="Right"
|
||||
VerticalAlignment="Center"
|
||||
Command="{Binding SaveCommand}"
|
||||
IsVisible="{Binding Modified}">
|
||||
<TextBlock Text="{Binding SaveLabel}" />
|
||||
</Button>
|
||||
<Button HorizontalAlignment="Right" VerticalAlignment="Center" Command="{Binding CancelCommand}"
|
||||
<Button HorizontalAlignment="Right"
|
||||
VerticalAlignment="Center"
|
||||
Command="{Binding CancelCommand}"
|
||||
IsVisible="{Binding Modified}">
|
||||
<TextBlock Text="{Binding CancelLabel}" />
|
||||
</Button>
|
||||
<Button HorizontalAlignment="Right" VerticalAlignment="Center" Command="{Binding CloseCommand}"
|
||||
<Button HorizontalAlignment="Right"
|
||||
VerticalAlignment="Center"
|
||||
Command="{Binding CloseCommand}"
|
||||
IsVisible="{Binding !Modified}">
|
||||
<TextBlock Text="{Binding CloseLabel}" />
|
||||
</Button>
|
||||
|
||||
@@ -26,12 +26,11 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
|
||||
namespace RomRepoMgr.Views
|
||||
{
|
||||
public sealed class EditDat : Window
|
||||
{
|
||||
public EditDat() => InitializeComponent();
|
||||
namespace RomRepoMgr.Views;
|
||||
|
||||
void InitializeComponent() => AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
public sealed class EditDat : Window
|
||||
{
|
||||
public EditDat() => InitializeComponent();
|
||||
|
||||
void InitializeComponent() => AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
@@ -24,12 +24,21 @@
|
||||
// Copyright © 2020-2024 Natalia Portillo
|
||||
// ****************************************************************************/
|
||||
-->
|
||||
<Window xmlns="https://github.com/avaloniaui" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
<Window xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:vm="clr-namespace:RomRepoMgr.ViewModels;assembly=RomRepoMgr" mc:Ignorable="d" d:DesignWidth="800"
|
||||
d:DesignHeight="450" Width="480" Height="90" x:Class="RomRepoMgr.Views.ExportDat"
|
||||
Icon="/Assets/avalonia-logo.ico" CanResize="False" Title="{Binding Title}" WindowStartupLocation="CenterOwner">
|
||||
xmlns:vm="clr-namespace:RomRepoMgr.ViewModels;assembly=RomRepoMgr"
|
||||
mc:Ignorable="d"
|
||||
d:DesignWidth="800"
|
||||
d:DesignHeight="450"
|
||||
Width="480"
|
||||
Height="90"
|
||||
x:Class="RomRepoMgr.Views.ExportDat"
|
||||
Icon="/Assets/avalonia-logo.ico"
|
||||
CanResize="False"
|
||||
Title="{Binding Title}"
|
||||
WindowStartupLocation="CenterOwner">
|
||||
<Design.DataContext>
|
||||
<vm:ExportDatViewModel />
|
||||
</Design.DataContext>
|
||||
@@ -39,12 +48,22 @@
|
||||
<RowDefinition Height="Auto" /> <RowDefinition Height="auto" /> <RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<TextBlock Grid.Row="0" Text="{Binding StatusMessage}" HorizontalAlignment="Center" />
|
||||
<ProgressBar Grid.Row="1" IsIndeterminate="True" HorizontalAlignment="Stretch"
|
||||
<TextBlock Grid.Row="0"
|
||||
Text="{Binding StatusMessage}"
|
||||
HorizontalAlignment="Center" />
|
||||
<ProgressBar Grid.Row="1"
|
||||
IsIndeterminate="True"
|
||||
HorizontalAlignment="Stretch"
|
||||
IsVisible="{Binding ProgressVisible}" />
|
||||
<TextBlock Grid.Row="2" Text="{Binding ErrorMessage}" HorizontalAlignment="Center" Foreground="Red"
|
||||
<TextBlock Grid.Row="2"
|
||||
Text="{Binding ErrorMessage}"
|
||||
HorizontalAlignment="Center"
|
||||
Foreground="Red"
|
||||
IsVisible="{Binding ErrorVisible}" />
|
||||
<Button Grid.Row="3" HorizontalAlignment="Right" VerticalAlignment="Center" IsEnabled="{Binding CanClose}"
|
||||
<Button Grid.Row="3"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Center"
|
||||
IsEnabled="{Binding CanClose}"
|
||||
Command="{Binding CloseCommand}">
|
||||
<TextBlock Text="{Binding CloseLabel}" />
|
||||
</Button>
|
||||
|
||||
@@ -28,18 +28,17 @@ using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using RomRepoMgr.ViewModels;
|
||||
|
||||
namespace RomRepoMgr.Views
|
||||
namespace RomRepoMgr.Views;
|
||||
|
||||
public sealed class ExportDat : Window
|
||||
{
|
||||
public sealed class ExportDat : Window
|
||||
public ExportDat() => InitializeComponent();
|
||||
|
||||
void InitializeComponent() => AvaloniaXamlLoader.Load(this);
|
||||
|
||||
protected override void OnOpened(EventArgs e)
|
||||
{
|
||||
public ExportDat() => InitializeComponent();
|
||||
|
||||
void InitializeComponent() => AvaloniaXamlLoader.Load(this);
|
||||
|
||||
protected override void OnOpened(EventArgs e)
|
||||
{
|
||||
base.OnOpened(e);
|
||||
(DataContext as ExportDatViewModel)?.OnOpened();
|
||||
}
|
||||
base.OnOpened(e);
|
||||
(DataContext as ExportDatViewModel)?.OnOpened();
|
||||
}
|
||||
}
|
||||
@@ -24,12 +24,21 @@
|
||||
// Copyright © 2020-2024 Natalia Portillo
|
||||
// ****************************************************************************/
|
||||
-->
|
||||
<Window xmlns="https://github.com/avaloniaui" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
<Window xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:vm="clr-namespace:RomRepoMgr.ViewModels;assembly=RomRepoMgr" mc:Ignorable="d" d:DesignWidth="800"
|
||||
d:DesignHeight="450" Width="480" Height="150" x:Class="RomRepoMgr.Views.ExportRoms"
|
||||
Icon="/Assets/avalonia-logo.ico" CanResize="False" Title="{Binding Title}" WindowStartupLocation="CenterOwner">
|
||||
xmlns:vm="clr-namespace:RomRepoMgr.ViewModels;assembly=RomRepoMgr"
|
||||
mc:Ignorable="d"
|
||||
d:DesignWidth="800"
|
||||
d:DesignHeight="450"
|
||||
Width="480"
|
||||
Height="150"
|
||||
x:Class="RomRepoMgr.Views.ExportRoms"
|
||||
Icon="/Assets/avalonia-logo.ico"
|
||||
CanResize="False"
|
||||
Title="{Binding Title}"
|
||||
WindowStartupLocation="CenterOwner">
|
||||
<Design.DataContext>
|
||||
<vm:ExportRomsViewModel />
|
||||
</Design.DataContext>
|
||||
@@ -40,24 +49,43 @@
|
||||
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" /> <RowDefinition Height="*" /> <RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<StackPanel Grid.Row="0" Orientation="Horizontal" HorizontalAlignment="Stretch">
|
||||
<TextBlock Text="{Binding PathLabel}" FontWeight="Bold" /> <TextBlock Text="{Binding FolderPath}" />
|
||||
<StackPanel Grid.Row="0"
|
||||
Orientation="Horizontal"
|
||||
HorizontalAlignment="Stretch">
|
||||
<TextBlock Text="{Binding PathLabel}"
|
||||
FontWeight="Bold" />
|
||||
<TextBlock Text="{Binding FolderPath}" />
|
||||
</StackPanel>
|
||||
<TextBlock Grid.Row="1" Text="{Binding StatusMessage}" FontWeight="Bold" HorizontalAlignment="Center" />
|
||||
<ProgressBar Grid.Row="2" Minimum="{Binding ProgressMinimum}" Maximum="{Binding ProgressMaximum}"
|
||||
Value="{Binding ProgressValue}" IsIndeterminate="{Binding ProgressIsIndeterminate}"
|
||||
<TextBlock Grid.Row="1"
|
||||
Text="{Binding StatusMessage}"
|
||||
FontWeight="Bold"
|
||||
HorizontalAlignment="Center" />
|
||||
<ProgressBar Grid.Row="2"
|
||||
Minimum="{Binding ProgressMinimum}"
|
||||
Maximum="{Binding ProgressMaximum}"
|
||||
Value="{Binding ProgressValue}"
|
||||
IsIndeterminate="{Binding ProgressIsIndeterminate}"
|
||||
IsVisible="{Binding ProgressVisible}" />
|
||||
<StackPanel Grid.Row="3" IsVisible="{Binding Progress2Visible}">
|
||||
<StackPanel Grid.Row="3"
|
||||
IsVisible="{Binding Progress2Visible}">
|
||||
<TextBlock Text="{Binding Status2Message}" />
|
||||
<ProgressBar Minimum="{Binding Progress2Minimum}" Maximum="{Binding Progress2Maximum}"
|
||||
Value="{Binding Progress2Value}" IsIndeterminate="{Binding Progress2IsIndeterminate}" />
|
||||
<ProgressBar Minimum="{Binding Progress2Minimum}"
|
||||
Maximum="{Binding Progress2Maximum}"
|
||||
Value="{Binding Progress2Value}"
|
||||
IsIndeterminate="{Binding Progress2IsIndeterminate}" />
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Row="4" IsVisible="{Binding Progress3Visible}">
|
||||
<StackPanel Grid.Row="4"
|
||||
IsVisible="{Binding Progress3Visible}">
|
||||
<TextBlock Text="{Binding Status3Message}" />
|
||||
<ProgressBar Minimum="{Binding Progress3Minimum}" Maximum="{Binding Progress3Maximum}"
|
||||
Value="{Binding Progress3Value}" IsIndeterminate="{Binding Progress3IsIndeterminate}" />
|
||||
<ProgressBar Minimum="{Binding Progress3Minimum}"
|
||||
Maximum="{Binding Progress3Maximum}"
|
||||
Value="{Binding Progress3Value}"
|
||||
IsIndeterminate="{Binding Progress3IsIndeterminate}" />
|
||||
</StackPanel>
|
||||
<Button Grid.Row="5" HorizontalAlignment="Right" VerticalAlignment="Center" IsEnabled="{Binding CanClose}"
|
||||
<Button Grid.Row="5"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Center"
|
||||
IsEnabled="{Binding CanClose}"
|
||||
Command="{Binding CloseCommand}">
|
||||
<TextBlock Text="{Binding CloseLabel}" />
|
||||
</Button>
|
||||
|
||||
@@ -28,18 +28,17 @@ using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using RomRepoMgr.ViewModels;
|
||||
|
||||
namespace RomRepoMgr.Views
|
||||
namespace RomRepoMgr.Views;
|
||||
|
||||
public sealed class ExportRoms : Window
|
||||
{
|
||||
public sealed class ExportRoms : Window
|
||||
public ExportRoms() => InitializeComponent();
|
||||
|
||||
void InitializeComponent() => AvaloniaXamlLoader.Load(this);
|
||||
|
||||
protected override void OnOpened(EventArgs e)
|
||||
{
|
||||
public ExportRoms() => InitializeComponent();
|
||||
|
||||
void InitializeComponent() => AvaloniaXamlLoader.Load(this);
|
||||
|
||||
protected override void OnOpened(EventArgs e)
|
||||
{
|
||||
base.OnOpened(e);
|
||||
(DataContext as ExportRomsViewModel)?.OnOpened();
|
||||
}
|
||||
base.OnOpened(e);
|
||||
(DataContext as ExportRomsViewModel)?.OnOpened();
|
||||
}
|
||||
}
|
||||
@@ -24,12 +24,21 @@
|
||||
// Copyright © 2020-2024 Natalia Portillo
|
||||
// ****************************************************************************/
|
||||
-->
|
||||
<Window xmlns="https://github.com/avaloniaui" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
<Window xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:vm="clr-namespace:RomRepoMgr.ViewModels;assembly=RomRepoMgr" mc:Ignorable="d" d:DesignWidth="800"
|
||||
d:DesignHeight="450" Width="480" Height="90" x:Class="RomRepoMgr.Views.ImportDat"
|
||||
Icon="/Assets/avalonia-logo.ico" CanResize="False" Title="{Binding Title}" WindowStartupLocation="CenterOwner">
|
||||
xmlns:vm="clr-namespace:RomRepoMgr.ViewModels;assembly=RomRepoMgr"
|
||||
mc:Ignorable="d"
|
||||
d:DesignWidth="800"
|
||||
d:DesignHeight="450"
|
||||
Width="480"
|
||||
Height="90"
|
||||
x:Class="RomRepoMgr.Views.ImportDat"
|
||||
Icon="/Assets/avalonia-logo.ico"
|
||||
CanResize="False"
|
||||
Title="{Binding Title}"
|
||||
WindowStartupLocation="CenterOwner">
|
||||
<Design.DataContext>
|
||||
<vm:ImportDatViewModel />
|
||||
</Design.DataContext>
|
||||
@@ -39,14 +48,25 @@
|
||||
<RowDefinition Height="Auto" /> <RowDefinition Height="auto" /> <RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<TextBlock Grid.Row="0" Text="{Binding StatusMessage}" HorizontalAlignment="Center" />
|
||||
<ProgressBar Grid.Row="1" IsIndeterminate="{Binding IndeterminateProgress}"
|
||||
Maximum="{Binding MaximumValue}" Minimum="{Binding MinimumValue}"
|
||||
Value="{Binding CurrentValue}" HorizontalAlignment="Stretch"
|
||||
<TextBlock Grid.Row="0"
|
||||
Text="{Binding StatusMessage}"
|
||||
HorizontalAlignment="Center" />
|
||||
<ProgressBar Grid.Row="1"
|
||||
IsIndeterminate="{Binding IndeterminateProgress}"
|
||||
Maximum="{Binding MaximumValue}"
|
||||
Minimum="{Binding MinimumValue}"
|
||||
Value="{Binding CurrentValue}"
|
||||
HorizontalAlignment="Stretch"
|
||||
IsVisible="{Binding ProgressVisible}" />
|
||||
<TextBlock Grid.Row="2" Text="{Binding ErrorMessage}" HorizontalAlignment="Center" Foreground="Red"
|
||||
<TextBlock Grid.Row="2"
|
||||
Text="{Binding ErrorMessage}"
|
||||
HorizontalAlignment="Center"
|
||||
Foreground="Red"
|
||||
IsVisible="{Binding ErrorVisible}" />
|
||||
<Button Grid.Row="3" HorizontalAlignment="Right" VerticalAlignment="Center" IsEnabled="{Binding CanClose}"
|
||||
<Button Grid.Row="3"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Center"
|
||||
IsEnabled="{Binding CanClose}"
|
||||
Command="{Binding CloseCommand}">
|
||||
<TextBlock Text="{Binding CloseLabel}" />
|
||||
</Button>
|
||||
|
||||
@@ -28,18 +28,17 @@ using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using RomRepoMgr.ViewModels;
|
||||
|
||||
namespace RomRepoMgr.Views
|
||||
namespace RomRepoMgr.Views;
|
||||
|
||||
public sealed class ImportDat : Window
|
||||
{
|
||||
public sealed class ImportDat : Window
|
||||
public ImportDat() => InitializeComponent();
|
||||
|
||||
void InitializeComponent() => AvaloniaXamlLoader.Load(this);
|
||||
|
||||
protected override void OnOpened(EventArgs e)
|
||||
{
|
||||
public ImportDat() => InitializeComponent();
|
||||
|
||||
void InitializeComponent() => AvaloniaXamlLoader.Load(this);
|
||||
|
||||
protected override void OnOpened(EventArgs e)
|
||||
{
|
||||
base.OnOpened(e);
|
||||
(DataContext as ImportDatViewModel)?.OnOpened();
|
||||
}
|
||||
base.OnOpened(e);
|
||||
(DataContext as ImportDatViewModel)?.OnOpened();
|
||||
}
|
||||
}
|
||||
@@ -24,12 +24,21 @@
|
||||
// Copyright © 2020-2024 Natalia Portillo
|
||||
// ****************************************************************************/
|
||||
-->
|
||||
<Window xmlns="https://github.com/avaloniaui" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
<Window xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:vm="clr-namespace:RomRepoMgr.ViewModels;assembly=RomRepoMgr" mc:Ignorable="d" d:DesignWidth="800"
|
||||
d:DesignHeight="450" Width="480" Height="360" x:Class="RomRepoMgr.Views.ImportDatFolder"
|
||||
Icon="/Assets/avalonia-logo.ico" CanResize="False" Title="{Binding Title}" WindowStartupLocation="CenterOwner">
|
||||
xmlns:vm="clr-namespace:RomRepoMgr.ViewModels;assembly=RomRepoMgr"
|
||||
mc:Ignorable="d"
|
||||
d:DesignWidth="800"
|
||||
d:DesignHeight="450"
|
||||
Width="480"
|
||||
Height="360"
|
||||
x:Class="RomRepoMgr.Views.ImportDatFolder"
|
||||
Icon="/Assets/avalonia-logo.ico"
|
||||
CanResize="False"
|
||||
Title="{Binding Title}"
|
||||
WindowStartupLocation="CenterOwner">
|
||||
<Design.DataContext>
|
||||
<vm:ImportDatFolderViewModel />
|
||||
</Design.DataContext>
|
||||
@@ -40,58 +49,95 @@
|
||||
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" /> <RowDefinition Height="*" /> <RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<StackPanel Grid.Row="0" Orientation="Horizontal" HorizontalAlignment="Stretch">
|
||||
<TextBlock Text="{Binding PathLabel}" FontWeight="Bold" /> <TextBlock Text="{Binding FolderPath}" />
|
||||
<StackPanel Grid.Row="0"
|
||||
Orientation="Horizontal"
|
||||
HorizontalAlignment="Stretch">
|
||||
<TextBlock Text="{Binding PathLabel}"
|
||||
FontWeight="Bold" />
|
||||
<TextBlock Text="{Binding FolderPath}" />
|
||||
</StackPanel>
|
||||
<Grid Grid.Row="1">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" /> <ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Grid.Column="0" HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||
Text="{Binding CategoryLabel}" FontWeight="Bold" Padding="5" />
|
||||
<TextBox Grid.Column="1" HorizontalAlignment="Stretch" VerticalAlignment="Center"
|
||||
Text="{Binding Category}" Padding="5" />
|
||||
<TextBlock Grid.Column="0"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Center"
|
||||
Text="{Binding CategoryLabel}"
|
||||
FontWeight="Bold"
|
||||
Padding="5" />
|
||||
<TextBox Grid.Column="1"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Center"
|
||||
Text="{Binding Category}"
|
||||
Padding="5" />
|
||||
</Grid>
|
||||
<CheckBox Grid.Row="2" IsChecked="{Binding AllFilesChecked}" IsEnabled="{Binding IsReady}">
|
||||
<CheckBox Grid.Row="2"
|
||||
IsChecked="{Binding AllFilesChecked}"
|
||||
IsEnabled="{Binding IsReady}">
|
||||
<CheckBox.Content>
|
||||
<TextBlock Text="{Binding AllFilesLabel}" />
|
||||
</CheckBox.Content>
|
||||
</CheckBox>
|
||||
<CheckBox Grid.Row="3" IsChecked="{Binding RecursiveChecked}" IsEnabled="{Binding IsReady}">
|
||||
<CheckBox Grid.Row="3"
|
||||
IsChecked="{Binding RecursiveChecked}"
|
||||
IsEnabled="{Binding IsReady}">
|
||||
<CheckBox.Content>
|
||||
<TextBlock Text="{Binding RecursiveLabel}" />
|
||||
</CheckBox.Content>
|
||||
</CheckBox>
|
||||
<TextBlock Grid.Row="4" Text="{Binding StatusMessage}" FontWeight="Bold" HorizontalAlignment="Center" />
|
||||
<ProgressBar Grid.Row="5" Minimum="{Binding ProgressMinimum}" Maximum="{Binding ProgressMaximum}"
|
||||
Value="{Binding ProgressValue}" IsIndeterminate="{Binding ProgressIsIndeterminate}"
|
||||
<TextBlock Grid.Row="4"
|
||||
Text="{Binding StatusMessage}"
|
||||
FontWeight="Bold"
|
||||
HorizontalAlignment="Center" />
|
||||
<ProgressBar Grid.Row="5"
|
||||
Minimum="{Binding ProgressMinimum}"
|
||||
Maximum="{Binding ProgressMaximum}"
|
||||
Value="{Binding ProgressValue}"
|
||||
IsIndeterminate="{Binding ProgressIsIndeterminate}"
|
||||
IsVisible="{Binding ProgressVisible}" />
|
||||
<StackPanel Grid.Row="6" IsVisible="{Binding Progress2Visible}">
|
||||
<StackPanel Grid.Row="6"
|
||||
IsVisible="{Binding Progress2Visible}">
|
||||
<TextBlock Text="{Binding Status2Message}" />
|
||||
<ProgressBar Minimum="{Binding Progress2Minimum}" Maximum="{Binding Progress2Maximum}"
|
||||
Value="{Binding Progress2Value}" IsIndeterminate="{Binding Progress2IsIndeterminate}" />
|
||||
<ProgressBar Minimum="{Binding Progress2Minimum}"
|
||||
Maximum="{Binding Progress2Maximum}"
|
||||
Value="{Binding Progress2Value}"
|
||||
IsIndeterminate="{Binding Progress2IsIndeterminate}" />
|
||||
</StackPanel>
|
||||
<DataGrid Grid.Row="7" Items="{Binding ImportResults}" HorizontalScrollBarVisibility="Visible"
|
||||
<DataGrid Grid.Row="7"
|
||||
Items="{Binding ImportResults}"
|
||||
HorizontalScrollBarVisibility="Visible"
|
||||
IsVisible="{Binding IsImporting}">
|
||||
<DataGrid.Columns>
|
||||
<DataGridTextColumn Binding="{Binding Filename}" Width="Auto" IsReadOnly="True">
|
||||
<DataGridTextColumn Binding="{Binding Filename}"
|
||||
Width="Auto"
|
||||
IsReadOnly="True">
|
||||
<DataGridTextColumn.Header>
|
||||
<TextBlock Text="{Binding ResultFilenameLabel}" />
|
||||
</DataGridTextColumn.Header>
|
||||
</DataGridTextColumn>
|
||||
<DataGridTextColumn Binding="{Binding Status}" Width="Auto" IsReadOnly="True">
|
||||
<DataGridTextColumn Binding="{Binding Status}"
|
||||
Width="Auto"
|
||||
IsReadOnly="True">
|
||||
<DataGridTextColumn.Header>
|
||||
<TextBlock Text="{Binding ResultStatusLabel}" />
|
||||
</DataGridTextColumn.Header>
|
||||
</DataGridTextColumn>
|
||||
</DataGrid.Columns>
|
||||
</DataGrid>
|
||||
<StackPanel Grid.Row="8" Orientation="Horizontal" IsVisible="{Binding IsReady}" HorizontalAlignment="Right">
|
||||
<Button HorizontalAlignment="Right" VerticalAlignment="Center" IsEnabled="{Binding CanClose}"
|
||||
<StackPanel Grid.Row="8"
|
||||
Orientation="Horizontal"
|
||||
IsVisible="{Binding IsReady}"
|
||||
HorizontalAlignment="Right">
|
||||
<Button HorizontalAlignment="Right"
|
||||
VerticalAlignment="Center"
|
||||
IsEnabled="{Binding CanClose}"
|
||||
Command="{Binding CloseCommand}">
|
||||
<TextBlock Text="{Binding CloseLabel}" />
|
||||
</Button>
|
||||
<Button HorizontalAlignment="Right" VerticalAlignment="Center" IsEnabled="{Binding CanStart}"
|
||||
<Button HorizontalAlignment="Right"
|
||||
VerticalAlignment="Center"
|
||||
IsEnabled="{Binding CanStart}"
|
||||
Command="{Binding StartCommand}">
|
||||
<TextBlock Text="{Binding StartLabel}" />
|
||||
</Button>
|
||||
|
||||
@@ -28,18 +28,17 @@ using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using RomRepoMgr.ViewModels;
|
||||
|
||||
namespace RomRepoMgr.Views
|
||||
namespace RomRepoMgr.Views;
|
||||
|
||||
public sealed class ImportDatFolder : Window
|
||||
{
|
||||
public sealed class ImportDatFolder : Window
|
||||
public ImportDatFolder() => InitializeComponent();
|
||||
|
||||
void InitializeComponent() => AvaloniaXamlLoader.Load(this);
|
||||
|
||||
protected override void OnOpened(EventArgs e)
|
||||
{
|
||||
public ImportDatFolder() => InitializeComponent();
|
||||
|
||||
void InitializeComponent() => AvaloniaXamlLoader.Load(this);
|
||||
|
||||
protected override void OnOpened(EventArgs e)
|
||||
{
|
||||
base.OnOpened(e);
|
||||
(DataContext as ImportDatFolderViewModel)?.OnOpened();
|
||||
}
|
||||
base.OnOpened(e);
|
||||
(DataContext as ImportDatFolderViewModel)?.OnOpened();
|
||||
}
|
||||
}
|
||||
@@ -24,12 +24,21 @@
|
||||
// Copyright © 2020-2024 Natalia Portillo
|
||||
// ****************************************************************************/
|
||||
-->
|
||||
<Window xmlns="https://github.com/avaloniaui" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
<Window xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:vm="clr-namespace:RomRepoMgr.ViewModels;assembly=RomRepoMgr" mc:Ignorable="d" d:DesignWidth="800"
|
||||
d:DesignHeight="450" Width="480" Height="360" x:Class="RomRepoMgr.Views.ImportRomFolder"
|
||||
Icon="/Assets/avalonia-logo.ico" CanResize="False" Title="{Binding Title}" WindowStartupLocation="CenterOwner">
|
||||
xmlns:vm="clr-namespace:RomRepoMgr.ViewModels;assembly=RomRepoMgr"
|
||||
mc:Ignorable="d"
|
||||
d:DesignWidth="800"
|
||||
d:DesignHeight="450"
|
||||
Width="480"
|
||||
Height="360"
|
||||
x:Class="RomRepoMgr.Views.ImportRomFolder"
|
||||
Icon="/Assets/avalonia-logo.ico"
|
||||
CanResize="False"
|
||||
Title="{Binding Title}"
|
||||
WindowStartupLocation="CenterOwner">
|
||||
<Design.DataContext>
|
||||
<vm:ImportRomFolderViewModel />
|
||||
</Design.DataContext>
|
||||
@@ -40,56 +49,87 @@
|
||||
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" /> <RowDefinition Height="*" /> <RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<StackPanel Grid.Row="0" Orientation="Horizontal" HorizontalAlignment="Stretch">
|
||||
<TextBlock Text="{Binding PathLabel}" FontWeight="Bold" /> <TextBlock Text="{Binding FolderPath}" />
|
||||
<StackPanel Grid.Row="0"
|
||||
Orientation="Horizontal"
|
||||
HorizontalAlignment="Stretch">
|
||||
<TextBlock Text="{Binding PathLabel}"
|
||||
FontWeight="Bold" />
|
||||
<TextBlock Text="{Binding FolderPath}" />
|
||||
</StackPanel>
|
||||
<CheckBox Grid.Row="1" IsChecked="{Binding RemoveFilesChecked}" IsEnabled="{Binding RemoveFilesEnabled}"
|
||||
<CheckBox Grid.Row="1"
|
||||
IsChecked="{Binding RemoveFilesChecked}"
|
||||
IsEnabled="{Binding RemoveFilesEnabled}"
|
||||
IsVisible="{Binding IsReady}">
|
||||
<CheckBox.Content>
|
||||
<TextBlock Text="{Binding RemoveFilesLabel}" />
|
||||
</CheckBox.Content>
|
||||
</CheckBox>
|
||||
<CheckBox Grid.Row="2" IsChecked="{Binding KnownOnlyChecked}" IsVisible="{Binding IsReady}">
|
||||
<CheckBox Grid.Row="2"
|
||||
IsChecked="{Binding KnownOnlyChecked}"
|
||||
IsVisible="{Binding IsReady}">
|
||||
<CheckBox.Content>
|
||||
<TextBlock Text="{Binding KnownOnlyLabel}" />
|
||||
</CheckBox.Content>
|
||||
</CheckBox>
|
||||
<CheckBox Grid.Row="3" IsChecked="{Binding RecurseArchivesChecked}"
|
||||
IsEnabled="{Binding RecurseArchivesEnabled}" IsVisible="{Binding IsReady}">
|
||||
<CheckBox Grid.Row="3"
|
||||
IsChecked="{Binding RecurseArchivesChecked}"
|
||||
IsEnabled="{Binding RecurseArchivesEnabled}"
|
||||
IsVisible="{Binding IsReady}">
|
||||
<CheckBox.Content>
|
||||
<TextBlock Text="{Binding RecurseArchivesLabel}" />
|
||||
</CheckBox.Content>
|
||||
</CheckBox>
|
||||
<TextBlock Grid.Row="4" Text="{Binding StatusMessage}" FontWeight="Bold" HorizontalAlignment="Center" />
|
||||
<ProgressBar Grid.Row="5" Minimum="{Binding ProgressMinimum}" Maximum="{Binding ProgressMaximum}"
|
||||
Value="{Binding ProgressValue}" IsIndeterminate="{Binding ProgressIsIndeterminate}"
|
||||
<TextBlock Grid.Row="4"
|
||||
Text="{Binding StatusMessage}"
|
||||
FontWeight="Bold"
|
||||
HorizontalAlignment="Center" />
|
||||
<ProgressBar Grid.Row="5"
|
||||
Minimum="{Binding ProgressMinimum}"
|
||||
Maximum="{Binding ProgressMaximum}"
|
||||
Value="{Binding ProgressValue}"
|
||||
IsIndeterminate="{Binding ProgressIsIndeterminate}"
|
||||
IsVisible="{Binding ProgressVisible}" />
|
||||
<StackPanel Grid.Row="6" IsVisible="{Binding Progress2Visible}">
|
||||
<StackPanel Grid.Row="6"
|
||||
IsVisible="{Binding Progress2Visible}">
|
||||
<TextBlock Text="{Binding Status2Message}" />
|
||||
<ProgressBar Minimum="{Binding Progress2Minimum}" Maximum="{Binding Progress2Maximum}"
|
||||
Value="{Binding Progress2Value}" IsIndeterminate="{Binding Progress2IsIndeterminate}" />
|
||||
<ProgressBar Minimum="{Binding Progress2Minimum}"
|
||||
Maximum="{Binding Progress2Maximum}"
|
||||
Value="{Binding Progress2Value}"
|
||||
IsIndeterminate="{Binding Progress2IsIndeterminate}" />
|
||||
</StackPanel>
|
||||
<DataGrid Grid.Row="7" Items="{Binding ImportResults}" HorizontalScrollBarVisibility="Visible"
|
||||
<DataGrid Grid.Row="7"
|
||||
Items="{Binding ImportResults}"
|
||||
HorizontalScrollBarVisibility="Visible"
|
||||
IsVisible="{Binding IsImporting}">
|
||||
<DataGrid.Columns>
|
||||
<DataGridTextColumn Binding="{Binding Filename}" Width="Auto" IsReadOnly="True">
|
||||
<DataGridTextColumn Binding="{Binding Filename}"
|
||||
Width="Auto"
|
||||
IsReadOnly="True">
|
||||
<DataGridTextColumn.Header>
|
||||
<TextBlock Text="{Binding ResultFilenameLabel}" />
|
||||
</DataGridTextColumn.Header>
|
||||
</DataGridTextColumn>
|
||||
<DataGridTextColumn Binding="{Binding Status}" Width="Auto" IsReadOnly="True">
|
||||
<DataGridTextColumn Binding="{Binding Status}"
|
||||
Width="Auto"
|
||||
IsReadOnly="True">
|
||||
<DataGridTextColumn.Header>
|
||||
<TextBlock Text="{Binding ResultStatusLabel}" />
|
||||
</DataGridTextColumn.Header>
|
||||
</DataGridTextColumn>
|
||||
</DataGrid.Columns>
|
||||
</DataGrid>
|
||||
<StackPanel Grid.Row="8" Orientation="Horizontal" HorizontalAlignment="Right">
|
||||
<Button HorizontalAlignment="Right" VerticalAlignment="Center" IsEnabled="{Binding CanClose}"
|
||||
<StackPanel Grid.Row="8"
|
||||
Orientation="Horizontal"
|
||||
HorizontalAlignment="Right">
|
||||
<Button HorizontalAlignment="Right"
|
||||
VerticalAlignment="Center"
|
||||
IsEnabled="{Binding CanClose}"
|
||||
Command="{Binding CloseCommand}">
|
||||
<TextBlock Text="{Binding CloseLabel}" />
|
||||
</Button>
|
||||
<Button HorizontalAlignment="Right" VerticalAlignment="Center" IsEnabled="{Binding CanStart}"
|
||||
<Button HorizontalAlignment="Right"
|
||||
VerticalAlignment="Center"
|
||||
IsEnabled="{Binding CanStart}"
|
||||
Command="{Binding StartCommand}">
|
||||
<TextBlock Text="{Binding StartLabel}" />
|
||||
</Button>
|
||||
|
||||
@@ -26,12 +26,11 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
|
||||
namespace RomRepoMgr.Views
|
||||
{
|
||||
public sealed class ImportRomFolder : Window
|
||||
{
|
||||
public ImportRomFolder() => InitializeComponent();
|
||||
namespace RomRepoMgr.Views;
|
||||
|
||||
void InitializeComponent() => AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
public sealed class ImportRomFolder : Window
|
||||
{
|
||||
public ImportRomFolder() => InitializeComponent();
|
||||
|
||||
void InitializeComponent() => AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
@@ -1,130 +1,183 @@
|
||||
<Window xmlns="https://github.com/avaloniaui" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
<Window xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:vm="clr-namespace:RomRepoMgr.ViewModels;assembly=RomRepoMgr"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" d:DesignWidth="800"
|
||||
d:DesignHeight="450" x:Class="RomRepoMgr.Views.MainWindow" Icon="/Assets/avalonia-logo.ico" Title="RomRepoMgr">
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d"
|
||||
d:DesignWidth="800"
|
||||
d:DesignHeight="450"
|
||||
x:Class="RomRepoMgr.Views.MainWindow"
|
||||
Icon="/Assets/avalonia-logo.ico"
|
||||
Title="RomRepoMgr">
|
||||
<Design.DataContext>
|
||||
<vm:MainWindowViewModel />
|
||||
</Design.DataContext>
|
||||
<DockPanel>
|
||||
<Menu DockPanel.Dock="Top">
|
||||
<MenuItem Header="{Binding FileMenuText}">
|
||||
<MenuItem Header="{Binding FileMenuImportDatFileText}" Command="{Binding ImportDatCommand}" />
|
||||
<MenuItem Header="{Binding FileMenuImportDatFileText}"
|
||||
Command="{Binding ImportDatCommand}" />
|
||||
<Separator />
|
||||
<MenuItem Header="{Binding FileMenuImportDatFolderText}" Command="{Binding ImportDatFolderCommand}" />
|
||||
<MenuItem Header="{Binding FileMenuImportDatFolderText}"
|
||||
Command="{Binding ImportDatFolderCommand}" />
|
||||
<Separator />
|
||||
<MenuItem Header="{Binding FileMenuSettingsText}" IsVisible="{Binding !NativeMenuSupported}"
|
||||
<MenuItem Header="{Binding FileMenuSettingsText}"
|
||||
IsVisible="{Binding !NativeMenuSupported}"
|
||||
Command="{Binding SettingsCommand}" />
|
||||
<Separator />
|
||||
<MenuItem Header="{Binding FileMenuExitText}" IsVisible="{Binding !NativeMenuSupported}"
|
||||
<MenuItem Header="{Binding FileMenuExitText}"
|
||||
IsVisible="{Binding !NativeMenuSupported}"
|
||||
Command="{Binding ExitCommand}" />
|
||||
</MenuItem>
|
||||
<MenuItem Header="{Binding FilesystemMenuText}" IsEnabled="{Binding IsVfsAvailable}">
|
||||
<MenuItem Header="{Binding FilesystemMenuMountText}" Command="{Binding MountCommand}"
|
||||
<MenuItem Header="{Binding FilesystemMenuText}"
|
||||
IsEnabled="{Binding IsVfsAvailable}">
|
||||
<MenuItem Header="{Binding FilesystemMenuMountText}"
|
||||
Command="{Binding MountCommand}"
|
||||
IsEnabled="{Binding Vfs, Converter={x:Static ObjectConverters.IsNull}}" />
|
||||
<Separator />
|
||||
<MenuItem Header="{Binding FilesystemMenuUmountText}" Command="{Binding UmountCommand}"
|
||||
<MenuItem Header="{Binding FilesystemMenuUmountText}"
|
||||
Command="{Binding UmountCommand}"
|
||||
IsEnabled="{Binding Vfs, Converter={x:Static ObjectConverters.IsNotNull}}" />
|
||||
<Separator />
|
||||
</MenuItem>
|
||||
<MenuItem Header="{Binding RomsMenuText}">
|
||||
<MenuItem Header="{Binding RomsMenuImportText}" Command="{Binding ImportRomFolderCommand}" />
|
||||
<MenuItem Header="{Binding RomsMenuImportText}"
|
||||
Command="{Binding ImportRomFolderCommand}" />
|
||||
<Separator />
|
||||
</MenuItem>
|
||||
<MenuItem Header="{Binding RomSetsMenuText}"
|
||||
IsEnabled="{Binding SelectedRomSet, Converter={x:Static ObjectConverters.IsNotNull}}">
|
||||
<MenuItem Header="{Binding RomSetsMenuSaveRomsText}" Command="{Binding ExportRomsCommand}" />
|
||||
<MenuItem Header="{Binding RomSetsMenuSaveRomsText}"
|
||||
Command="{Binding ExportRomsCommand}" />
|
||||
<Separator />
|
||||
<MenuItem Header="{Binding RomSetsMenuSaveDatText}" Command="{Binding ExportDatCommand}" />
|
||||
<Separator /> <MenuItem Header="{Binding RomSetsMenuEditText}" Command="{Binding EditRomSetCommand}" />
|
||||
<MenuItem Header="{Binding RomSetsMenuSaveDatText}"
|
||||
Command="{Binding ExportDatCommand}" />
|
||||
<Separator />
|
||||
<MenuItem Header="{Binding RomSetsMenuDeleteText}" Command="{Binding DeleteRomSetCommand}" />
|
||||
<MenuItem Header="{Binding RomSetsMenuEditText}"
|
||||
Command="{Binding EditRomSetCommand}" />
|
||||
<Separator />
|
||||
<MenuItem Header="{Binding RomSetsMenuDeleteText}"
|
||||
Command="{Binding DeleteRomSetCommand}" />
|
||||
<Separator />
|
||||
</MenuItem>
|
||||
<MenuItem Header="{Binding DatabaseMenuText}">
|
||||
<MenuItem Header="{Binding DatabaseMenuUpdateStatsText}" Command="{Binding UpdateStatsCommand}" />
|
||||
<MenuItem Header="{Binding DatabaseMenuUpdateStatsText}"
|
||||
Command="{Binding UpdateStatsCommand}" />
|
||||
<Separator />
|
||||
</MenuItem>
|
||||
<MenuItem Header="{Binding HelpMenuText}">
|
||||
<MenuItem Header="{Binding HelpMenuAboutText}" Name="AboutMenuItem"
|
||||
IsVisible="{Binding !NativeMenuSupported}" Command="{Binding AboutCommand}" />
|
||||
<MenuItem Header="{Binding HelpMenuAboutText}"
|
||||
Name="AboutMenuItem"
|
||||
IsVisible="{Binding !NativeMenuSupported}"
|
||||
Command="{Binding AboutCommand}" />
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
<TabControl HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
|
||||
<TabControl HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch">
|
||||
<TabItem>
|
||||
<TabItem.Header>
|
||||
<TextBlock Text="{Binding RomSetLabel}" />
|
||||
</TabItem.Header>
|
||||
<DataGrid Items="{Binding RomSets}" HorizontalScrollBarVisibility="Visible"
|
||||
SelectedItem="{Binding SelectedRomSet, Mode=TwoWay}" CanUserSortColumns="True"
|
||||
<DataGrid Items="{Binding RomSets}"
|
||||
HorizontalScrollBarVisibility="Visible"
|
||||
SelectedItem="{Binding SelectedRomSet, Mode=TwoWay}"
|
||||
CanUserSortColumns="True"
|
||||
CanUserResizeColumns="True">
|
||||
<DataGrid.Columns>
|
||||
<DataGridTextColumn Binding="{Binding Name}" Width="Auto" IsReadOnly="True">
|
||||
<DataGridTextColumn Binding="{Binding Name}"
|
||||
Width="Auto"
|
||||
IsReadOnly="True">
|
||||
<DataGridTextColumn.Header>
|
||||
<TextBlock Text="{Binding RomSetNameLabel}" />
|
||||
</DataGridTextColumn.Header>
|
||||
</DataGridTextColumn>
|
||||
<DataGridTextColumn Binding="{Binding Version}" Width="Auto" IsReadOnly="True">
|
||||
<DataGridTextColumn Binding="{Binding Version}"
|
||||
Width="Auto"
|
||||
IsReadOnly="True">
|
||||
<DataGridTextColumn.Header>
|
||||
<TextBlock Text="{Binding RomSetVersionLabel}" />
|
||||
</DataGridTextColumn.Header>
|
||||
</DataGridTextColumn>
|
||||
<DataGridTextColumn Binding="{Binding Author}" Width="Auto" IsReadOnly="True">
|
||||
<DataGridTextColumn Binding="{Binding Author}"
|
||||
Width="Auto"
|
||||
IsReadOnly="True">
|
||||
<DataGridTextColumn.Header>
|
||||
<TextBlock Text="{Binding RomSetAuthorLabel}" />
|
||||
</DataGridTextColumn.Header>
|
||||
</DataGridTextColumn>
|
||||
<DataGridTextColumn Binding="{Binding Category}" Width="Auto" IsReadOnly="True">
|
||||
<DataGridTextColumn Binding="{Binding Category}"
|
||||
Width="Auto"
|
||||
IsReadOnly="True">
|
||||
<DataGridTextColumn.Header>
|
||||
<TextBlock Text="{Binding RomSetCategoryLabel}" />
|
||||
</DataGridTextColumn.Header>
|
||||
</DataGridTextColumn>
|
||||
<DataGridTextColumn Binding="{Binding Date}" Width="Auto" IsReadOnly="True">
|
||||
<DataGridTextColumn Binding="{Binding Date}"
|
||||
Width="Auto"
|
||||
IsReadOnly="True">
|
||||
<DataGridTextColumn.Header>
|
||||
<TextBlock Text="{Binding RomSetDateLabel}" />
|
||||
</DataGridTextColumn.Header>
|
||||
</DataGridTextColumn>
|
||||
<DataGridTextColumn Binding="{Binding Description}" Width="Auto" IsReadOnly="True">
|
||||
<DataGridTextColumn Binding="{Binding Description}"
|
||||
Width="Auto"
|
||||
IsReadOnly="True">
|
||||
<DataGridTextColumn.Header>
|
||||
<TextBlock Text="{Binding RomSetDescriptionLabel}" />
|
||||
</DataGridTextColumn.Header>
|
||||
</DataGridTextColumn>
|
||||
<DataGridTextColumn Binding="{Binding Comment}" Width="Auto" IsReadOnly="True">
|
||||
<DataGridTextColumn Binding="{Binding Comment}"
|
||||
Width="Auto"
|
||||
IsReadOnly="True">
|
||||
<DataGridTextColumn.Header>
|
||||
<TextBlock Text="{Binding RomSetCommentLabel}" />
|
||||
</DataGridTextColumn.Header>
|
||||
</DataGridTextColumn>
|
||||
<DataGridTextColumn Binding="{Binding Homepage}" Width="Auto" IsReadOnly="True">
|
||||
<DataGridTextColumn Binding="{Binding Homepage}"
|
||||
Width="Auto"
|
||||
IsReadOnly="True">
|
||||
<DataGridTextColumn.Header>
|
||||
<TextBlock Text="{Binding RomSetHomepageLabel}" />
|
||||
</DataGridTextColumn.Header>
|
||||
</DataGridTextColumn>
|
||||
<DataGridTextColumn Binding="{Binding TotalMachines}" Width="Auto" IsReadOnly="True">
|
||||
<DataGridTextColumn Binding="{Binding TotalMachines}"
|
||||
Width="Auto"
|
||||
IsReadOnly="True">
|
||||
<DataGridTextColumn.Header>
|
||||
<TextBlock Text="{Binding RomSetTotalMachinesLabel}" />
|
||||
</DataGridTextColumn.Header>
|
||||
</DataGridTextColumn>
|
||||
<DataGridTextColumn Binding="{Binding CompleteMachines}" Width="Auto" IsReadOnly="True">
|
||||
<DataGridTextColumn Binding="{Binding CompleteMachines}"
|
||||
Width="Auto"
|
||||
IsReadOnly="True">
|
||||
<DataGridTextColumn.Header>
|
||||
<TextBlock Text="{Binding RomSetCompleteMachinesLabel}" />
|
||||
</DataGridTextColumn.Header>
|
||||
</DataGridTextColumn>
|
||||
<DataGridTextColumn Binding="{Binding IncompleteMachines}" Width="Auto" IsReadOnly="True">
|
||||
<DataGridTextColumn Binding="{Binding IncompleteMachines}"
|
||||
Width="Auto"
|
||||
IsReadOnly="True">
|
||||
<DataGridTextColumn.Header>
|
||||
<TextBlock Text="{Binding RomSetIncompleteMachinesLabel}" />
|
||||
</DataGridTextColumn.Header>
|
||||
</DataGridTextColumn>
|
||||
<DataGridTextColumn Binding="{Binding TotalRoms}" Width="Auto" IsReadOnly="True">
|
||||
<DataGridTextColumn Binding="{Binding TotalRoms}"
|
||||
Width="Auto"
|
||||
IsReadOnly="True">
|
||||
<DataGridTextColumn.Header>
|
||||
<TextBlock Text="{Binding RomSetTotalRomsLabel}" />
|
||||
</DataGridTextColumn.Header>
|
||||
</DataGridTextColumn>
|
||||
<DataGridTextColumn Binding="{Binding HaveRoms}" Width="Auto" IsReadOnly="True">
|
||||
<DataGridTextColumn Binding="{Binding HaveRoms}"
|
||||
Width="Auto"
|
||||
IsReadOnly="True">
|
||||
<DataGridTextColumn.Header>
|
||||
<TextBlock Text="{Binding RomSetHaveRomsLabel}" />
|
||||
</DataGridTextColumn.Header>
|
||||
</DataGridTextColumn>
|
||||
<DataGridTextColumn Binding="{Binding MissRoms}" Width="Auto" IsReadOnly="True">
|
||||
<DataGridTextColumn Binding="{Binding MissRoms}"
|
||||
Width="Auto"
|
||||
IsReadOnly="True">
|
||||
<DataGridTextColumn.Header>
|
||||
<TextBlock Text="{Binding RomSetMissRomsLabel}" />
|
||||
</DataGridTextColumn.Header>
|
||||
|
||||
@@ -27,18 +27,17 @@ using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
|
||||
namespace RomRepoMgr.Views
|
||||
{
|
||||
public class MainWindow : Window
|
||||
{
|
||||
public MainWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
#if DEBUG
|
||||
this.AttachDevTools();
|
||||
#endif
|
||||
}
|
||||
namespace RomRepoMgr.Views;
|
||||
|
||||
void InitializeComponent() => AvaloniaXamlLoader.Load(this);
|
||||
public class MainWindow : Window
|
||||
{
|
||||
public MainWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
#if DEBUG
|
||||
this.AttachDevTools();
|
||||
#endif
|
||||
}
|
||||
|
||||
void InitializeComponent() => AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
@@ -24,12 +24,21 @@
|
||||
// Copyright © 2020-2024 Natalia Portillo
|
||||
// ****************************************************************************/
|
||||
-->
|
||||
<Window xmlns="https://github.com/avaloniaui" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
<Window xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:vm="clr-namespace:RomRepoMgr.ViewModels;assembly=RomRepoMgr" mc:Ignorable="d" d:DesignWidth="800"
|
||||
d:DesignHeight="450" Width="480" Height="90" x:Class="RomRepoMgr.Views.RemoveDat"
|
||||
Icon="/Assets/avalonia-logo.ico" CanResize="False" Title="{Binding Title}" WindowStartupLocation="CenterOwner">
|
||||
xmlns:vm="clr-namespace:RomRepoMgr.ViewModels;assembly=RomRepoMgr"
|
||||
mc:Ignorable="d"
|
||||
d:DesignWidth="800"
|
||||
d:DesignHeight="450"
|
||||
Width="480"
|
||||
Height="90"
|
||||
x:Class="RomRepoMgr.Views.RemoveDat"
|
||||
Icon="/Assets/avalonia-logo.ico"
|
||||
CanResize="False"
|
||||
Title="{Binding Title}"
|
||||
WindowStartupLocation="CenterOwner">
|
||||
<Design.DataContext>
|
||||
<vm:RemoveDatViewModel />
|
||||
</Design.DataContext>
|
||||
@@ -38,8 +47,12 @@
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" /> <RowDefinition Height="auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<TextBlock Grid.Row="0" Text="{Binding StatusMessage}" HorizontalAlignment="Center" />
|
||||
<ProgressBar Grid.Row="1" IsIndeterminate="True" HorizontalAlignment="Stretch" />
|
||||
<TextBlock Grid.Row="0"
|
||||
Text="{Binding StatusMessage}"
|
||||
HorizontalAlignment="Center" />
|
||||
<ProgressBar Grid.Row="1"
|
||||
IsIndeterminate="True"
|
||||
HorizontalAlignment="Stretch" />
|
||||
</Grid>
|
||||
</Border>
|
||||
</Window>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user