Compare commits

...

23 Commits
2.7.0 ... 2.7.1

Author SHA1 Message Date
Matt Nadareski
367d0c104b Bump version 2023-10-11 13:48:32 -04:00
Matt Nadareski
5d4bed2d9e Remove unnecessary namespacing 2023-10-11 13:41:42 -04:00
Matt Nadareski
63756192d8 Enable path browse button by default 2023-10-11 13:13:36 -04:00
Matt Nadareski
b68ec78184 Version-gate some more newer syntax 2023-10-11 13:07:45 -04:00
Matt Nadareski
c55d5183fb Fix Check always showing Help text 2023-10-11 12:54:40 -04:00
Matt Nadareski
f82e925944 Version-gate some newer syntax 2023-10-11 12:37:31 -04:00
Matt Nadareski
c19f9ea173 Var-ify many instances 2023-10-11 12:29:06 -04:00
Matt Nadareski
76b2dd79ab Handle some suggested changes 2023-10-11 12:26:24 -04:00
Matt Nadareski
c96ff23ad1 Update changelog 2023-10-11 12:14:56 -04:00
Matt Nadareski
cd68b55b93 Enable nullability in MPF.Test 2023-10-11 12:14:42 -04:00
Matt Nadareski
cad14d96f7 Enable nullability in MPF.UI.Core 2023-10-11 11:49:56 -04:00
Matt Nadareski
daaf9f1932 Enable nullability in MPF 2023-10-11 11:16:34 -04:00
Matt Nadareski
cb7502b450 Update changelog 2023-10-11 10:34:00 -04:00
Deterous
ece142bbf1 Place message boxes at center of main window (#574) 2023-10-11 07:33:26 -07:00
Matt Nadareski
611fee4605 Remove all but .NET 6 for AppVeyor packaging (fixes #573) 2023-10-10 23:44:30 -04:00
Matt Nadareski
791e2d0272 Enable nullability in Check 2023-10-10 23:22:21 -04:00
Matt Nadareski
81742a4676 Unify handling of enable/disable events 2023-10-10 22:05:39 -04:00
Matt Nadareski
1ff3f2210c Handle numeric disc titles as issue numbers (fixes #543) 2023-10-10 21:55:51 -04:00
Matt Nadareski
be9e4b91d5 Add generic drive flag for Redumper (fixes #546) 2023-10-10 21:45:17 -04:00
Matt Nadareski
854dcc5f95 Add BE read flag for Redumper (fixes #545) 2023-10-10 21:42:16 -04:00
Matt Nadareski
29b71db33a Allow user-supplied information in Check (fixes #572) 2023-10-10 21:27:36 -04:00
Matt Nadareski
2ee64b222a Fix errant version detection issue 2023-10-10 20:56:53 -04:00
Matt Nadareski
afda54f97b Add pull-all flag for Check (fixes #571) 2023-10-10 20:51:39 -04:00
39 changed files with 1144 additions and 369 deletions

View File

@@ -1,3 +1,26 @@
### 2.7.1 (2023-10-11)
- Add pull-all flag for Check
- Fix errant version detection issue
- Allow user-supplied information in Check
- Add BE read flag for Redumper
- Add generic drive flag for Redumper
- Handle numeric disc titles as issue numbers
- Unify handling of enable/disable events
- Enable nullability in Check
- Remove all but .NET 6 for AppVeyor packaging
- Place message boxes at center of main window (Deterous)
- Enable nullability in MPF
- Enable nullability in MPF.UI.Core
- Enable nullability in MPF.Test
- Handle some suggested changes
- Var-ify many instances
- Version-gate some newer syntax
- Fix Check always showing Help text
- Version-gate some more newer syntax
- Enable path browse button by default
- Remove unnecessary namespacing
### 2.7.0 (2023-10-11)
- Attempt to replace NRT

View File

@@ -8,7 +8,11 @@
<Description>Validator for various dumping programs</Description>
<Authors>Matt Nadareski;ReignStumble;Jakz</Authors>
<Copyright>Copyright (c)2019-2023</Copyright>
<VersionPrefix>2.7.0</VersionPrefix>
<VersionPrefix>2.7.1</VersionPrefix>
</PropertyGroup>
<PropertyGroup Condition="'$(TargetFramework)'!='net48'">
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>

View File

@@ -14,14 +14,16 @@ namespace MPF.Check
public static void Main(string[] args)
{
// Try processing the standalone arguments
if (!OptionsLoader.ProcessStandaloneArguments(args))
bool? standaloneProcessed = OptionsLoader.ProcessStandaloneArguments(args);
if (standaloneProcessed != false)
{
DisplayHelp();
if (standaloneProcessed == null)
DisplayHelp();
return;
}
// Try processing the common arguments
(bool success, MediaType mediaType, RedumpSystem? knownSystem, string error) = OptionsLoader.ProcessCommonArguments(args);
(bool success, MediaType mediaType, RedumpSystem? knownSystem, var error) = OptionsLoader.ProcessCommonArguments(args);
if (!success)
{
DisplayHelp(error);
@@ -29,7 +31,7 @@ namespace MPF.Check
}
// Loop through and process options
(Core.Data.Options options, string path, int startIndex) = OptionsLoader.LoadFromArguments(args, startIndex: 2);
(var options, var seedInfo, var path, int startIndex) = OptionsLoader.LoadFromArguments(args, startIndex: 2);
if (options.InternalProgram == InternalProgram.NONE)
{
DisplayHelp("A program name needs to be provided");
@@ -46,7 +48,7 @@ namespace MPF.Check
#if NET48
(bool? _, string message) = RedumpWebClient.ValidateCredentials(options?.RedumpUsername, options?.RedumpPassword);
#else
(bool? _, string message) = RedumpHttpClient.ValidateCredentials(options?.RedumpUsername, options?.RedumpPassword).ConfigureAwait(false).GetAwaiter().GetResult();
(bool? _, string? message) = RedumpHttpClient.ValidateCredentials(options.RedumpUsername ?? string.Empty, options.RedumpPassword ?? string.Empty).ConfigureAwait(false).GetAwaiter().GetResult();
#endif
if (!string.IsNullOrWhiteSpace(message))
Console.WriteLine(message);
@@ -65,7 +67,11 @@ namespace MPF.Check
string filepath = Path.GetFullPath(args[i].Trim('"'));
// Now populate an environment
#if NET48
Drive drive = null;
#else
Drive? drive = null;
#endif
if (!string.IsNullOrWhiteSpace(path))
drive = Drive.Create(null, path);
@@ -81,7 +87,11 @@ namespace MPF.Check
/// Display help for MPF.Check
/// </summary>
/// <param name="error">Error string to prefix the help text with</param>
#if NET48
private static void DisplayHelp(string error = null)
#else
private static void DisplayHelp(string? error = null)
#endif
{
if (error != null)
Console.WriteLine(error);

View File

@@ -9,7 +9,11 @@ namespace MPF.Core
/// <summary>
/// Simple process counter to write to console
/// </summary>
#if NET48
public static void ProgressUpdated(object sender, Result value)
#else
public static void ProgressUpdated(object? sender, Result value)
#endif
{
Console.WriteLine(value.Message);
}
@@ -17,7 +21,11 @@ namespace MPF.Core
/// <summary>
/// Simple process counter to write to console
/// </summary>
#if NET48
public static void ProgressUpdated(object sender, ProtectionProgress value)
#else
public static void ProgressUpdated(object? sender, ProtectionProgress value)
#endif
{
Console.WriteLine($"{value.Percentage * 100:N2}%: {value.Filename} - {value.Protection}");
}

View File

@@ -4,11 +4,7 @@ using SabreTools.RedumpLib.Data;
namespace MPF.Core.Data
{
#if NET48
public class Options
#else
public class Options
#endif
{
/// <summary>
/// All settings in the form of a dictionary
@@ -340,6 +336,24 @@ namespace MPF.Core.Data
set { Settings["RedumperEnableVerbose"] = value.ToString(); }
}
/// <summary>
/// Enable BE reading by default with Redumper
/// </summary>
public bool RedumperUseBEReading
{
get { return GetBooleanSetting(Settings, "RedumperUseBEReading", false); }
set { Settings["RedumperUseBEReading"] = value.ToString(); }
}
/// <summary>
/// Enable generic drive type by default with Redumper
/// </summary>
public bool RedumperUseGenericDriveType
{
get { return GetBooleanSetting(Settings, "RedumperUseGenericDriveType", false); }
set { Settings["RedumperUseGenericDriveType"] = value.ToString(); }
}
/// <summary>
/// Default number of rereads
/// </summary>
@@ -610,12 +624,16 @@ namespace MPF.Core.Data
/// Constructor taking an existing Options object
/// </summary>
/// <param name="source"></param>
#if NET48
public Options(Options source)
#else
public Options(Options? source)
#endif
{
#if NET48
Settings = new Dictionary<string, string>(source.Settings);
Settings = new Dictionary<string, string>(source?.Settings ?? new Dictionary<string, string>());
#else
Settings = new Dictionary<string, string?>(source.Settings);
Settings = new Dictionary<string, string?>(source?.Settings ?? new Dictionary<string, string?>());
#endif
}
@@ -642,9 +660,9 @@ namespace MPF.Core.Data
/// <param name="defaultValue">Default value to return if no value is found</param>
/// <returns>Setting value if possible, default value otherwise</returns>
#if NET48
private bool GetBooleanSetting(Dictionary<string, string> settings, string key, bool defaultValue)
private static bool GetBooleanSetting(Dictionary<string, string> settings, string key, bool defaultValue)
#else
private bool GetBooleanSetting(Dictionary<string, string?> settings, string key, bool defaultValue)
private static bool GetBooleanSetting(Dictionary<string, string?> settings, string key, bool defaultValue)
#endif
{
if (settings.ContainsKey(key))
@@ -668,9 +686,9 @@ namespace MPF.Core.Data
/// <param name="defaultValue">Default value to return if no value is found</param>
/// <returns>Setting value if possible, default value otherwise</returns>
#if NET48
private int GetInt32Setting(Dictionary<string, string> settings, string key, int defaultValue)
private static int GetInt32Setting(Dictionary<string, string> settings, string key, int defaultValue)
#else
private int GetInt32Setting(Dictionary<string, string?> settings, string key, int defaultValue)
private static int GetInt32Setting(Dictionary<string, string?> settings, string key, int defaultValue)
#endif
{
if (settings.ContainsKey(key))
@@ -694,9 +712,9 @@ namespace MPF.Core.Data
/// <param name="defaultValue">Default value to return if no value is found</param>
/// <returns>Setting value if possible, default value otherwise</returns>
#if NET48
private string GetStringSetting(Dictionary<string, string> settings, string key, string defaultValue)
private static string GetStringSetting(Dictionary<string, string> settings, string key, string defaultValue)
#else
private string? GetStringSetting(Dictionary<string, string?> settings, string key, string? defaultValue)
private static string? GetStringSetting(Dictionary<string, string?> settings, string key, string? defaultValue)
#endif
{
if (settings.ContainsKey(key))

View File

@@ -123,7 +123,11 @@ namespace MPF.Core
RedumpSystem? system,
MediaType? type,
InternalProgram? internalProgram,
#if NET48
string parameters)
#else
string? parameters)
#endif
{
// Set options object
this.Options = options;
@@ -194,7 +198,11 @@ namespace MPF.Core
/// Set the parameters object based on the internal program and parameters string
/// </summary>
/// <param name="parameters">String representation of the parameters</param>
#if NET48
public void SetParameters(string parameters)
#else
public void SetParameters(string? parameters)
#endif
{
switch (this.InternalProgram)
{
@@ -284,7 +292,7 @@ namespace MPF.Core
return null;
}
#endregion
#endregion
#region Dumping
@@ -371,16 +379,19 @@ namespace MPF.Core
/// <param name="resultProgress">Optional result progress callback</param>
/// <param name="protectionProgress">Optional protection progress callback</param>
/// <param name="processUserInfo">Optional user prompt to deal with submission information</param>
/// <param name="seedInfo">A seed SubmissionInfo object that contains user data</param>
/// <returns>Result instance with the outcome</returns>
public async Task<Result> VerifyAndSaveDumpOutput(
#if NET48
IProgress<Result> resultProgress = null,
IProgress<ProtectionProgress> protectionProgress = null,
Func<SubmissionInfo, (bool?, SubmissionInfo)> processUserInfo = null)
Func<SubmissionInfo, (bool?, SubmissionInfo)> processUserInfo = null,
SubmissionInfo seedInfo = null)
#else
IProgress<Result>? resultProgress = null,
IProgress<ProtectionProgress>? protectionProgress = null,
Func<SubmissionInfo?, (bool?, SubmissionInfo?)>? processUserInfo = null)
Func<SubmissionInfo?, (bool?, SubmissionInfo?)>? processUserInfo = null,
SubmissionInfo? seedInfo = null)
#endif
{
resultProgress?.Report(Result.Success("Gathering submission information... please wait!"));
@@ -410,6 +421,14 @@ namespace MPF.Core
protectionProgress);
resultProgress?.Report(Result.Success("Extracting information complete!"));
// Inject seed submission info data, if necessary
if (seedInfo != null)
{
resultProgress?.Report(Result.Success("Injecting user-supplied information..."));
InjectSubmissionInformation(submissionInfo, seedInfo);
resultProgress?.Report(Result.Success("Information injection complete!"));
}
// Eject the disc automatically if configured to
if (Options.EjectAfterDump == true)
{
@@ -559,6 +578,82 @@ namespace MPF.Core
return output;
}
/// <summary>
/// Inject information from a seed SubmissionInfo into the existing one
/// </summary>
/// <param name="info">Existing submission information</param>
/// <param name="seed">User-supplied submission information</param>
#if NET48
private void InjectSubmissionInformation(SubmissionInfo info, SubmissionInfo seed)
#else
private void InjectSubmissionInformation(SubmissionInfo? info, SubmissionInfo? seed)
#endif
{
// If we have any invalid info
if (info == null || seed == null)
return;
// Otherwise, inject information as necessary
if (seed.CommonDiscInfo != null)
{
if (info.CommonDiscInfo == null) info.CommonDiscInfo = new CommonDiscInfoSection();
// Info that only overwrites if supplied
if (!string.IsNullOrWhiteSpace(seed.CommonDiscInfo.Title)) info.CommonDiscInfo.Title = seed.CommonDiscInfo.Title;
if (!string.IsNullOrWhiteSpace(seed.CommonDiscInfo.ForeignTitleNonLatin)) info.CommonDiscInfo.ForeignTitleNonLatin = seed.CommonDiscInfo.ForeignTitleNonLatin;
if (!string.IsNullOrWhiteSpace(seed.CommonDiscInfo.DiscNumberLetter)) info.CommonDiscInfo.DiscNumberLetter = seed.CommonDiscInfo.DiscNumberLetter;
if (!string.IsNullOrWhiteSpace(seed.CommonDiscInfo.DiscTitle)) info.CommonDiscInfo.DiscTitle = seed.CommonDiscInfo.DiscTitle;
if (seed.CommonDiscInfo.Category != null) info.CommonDiscInfo.Category = seed.CommonDiscInfo.Category;
if (seed.CommonDiscInfo.Region != null) info.CommonDiscInfo.Region = seed.CommonDiscInfo.Region;
if (seed.CommonDiscInfo.Languages != null) info.CommonDiscInfo.Languages = seed.CommonDiscInfo.Languages;
if (seed.CommonDiscInfo.LanguageSelection != null) info.CommonDiscInfo.LanguageSelection = seed.CommonDiscInfo.LanguageSelection;
if (seed.CommonDiscInfo.Serial != null) info.CommonDiscInfo.Serial = seed.CommonDiscInfo.Serial;
if (!string.IsNullOrWhiteSpace(seed.CommonDiscInfo.Barcode)) info.CommonDiscInfo.Barcode = seed.CommonDiscInfo.Barcode;
if (!string.IsNullOrWhiteSpace(seed.CommonDiscInfo.Comments)) info.CommonDiscInfo.Comments = seed.CommonDiscInfo.Comments;
if (seed.CommonDiscInfo.CommentsSpecialFields != null) info.CommonDiscInfo.CommentsSpecialFields = seed.CommonDiscInfo.CommentsSpecialFields;
if (!string.IsNullOrWhiteSpace(seed.CommonDiscInfo.Contents)) info.CommonDiscInfo.Contents = seed.CommonDiscInfo.Contents;
if (seed.CommonDiscInfo.ContentsSpecialFields != null) info.CommonDiscInfo.ContentsSpecialFields = seed.CommonDiscInfo.ContentsSpecialFields;
// Info that always overwrites
info.CommonDiscInfo.Layer0MasteringRing = seed.CommonDiscInfo.Layer0MasteringRing;
info.CommonDiscInfo.Layer0MasteringSID = seed.CommonDiscInfo.Layer0MasteringSID;
info.CommonDiscInfo.Layer0ToolstampMasteringCode = seed.CommonDiscInfo.Layer0ToolstampMasteringCode;
info.CommonDiscInfo.Layer0MouldSID = seed.CommonDiscInfo.Layer0MouldSID;
info.CommonDiscInfo.Layer0AdditionalMould = seed.CommonDiscInfo.Layer0AdditionalMould;
info.CommonDiscInfo.Layer1MasteringRing = seed.CommonDiscInfo.Layer1MasteringRing;
info.CommonDiscInfo.Layer1MasteringSID = seed.CommonDiscInfo.Layer1MasteringSID;
info.CommonDiscInfo.Layer1ToolstampMasteringCode = seed.CommonDiscInfo.Layer1ToolstampMasteringCode;
info.CommonDiscInfo.Layer1MouldSID = seed.CommonDiscInfo.Layer1MouldSID;
info.CommonDiscInfo.Layer1AdditionalMould = seed.CommonDiscInfo.Layer1AdditionalMould;
info.CommonDiscInfo.Layer2MasteringRing = seed.CommonDiscInfo.Layer2MasteringRing;
info.CommonDiscInfo.Layer2MasteringSID = seed.CommonDiscInfo.Layer2MasteringSID;
info.CommonDiscInfo.Layer2ToolstampMasteringCode = seed.CommonDiscInfo.Layer2ToolstampMasteringCode;
info.CommonDiscInfo.Layer3MasteringRing = seed.CommonDiscInfo.Layer3MasteringRing;
info.CommonDiscInfo.Layer3MasteringSID = seed.CommonDiscInfo.Layer3MasteringSID;
info.CommonDiscInfo.Layer3ToolstampMasteringCode = seed.CommonDiscInfo.Layer3ToolstampMasteringCode;
}
if (seed.VersionAndEditions != null)
{
if (info.VersionAndEditions == null) info.VersionAndEditions = new VersionAndEditionsSection();
// Info that only overwrites if supplied
if (!string.IsNullOrWhiteSpace(seed.VersionAndEditions.Version)) info.VersionAndEditions.Version = seed.VersionAndEditions.Version;
if (!string.IsNullOrWhiteSpace(seed.VersionAndEditions.OtherEditions)) info.VersionAndEditions.OtherEditions = seed.VersionAndEditions.OtherEditions;
}
if (seed.CopyProtection != null)
{
if (info.CopyProtection == null) info.CopyProtection = new CopyProtectionSection();
// Info that only overwrites if supplied
if (!string.IsNullOrWhiteSpace(seed.CopyProtection.Protection)) info.CopyProtection.Protection = seed.CopyProtection.Protection;
}
}
/// <summary>
/// Validate the current environment is ready for a dump
/// </summary>

View File

@@ -23,6 +23,39 @@ namespace MPF.Core
{
#region Information Extraction
/// <summary>
/// Create a SubmissionInfo from a JSON file path
/// </summary>
/// <param name="path">Path to the SubmissionInfo JSON</param>
/// <returns>Filled SubmissionInfo on success, null on error</returns>
#if NET48
public static SubmissionInfo CreateFromFile(string path)
#else
public static SubmissionInfo? CreateFromFile(string? path)
#endif
{
// If the path is invalid
if (string.IsNullOrWhiteSpace(path))
return null;
// If the file doesn't exist
if (!File.Exists(path))
return null;
// Try to open and deserialize the file
try
{
byte[] data = File.ReadAllBytes(path);
string dataString = Encoding.UTF8.GetString(data);
return JsonConvert.DeserializeObject<SubmissionInfo>(dataString);
}
catch
{
// We don't care what the exception was
return null;
}
}
/// <summary>
/// Extract all of the possible information from a given input combination
/// </summary>
@@ -2163,6 +2196,10 @@ namespace MPF.Core
if (subMatchValue.StartsWith("Disc"))
info.CommonDiscInfo.DiscNumberLetter = subMatchValue.Remove(0, "Disc ".Length);
// Issue number
else if (subMatchValue.All(c => char.IsNumber(c)))
info.CommonDiscInfo.Title += $" ({subMatchValue})";
// Disc title
else
info.CommonDiscInfo.DiscTitle = subMatchValue;

View File

@@ -5,7 +5,7 @@
<RuntimeIdentifiers>win-x64;linux-x64;osx-x64</RuntimeIdentifiers>
<Authors>Matt Nadareski;ReignStumble;Jakz</Authors>
<Copyright>Copyright (c)2019-2023</Copyright>
<VersionPrefix>2.7.0</VersionPrefix>
<VersionPrefix>2.7.1</VersionPrefix>
</PropertyGroup>
<PropertyGroup Condition="'$(TargetFramework)'!='net48'">

View File

@@ -256,7 +256,11 @@ namespace MPF.Core.Modules.Aaru
#endregion
/// <inheritdoc/>
#if NET48
public Parameters(string parameters) : base(parameters) { }
#else
public Parameters(string? parameters) : base(parameters) { }
#endif
/// <inheritdoc/>
public Parameters(RedumpSystem? system, MediaType? type, char driveLetter, string filename, int? driveSpeed, Options options)
@@ -1814,7 +1818,11 @@ namespace MPF.Core.Modules.Aaru
}
/// <inheritdoc/>
#if NET48
protected override bool ValidateAndSetParameters(string parameters)
#else
protected override bool ValidateAndSetParameters(string? parameters)
#endif
{
BaseCommand = CommandStrings.NONE;

View File

@@ -148,7 +148,11 @@ namespace MPF.Core.Modules
/// Populate a Parameters object from a param string
/// </summary>
/// <param name="parameters">String possibly representing a set of parameters</param>
#if NET48
public BaseParameters(string parameters)
#else
public BaseParameters(string? parameters)
#endif
{
// If any parameters are not valid, wipe out everything
if (!ValidateAndSetParameters(parameters))
@@ -290,7 +294,11 @@ namespace MPF.Core.Modules
/// </summary>
/// <param name="parameters">String possibly representing parameters</param>
/// <returns>True if the parameters were set correctly, false otherwise</returns>
#if NET48
protected virtual bool ValidateAndSetParameters(string parameters) => !string.IsNullOrWhiteSpace(parameters);
#else
protected virtual bool ValidateAndSetParameters(string? parameters) => !string.IsNullOrWhiteSpace(parameters);
#endif
#endregion

View File

@@ -22,7 +22,11 @@ namespace MPF.Core.Modules.CleanRip
#endregion
/// <inheritdoc/>
#if NET48
public Parameters(string parameters) : base(parameters) { }
#else
public Parameters(string? parameters) : base(parameters) { }
#endif
/// <inheritdoc/>
public Parameters(RedumpSystem? system, MediaType? type, char driveLetter, string filename, int? driveSpeed, Options options)

View File

@@ -187,7 +187,11 @@ namespace MPF.Core.Modules.DiscImageCreator
#endregion
/// <inheritdoc/>
#if NET48
public Parameters(string parameters) : base(parameters) { }
#else
public Parameters(string? parameters) : base(parameters) { }
#endif
/// <inheritdoc/>
public Parameters(RedumpSystem? system, MediaType? type, char driveLetter, string filename, int? driveSpeed, Options options)
@@ -2074,7 +2078,11 @@ namespace MPF.Core.Modules.DiscImageCreator
}
/// <inheritdoc/>
#if NET48
protected override bool ValidateAndSetParameters(string parameters)
#else
protected override bool ValidateAndSetParameters(string? parameters)
#endif
{
BaseCommand = CommandStrings.NONE;

View File

@@ -209,7 +209,11 @@ namespace MPF.Core.Modules.Redumper
#endregion
/// <inheritdoc/>
#if NET48
public Parameters(string parameters) : base(parameters) { }
#else
public Parameters(string? parameters) : base(parameters) { }
#endif
/// <inheritdoc/>
public Parameters(RedumpSystem? system, MediaType? type, char driveLetter, string filename, int? driveSpeed, Options options)
@@ -1026,6 +1030,16 @@ namespace MPF.Core.Modules.Redumper
this[FlagStrings.Verbose] = options.RedumperEnableVerbose;
if (options.RedumperEnableDebug)
this[FlagStrings.Debug] = options.RedumperEnableDebug;
if (options.RedumperUseBEReading)
{
this[FlagStrings.DriveReadMethod] = true;
DriveReadMethodValue = "BE_CDDA";
}
if (options.RedumperUseGenericDriveType)
{
this[FlagStrings.DriveType] = true;
DriveTypeValue = "Generic";
}
// Set the output paths
if (!string.IsNullOrWhiteSpace(filename))
@@ -1050,7 +1064,11 @@ namespace MPF.Core.Modules.Redumper
}
/// <inheritdoc/>
#if NET48
protected override bool ValidateAndSetParameters(string parameters)
#else
protected override bool ValidateAndSetParameters(string? parameters)
#endif
{
BaseCommand = CommandStrings.NONE;

View File

@@ -21,7 +21,11 @@ namespace MPF.Core.Modules.UmdImageCreator
#endregion
/// <inheritdoc/>
#if NET48
public Parameters(string parameters) : base(parameters) { }
#else
public Parameters(string? parameters) : base(parameters) { }
#endif
/// <inheritdoc/>
public Parameters(RedumpSystem? system, MediaType? type, char driveLetter, string filename, int? driveSpeed, Options options)

View File

@@ -38,7 +38,11 @@ namespace MPF.Core.UI.ViewModels
/// <summary>
/// List of Redump-supported Regions
/// </summary>
#if NET48
private static readonly List<Region> RedumpRegions = new List<Region>
#else
private static readonly List<Region> RedumpRegions = new()
#endif
{
Region.Argentina,
Region.Asia,
@@ -129,7 +133,11 @@ namespace MPF.Core.UI.ViewModels
/// <summary>
/// List of Redump-supported Languages
/// </summary>
#if NET48
private static readonly List<Language> RedumpLanguages = new List<Language>
#else
private static readonly List<Language> RedumpLanguages = new()
#endif
{
Language.Afrikaans,
Language.Albanian,
@@ -191,10 +199,14 @@ namespace MPF.Core.UI.ViewModels
/// <summary>
/// Constructor
/// </summary>
#if NET48
public DiscInformationViewModel(Options options, SubmissionInfo submissionInfo)
#else
public DiscInformationViewModel(Options options, SubmissionInfo? submissionInfo)
#endif
{
Options = options;
SubmissionInfo = submissionInfo.Clone() as SubmissionInfo ?? new SubmissionInfo();
SubmissionInfo = submissionInfo?.Clone() as SubmissionInfo ?? new SubmissionInfo();
}
#region Helpers

View File

@@ -104,7 +104,7 @@ namespace MPF.Core.UI.ViewModels
set
{
_optionsMenuItemEnabled = value;
TriggerPropertyChanged("OptionsMenuItemEnabled");
TriggerPropertyChanged(nameof(OptionsMenuItemEnabled));
}
}
private bool _optionsMenuItemEnabled;
@@ -118,7 +118,7 @@ namespace MPF.Core.UI.ViewModels
set
{
_currentSystem = value;
TriggerPropertyChanged("CurrentSystem");
TriggerPropertyChanged(nameof(CurrentSystem));
}
}
private RedumpSystem? _currentSystem;
@@ -132,7 +132,7 @@ namespace MPF.Core.UI.ViewModels
set
{
_systemTypeComboBoxEnabled = value;
TriggerPropertyChanged("SystemTypeComboBoxEnabled");
TriggerPropertyChanged(nameof(SystemTypeComboBoxEnabled));
}
}
private bool _systemTypeComboBoxEnabled;
@@ -146,7 +146,7 @@ namespace MPF.Core.UI.ViewModels
set
{
_currentMediaType = value;
TriggerPropertyChanged("CurrentMediaType");
TriggerPropertyChanged(nameof(CurrentMediaType));
}
}
private MediaType? _currentMediaType;
@@ -160,7 +160,7 @@ namespace MPF.Core.UI.ViewModels
set
{
_mediaTypeComboBoxEnabled = value;
TriggerPropertyChanged("MediaTypeComboBoxEnabled");
TriggerPropertyChanged(nameof(MediaTypeComboBoxEnabled));
}
}
private bool _mediaTypeComboBoxEnabled;
@@ -174,7 +174,7 @@ namespace MPF.Core.UI.ViewModels
set
{
_outputPath = value;
TriggerPropertyChanged("OutputPath");
TriggerPropertyChanged(nameof(OutputPath));
}
}
private string _outputPath;
@@ -188,7 +188,7 @@ namespace MPF.Core.UI.ViewModels
set
{
_outputPathTextBoxEnabled = value;
TriggerPropertyChanged("OutputPathTextBoxEnabled");
TriggerPropertyChanged(nameof(OutputPathTextBoxEnabled));
}
}
private bool _outputPathTextBoxEnabled;
@@ -202,7 +202,7 @@ namespace MPF.Core.UI.ViewModels
set
{
_outputPathBrowseButtonEnabled = value;
TriggerPropertyChanged("OutputPathBrowseButtonEnabled");
TriggerPropertyChanged(nameof(OutputPathBrowseButtonEnabled));
}
}
private bool _outputPathBrowseButtonEnabled;
@@ -220,7 +220,7 @@ namespace MPF.Core.UI.ViewModels
set
{
_currentDrive = value;
TriggerPropertyChanged("CurrentDrive");
TriggerPropertyChanged(nameof(CurrentDrive));
}
}
#if NET48
@@ -238,7 +238,7 @@ namespace MPF.Core.UI.ViewModels
set
{
_driveLetterComboBoxEnabled = value;
TriggerPropertyChanged("DriveLetterComboBoxEnabled");
TriggerPropertyChanged(nameof(DriveLetterComboBoxEnabled));
}
}
private bool _driveLetterComboBoxEnabled;
@@ -252,7 +252,7 @@ namespace MPF.Core.UI.ViewModels
set
{
_driveSpeed = value;
TriggerPropertyChanged("DriveSpeed");
TriggerPropertyChanged(nameof(DriveSpeed));
}
}
private int _driveSpeed;
@@ -266,7 +266,7 @@ namespace MPF.Core.UI.ViewModels
set
{
_driveSpeedComboBoxEnabled = value;
TriggerPropertyChanged("DriveSpeedComboBoxEnabled");
TriggerPropertyChanged(nameof(DriveSpeedComboBoxEnabled));
}
}
private bool _driveSpeedComboBoxEnabled;
@@ -280,7 +280,7 @@ namespace MPF.Core.UI.ViewModels
set
{
_currentProgram = value;
TriggerPropertyChanged("CurrentProgram");
TriggerPropertyChanged(nameof(CurrentProgram));
}
}
private InternalProgram _currentProgram;
@@ -294,7 +294,7 @@ namespace MPF.Core.UI.ViewModels
set
{
_dumpingProgramComboBoxEnabled = value;
TriggerPropertyChanged("DumpingProgramComboBoxEnabled");
TriggerPropertyChanged(nameof(DumpingProgramComboBoxEnabled));
}
}
private bool _dumpingProgramComboBoxEnabled;
@@ -308,7 +308,7 @@ namespace MPF.Core.UI.ViewModels
set
{
_parameters = value;
TriggerPropertyChanged("Parameters");
TriggerPropertyChanged(nameof(Parameters));
}
}
private string _parameters;
@@ -322,7 +322,7 @@ namespace MPF.Core.UI.ViewModels
set
{
_parametersCheckBoxEnabled = value;
TriggerPropertyChanged("ParametersCheckBoxEnabled");
TriggerPropertyChanged(nameof(ParametersCheckBoxEnabled));
}
}
private bool _parametersCheckBoxEnabled;
@@ -336,7 +336,7 @@ namespace MPF.Core.UI.ViewModels
set
{
_enableParametersCheckBoxEnabled = value;
TriggerPropertyChanged("EnableParametersCheckBoxEnabled");
TriggerPropertyChanged(nameof(EnableParametersCheckBoxEnabled));
}
}
private bool _enableParametersCheckBoxEnabled;
@@ -350,7 +350,7 @@ namespace MPF.Core.UI.ViewModels
set
{
_startStopButtonEnabled = value;
TriggerPropertyChanged("StartStopButtonEnabled");
TriggerPropertyChanged(nameof(StartStopButtonEnabled));
}
}
private bool _startStopButtonEnabled;
@@ -364,7 +364,7 @@ namespace MPF.Core.UI.ViewModels
set
{
_startStopButtonText = (value as string) ?? string.Empty;
TriggerPropertyChanged("StartStopButtonText");
TriggerPropertyChanged(nameof(StartStopButtonText));
}
}
private string _startStopButtonText;
@@ -378,7 +378,7 @@ namespace MPF.Core.UI.ViewModels
set
{
_mediaScanButtonEnabled = value;
TriggerPropertyChanged("MediaScanButtonEnabled");
TriggerPropertyChanged(nameof(MediaScanButtonEnabled));
}
}
private bool _mediaScanButtonEnabled;
@@ -392,7 +392,7 @@ namespace MPF.Core.UI.ViewModels
set
{
_updateVolumeLabelEnabled = value;
TriggerPropertyChanged("UpdateVolumeLabelEnabled");
TriggerPropertyChanged(nameof(UpdateVolumeLabelEnabled));
}
}
private bool _updateVolumeLabelEnabled;
@@ -406,7 +406,7 @@ namespace MPF.Core.UI.ViewModels
set
{
_copyProtectScanButtonEnabled = value;
TriggerPropertyChanged("CopyProtectScanButtonEnabled");
TriggerPropertyChanged(nameof(CopyProtectScanButtonEnabled));
}
}
private bool _copyProtectScanButtonEnabled;
@@ -420,7 +420,7 @@ namespace MPF.Core.UI.ViewModels
set
{
_status = value;
TriggerPropertyChanged("Status");
TriggerPropertyChanged(nameof(Status));
}
}
private string _status;
@@ -434,7 +434,7 @@ namespace MPF.Core.UI.ViewModels
set
{
_logPanelExpanded = value;
TriggerPropertyChanged("LogPanelExpanded");
TriggerPropertyChanged(nameof(LogPanelExpanded));
}
}
private bool _logPanelExpanded;
@@ -452,7 +452,7 @@ namespace MPF.Core.UI.ViewModels
set
{
_drives = value;
TriggerPropertyChanged("Drives");
TriggerPropertyChanged(nameof(Drives));
}
}
private List<Drive> _drives;
@@ -466,7 +466,7 @@ namespace MPF.Core.UI.ViewModels
set
{
_driveSpeeds = value;
TriggerPropertyChanged("DriveSpeeds");
TriggerPropertyChanged(nameof(DriveSpeeds));
}
}
private List<int> _driveSpeeds;
@@ -484,7 +484,7 @@ namespace MPF.Core.UI.ViewModels
set
{
_mediaTypes = value;
TriggerPropertyChanged("MediaTypes");
TriggerPropertyChanged(nameof(MediaTypes));
}
}
#if NET48
@@ -502,7 +502,7 @@ namespace MPF.Core.UI.ViewModels
set
{
_systems = value;
TriggerPropertyChanged("Systems");
TriggerPropertyChanged(nameof(Systems));
}
}
private List<RedumpSystemComboBoxItem> _systems;
@@ -516,7 +516,7 @@ namespace MPF.Core.UI.ViewModels
set
{
_internalPrograms = value;
TriggerPropertyChanged("InternalPrograms");
TriggerPropertyChanged(nameof(InternalPrograms));
}
}
private List<Element<InternalProgram>> _internalPrograms;
@@ -544,6 +544,7 @@ namespace MPF.Core.UI.ViewModels
SystemTypeComboBoxEnabled = true;
MediaTypeComboBoxEnabled = true;
OutputPathTextBoxEnabled = true;
OutputPathBrowseButtonEnabled = true;
DriveLetterComboBoxEnabled = true;
DumpingProgramComboBoxEnabled = true;
StartStopButtonEnabled = true;
@@ -585,14 +586,14 @@ namespace MPF.Core.UI.ViewModels
private void TriggerPropertyChanged(string propertyName)
{
// Disable event handlers temporarily
CanExecuteSelectionChanged = false;
bool cachedCanExecuteSelectionChanged = CanExecuteSelectionChanged;
DisableEventHandlers();
// If the property change event is initialized
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
// Reenable event handlers
CanExecuteSelectionChanged = true;
// Reenable event handlers, if necessary
if (cachedCanExecuteSelectionChanged) EnableEventHandlers();
}
#endregion
@@ -606,7 +607,8 @@ namespace MPF.Core.UI.ViewModels
private void PopulateDrives()
{
// Disable other UI updates
CanExecuteSelectionChanged = false;
bool cachedCanExecuteSelectionChanged = CanExecuteSelectionChanged;
DisableEventHandlers();
VerboseLogLn("Scanning for drives..");
@@ -662,8 +664,8 @@ namespace MPF.Core.UI.ViewModels
this.CopyProtectScanButtonEnabled = false;
}
// Reenable UI updates
CanExecuteSelectionChanged = true;
// Reenable event handlers, if necessary
if (cachedCanExecuteSelectionChanged) EnableEventHandlers();
}
/// <summary>
@@ -672,7 +674,8 @@ namespace MPF.Core.UI.ViewModels
private void PopulateMediaType()
{
// Disable other UI updates
CanExecuteSelectionChanged = false;
bool cachedCanExecuteSelectionChanged = CanExecuteSelectionChanged;
DisableEventHandlers();
if (this.CurrentSystem != null)
{
@@ -692,8 +695,8 @@ namespace MPF.Core.UI.ViewModels
this.CurrentMediaType = null;
}
// Reenable UI updates
CanExecuteSelectionChanged = true;
// Reenable event handlers, if necessary
if (cachedCanExecuteSelectionChanged) EnableEventHandlers();
}
/// <summary>
@@ -702,7 +705,8 @@ namespace MPF.Core.UI.ViewModels
private void PopulateInternalPrograms()
{
// Disable other UI updates
CanExecuteSelectionChanged = false;
bool cachedCanExecuteSelectionChanged = CanExecuteSelectionChanged;
DisableEventHandlers();
// Get the current internal program
InternalProgram internalProgram = this.Options.InternalProgram;
@@ -715,8 +719,8 @@ namespace MPF.Core.UI.ViewModels
int currentIndex = InternalPrograms.FindIndex(m => m == internalProgram);
this.CurrentProgram = (currentIndex > -1 ? InternalPrograms[currentIndex].Value : InternalPrograms[0].Value);
// Reenable UI updates
CanExecuteSelectionChanged = true;
// Reenable event handlers, if necessary
if (cachedCanExecuteSelectionChanged) EnableEventHandlers();
}
#endregion
@@ -797,7 +801,7 @@ namespace MPF.Core.UI.ViewModels
/// <summary>
/// Build a dummy SubmissionInfo
/// </summary>
public SubmissionInfo CreateDebugSubmissionInfo()
public static SubmissionInfo CreateDebugSubmissionInfo()
{
return new SubmissionInfo()
{
@@ -977,7 +981,11 @@ namespace MPF.Core.UI.ViewModels
/// </summary>
/// <param name="savedSettings">Indicates if the settings were saved or not</param>
/// <param name="newOptions">Options representing the new, saved values</param>
#if NET48
public void UpdateOptions(bool savedSettings, Data.Options newOptions)
#else
public void UpdateOptions(bool savedSettings, Data.Options? newOptions)
#endif
{
if (savedSettings)
{
@@ -998,14 +1006,15 @@ namespace MPF.Core.UI.ViewModels
public void InitializeUIValues(bool removeEventHandlers, bool rescanDrives)
{
// Disable the dumping button
this.StartStopButtonEnabled = false;
StartStopButtonEnabled = false;
// Safely uncheck the parameters box, just in case
if (this.ParametersCheckBoxEnabled == true)
if (ParametersCheckBoxEnabled == true)
{
this.CanExecuteSelectionChanged = false;
this.ParametersCheckBoxEnabled = false;
this.CanExecuteSelectionChanged = true;
bool cachedCanExecuteSelectionChanged = CanExecuteSelectionChanged;
DisableEventHandlers();
ParametersCheckBoxEnabled = false;
if (cachedCanExecuteSelectionChanged) EnableEventHandlers();
}
// Remove event handlers to ensure ordering
@@ -1015,7 +1024,7 @@ namespace MPF.Core.UI.ViewModels
// Populate the list of drives and determine the system
if (rescanDrives)
{
this.Status = "Creating drive list, please wait!";
Status = "Creating drive list, please wait!";
PopulateDrives();
}
else
@@ -1041,7 +1050,7 @@ namespace MPF.Core.UI.ViewModels
EnableEventHandlers();
// Enable the dumping button, if necessary
this.StartStopButtonEnabled = ShouldEnableDumpingButton();
StartStopButtonEnabled = ShouldEnableDumpingButton();
}
/// <summary>
@@ -1056,9 +1065,10 @@ namespace MPF.Core.UI.ViewModels
// Safely uncheck the parameters box, just in case
if (this.ParametersCheckBoxEnabled == true)
{
this.CanExecuteSelectionChanged = false;
bool cachedCanExecuteSelectionChanged = CanExecuteSelectionChanged;
this.DisableEventHandlers();
this.ParametersCheckBoxEnabled = false;
this.CanExecuteSelectionChanged = true;
if (cachedCanExecuteSelectionChanged) EnableEventHandlers();
}
// Remove event handlers to ensure ordering
@@ -1106,8 +1116,7 @@ namespace MPF.Core.UI.ViewModels
/// <param name="text">Text to write to the log</param>
private void Log(string text)
{
if (_logger != null)
_logger(LogLevel.USER, text);
_logger?.Invoke(LogLevel.USER, text);
}
/// <summary>
@@ -1122,8 +1131,7 @@ namespace MPF.Core.UI.ViewModels
/// <param name="text">Text to write to the log</param>
private void ErrorLog(string text)
{
if (_logger != null)
_logger(LogLevel.ERROR, text);
_logger?.Invoke(LogLevel.ERROR, text);
}
/// <summary>
@@ -1138,8 +1146,7 @@ namespace MPF.Core.UI.ViewModels
/// <param name="text">Text to write to the log</param>
private void SecretLog(string text)
{
if (_logger != null)
_logger(LogLevel.SECRET, text);
_logger?.Invoke(LogLevel.SECRET, text);
}
/// <summary>
@@ -1423,7 +1430,7 @@ namespace MPF.Core.UI.ViewModels
// Catch this in case there's an input path issue
try
{
int driveIndex = Drives.Select(d => d.Letter).ToList().IndexOf(_environment.Parameters?.InputPath?[0] ?? default(char));
int driveIndex = Drives.Select(d => d.Letter).ToList().IndexOf(_environment.Parameters?.InputPath?[0] ?? default);
this.CurrentDrive = (driveIndex != -1 ? Drives[driveIndex] : Drives[0]);
}
catch { }
@@ -1460,8 +1467,12 @@ namespace MPF.Core.UI.ViewModels
#endif
{
// Determine current environment, just in case
#if NET48
if (_environment == null)
_environment = DetermineEnvironment();
#else
_environment ??= DetermineEnvironment();
#endif
// If we don't have a valid drive
if (this.CurrentDrive == null || this.CurrentDrive.Letter == default(char))
@@ -1779,7 +1790,7 @@ namespace MPF.Core.UI.ViewModels
return true;
}
#endregion
#endregion
#region Progress Reporting
@@ -1794,7 +1805,11 @@ namespace MPF.Core.UI.ViewModels
{
try
{
#if NET48
value = value ?? string.Empty;
#else
value ??= string.Empty;
#endif
LogLn(value);
}
catch { }
@@ -1812,7 +1827,11 @@ namespace MPF.Core.UI.ViewModels
var message = value?.Message;
// Update the label with only the first line of output
#if NET48
if (message != null && message.Contains("\n"))
#else
if (message != null && message.Contains('\n'))
#endif
this.Status = value?.Message?.Split('\n')[0] + " (See log output)";
else
this.Status = value?.Message ?? string.Empty;
@@ -1838,6 +1857,6 @@ namespace MPF.Core.UI.ViewModels
VerboseLogLn(message);
}
#endregion
#endregion
}
}

View File

@@ -18,7 +18,7 @@ namespace MPF.Core.Utilities
/// Process any standalone arguments for the program
/// </summary>
/// <returns>True if one of the arguments was processed, false otherwise</returns>
public static bool ProcessStandaloneArguments(string[] args)
public static bool? ProcessStandaloneArguments(string[] args)
{
// Help options
if (args.Length == 0 || args[0] == "-h" || args[0] == "-?")
@@ -90,9 +90,9 @@ namespace MPF.Core.Utilities
/// Load the current set of options from application arguments
/// </summary>
#if NET48
public static (Options, string, int) LoadFromArguments(string[] args, int startIndex = 0)
public static (Options, SubmissionInfo, string, int) LoadFromArguments(string[] args, int startIndex = 0)
#else
public static (Options, string?, int) LoadFromArguments(string[] args, int startIndex = 0)
public static (Options, SubmissionInfo?, string?, int) LoadFromArguments(string[] args, int startIndex = 0)
#endif
{
// Create the output values with defaults
@@ -105,9 +105,12 @@ namespace MPF.Core.Utilities
CompressLogFiles = false,
};
// Create the submission info to return, if necessary
#if NET48
SubmissionInfo info = null;
string parsedPath = null;
#else
SubmissionInfo? info = null;
string? parsedPath = null;
#endif
@@ -116,17 +119,30 @@ namespace MPF.Core.Utilities
// If we have no arguments, just return
if (args == null || args.Length == 0)
return (options, null, 0);
return (options, null, null, 0);
// If we have an invalid start index, just return
if (startIndex < 0 || startIndex >= args.Length)
return (options, null, startIndex);
return (options, null, null, startIndex);
// Loop through the arguments and parse out values
for (; startIndex < args.Length; startIndex++)
{
// Use specific program
if (args[startIndex].StartsWith("-u=") || args[startIndex].StartsWith("--use="))
{
string internalProgram = args[startIndex].Split('=')[1];
options.InternalProgram = EnumConverter.ToInternalProgram(internalProgram);
}
else if (args[startIndex] == "-u" || args[startIndex] == "--use")
{
string internalProgram = args[startIndex + 1];
options.InternalProgram = EnumConverter.ToInternalProgram(internalProgram);
startIndex++;
}
// Redump login
if (args[startIndex].StartsWith("-c=") || args[startIndex].StartsWith("--credentials="))
else if (args[startIndex].StartsWith("-c=") || args[startIndex].StartsWith("--credentials="))
{
string[] credentials = args[startIndex].Split('=')[1].Split(';');
options.RedumpUsername = credentials[0];
@@ -139,17 +155,10 @@ namespace MPF.Core.Utilities
startIndex += 2;
}
// Use specific program
else if (args[startIndex].StartsWith("-u=") || args[startIndex].StartsWith("--use="))
// Pull all information (requires Redump login)
else if (args[startIndex].Equals("-a") || args[startIndex].Equals("--pull-all"))
{
string internalProgram = args[startIndex].Split('=')[1];
options.InternalProgram = EnumConverter.ToInternalProgram(internalProgram);
}
else if (args[startIndex] == "-u" || args[startIndex] == "--use")
{
string internalProgram = args[startIndex + 1];
options.InternalProgram = EnumConverter.ToInternalProgram(internalProgram);
startIndex++;
options.PullAllInformation = true;
}
// Use a device path for physical checks
@@ -175,6 +184,19 @@ namespace MPF.Core.Utilities
protectFile = true;
}
// Include seed info file
if (args[startIndex].StartsWith("-l=") || args[startIndex].StartsWith("--load-seed="))
{
string seedInfo = args[startIndex].Split('=')[1];
info = InfoTool.CreateFromFile(seedInfo);
}
else if (args[startIndex] == "-l" || args[startIndex] == "--load-seed")
{
string seedInfo = args[startIndex + 1];
info = InfoTool.CreateFromFile(seedInfo);
startIndex++;
}
// Output submission JSON
else if (args[startIndex].Equals("-j") || args[startIndex].Equals("--json"))
{
@@ -198,7 +220,7 @@ namespace MPF.Core.Utilities
options.ScanForProtection = scan && !string.IsNullOrWhiteSpace(parsedPath);
options.OutputSeparateProtectionFile = scan && protectFile && !string.IsNullOrWhiteSpace(parsedPath);
return (options, parsedPath, startIndex);
return (options, info, parsedPath, startIndex);
}
/// <summary>
@@ -206,15 +228,18 @@ namespace MPF.Core.Utilities
/// </summary>
public static List<string> PrintSupportedArguments()
{
var supportedArguments = new List<string>();
supportedArguments.Add("-u, --use <program> Dumping program output type [REQUIRED]");
supportedArguments.Add("-c, --credentials <user> <pw> Redump username and password");
supportedArguments.Add("-p, --path <drivepath> Physical drive path for additional checks");
supportedArguments.Add("-s, --scan Enable copy protection scan (requires --path)");
supportedArguments.Add("-f, --protect-file Output protection to separate file (requires --scan)");
supportedArguments.Add("-j, --json Enable submission JSON output");
supportedArguments.Add("-z, --zip Enable log file compression");
var supportedArguments = new List<string>
{
"-u, --use <program> Dumping program output type [REQUIRED]",
"-c, --credentials <user> <pw> Redump username and password",
"-a, --pull-all Pull all information from Redump (requires --credentials)",
"-p, --path <drivepath> Physical drive path for additional checks",
"-s, --scan Enable copy protection scan (requires --path)",
"-f, --protect-file Output protection to separate file (requires --scan)",
"-l, --load-seed <path> Load a seed submission JSON for user information",
"-j, --json Enable submission JSON output",
"-z, --zip Enable log file compression"
};
return supportedArguments;
}

View File

@@ -143,7 +143,7 @@ namespace MPF.Core.Utilities
if (assemblyVersion == null)
return (false, "Assembly version could not be determined", null);
string version = $"{assemblyVersion.Major}.{assemblyVersion.Minor}" + (assemblyVersion.Build != 0 ? $".{assemblyVersion.Build}" : string.Empty);
string version = $"{assemblyVersion.Major}.{assemblyVersion.Minor}.{assemblyVersion.Build}";
// Get the latest tag from GitHub
var (tag, url) = GetRemoteVersionAndUrl();

View File

@@ -43,21 +43,37 @@ namespace MPF.Test.Core.Converters
/// Generate a test set of DriveType values
/// </summary>
/// <returns>MemberData-compatible list of DriveType values</returns>
#if NET48
public static List<object[]> GenerateDriveTypeMappingTestData()
#else
public static List<object?[]> GenerateDriveTypeMappingTestData()
#endif
{
#if NET48
var testData = new List<object[]>() { new object[] { null, true } };
#else
var testData = new List<object?[]>() { new object?[] { null, true } };
#endif
foreach (DriveType driveType in Enum.GetValues(typeof(DriveType)))
{
if (_mappableDriveTypes.Contains(driveType))
#if NET48
testData.Add(new object[] { driveType, false });
#else
testData.Add(new object?[] { driveType, false });
#endif
else
#if NET48
testData.Add(new object[] { driveType, true });
#else
testData.Add(new object?[] { driveType, true });
#endif
}
return testData;
}
#endregion
#endregion
#region Convert to Long Name
@@ -79,18 +95,30 @@ namespace MPF.Test.Core.Converters
/// Generate a test set of InternalProgram values
/// </summary>
/// <returns>MemberData-compatible list of InternalProgram values</returns>
#if NET48
public static List<object[]> GenerateInternalProgramTestData()
#else
public static List<object?[]> GenerateInternalProgramTestData()
#endif
{
#if NET48
var testData = new List<object[]>() { new object[] { null } };
#else
var testData = new List<object?[]>() { new object?[] { null } };
#endif
foreach (InternalProgram? internalProgram in Enum.GetValues(typeof(InternalProgram)))
{
#if NET48
testData.Add(new object[] { internalProgram });
#else
testData.Add(new object?[] { internalProgram });
#endif
}
return testData;
}
#endregion
#endregion
// TODO: Add from-string tests
}

View File

@@ -13,7 +13,7 @@ namespace MPF.Test.Core.Data
[InlineData("123456789")]
public void UnmatchedStringTests(string invalidString)
{
XgdInfo xgdInfo = new XgdInfo(invalidString);
var xgdInfo = new XgdInfo(invalidString);
Assert.False(xgdInfo.Initialized);
}
@@ -22,9 +22,10 @@ namespace MPF.Test.Core.Data
[InlineData("AV00100W\0", "AV", "001", "00", 'W')]
public void XGD1ValidTests(string validString, string publisher, string gameId, string version, char regionIdentifier)
{
XgdInfo xgdInfo = new XgdInfo(validString);
var xgdInfo = new XgdInfo(validString);
Assert.True(xgdInfo.Initialized);
Assert.NotNull(xgdInfo.XMID);
Assert.Equal(publisher, xgdInfo.XMID.PublisherIdentifier);
Assert.Equal(gameId, xgdInfo.XMID.GameID);
Assert.Equal(version, xgdInfo.XMID.VersionNumber);
@@ -40,7 +41,7 @@ namespace MPF.Test.Core.Data
[InlineData("AV00000Z\0")]
public void XGD1InvalidTests(string invalidString)
{
XgdInfo xgdInfo = new XgdInfo(invalidString);
var xgdInfo = new XgdInfo(invalidString);
Assert.False(xgdInfo.Initialized);
}
@@ -55,9 +56,10 @@ namespace MPF.Test.Core.Data
[InlineData("AV200100W01F11DEADBEEF\0", "AV", "001", "00", 'W', "01", 'F', "11", "DEADBEEF")]
public void XGD23ValidTests(string validString, string publisher, string gameId, string sku, char regionIdentifier, string baseVersion, char mediaSubtype, string discNumber, string cert)
{
XgdInfo xgdInfo = new XgdInfo(validString);
var xgdInfo = new XgdInfo(validString);
Assert.True(xgdInfo.Initialized);
Assert.NotNull(xgdInfo.XeMID);
Assert.Equal(publisher, xgdInfo.XeMID.PublisherIdentifier);
Assert.Equal('2', xgdInfo.XeMID.PlatformIdentifier);
Assert.Equal(gameId, xgdInfo.XeMID.GameID);
@@ -108,7 +110,7 @@ namespace MPF.Test.Core.Data
[InlineData("AV200000W00A0000000000\0")]
public void XGD23InvalidTests(string invalidString)
{
XgdInfo xgdInfo = new XgdInfo(invalidString);
var xgdInfo = new XgdInfo(invalidString);
Assert.False(xgdInfo.Initialized);
}
}

View File

@@ -143,15 +143,31 @@ namespace MPF.Test.Core.Utilities
/// Generate a test set of MediaType values that support drive speeds
/// </summary>
/// <returns>MemberData-compatible list of MediaType values</returns>
#if NET48
public static List<object[]> GenerateSupportDriveSpeedsTestData()
#else
public static List<object?[]> GenerateSupportDriveSpeedsTestData()
#endif
{
#if NET48
var testData = new List<object[]>() { new object[] { null, false } };
#else
var testData = new List<object?[]>() { new object?[] { null, false } };
#endif
foreach (MediaType mediaType in Enum.GetValues(typeof(MediaType)))
{
if (_supportDriveSpeeds.Contains(mediaType))
#if NET48
testData.Add(new object[] { mediaType, true });
#else
testData.Add(new object?[] { mediaType, true });
#endif
else
#if NET48
testData.Add(new object[] { mediaType, false });
#else
testData.Add(new object?[] { mediaType, false });
#endif
}
return testData;
@@ -161,15 +177,31 @@ namespace MPF.Test.Core.Utilities
/// Generate a test set of RedumpSystem values that are considered Audio
/// </summary>
/// <returns>MemberData-compatible list of RedumpSystem values</returns>
#if NET48
public static List<object[]> GenerateAudioSystemsTestData()
#else
public static List<object?[]> GenerateAudioSystemsTestData()
#endif
{
#if NET48
var testData = new List<object[]>() { new object[] { null, false } };
#else
var testData = new List<object?[]>() { new object?[] { null, false } };
#endif
foreach (RedumpSystem redumpSystem in Enum.GetValues(typeof(RedumpSystem)))
{
if (_audioSystems.Contains(redumpSystem))
#if NET48
testData.Add(new object[] { redumpSystem, true });
#else
testData.Add(new object?[] { redumpSystem, true });
#endif
else
#if NET48
testData.Add(new object[] { redumpSystem, false });
#else
testData.Add(new object?[] { redumpSystem, false });
#endif
}
return testData;
@@ -179,15 +211,31 @@ namespace MPF.Test.Core.Utilities
/// Generate a test set of RedumpSystem values that are considered markers
/// </summary>
/// <returns>MemberData-compatible list of RedumpSystem values</returns>
#if NET48
public static List<object[]> GenerateMarkerSystemsTestData()
#else
public static List<object?[]> GenerateMarkerSystemsTestData()
#endif
{
#if NET48
var testData = new List<object[]>() { new object[] { null, false } };
#else
var testData = new List<object?[]>() { new object?[] { null, false } };
#endif
foreach (RedumpSystem redumpSystem in Enum.GetValues(typeof(RedumpSystem)))
{
if (_markerSystems.Contains(redumpSystem))
#if NET48
testData.Add(new object[] { redumpSystem, true });
#else
testData.Add(new object?[] { redumpSystem, true });
#endif
else
#if NET48
testData.Add(new object[] { redumpSystem, false });
#else
testData.Add(new object?[] { redumpSystem, false });
#endif
}
return testData;
@@ -197,15 +245,31 @@ namespace MPF.Test.Core.Utilities
/// Generate a test set of RedumpSystem values that are considered markers
/// </summary>
/// <returns>MemberData-compatible list of RedumpSystem values</returns>
#if NET48
public static List<object[]> GenerateReversedRingcodeSystemsTestData()
#else
public static List<object?[]> GenerateReversedRingcodeSystemsTestData()
#endif
{
#if NET48
var testData = new List<object[]>() { new object[] { null, false } };
#else
var testData = new List<object?[]>() { new object?[] { null, false } };
#endif
foreach (RedumpSystem redumpSystem in Enum.GetValues(typeof(RedumpSystem)))
{
if (_reverseRingcodeSystems.Contains(redumpSystem))
#if NET48
testData.Add(new object[] { redumpSystem, true });
#else
testData.Add(new object?[] { redumpSystem, true });
#endif
else
#if NET48
testData.Add(new object[] { redumpSystem, false });
#else
testData.Add(new object?[] { redumpSystem, false });
#endif
}
return testData;
@@ -215,15 +279,31 @@ namespace MPF.Test.Core.Utilities
/// Generate a test set of RedumpSystem values that are considered XGD
/// </summary>
/// <returns>MemberData-compatible list of RedumpSystem values</returns>
#if NET48
public static List<object[]> GenerateXGDSystemsTestData()
#else
public static List<object?[]> GenerateXGDSystemsTestData()
#endif
{
#if NET48
var testData = new List<object[]>() { new object[] { null, false } };
#else
var testData = new List<object?[]>() { new object?[] { null, false } };
#endif
foreach (RedumpSystem redumpSystem in Enum.GetValues(typeof(RedumpSystem)))
{
if (_xgdSystems.Contains(redumpSystem))
#if NET48
testData.Add(new object[] { redumpSystem, true });
#else
testData.Add(new object?[] { redumpSystem, true });
#endif
else
#if NET48
testData.Add(new object[] { redumpSystem, false });
#else
testData.Add(new object?[] { redumpSystem, false });
#endif
}
return testData;

View File

@@ -42,10 +42,14 @@ namespace MPF.Test.Library
long layerbreak,
long layerbreak2,
long layerbreak3,
#if NET48
string expected)
#else
string? expected)
#endif
{
// TODO: Add tests around BDU
string actual = InfoTool.GetFixedMediaType(mediaType, null, size, layerbreak, layerbreak2, layerbreak3);
var actual = InfoTool.GetFixedMediaType(mediaType, null, size, layerbreak, layerbreak2, layerbreak3);
Assert.Equal(expected, actual);
}
@@ -58,7 +62,11 @@ namespace MPF.Test.Library
[InlineData("superhero\\blah.rev.bin", "superhero\\blah.rev.bin")]
[InlineData("super&hero\\blah.bin", "super&hero\\blah.bin")]
[InlineData("superhero\\blah&foo.bin", "superhero\\blah&foo.bin")]
#if NET48
public void NormalizeOutputPathsTest(string outputPath, string expectedPath)
#else
public void NormalizeOutputPathsTest(string? outputPath, string? expectedPath)
#endif
{
if (!string.IsNullOrWhiteSpace(expectedPath))
expectedPath = Path.GetFullPath(expectedPath);
@@ -71,7 +79,7 @@ namespace MPF.Test.Library
public void ProcessSpecialFieldsCompleteTest()
{
// Create a new SubmissionInfo object
SubmissionInfo info = new SubmissionInfo()
var info = new SubmissionInfo()
{
CommonDiscInfo = new CommonDiscInfoSection()
{
@@ -119,7 +127,7 @@ namespace MPF.Test.Library
public void ProcessSpecialFieldsNullObjectTest()
{
// Create a new SubmissionInfo object
SubmissionInfo info = new SubmissionInfo()
var info = new SubmissionInfo()
{
CommonDiscInfo = null,
};
@@ -135,7 +143,7 @@ namespace MPF.Test.Library
public void ProcessSpecialFieldsNullCommentsContentsTest()
{
// Create a new SubmissionInfo object
SubmissionInfo info = new SubmissionInfo()
var info = new SubmissionInfo()
{
CommonDiscInfo = new CommonDiscInfoSection()
{
@@ -183,7 +191,7 @@ namespace MPF.Test.Library
public void ProcessSpecialFieldsNullDictionariesTest()
{
// Create a new SubmissionInfo object
SubmissionInfo info = new SubmissionInfo()
var info = new SubmissionInfo()
{
CommonDiscInfo = new CommonDiscInfoSection()
{

View File

@@ -5,6 +5,10 @@
<IsPackable>false</IsPackable>
</PropertyGroup>
<PropertyGroup Condition="'$(TargetFramework)'!='net48'">
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\MPF\MPF.csproj" />
</ItemGroup>

View File

@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using MPF.Core.Data;
using MPF.Core.Modules.DiscImageCreator;
using SabreTools.RedumpLib.Data;
@@ -33,7 +34,7 @@ namespace MPF.Test.Modules
var options = new Options();
var actual = new Parameters(knownSystem, mediaType, 'D', "disc.bin", 16, options);
HashSet<string> expectedSet = new HashSet<string>(expected ?? new string[0]);
var expectedSet = new HashSet<string>(expected ?? Array.Empty<string>());
HashSet<string> actualSet = GenerateUsedKeys(actual);
Assert.Equal(expectedSet, actualSet);
}
@@ -46,7 +47,7 @@ namespace MPF.Test.Modules
var options = new Options { DICRereadCount = rereadC2 };
var actual = new Parameters(knownSystem, mediaType, 'D', "disc.bin", 16, options);
HashSet<string> expectedSet = new HashSet<string>(expected ?? new string[0]);
var expectedSet = new HashSet<string>(expected ?? Array.Empty<string>());
HashSet<string> actualSet = GenerateUsedKeys(actual);
Assert.Equal(expectedSet, actualSet);
@@ -66,7 +67,7 @@ namespace MPF.Test.Modules
var options = new Options { DICDVDRereadCount = rereadDVDBD };
var actual = new Parameters(knownSystem, mediaType, 'D', "disc.bin", 16, options);
HashSet<string> expectedSet = new HashSet<string>(expected ?? new string[0]);
var expectedSet = new HashSet<string>(expected ?? Array.Empty<string>());
HashSet<string> actualSet = GenerateUsedKeys(actual);
Assert.Equal(expectedSet, actualSet);
@@ -90,7 +91,7 @@ namespace MPF.Test.Modules
var options = new Options { DICMultiSectorRead = multiSectorRead };
var actual = new Parameters(knownSystem, mediaType, 'D', "disc.bin", 16, options);
HashSet<string> expectedSet = new HashSet<string>(expected ?? new string[0]);
var expectedSet = new HashSet<string>(expected ?? Array.Empty<string>());
HashSet<string> actualSet = GenerateUsedKeys(actual);
Assert.Equal(expectedSet, actualSet);
if (expectedSet.Count != 1 && multiSectorRead)
@@ -111,7 +112,7 @@ namespace MPF.Test.Modules
var options = new Options { DICParanoidMode = paranoidMode };
var actual = new Parameters(knownSystem, mediaType, 'D', "disc.bin", 16, options);
HashSet<string> expectedSet = new HashSet<string>(expected ?? new string[0]);
var expectedSet = new HashSet<string>(expected ?? Array.Empty<string>());
HashSet<string> actualSet = GenerateUsedKeys(actual);
Assert.Equal(expectedSet, actualSet);
if (paranoidMode)
@@ -160,9 +161,13 @@ namespace MPF.Test.Modules
[InlineData(MediaType.FloppyDisk, ".img")]
[InlineData(MediaType.Cassette, ".wav")]
[InlineData(MediaType.NONE, null)]
#if NET48
public void MediaTypeToExtensionTest(MediaType? mediaType, string expected)
#else
public void MediaTypeToExtensionTest(MediaType? mediaType, string? expected)
#endif
{
string actual = Converters.Extension(mediaType);
var actual = Converters.Extension(mediaType);
Assert.Equal(expected, actual);
}
@@ -214,7 +219,7 @@ namespace MPF.Test.Modules
Assert.Equal(expected, actual);
}
#endregion
#endregion
[Fact]
public void DiscImageCreatorAudioParametersTest()
@@ -226,7 +231,7 @@ namespace MPF.Test.Modules
Assert.NotNull(parametersObject);
// Validate that the same set of parameters are generated on the output
string newParameters = parametersObject.GenerateParameters();
var newParameters = parametersObject.GenerateParameters();
Assert.NotNull(newParameters);
Assert.Equal(originalParameters, newParameters);
}
@@ -241,7 +246,7 @@ namespace MPF.Test.Modules
Assert.NotNull(parametersObject);
// Validate that the same set of parameters are generated on the output
string newParameters = parametersObject.GenerateParameters();
var newParameters = parametersObject.GenerateParameters();
Assert.NotNull(newParameters);
Assert.Equal(originalParameters, newParameters);
}
@@ -253,7 +258,7 @@ namespace MPF.Test.Modules
/// <returns>HashSet representing the strings</returns>
private static HashSet<string> GenerateUsedKeys(Parameters parameters)
{
HashSet<string> usedKeys = new HashSet<string>();
var usedKeys = new HashSet<string>();
if (parameters?.Keys == null)
return usedKeys;

View File

@@ -95,15 +95,31 @@ namespace MPF.Test.RedumpLib
/// Generate a test set of DiscType values
/// </summary>
/// <returns>MemberData-compatible list of DiscType values</returns>
#if NET48
public static List<object[]> GenerateDiscTypeMappingTestData()
#else
public static List<object?[]> GenerateDiscTypeMappingTestData()
#endif
{
#if NET48
var testData = new List<object[]>() { new object[] { null, true } };
#else
var testData = new List<object?[]>() { new object?[] { null, true } };
#endif
foreach (DiscType? discType in Enum.GetValues(typeof(DiscType)))
{
if (_mappableDiscTypes.Contains(discType))
#if NET48
testData.Add(new object[] { discType, false });
#else
testData.Add(new object?[] { discType, false });
#endif
else
#if NET48
testData.Add(new object[] { discType, true });
#else
testData.Add(new object?[] { discType, true });
#endif
}
return testData;
@@ -113,12 +129,24 @@ namespace MPF.Test.RedumpLib
/// Generate a test set of RedumpSystem values
/// </summary>
/// <returns>MemberData-compatible list of RedumpSystem values</returns>
#if NET48
public static List<object[]> GenerateRedumpSystemMappingTestData()
#else
public static List<object?[]> GenerateRedumpSystemMappingTestData()
#endif
{
#if NET48
var testData = new List<object[]>() { new object[] { null } };
#else
var testData = new List<object?[]>() { new object?[] { null } };
#endif
foreach (RedumpSystem? redumpSystem in Enum.GetValues(typeof(RedumpSystem)))
{
#if NET48
testData.Add(new object[] { redumpSystem });
#else
testData.Add(new object?[] { redumpSystem });
#endif
}
return testData;
@@ -128,16 +156,32 @@ namespace MPF.Test.RedumpLib
/// Generate a test set of mappable media types
/// </summary>
/// <returns>MemberData-compatible list of MediaTypes</returns>
#if NET48
public static List<object[]> GenerateMediaTypeMappingTestData()
#else
public static List<object?[]> GenerateMediaTypeMappingTestData()
#endif
{
#if NET48
var testData = new List<object[]>() { new object[] { null, true } };
#else
var testData = new List<object?[]>() { new object?[] { null, true } };
#endif
foreach (MediaType? mediaType in Enum.GetValues(typeof(MediaType)))
{
if (_mappableMediaTypes.Contains(mediaType))
#if NET48
testData.Add(new object[] { mediaType, false });
#else
testData.Add(new object?[] { mediaType, false });
#endif
else
#if NET48
testData.Add(new object[] { mediaType, true });
#else
testData.Add(new object?[] { mediaType, true });
#endif
}
return testData;
@@ -156,7 +200,7 @@ namespace MPF.Test.RedumpLib
[MemberData(nameof(GenerateDiscCategoryTestData))]
public void DiscCategoryLongNameTest(DiscCategory? discCategory, bool expectNull)
{
string actual = discCategory.LongName();
var actual = discCategory.LongName();
if (expectNull)
Assert.Null(actual);
@@ -168,12 +212,24 @@ namespace MPF.Test.RedumpLib
/// Generate a test set of DiscCategory values
/// </summary>
/// <returns>MemberData-compatible list of DiscCategory values</returns>
#if NET48
public static List<object[]> GenerateDiscCategoryTestData()
#else
public static List<object?[]> GenerateDiscCategoryTestData()
#endif
{
#if NET48
var testData = new List<object[]>() { new object[] { null, true } };
#else
var testData = new List<object?[]>() { new object?[] { null, true } };
#endif
foreach (DiscCategory? discCategory in Enum.GetValues(typeof(DiscCategory)))
{
#if NET48
testData.Add(new object[] { discCategory, false });
#else
testData.Add(new object?[] { discCategory, false });
#endif
}
return testData;
@@ -192,7 +248,7 @@ namespace MPF.Test.RedumpLib
[MemberData(nameof(GenerateDiscTypeTestData))]
public void DiscTypeLongNameTest(DiscType? discType, bool expectNull)
{
string actual = discType.LongName();
var actual = discType.LongName();
if (expectNull)
Assert.Null(actual);
@@ -204,15 +260,31 @@ namespace MPF.Test.RedumpLib
/// Generate a test set of DiscType values
/// </summary>
/// <returns>MemberData-compatible list of DiscType values</returns>
#if NET48
public static List<object[]> GenerateDiscTypeTestData()
#else
public static List<object?[]> GenerateDiscTypeTestData()
#endif
{
#if NET48
var testData = new List<object[]>() { new object[] { null, true } };
#else
var testData = new List<object?[]>() { new object?[] { null, true } };
#endif
foreach (DiscType? discType in Enum.GetValues(typeof(DiscType)))
{
if (discType == DiscType.NONE)
#if NET48
testData.Add(new object[] { discType, true });
#else
testData.Add(new object?[] { discType, true });
#endif
else
#if NET48
testData.Add(new object[] { discType, false });
#else
testData.Add(new object?[] { discType, false });
#endif
}
return testData;
@@ -231,7 +303,7 @@ namespace MPF.Test.RedumpLib
[MemberData(nameof(GenerateLanguageTestData))]
public void LanguageLongNameTest(Language? language, bool expectNull)
{
string actual = language.LongName();
var actual = language.LongName();
if (expectNull)
Assert.Null(actual);
@@ -248,7 +320,7 @@ namespace MPF.Test.RedumpLib
[MemberData(nameof(GenerateLanguageTestData))]
public void LanguageShortNameTest(Language? language, bool expectNull)
{
string actual = language.ShortName();
var actual = language.ShortName();
if (expectNull)
Assert.Null(actual);
@@ -268,7 +340,7 @@ namespace MPF.Test.RedumpLib
int totalCount = 0;
foreach (Language? language in fullLanguages)
{
string code = language.TwoLetterCode();
var code = language.TwoLetterCode();
if (string.IsNullOrWhiteSpace(code))
continue;
@@ -295,7 +367,7 @@ namespace MPF.Test.RedumpLib
int totalCount = 0;
foreach (Language? language in fullLanguages)
{
string code = language.ThreeLetterCode();
var code = language.ThreeLetterCode();
if (string.IsNullOrWhiteSpace(code))
continue;
@@ -322,7 +394,7 @@ namespace MPF.Test.RedumpLib
int totalCount = 0;
foreach (Language? language in fullLanguages)
{
string code = language.ThreeLetterCodeAlt();
var code = language.ThreeLetterCodeAlt();
if (string.IsNullOrWhiteSpace(code))
continue;
@@ -341,12 +413,24 @@ namespace MPF.Test.RedumpLib
/// Generate a test set of Language values
/// </summary>
/// <returns>MemberData-compatible list of Language values</returns>
#if NET48
public static List<object[]> GenerateLanguageTestData()
#else
public static List<object?[]> GenerateLanguageTestData()
#endif
{
#if NET48
var testData = new List<object[]>() { new object[] { null, true } };
#else
var testData = new List<object?[]>() { new object?[] { null, true } };
#endif
foreach (Language? language in Enum.GetValues(typeof(Language)))
{
#if NET48
testData.Add(new object[] { language, false });
#else
testData.Add(new object?[] { language, false });
#endif
}
return testData;
@@ -365,7 +449,7 @@ namespace MPF.Test.RedumpLib
[MemberData(nameof(GenerateLanguageSelectionTestData))]
public void LanguageSelectionLongNameTest(LanguageSelection? languageSelection, bool expectNull)
{
string actual = languageSelection.LongName();
var actual = languageSelection.LongName();
if (expectNull)
Assert.Null(actual);
@@ -377,12 +461,24 @@ namespace MPF.Test.RedumpLib
/// Generate a test set of LanguageSelection values
/// </summary>
/// <returns>MemberData-compatible list of LanguageSelection values</returns>
#if NET48
public static List<object[]> GenerateLanguageSelectionTestData()
#else
public static List<object?[]> GenerateLanguageSelectionTestData()
#endif
{
#if NET48
var testData = new List<object[]>() { new object[] { null, true } };
#else
var testData = new List<object?[]>() { new object?[] { null, true } };
#endif
foreach (LanguageSelection? languageSelection in Enum.GetValues(typeof(LanguageSelection)))
{
#if NET48
testData.Add(new object[] { languageSelection, false });
#else
testData.Add(new object?[] { languageSelection, false });
#endif
}
return testData;
@@ -401,7 +497,7 @@ namespace MPF.Test.RedumpLib
[MemberData(nameof(GenerateMediaTypeTestData))]
public void MediaTypeLongNameTest(MediaType? mediaType, bool expectNull)
{
string actual = mediaType.LongName();
var actual = mediaType.LongName();
if (expectNull)
Assert.Null(actual);
@@ -418,7 +514,7 @@ namespace MPF.Test.RedumpLib
[MemberData(nameof(GenerateMediaTypeTestData))]
public void MediaTypeShortNameTest(MediaType? mediaType, bool expectNull)
{
string actual = mediaType.ShortName();
var actual = mediaType.ShortName();
if (expectNull)
Assert.Null(actual);
@@ -430,12 +526,24 @@ namespace MPF.Test.RedumpLib
/// Generate a test set of MediaType values
/// </summary>
/// <returns>MemberData-compatible list of MediaType values</returns>
#if NET48
public static List<object[]> GenerateMediaTypeTestData()
#else
public static List<object?[]> GenerateMediaTypeTestData()
#endif
{
#if NET48
var testData = new List<object[]>() { new object[] { null, true } };
#else
var testData = new List<object?[]>() { new object?[] { null, true } };
#endif
foreach (MediaType? mediaType in Enum.GetValues(typeof(MediaType)))
{
#if NET48
testData.Add(new object[] { mediaType, false });
#else
testData.Add(new object?[] { mediaType, false });
#endif
}
return testData;
@@ -454,7 +562,7 @@ namespace MPF.Test.RedumpLib
[MemberData(nameof(GenerateRegionTestData))]
public void RegionLongNameTest(Region? region, bool expectNull)
{
string actual = region.LongName();
var actual = region.LongName();
if (expectNull)
Assert.Null(actual);
@@ -471,7 +579,7 @@ namespace MPF.Test.RedumpLib
[MemberData(nameof(GenerateRegionTestData))]
public void RegionShortNameTest(Region? region, bool expectNull)
{
string actual = region.ShortName();
var actual = region.ShortName();
if (expectNull)
Assert.Null(actual);
@@ -491,7 +599,7 @@ namespace MPF.Test.RedumpLib
int totalCount = 0;
foreach (Region? region in fullRegions)
{
string code = region.ShortName();
var code = region.ShortName();
if (string.IsNullOrWhiteSpace(code))
continue;
@@ -510,12 +618,24 @@ namespace MPF.Test.RedumpLib
/// Generate a test set of Region values
/// </summary>
/// <returns>MemberData-compatible list of Region values</returns>
#if NET48
public static List<object[]> GenerateRegionTestData()
#else
public static List<object?[]> GenerateRegionTestData()
#endif
{
#if NET48
var testData = new List<object[]>() { new object[] { null, true } };
#else
var testData = new List<object?[]>() { new object?[] { null, true } };
#endif
foreach (Region? region in Enum.GetValues(typeof(Region)))
{
#if NET48
testData.Add(new object[] { region, false });
#else
testData.Add(new object?[] { region, false });
#endif
}
return testData;
@@ -534,7 +654,7 @@ namespace MPF.Test.RedumpLib
[MemberData(nameof(GenerateSiteCodeTestData))]
public void SiteCodeLongNameTest(SiteCode? siteCode, bool expectNull)
{
string actual = siteCode.LongName();
var actual = siteCode.LongName();
if (expectNull)
Assert.Null(actual);
@@ -551,7 +671,7 @@ namespace MPF.Test.RedumpLib
[MemberData(nameof(GenerateSiteCodeTestData))]
public void SiteCodeShortNameTest(SiteCode? siteCode, bool expectNull)
{
string actual = siteCode.ShortName();
var actual = siteCode.ShortName();
if (expectNull)
Assert.Null(actual);
@@ -563,12 +683,24 @@ namespace MPF.Test.RedumpLib
/// Generate a test set of SiteCode values
/// </summary>
/// <returns>MemberData-compatible list of SiteCode values</returns>
#if NET48
public static List<object[]> GenerateSiteCodeTestData()
#else
public static List<object?[]> GenerateSiteCodeTestData()
#endif
{
#if NET48
var testData = new List<object[]>() { new object[] { null, true } };
#else
var testData = new List<object?[]>() { new object?[] { null, true } };
#endif
foreach (SiteCode? siteCode in Enum.GetValues(typeof(SiteCode)))
{
#if NET48
testData.Add(new object[] { siteCode, false });
#else
testData.Add(new object?[] { siteCode, false });
#endif
}
return testData;
@@ -587,7 +719,7 @@ namespace MPF.Test.RedumpLib
[MemberData(nameof(GenerateRedumpSystemTestData))]
public void RedumpSystemLongNameTest(RedumpSystem? redumpSystem, bool expectNull)
{
string actual = redumpSystem.LongName();
var actual = redumpSystem.LongName();
if (expectNull)
Assert.Null(actual);
@@ -622,16 +754,28 @@ namespace MPF.Test.RedumpLib
/// Generate a test set of RedumpSystem values
/// </summary>
/// <returns>MemberData-compatible list of RedumpSystem values</returns>
#if NET48
public static List<object[]> GenerateRedumpSystemTestData()
#else
public static List<object?[]> GenerateRedumpSystemTestData()
#endif
{
#if NET48
var testData = new List<object[]>() { new object[] { null, true } };
#else
var testData = new List<object?[]>() { new object?[] { null, true } };
#endif
foreach (RedumpSystem? redumpSystem in Enum.GetValues(typeof(RedumpSystem)))
{
// We want to skip all markers for this
if (redumpSystem.IsMarker())
continue;
#if NET48
testData.Add(new object[] { redumpSystem, false });
#else
testData.Add(new object?[] { redumpSystem, false });
#endif
}
return testData;
@@ -650,7 +794,7 @@ namespace MPF.Test.RedumpLib
[MemberData(nameof(GenerateSystemCategoryTestData))]
public void SystemCategoryLongNameTest(SystemCategory? systemCategory, bool expectNull)
{
string actual = systemCategory.LongName();
var actual = systemCategory.LongName();
if (expectNull)
Assert.Null(actual);
@@ -662,15 +806,31 @@ namespace MPF.Test.RedumpLib
/// Generate a test set of SystemCategory values
/// </summary>
/// <returns>MemberData-compatible list of SystemCategory values</returns>
#if NET48
public static List<object[]> GenerateSystemCategoryTestData()
#else
public static List<object?[]> GenerateSystemCategoryTestData()
#endif
{
#if NET48
var testData = new List<object[]>() { new object[] { null, true } };
#else
var testData = new List<object?[]>() { new object?[] { null, true } };
#endif
foreach (SystemCategory? systemCategory in Enum.GetValues(typeof(SystemCategory)))
{
if (systemCategory == SystemCategory.NONE)
#if NET48
testData.Add(new object[] { systemCategory, true });
#else
testData.Add(new object?[] { systemCategory, true });
#endif
else
#if NET48
testData.Add(new object[] { systemCategory, false });
#else
testData.Add(new object?[] { systemCategory, false });
#endif
}
return testData;
@@ -701,12 +861,24 @@ namespace MPF.Test.RedumpLib
/// Generate a test set of YesNo values
/// </summary>
/// <returns>MemberData-compatible list of YesNo values</returns>
#if NET48
public static List<object[]> GenerateYesNoTestData()
#else
public static List<object?[]> GenerateYesNoTestData()
#endif
{
#if NET48
var testData = new List<object[]>() { new object[] { null, false } };
#else
var testData = new List<object?[]>() { new object?[] { null, false } };
#endif
foreach (YesNo? yesNo in Enum.GetValues(typeof(YesNo)))
{
#if NET48
testData.Add(new object[] { yesNo, false });
#else
testData.Add(new object?[] { yesNo, false });
#endif
}
return testData;

View File

@@ -30,11 +30,18 @@ namespace MPF.UI.Core
}
}
#if NET48
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
#else
public object? ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
#endif
{
// If it's an IElement but ends up null
var element = value as IElement;
if (element == null)
#if NET48
if (!(value is IElement element))
#else
if (value is not IElement element)
#endif
return null;
switch (element)

View File

@@ -18,7 +18,7 @@ namespace WPFCustomMessageBox
/// Global parameter to enable (true) or disable (false) the removal of the title bar icon.
/// If you are using a custom window style, the icon removal may cause issues like displaying two title bar (the default windows one and the custom one).
/// </summary>
public static bool RemoveTitleBarIcon = true;
private static readonly bool RemoveTitleBarIcon = true;
/// <summary>
/// Displays a message box that has a message and returns a result.
@@ -173,7 +173,11 @@ namespace WPFCustomMessageBox
/// </param>
/// <param name="timeoutResult">If the message box closes automatically due to the <paramref name="timeout"/> being exceeded, this result is returned.</param>
/// <returns>A System.Windows.MessageBoxResult value that specifies which message box button is clicked by the user.</returns>
#if NET48
public static MessageBoxResult Show(Window owner, string messageBoxText, string caption, MessageBoxButton button, MessageBoxImage icon, int? timeout = null, MessageBoxResult timeoutResult = MessageBoxResult.None)
#else
public static MessageBoxResult Show(Window owner, string? messageBoxText, string caption, MessageBoxButton button, MessageBoxImage icon, int? timeout = null, MessageBoxResult timeoutResult = MessageBoxResult.None)
#endif
{
switch (button)
{
@@ -515,11 +519,15 @@ namespace WPFCustomMessageBox
/// <param name="timeout">The message box will close automatically after given milliseconds</param>
/// <param name="timeoutResult">If the message box closes automatically due to <paramref name="timeout"/> being exceeded, this result is returned.</param>
/// <returns>A System.Windows.MessageBoxResult value that specifies which message box button is clicked by the user.</returns>
#if NET48
private static MessageBoxResult ShowOKMessage(Window owner, string messageBoxText, string caption, string okButtonText, string cancelButtonText, MessageBoxImage? icon, int? timeout = null, MessageBoxResult timeoutResult = MessageBoxResult.None)
#else
private static MessageBoxResult ShowOKMessage(Window? owner, string? messageBoxText, string caption, string? okButtonText, string? cancelButtonText, MessageBoxImage? icon, int? timeout = null, MessageBoxResult timeoutResult = MessageBoxResult.None)
#endif
{
MessageBoxButton buttonLayout = string.IsNullOrEmpty(cancelButtonText) ? MessageBoxButton.OK : MessageBoxButton.OKCancel;
CustomMessageBoxWindow msg = new CustomMessageBoxWindow(owner, messageBoxText, caption, buttonLayout, icon, RemoveTitleBarIcon);
var msg = new CustomMessageBoxWindow(owner, messageBoxText, caption, buttonLayout, icon, RemoveTitleBarIcon);
if (!string.IsNullOrEmpty(okButtonText))
msg.OkButtonText = okButtonText;
if (!string.IsNullOrEmpty(cancelButtonText))
@@ -545,11 +553,15 @@ namespace WPFCustomMessageBox
/// <param name="timeout">The message box will close automatically after given milliseconds</param>
/// <param name="timeoutResult">If the message box closes automatically due to <paramref name="timeout"/> being exceeded, this result is returned.</param>
/// <returns>A System.Windows.MessageBoxResult value that specifies which message box button is clicked by the user.</returns>
#if NET48
private static MessageBoxResult ShowYesNoMessage(Window owner, string messageBoxText, string caption, string yesButtonText, string noButtonText, string cancelButtonText, MessageBoxImage? icon, int? timeout = null, MessageBoxResult timeoutResult = MessageBoxResult.None)
#else
private static MessageBoxResult ShowYesNoMessage(Window? owner, string? messageBoxText, string caption, string? yesButtonText, string? noButtonText, string? cancelButtonText, MessageBoxImage? icon, int? timeout = null, MessageBoxResult timeoutResult = MessageBoxResult.None)
#endif
{
MessageBoxButton buttonLayout = string.IsNullOrEmpty(cancelButtonText) ? MessageBoxButton.YesNo : MessageBoxButton.YesNoCancel;
CustomMessageBoxWindow msg = new CustomMessageBoxWindow(owner, messageBoxText, caption, buttonLayout, icon, RemoveTitleBarIcon);
var msg = new CustomMessageBoxWindow(owner, messageBoxText, caption, buttonLayout, icon, RemoveTitleBarIcon);
if (!string.IsNullOrEmpty(yesButtonText))
msg.YesButtonText = yesButtonText;
if (!string.IsNullOrEmpty(noButtonText))
@@ -566,14 +578,14 @@ namespace WPFCustomMessageBox
{
if (timeout.HasValue && timeout.Value <= 0)
{
throw new ArgumentOutOfRangeException("timeout", string.Format("Timeout must be greater than 0."));
throw new ArgumentOutOfRangeException(nameof(timeout), string.Format("Timeout must be greater than 0."));
}
if (timeout.HasValue)
{
//System.Threading.Timer timer = null;
//timer = new System.Threading.Timer(s => { msg.Close(); timer.Dispose(); }, null, timeout.Value, System.Threading.Timeout.Infinite);
System.Timers.Timer timer = new System.Timers.Timer(timeout.Value) { AutoReset = false };
var timer = new System.Timers.Timer(timeout.Value) { AutoReset = false };
timer.Elapsed += delegate {
Application.Current.Dispatcher.Invoke(new Action(() =>
{

View File

@@ -10,9 +10,13 @@ namespace WPFCustomMessageBox
/// </summary>
internal partial class CustomMessageBoxWindow : Window
{
private bool _removeTitleBarIcon = true;
private readonly bool _removeTitleBarIcon = true;
#if NET48
public string Caption
#else
public string? Caption
#endif
{
get
{
@@ -24,7 +28,11 @@ namespace WPFCustomMessageBox
}
}
#if NET48
public string Message
#else
public string? Message
#endif
{
get
{
@@ -36,7 +44,11 @@ namespace WPFCustomMessageBox
}
}
#if NET48
public string OkButtonText
#else
public string? OkButtonText
#endif
{
get
{
@@ -48,7 +60,11 @@ namespace WPFCustomMessageBox
}
}
#if NET48
public string CancelButtonText
#else
public string? CancelButtonText
#endif
{
get
{
@@ -60,7 +76,11 @@ namespace WPFCustomMessageBox
}
}
#if NET48
public string YesButtonText
#else
public string? YesButtonText
#endif
{
get
{
@@ -72,7 +92,11 @@ namespace WPFCustomMessageBox
}
}
#if NET48
public string NoButtonText
#else
public string? NoButtonText
#endif
{
get
{
@@ -86,7 +110,11 @@ namespace WPFCustomMessageBox
public MessageBoxResult Result { get; set; }
#if NET48
internal CustomMessageBoxWindow(Window owner, string message, string caption = null, MessageBoxButton? button = null, MessageBoxImage? image = null, bool removeTitleBarIcon = true)
#else
internal CustomMessageBoxWindow(Window? owner, string? message, string? caption = null, MessageBoxButton? button = null, MessageBoxImage? image = null, bool removeTitleBarIcon = true)
#endif
{
InitializeComponent();
@@ -109,7 +137,7 @@ namespace WPFCustomMessageBox
if (image.HasValue)
DisplayImage(image.Value);
else
Image_MessageBox.Visibility = System.Windows.Visibility.Collapsed;
Image_MessageBox.Visibility = Visibility.Collapsed;
}
protected override void OnSourceInitialized(EventArgs e)
@@ -126,39 +154,39 @@ namespace WPFCustomMessageBox
{
case MessageBoxButton.OKCancel:
// Hide all but OK, Cancel
Button_OK.Visibility = System.Windows.Visibility.Visible;
Button_OK.Visibility = Visibility.Visible;
Button_OK.Focus();
Button_Cancel.Visibility = System.Windows.Visibility.Visible;
Button_Cancel.Visibility = Visibility.Visible;
Button_Yes.Visibility = System.Windows.Visibility.Collapsed;
Button_No.Visibility = System.Windows.Visibility.Collapsed;
Button_Yes.Visibility = Visibility.Collapsed;
Button_No.Visibility = Visibility.Collapsed;
break;
case MessageBoxButton.YesNo:
// Hide all but Yes, No
Button_Yes.Visibility = System.Windows.Visibility.Visible;
Button_Yes.Visibility = Visibility.Visible;
Button_Yes.Focus();
Button_No.Visibility = System.Windows.Visibility.Visible;
Button_No.Visibility = Visibility.Visible;
Button_OK.Visibility = System.Windows.Visibility.Collapsed;
Button_Cancel.Visibility = System.Windows.Visibility.Collapsed;
Button_OK.Visibility = Visibility.Collapsed;
Button_Cancel.Visibility = Visibility.Collapsed;
break;
case MessageBoxButton.YesNoCancel:
// Hide only OK
Button_Yes.Visibility = System.Windows.Visibility.Visible;
Button_Yes.Visibility = Visibility.Visible;
Button_Yes.Focus();
Button_No.Visibility = System.Windows.Visibility.Visible;
Button_Cancel.Visibility = System.Windows.Visibility.Visible;
Button_No.Visibility = Visibility.Visible;
Button_Cancel.Visibility = Visibility.Visible;
Button_OK.Visibility = System.Windows.Visibility.Collapsed;
Button_OK.Visibility = Visibility.Collapsed;
break;
default:
// Hide all but OK
Button_OK.Visibility = System.Windows.Visibility.Visible;
Button_OK.Visibility = Visibility.Visible;
Button_OK.Focus();
Button_Yes.Visibility = System.Windows.Visibility.Collapsed;
Button_No.Visibility = System.Windows.Visibility.Collapsed;
Button_Cancel.Visibility = System.Windows.Visibility.Collapsed;
Button_Yes.Visibility = Visibility.Collapsed;
Button_No.Visibility = Visibility.Collapsed;
Button_Cancel.Visibility = Visibility.Collapsed;
break;
}
}
@@ -187,7 +215,7 @@ namespace WPFCustomMessageBox
}
Image_MessageBox.Source = icon.ToImageSource();
Image_MessageBox.Visibility = System.Windows.Visibility.Visible;
Image_MessageBox.Visibility = Visibility.Visible;
}
private void Button_OK_Click(object sender, RoutedEventArgs e)

View File

@@ -37,7 +37,7 @@ namespace WPFCustomMessageBox
const int SWP_NOMOVE = 0x0002;
const int SWP_NOZORDER = 0x0004;
const int SWP_FRAMECHANGED = 0x0020;
const uint WM_SETICON = 0x0080;
//const uint WM_SETICON = 0x0080;
internal static ImageSource ToImageSource(this Icon icon)
@@ -60,7 +60,11 @@ namespace WPFCustomMessageBox
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
#if NET48
internal static string TryAddKeyboardAccellerator(this string input)
#else
internal static string? TryAddKeyboardAccellerator(this string? input)
#endif
{
if (input == null)
return input;
@@ -84,7 +88,7 @@ namespace WPFCustomMessageBox
IntPtr hwnd = new WindowInteropHelper(window).Handle;
// Change the extended window style to not show a window icon
int extendedStyle = GetWindowLong(hwnd, GWL_EXSTYLE);
SetWindowLong(hwnd, GWL_EXSTYLE, extendedStyle | WS_EX_DLGMODALFRAME);
_ = SetWindowLong(hwnd, GWL_EXSTYLE, extendedStyle | WS_EX_DLGMODALFRAME);
// Update the window's non-client area to reflect the changes
SetWindowPos(hwnd, IntPtr.Zero, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
}

View File

@@ -7,7 +7,11 @@
<UseWPF>true</UseWPF>
<Authors>Matt Nadareski;ReignStumble;Jakz</Authors>
<Copyright>Copyright (c)2019-2023</Copyright>
<VersionPrefix>2.7.0</VersionPrefix>
<VersionPrefix>2.7.1</VersionPrefix>
</PropertyGroup>
<PropertyGroup Condition="'$(TargetFramework)'!='net48'">
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>

View File

@@ -6,39 +6,63 @@ namespace MPF.UI.Core
/// <summary>
/// Represents all required mapping values for the UI
/// </summary>
public class Theme
public abstract class Theme
{
#region Application-Wide
/// <summary>
/// SolidColorBrush used to paint the active window's border.
/// </summary>
public SolidColorBrush ActiveBorderBrush { get; set; }
#if NET48
public SolidColorBrush ActiveBorderBrush { get; protected set; }
#else
public SolidColorBrush? ActiveBorderBrush { get; protected set; }
#endif
/// <summary>
/// SolidColorBrush that paints the face of a three-dimensional display element.
/// </summary>
public SolidColorBrush ControlBrush { get; set; }
#if NET48
public SolidColorBrush ControlBrush { get; protected set; }
#else
public SolidColorBrush? ControlBrush { get; protected set; }
#endif
/// <summary>
/// SolidColorBrush that paints text in a three-dimensional display element.
/// </summary>
public SolidColorBrush ControlTextBrush { get; set; }
#if NET48
public SolidColorBrush ControlTextBrush { get; protected set; }
#else
public SolidColorBrush? ControlTextBrush { get; protected set; }
#endif
/// <summary>
/// SolidColorBrush that paints disabled text.
/// </summary>
public SolidColorBrush GrayTextBrush { get; set; }
#if NET48
public SolidColorBrush GrayTextBrush { get; protected set; }
#else
public SolidColorBrush? GrayTextBrush { get; protected set; }
#endif
/// <summary>
/// SolidColorBrush that paints the background of a window's client area.
/// </summary>
public SolidColorBrush WindowBrush { get; set; }
#if NET48
public SolidColorBrush WindowBrush { get; protected set; }
#else
public SolidColorBrush? WindowBrush { get; protected set; }
#endif
/// <summary>
/// SolidColorBrush that paints the text in the client area of a window.
/// </summary>
public SolidColorBrush WindowTextBrush { get; set; }
#if NET48
public SolidColorBrush WindowTextBrush { get; protected set; }
#else
public SolidColorBrush? WindowTextBrush { get; protected set; }
#endif
#endregion
@@ -47,22 +71,38 @@ namespace MPF.UI.Core
/// <summary>
/// Brush for the Button.Disabled.Background resource
/// </summary>
public Brush Button_Disabled_Background { get; set; }
#if NET48
public Brush Button_Disabled_Background { get; protected set; }
#else
public Brush? Button_Disabled_Background { get; protected set; }
#endif
/// <summary>
/// Brush for the Button.MouseOver.Background resource
/// </summary>
public Brush Button_MouseOver_Background { get; set; }
#if NET48
public Brush Button_MouseOver_Background { get; protected set; }
#else
public Brush? Button_MouseOver_Background { get; protected set; }
#endif
/// <summary>
/// Brush for the Button.Pressed.Background resource
/// </summary>
public Brush Button_Pressed_Background { get; set; }
#if NET48
public Brush Button_Pressed_Background { get; protected set; }
#else
public Brush? Button_Pressed_Background { get; protected set; }
#endif
/// <summary>
/// Brush for the Button.Static.Background resource
/// </summary>
public Brush Button_Static_Background { get; set; }
#if NET48
public Brush Button_Static_Background { get; protected set; }
#else
public Brush? Button_Static_Background { get; protected set; }
#endif
#endregion
@@ -71,62 +111,110 @@ namespace MPF.UI.Core
/// <summary>
/// Brush for the ComboBox.Disabled.Background resource
/// </summary>
public Brush ComboBox_Disabled_Background { get; set; }
#if NET48
public Brush ComboBox_Disabled_Background { get; protected set; }
#else
public Brush? ComboBox_Disabled_Background { get; protected set; }
#endif
/// <summary>
/// Brush for the ComboBox.Disabled.Editable.Background resource
/// </summary>
public Brush ComboBox_Disabled_Editable_Background { get; set; }
#if NET48
public Brush ComboBox_Disabled_Editable_Background { get; protected set; }
#else
public Brush? ComboBox_Disabled_Editable_Background { get; protected set; }
#endif
/// <summary>
/// Brush for the ComboBox.Disabled.Editable.Button.Background resource
/// </summary>
public Brush ComboBox_Disabled_Editable_Button_Background { get; set; }
#if NET48
public Brush ComboBox_Disabled_Editable_Button_Background { get; protected set; }
#else
public Brush? ComboBox_Disabled_Editable_Button_Background { get; protected set; }
#endif
/// <summary>
/// Brush for the ComboBox.MouseOver.Background resource
/// </summary>
public Brush ComboBox_MouseOver_Background { get; set; }
#if NET48
public Brush ComboBox_MouseOver_Background { get; protected set; }
#else
public Brush? ComboBox_MouseOver_Background { get; protected set; }
#endif
/// <summary>
/// Brush for the ComboBox.MouseOver.Editable.Background resource
/// </summary>
public Brush ComboBox_MouseOver_Editable_Background { get; set; }
#if NET48
public Brush ComboBox_MouseOver_Editable_Background { get; protected set; }
#else
public Brush? ComboBox_MouseOver_Editable_Background { get; protected set; }
#endif
/// <summary>
/// Brush for the ComboBox.MouseOver.Editable.Button.Background resource
/// </summary>
public Brush ComboBox_MouseOver_Editable_Button_Background { get; set; }
#if NET48
public Brush ComboBox_MouseOver_Editable_Button_Background { get; protected set; }
#else
public Brush? ComboBox_MouseOver_Editable_Button_Background { get; protected set; }
#endif
/// <summary>
/// Brush for the ComboBox.Pressed.Background resource
/// </summary>
public Brush ComboBox_Pressed_Background { get; set; }
#if NET48
public Brush ComboBox_Pressed_Background { get; protected set; }
#else
public Brush? ComboBox_Pressed_Background { get; protected set; }
#endif
/// <summary>
/// Brush for the ComboBox.Pressed.Editable.Background resource
/// </summary>
public Brush ComboBox_Pressed_Editable_Background { get; set; }
#if NET48
public Brush ComboBox_Pressed_Editable_Background { get; protected set; }
#else
public Brush? ComboBox_Pressed_Editable_Background { get; protected set; }
#endif
/// <summary>
/// Brush for the ComboBox.Pressed.Editable.Button.Background resource
/// </summary>
public Brush ComboBox_Pressed_Editable_Button_Background { get; set; }
#if NET48
public Brush ComboBox_Pressed_Editable_Button_Background { get; protected set; }
#else
public Brush? ComboBox_Pressed_Editable_Button_Background { get; protected set; }
#endif
/// <summary>
/// Brush for the ComboBox.Static.Background resource
/// </summary>
public Brush ComboBox_Static_Background { get; set; }
#if NET48
public Brush ComboBox_Static_Background { get; protected set; }
#else
public Brush? ComboBox_Static_Background { get; protected set; }
#endif
/// <summary>
/// Brush for the ComboBox.Static.Editable.Background resource
/// </summary>
public Brush ComboBox_Static_Editable_Background { get; set; }
#if NET48
public Brush ComboBox_Static_Editable_Background { get; protected set; }
#else
public Brush? ComboBox_Static_Editable_Background { get; protected set; }
#endif
/// <summary>
/// Brush for the ComboBox.Static.Editable.Button.Background resource
/// </summary>
public Brush ComboBox_Static_Editable_Button_Background { get; set; }
#if NET48
public Brush ComboBox_Static_Editable_Button_Background { get; protected set; }
#else
public Brush? ComboBox_Static_Editable_Button_Background { get; protected set; }
#endif
#endregion
@@ -135,7 +223,11 @@ namespace MPF.UI.Core
/// <summary>
/// Brush for the CustomMessageBox.Static.Background resource
/// </summary>
public Brush CustomMessageBox_Static_Background { get; set; }
#if NET48
public Brush CustomMessageBox_Static_Background { get; protected set; }
#else
public Brush? CustomMessageBox_Static_Background { get; protected set; }
#endif
#endregion
@@ -144,12 +236,20 @@ namespace MPF.UI.Core
/// <summary>
/// Brush for the MenuItem.SubMenu.Background resource
/// </summary>
public Brush MenuItem_SubMenu_Background { get; set; }
#if NET48
public Brush MenuItem_SubMenu_Background { get; protected set; }
#else
public Brush? MenuItem_SubMenu_Background { get; protected set; }
#endif
/// <summary>
/// Brush for the MenuItem.SubMenu.Border resource
/// </summary>
public Brush MenuItem_SubMenu_Border { get; set; }
#if NET48
public Brush MenuItem_SubMenu_Border { get; protected set; }
#else
public Brush? MenuItem_SubMenu_Border { get; protected set; }
#endif
#endregion
@@ -158,7 +258,11 @@ namespace MPF.UI.Core
/// <summary>
/// Brush for the ProgressBar.Background resource
/// </summary>
public Brush ProgressBar_Background { get; set; }
#if NET48
public Brush ProgressBar_Background { get; protected set; }
#else
public Brush? ProgressBar_Background { get; protected set; }
#endif
#endregion
@@ -167,7 +271,11 @@ namespace MPF.UI.Core
/// <summary>
/// Brush for the ScrollViewer.ScrollBar.Background resource
/// </summary>
public Brush ScrollViewer_ScrollBar_Background { get; set; }
#if NET48
public Brush ScrollViewer_ScrollBar_Background { get; protected set; }
#else
public Brush? ScrollViewer_ScrollBar_Background { get; protected set; }
#endif
#endregion
@@ -176,17 +284,29 @@ namespace MPF.UI.Core
/// <summary>
/// Brush for the TabItem.Selected.Background resource
/// </summary>
public Brush TabItem_Selected_Background { get; set; }
#if NET48
public Brush TabItem_Selected_Background { get; protected set; }
#else
public Brush? TabItem_Selected_Background { get; protected set; }
#endif
/// <summary>
/// Brush for the TabItem.Static.Background resource
/// </summary>
public Brush TabItem_Static_Background { get; set; }
#if NET48
public Brush TabItem_Static_Background { get; protected set; }
#else
public Brush? TabItem_Static_Background { get; protected set; }
#endif
/// <summary>
/// Brush for the TabItem.Static.Border resource
/// </summary>
public Brush TabItem_Static_Border { get; set; }
#if NET48
public Brush TabItem_Static_Border { get; protected set; }
#else
public Brush? TabItem_Static_Border { get; protected set; }
#endif
#endregion
@@ -195,7 +315,11 @@ namespace MPF.UI.Core
/// <summary>
/// Brush for the TextBox.Static.Background resource
/// </summary>
public Brush TextBox_Static_Background { get; set; }
#if NET48
public Brush TextBox_Static_Background { get; protected set; }
#else
public Brush? TextBox_Static_Background { get; protected set; }
#endif
#endregion

View File

@@ -29,7 +29,11 @@ namespace MPF.UI.Core.UserControls
/// <summary>
/// Cached value of the last line written
/// </summary>
#if NET48
private Run lastLine = null;
#else
private Run? lastLine = null;
#endif
public LogOutput()
{
@@ -164,12 +168,17 @@ namespace MPF.UI.Core.UserControls
{
Dispatcher.Invoke(() =>
{
#if NET48
if (lastLine == null) lastLine = new Run();
#else
lastLine ??= new Run();
#endif
lastLine.Text = logLine.Text;
lastLine.Foreground = logLine.GetForegroundColor();
});
}
#endregion
#endregion
#region Helpers
@@ -183,12 +192,12 @@ namespace MPF.UI.Core.UserControls
/// </summary>
private void SaveInlines()
{
using (StreamWriter tw = new StreamWriter(File.OpenWrite("console.log")))
using (var sw = new StreamWriter(File.OpenWrite("console.log")))
{
foreach (var inline in _paragraph.Inlines)
{
if (inline is Run run)
tw.Write(run.Text);
sw.Write(run.Text);
}
}
}

View File

@@ -15,12 +15,16 @@ namespace MPF.UI.Core.Windows
/// <summary>
/// Read-only access to the current disc information view model
/// </summary>
public DiscInformationViewModel DiscInformationViewModel => DataContext as DiscInformationViewModel;
public DiscInformationViewModel DiscInformationViewModel => DataContext as DiscInformationViewModel ?? new DiscInformationViewModel(new Options(), new SubmissionInfo());
/// <summary>
/// Constructor
/// </summary>
#if NET48
public DiscInformationWindow(Options options, SubmissionInfo submissionInfo)
#else
public DiscInformationWindow(Options options, SubmissionInfo? submissionInfo)
#endif
{
InitializeComponent();
DataContext = new DiscInformationViewModel(options, submissionInfo);
@@ -47,7 +51,11 @@ namespace MPF.UI.Core.Windows
/// <summary>
/// Manipulate fields based on the current disc
/// </summary>
#if NET48
private void ManipulateFields(Options options, SubmissionInfo submissionInfo)
#else
private void ManipulateFields(Options options, SubmissionInfo? submissionInfo)
#endif
{
// Enable tabs in all fields, if required
if (options.EnableTabsInInputFields)
@@ -115,63 +123,71 @@ namespace MPF.UI.Core.Windows
/// </summary>
/// TODO: Figure out how to bind the PartiallyMatchedIDs array to a text box
/// TODO: Convert visibility to a binding
#if NET48
private void HideReadOnlyFields(SubmissionInfo submissionInfo)
#else
private void HideReadOnlyFields(SubmissionInfo? submissionInfo)
#endif
{
if (submissionInfo?.FullyMatchedID == null)
// If there's no submission information
if (submissionInfo == null)
return;
if (submissionInfo.FullyMatchedID == null)
FullyMatchedID.Visibility = Visibility.Collapsed;
if (submissionInfo?.PartiallyMatchedIDs == null)
if (submissionInfo.PartiallyMatchedIDs == null)
PartiallyMatchedIDs.Visibility = Visibility.Collapsed;
else
PartiallyMatchedIDs.Text = string.Join(", ", submissionInfo.PartiallyMatchedIDs);
if (submissionInfo?.CopyProtection?.AntiModchip == null)
if (submissionInfo.CopyProtection?.AntiModchip == null)
AntiModchip.Visibility = Visibility.Collapsed;
if (submissionInfo?.TracksAndWriteOffsets?.OtherWriteOffsets == null)
if (submissionInfo.TracksAndWriteOffsets?.OtherWriteOffsets == null)
DiscOffset.Visibility = Visibility.Collapsed;
if (submissionInfo?.CommonDiscInfo?.CommentsSpecialFields.Keys.Contains(SiteCode.DMIHash) != true)
if (submissionInfo.CommonDiscInfo?.CommentsSpecialFields?.Keys?.Contains(SiteCode.DMIHash) != true)
DMIHash.Visibility = Visibility.Collapsed;
if (submissionInfo?.EDC?.EDC == null)
if (submissionInfo.EDC?.EDC == null)
EDC.Visibility = Visibility.Collapsed;
if (string.IsNullOrWhiteSpace(submissionInfo?.CommonDiscInfo?.ErrorsCount))
if (string.IsNullOrWhiteSpace(submissionInfo.CommonDiscInfo?.ErrorsCount))
ErrorsCount.Visibility = Visibility.Collapsed;
if (string.IsNullOrWhiteSpace(submissionInfo?.CommonDiscInfo?.EXEDateBuildDate))
if (string.IsNullOrWhiteSpace(submissionInfo.CommonDiscInfo?.EXEDateBuildDate))
EXEDateBuildDate.Visibility = Visibility.Collapsed;
if (submissionInfo?.CommonDiscInfo?.CommentsSpecialFields.Keys.Contains(SiteCode.Filename) != true)
if (submissionInfo.CommonDiscInfo?.CommentsSpecialFields?.ContainsKey(SiteCode.Filename) != true)
Filename.Visibility = Visibility.Collapsed;
if (string.IsNullOrWhiteSpace(submissionInfo?.Extras?.Header))
if (string.IsNullOrWhiteSpace(submissionInfo.Extras?.Header))
Header.Visibility = Visibility.Collapsed;
if (submissionInfo?.CommonDiscInfo?.CommentsSpecialFields.Keys.Contains(SiteCode.InternalName) != true)
if (submissionInfo.CommonDiscInfo?.CommentsSpecialFields?.ContainsKey(SiteCode.InternalName) != true)
InternalName.Visibility = Visibility.Collapsed;
if (submissionInfo?.CommonDiscInfo?.CommentsSpecialFields.Keys.Contains(SiteCode.InternalSerialName) != true)
if (submissionInfo.CommonDiscInfo?.CommentsSpecialFields?.ContainsKey(SiteCode.InternalSerialName) != true)
InternalSerialName.Visibility = Visibility.Collapsed;
if (submissionInfo?.CommonDiscInfo?.CommentsSpecialFields.Keys.Contains(SiteCode.Multisession) != true)
if (submissionInfo.CommonDiscInfo?.CommentsSpecialFields?.ContainsKey(SiteCode.Multisession) != true)
Multisession.Visibility = Visibility.Collapsed;
if (submissionInfo?.CopyProtection?.LibCrypt == null)
if (submissionInfo.CopyProtection?.LibCrypt == null)
LibCrypt.Visibility = Visibility.Collapsed;
if (string.IsNullOrWhiteSpace(submissionInfo?.CopyProtection?.LibCryptData))
if (string.IsNullOrWhiteSpace(submissionInfo.CopyProtection?.LibCryptData))
LibCryptData.Visibility = Visibility.Collapsed;
if (submissionInfo?.CommonDiscInfo?.CommentsSpecialFields.Keys.Contains(SiteCode.PFIHash) != true)
if (submissionInfo.CommonDiscInfo?.CommentsSpecialFields?.ContainsKey(SiteCode.PFIHash) != true)
PFIHash.Visibility = Visibility.Collapsed;
if (string.IsNullOrWhiteSpace(submissionInfo?.Extras?.PIC))
if (string.IsNullOrWhiteSpace(submissionInfo.Extras?.PIC))
PIC.Visibility = Visibility.Collapsed;
if (string.IsNullOrWhiteSpace(submissionInfo?.Extras?.PVD))
if (string.IsNullOrWhiteSpace(submissionInfo.Extras?.PVD))
PVD.Visibility = Visibility.Collapsed;
if (submissionInfo?.CommonDiscInfo?.CommentsSpecialFields.Keys.Contains(SiteCode.RingNonZeroDataStart) != true)
if (submissionInfo.CommonDiscInfo?.CommentsSpecialFields?.ContainsKey(SiteCode.RingNonZeroDataStart) != true)
RingNonZeroDataStart.Visibility = Visibility.Collapsed;
if (string.IsNullOrWhiteSpace(submissionInfo?.CopyProtection?.SecuROMData))
if (string.IsNullOrWhiteSpace(submissionInfo.CopyProtection?.SecuROMData))
SecuROMData.Visibility = Visibility.Collapsed;
if (submissionInfo?.CommonDiscInfo?.CommentsSpecialFields.Keys.Contains(SiteCode.SSHash) != true)
if (submissionInfo.CommonDiscInfo?.CommentsSpecialFields?.ContainsKey(SiteCode.SSHash) != true)
SSHash.Visibility = Visibility.Collapsed;
if (string.IsNullOrWhiteSpace(submissionInfo?.Extras?.SecuritySectorRanges))
if (string.IsNullOrWhiteSpace(submissionInfo.Extras?.SecuritySectorRanges))
SecuritySectorRanges.Visibility = Visibility.Collapsed;
if (submissionInfo?.CommonDiscInfo?.CommentsSpecialFields.Keys.Contains(SiteCode.SSVersion) != true)
if (submissionInfo.CommonDiscInfo?.CommentsSpecialFields?.ContainsKey(SiteCode.SSVersion) != true)
SSVersion.Visibility = Visibility.Collapsed;
if (submissionInfo?.CommonDiscInfo?.CommentsSpecialFields.Keys.Contains(SiteCode.UniversalHash) != true)
if (submissionInfo.CommonDiscInfo?.CommentsSpecialFields?.ContainsKey(SiteCode.UniversalHash) != true)
UniversalHash.Visibility = Visibility.Collapsed;
if (submissionInfo?.CommonDiscInfo?.CommentsSpecialFields.Keys.Contains(SiteCode.VolumeLabel) != true)
if (submissionInfo.CommonDiscInfo?.CommentsSpecialFields?.ContainsKey(SiteCode.VolumeLabel) != true)
VolumeLabel.Visibility = Visibility.Collapsed;
if (submissionInfo?.CommonDiscInfo?.CommentsSpecialFields.Keys.Contains(SiteCode.XeMID) != true)
if (submissionInfo.CommonDiscInfo?.CommentsSpecialFields?.ContainsKey(SiteCode.XeMID) != true)
XeMID.Visibility = Visibility.Collapsed;
if (submissionInfo?.CommonDiscInfo?.CommentsSpecialFields.Keys.Contains(SiteCode.XMID) != true)
if (submissionInfo.CommonDiscInfo?.CommentsSpecialFields?.ContainsKey(SiteCode.XMID) != true)
XMID.Visibility = Visibility.Collapsed;
}
@@ -179,7 +195,11 @@ namespace MPF.UI.Core.Windows
/// Update visible fields and sections based on the media type
/// </summary>
/// TODO: See if these can be done by binding
#if NET48
private void UpdateFromDiscType(SubmissionInfo submissionInfo)
#else
private void UpdateFromDiscType(SubmissionInfo? submissionInfo)
#endif
{
// Sony-printed discs have layers in the opposite order
var system = submissionInfo?.CommonDiscInfo?.System;
@@ -326,7 +346,11 @@ namespace MPF.UI.Core.Windows
/// Update visible fields and sections based on the system type
/// </summary>
/// TODO: See if these can be done by binding
#if NET48
private void UpdateFromSystemType(SubmissionInfo submissionInfo)
#else
private void UpdateFromSystemType(SubmissionInfo? submissionInfo)
#endif
{
var system = submissionInfo?.CommonDiscInfo?.System;
switch (system)
@@ -337,7 +361,7 @@ namespace MPF.UI.Core.Windows
}
}
#endregion
#endregion
#region Event Handlers

View File

@@ -15,7 +15,7 @@ namespace MPF.UI.Core.Windows
/// <summary>
/// Read-only access to the current main view model
/// </summary>
public MainViewModel MainViewModel => DataContext as MainViewModel;
public MainViewModel MainViewModel => DataContext as MainViewModel ?? new MainViewModel();
/// <summary>
/// Constructor
@@ -95,8 +95,10 @@ namespace MPF.UI.Core.Windows
{
// Get the current path, if possible
string currentPath = MainViewModel.OutputPath;
if (string.IsNullOrWhiteSpace(currentPath))
if (string.IsNullOrWhiteSpace(currentPath) && !string.IsNullOrWhiteSpace(MainViewModel.Options.DefaultOutputPath))
currentPath = Path.Combine(MainViewModel.Options.DefaultOutputPath, "track.bin");
else if (string.IsNullOrWhiteSpace(currentPath))
currentPath = "track.bin";
if (string.IsNullOrWhiteSpace(currentPath))
currentPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "track.bin");
@@ -104,7 +106,7 @@ namespace MPF.UI.Core.Windows
currentPath = Path.GetFullPath(currentPath);
// Get the directory
string directory = Path.GetDirectoryName(currentPath);
var directory = Path.GetDirectoryName(currentPath);
// Get the filename
string filename = Path.GetFileName(currentPath);
@@ -128,14 +130,14 @@ namespace MPF.UI.Core.Windows
/// <param name="showIfSame">True to show the box even if it's the same, false to only show if it's different</param>
public void CheckForUpdates(bool showIfSame)
{
(bool different, string message, string url) = MainViewModel.CheckForUpdates();
(bool different, string message, var url) = MainViewModel.CheckForUpdates();
// If we have a new version, put it in the clipboard
if (different)
Clipboard.SetText(url);
if (showIfSame || different)
CustomMessageBox.Show(message, "Version Update Check", MessageBoxButton.OK, different ? MessageBoxImage.Exclamation : MessageBoxImage.Information);
CustomMessageBox.Show(this, message, "Version Update Check", MessageBoxButton.OK, different ? MessageBoxImage.Exclamation : MessageBoxImage.Information);
}
/// <summary>
@@ -204,10 +206,14 @@ namespace MPF.UI.Core.Windows
/// </summary>
/// <param name="submissionInfo">SubmissionInfo object to display and possibly change</param>
/// <returns>Dialog open result</returns>
#if NET48
public (bool?, SubmissionInfo) ShowDiscInformationWindow(SubmissionInfo submissionInfo)
#else
public (bool?, SubmissionInfo?) ShowDiscInformationWindow(SubmissionInfo? submissionInfo)
#endif
{
if (MainViewModel.Options.ShowDiscEjectReminder)
CustomMessageBox.Show("It is now safe to eject the disc", "Eject", MessageBoxButton.OK, MessageBoxImage.Information);
CustomMessageBox.Show(this, "It is now safe to eject the disc", "Eject", MessageBoxButton.OK, MessageBoxImage.Information);
var discInformationWindow = new DiscInformationWindow(MainViewModel.Options, submissionInfo)
{
@@ -221,9 +227,17 @@ namespace MPF.UI.Core.Windows
// Copy back the submission info changes, if necessary
if (result == true)
#if NET48
submissionInfo = discInformationWindow.DiscInformationViewModel.SubmissionInfo.Clone() as SubmissionInfo;
#else
submissionInfo = (discInformationWindow.DiscInformationViewModel.SubmissionInfo.Clone() as SubmissionInfo)!;
#endif
#if NET48
return (result, submissionInfo);
#else
return (result, submissionInfo!);
#endif
}
/// <summary>
@@ -268,10 +282,14 @@ namespace MPF.UI.Core.Windows
/// <summary>
/// Handler for OptionsWindow OnUpdated event
/// </summary>
#if NET48
public void OnOptionsUpdated(object sender, EventArgs e)
#else
public void OnOptionsUpdated(object? sender, EventArgs e)
#endif
{
bool savedSettings = (sender as OptionsWindow)?.OptionsViewModel?.SavedSettings ?? false;
var options = (sender as OptionsWindow).OptionsViewModel.Options;
var options = (sender as OptionsWindow)?.OptionsViewModel?.Options;
MainViewModel.UpdateOptions(savedSettings, options);
}
@@ -283,7 +301,7 @@ namespace MPF.UI.Core.Windows
public void AboutClick(object sender, RoutedEventArgs e)
{
string aboutText = MainViewModel.CreateAboutText();
CustomMessageBox.Show(aboutText, "About", MessageBoxButton.OK, MessageBoxImage.Information);
CustomMessageBox.Show(this, aboutText, "About", MessageBoxButton.OK, MessageBoxImage.Information);
}
/// <summary>
@@ -319,14 +337,14 @@ namespace MPF.UI.Core.Windows
/// </summary>
public async void CopyProtectScanButtonClick(object sender, RoutedEventArgs e)
{
(string output, string error) = await MainViewModel.ScanAndShowProtection();
var (output, error) = await MainViewModel.ScanAndShowProtection();
if (!MainViewModel.LogPanelExpanded)
{
if (string.IsNullOrEmpty(error))
CustomMessageBox.Show(output, "Detected Protection(s)", MessageBoxButton.OK, MessageBoxImage.Information);
if (!string.IsNullOrEmpty(output) && string.IsNullOrEmpty(error))
CustomMessageBox.Show(this, output, "Detected Protection(s)", MessageBoxButton.OK, MessageBoxImage.Information);
else
CustomMessageBox.Show("An exception occurred, see the log for details", "Error!", MessageBoxButton.OK, MessageBoxImage.Error);
CustomMessageBox.Show(this, "An exception occurred, see the log for details", "Error!", MessageBoxButton.OK, MessageBoxImage.Error);
}
}

View File

@@ -63,7 +63,7 @@
</Button>
</Grid>
</Grid>
<TabControl Margin="5,5,5,5" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
Background="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"
Foreground="{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}"
@@ -84,7 +84,7 @@
/>
</UniformGrid>
</TabItem>
<TabItem Header="Paths" Style="{DynamicResource CustomTabItemStyle}">
<Grid Margin="5,5,5,5">
<Grid.ColumnDefinitions>
@@ -232,7 +232,7 @@
/>
</UniformGrid>
</GroupBox>
<GroupBox Margin="5,5,5,5" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Header="Default Speeds" Grid.ColumnSpan="2">
<Grid>
<Grid.ColumnDefinitions>
@@ -247,7 +247,7 @@
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Label Grid.Row="0" Grid.Column="0" Content="CD" />
<Slider x:Name="DumpSpeedCDSlider" Grid.Row="0" Grid.Column="1" Minimum="1" Maximum="72" IsSnapToTickEnabled="True" TickPlacement="BottomRight"
Ticks="{Binding Source={x:Static core:Constants.SpeedsForCDAsCollection}}"
@@ -357,7 +357,8 @@
IsChecked="{Binding Options.DICMultiSectorRead}"
ToolTip="Enable the /mr flag for BD drive dumping" Margin="0,4"
/>
<Label/> <!-- Empty label for padding -->
<Label/>
<!-- Empty label for padding -->
<Label Content="Multi-Sector Read Value:" VerticalAlignment="Center" HorizontalAlignment="Right"/>
<TextBox VerticalAlignment="Center" VerticalContentAlignment="Center"
@@ -390,7 +391,17 @@
IsChecked="{Binding Options.RedumperEnableVerbose}"
ToolTip="Enable verbose output in logs" Margin="0,4"
/>
<CheckBox VerticalAlignment="Center" Content="Enable BE Drive Reading"
IsChecked="{Binding Options.RedumperUseBEReading}"
ToolTip="Enable setting drive read method to BE_CDDA by default" Margin="0,4"
/>
<CheckBox VerticalAlignment="Center" Content="Set Generic Drive Type"
IsChecked="{Binding Options.RedumperUseGenericDriveType}"
ToolTip="Enable setting drive type to Generic by default" Margin="0,4"
/>
<Label Content="Reread Tries:" VerticalAlignment="Center" HorizontalAlignment="Right"/>
<TextBox VerticalAlignment="Center" VerticalContentAlignment="Center"
Text="{Binding Options.RedumperRereadCount}"
@@ -441,12 +452,14 @@
<!-- Accept / Cancel -->
<GroupBox Margin="5,5,5,5" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<UniformGrid Columns="4" Margin="5,5,5,5" Height="28">
<Label/> <!-- Empty label for padding -->
<Label/>
<!-- Empty label for padding -->
<Button Name="AcceptButton" Height="25" Width="80" IsDefault="True" Content="Accept"
Style="{DynamicResource CustomButtonStyle}" />
<Button Name="CancelButton" Height="25" Width="80" IsCancel="True" Content="Cancel"
Style="{DynamicResource CustomButtonStyle}" />
<Label/> <!-- Empty label for padding -->
<Label/>
<!-- Empty label for padding -->
</UniformGrid>
</GroupBox>
</StackPanel>

View File

@@ -17,7 +17,7 @@ namespace MPF.UI.Core.Windows
/// <summary>
/// Read-only access to the current options view model
/// </summary>
public OptionsViewModel OptionsViewModel => DataContext as OptionsViewModel;
public OptionsViewModel OptionsViewModel => DataContext as OptionsViewModel ?? new OptionsViewModel(new Options());
/// <summary>
/// Constructor
@@ -46,20 +46,28 @@ namespace MPF.UI.Core.Windows
/// <summary>
/// Browse and set a path based on the invoking button
/// </summary>
#if NET48
private void BrowseForPath(Window parent, System.Windows.Controls.Button button)
#else
private void BrowseForPath(Window parent, System.Windows.Controls.Button? button)
#endif
{
// If the button is null, we can't do anything
if (button == null)
return;
// Strips button prefix to obtain the setting name
#if NET48
string pathSettingName = button.Name.Substring(0, button.Name.IndexOf("Button"));
#else
string pathSettingName = button.Name[..button.Name.IndexOf("Button")];
#endif
// TODO: hack for now, then we'll see
bool shouldBrowseForPath = pathSettingName == "DefaultOutputPath";
string currentPath = TextBoxForPathSetting(parent, pathSettingName)?.Text;
string initialDirectory = AppDomain.CurrentDomain.BaseDirectory;
var currentPath = TextBoxForPathSetting(parent, pathSettingName)?.Text;
var initialDirectory = AppDomain.CurrentDomain.BaseDirectory;
if (!shouldBrowseForPath && !string.IsNullOrEmpty(currentPath))
initialDirectory = Path.GetDirectoryName(Path.GetFullPath(currentPath));
@@ -88,7 +96,9 @@ namespace MPF.UI.Core.Windows
if (exists)
{
OptionsViewModel.Options[pathSettingName] = path;
TextBoxForPathSetting(parent, pathSettingName).Text = path;
var textBox = TextBoxForPathSetting(parent, pathSettingName);
if (textBox != null)
textBox.Text = path;
}
else
{
@@ -108,18 +118,30 @@ namespace MPF.UI.Core.Windows
/// </summary>
/// <param name="name">Setting name to find</param>
/// <returns>TextBox for that setting</returns>
private System.Windows.Controls.TextBox TextBoxForPathSetting(Window parent, string name) =>
#if NET48
private static System.Windows.Controls.TextBox TextBoxForPathSetting(Window parent, string name) =>
#else
private static System.Windows.Controls.TextBox? TextBoxForPathSetting(Window parent, string name) =>
#endif
parent.FindName(name + "TextBox") as System.Windows.Controls.TextBox;
/// <summary>
/// Create an open folder dialog box
/// </summary>
#if NET48
private static FolderBrowserDialog CreateFolderBrowserDialog() => new FolderBrowserDialog();
#else
private static FolderBrowserDialog CreateFolderBrowserDialog() => new();
#endif
/// <summary>
/// Create an open file dialog box
/// </summary>
#if NET48
private static OpenFileDialog CreateOpenFileDialog(string initialDirectory)
#else
private static OpenFileDialog CreateOpenFileDialog(string? initialDirectory)
#endif
{
return new OpenFileDialog()
{
@@ -142,7 +164,7 @@ namespace MPF.UI.Core.Windows
#if NET48
(bool? success, string message) = OptionsViewModel.TestRedumpLogin(RedumpUsernameTextBox.Text, RedumpPasswordBox.Password);
#else
(bool? success, string message) = await OptionsViewModel.TestRedumpLogin(RedumpUsernameTextBox.Text, RedumpPasswordBox.Password);
(bool? success, string? message) = await OptionsViewModel.TestRedumpLogin(RedumpUsernameTextBox.Text, RedumpPasswordBox.Password);
#endif
if (success == true)

View File

@@ -1,16 +1,7 @@
using System.Windows;
namespace MPF
namespace MPF
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
/// <remarks>
/// This application is not fully MVVM. The following steps are needed to get there:
/// - Use commands instead of event handlers, where at all possible
/// - Reduce the amount of manual UI adjustments needed, instead binding to the view models
/// </remarks>
public partial class App : Application
{
}
public partial class App : System.Windows.Application { }
}

View File

@@ -11,10 +11,14 @@
<Description>Frontend for various dumping programs</Description>
<Authors>Matt Nadareski;ReignStumble;Jakz</Authors>
<Copyright>Copyright (c)2019-2023</Copyright>
<VersionPrefix>2.7.0</VersionPrefix>
<VersionPrefix>2.7.1</VersionPrefix>
<InternalsVisibleTo>MPF.Test</InternalsVisibleTo>
</PropertyGroup>
<PropertyGroup Condition="'$(TargetFramework)'!='net48'">
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<Resource Include="Images\Icon.ico" />
</ItemGroup>

View File

@@ -1,5 +1,5 @@
# version format
version: 2.7.0-{build}
version: 2.7.1-{build}
# pull request template
pull_requests:
@@ -49,78 +49,27 @@ after_build:
# Aaru
- ps: appveyor DownloadFile https://github.com/aaru-dps/Aaru/releases/download/v5.3.2/aaru-5.3.2_windows_x64.zip
- 7z x aaru-5.3.2_windows_x64.zip -oMPF\bin\Debug\net48\win7-x64\publish\Programs\Aaru *
- 7z x aaru-5.3.2_windows_x64.zip -oMPF\bin\Debug\net6.0-windows\win-x64\publish\Programs\Aaru *
- 7z x aaru-5.3.2_windows_x64.zip -oMPF\bin\Debug\net7.0-windows\win-x64\publish\Programs\Aaru *
# - 7z x aaru-5.3.2_windows_x64.zip -oMPF\bin\Release\net48\win7-x64\publish\Programs\Aaru *
# - 7z x aaru-5.3.2_windows_x64.zip -oMPF\bin\Release\net6.0-windows\win-x64\publish\Programs\Aaru *
# - 7z x aaru-5.3.2_windows_x64.zip -oMPF\bin\Release\net7.0-windows\win-x64\publish\Programs\Aaru *
# DiscImageCreator
- ps: appveyor DownloadFile https://github.com/saramibreak/DiscImageCreator/files/11660558/DiscImageCreator_20230606.zip
- 7z e DiscImageCreator_20230606.zip -oMPF\bin\Debug\net48\win7-x64\publish\Programs\Creator Release_ANSI\*
- 7z e DiscImageCreator_20230606.zip -oMPF\bin\Debug\net6.0-windows\win-x64\publish\Programs\Creator Release_ANSI\*
- 7z e DiscImageCreator_20230606.zip -oMPF\bin\Debug\net7.0-windows\win-x64\publish\Programs\Creator Release_ANSI\*
# - 7z e DiscImageCreator_20230606.zip -oMPF\bin\Release\net48\win7-x64\publish\Programs\Creator Release_ANSI\*
# - 7z e DiscImageCreator_20230606.zip -oMPF\bin\Release\net6.0-windows\win-x64\publish\Programs\Creator Release_ANSI\*
# - 7z e DiscImageCreator_20230606.zip -oMPF\bin\Release\net7.0-windows\win-x64\publish\Programs\Creator Release_ANSI\*
# Redumper
- ps: appveyor DownloadFile https://github.com/superg/redumper/releases/download/build_221/redumper-2023.10.02_build221-win64.zip
- 7z e redumper-2023.10.02_build221-win64.zip -oMPF\bin\Debug\net48\win7-x64\publish\Programs\Redumper redumper-2023.10.02_build221-win64\bin\*
- 7z e redumper-2023.10.02_build221-win64.zip -oMPF\bin\Debug\net6.0-windows\win-x64\publish\Programs\Redumper redumper-2023.10.02_build221-win64\bin\*
- 7z e redumper-2023.10.02_build221-win64.zip -oMPF\bin\Debug\net7.0-windows\win-x64\publish\Programs\Redumper redumper-2023.10.02_build221-win64\bin\*
# - 7z e redumper-2023.10.02_build221-win64.zip -oMPF\bin\Release\net48\win7-x64\publish\Programs\Redumper redumper-2023.10.02_build221-win64\bin\*
# - 7z e redumper-2023.10.02_build221-win64.zip -oMPF\bin\Release\net6.0-windows\win-x64\publish\Programs\Redumper redumper-2023.10.02_build221-win64\bin\*
# - 7z e redumper-2023.10.02_build221-win64.zip -oMPF\bin\Release\net7.0-windows\win-x64\publish\Programs\Redumper redumper-2023.10.02_build221-win64\bin\*
# Create MPF Debug archives
- cd %APPVEYOR_BUILD_FOLDER%\MPF\bin\Debug\net48\win7-x64\publish\
- 7z a -tzip %APPVEYOR_BUILD_FOLDER%\MPF_%APPVEYOR_BUILD_NUMBER%_net48_debug.zip *
- cd %APPVEYOR_BUILD_FOLDER%\MPF\bin\Debug\net6.0-windows\win-x64\publish\
- 7z a -tzip %APPVEYOR_BUILD_FOLDER%\MPF_%APPVEYOR_BUILD_NUMBER%_net6.0_win-x64_debug.zip *
- cd %APPVEYOR_BUILD_FOLDER%\MPF\bin\Debug\net7.0-windows\win-x64\publish\
- 7z a -tzip %APPVEYOR_BUILD_FOLDER%\MPF_%APPVEYOR_BUILD_NUMBER%_net7.0_win-x64_debug.zip *
# # Create MPF Release archives
# - cd %APPVEYOR_BUILD_FOLDER%\MPF\bin\Release\net48\win7-x64\publish\
# - 7z a -tzip %APPVEYOR_BUILD_FOLDER%\MPF_%APPVEYOR_BUILD_NUMBER%_net48_release.zip *
# - cd %APPVEYOR_BUILD_FOLDER%\MPF\bin\Release\net6.0-windows\win-x64\publish\
# - 7z a -tzip %APPVEYOR_BUILD_FOLDER%\MPF_%APPVEYOR_BUILD_NUMBER%_net6.0_win-x64_release.zip *
# - cd %APPVEYOR_BUILD_FOLDER%\MPF\bin\Release\net7.0-windows\win-x64\publish\
# - 7z a -tzip %APPVEYOR_BUILD_FOLDER%\MPF_%APPVEYOR_BUILD_NUMBER%_net7.0_win-x64_release.zip *
# Create MPF.Check Debug archives
- cd %APPVEYOR_BUILD_FOLDER%\MPF.Check\bin\Debug\net48\win7-x64\publish\
- 7z a -tzip %APPVEYOR_BUILD_FOLDER%\MPF.Check_%APPVEYOR_BUILD_NUMBER%_net48_debug.zip *
- cd %APPVEYOR_BUILD_FOLDER%\MPF.Check\bin\Debug\net6.0\win-x64\publish\
- 7z a -tzip %APPVEYOR_BUILD_FOLDER%\MPF.Check_%APPVEYOR_BUILD_NUMBER%_net6.0_win-x64_debug.zip *
- cd %APPVEYOR_BUILD_FOLDER%\MPF.Check\bin\Debug\net6.0\linux-x64\publish\
- 7z a -tzip %APPVEYOR_BUILD_FOLDER%\MPF.Check_%APPVEYOR_BUILD_NUMBER%_net6.0_linux-x64_debug.zip *
- cd %APPVEYOR_BUILD_FOLDER%\MPF.Check\bin\Debug\net6.0\osx-x64\publish\
- 7z a -tzip %APPVEYOR_BUILD_FOLDER%\MPF.Check_%APPVEYOR_BUILD_NUMBER%_net6.0_osx-x64_debug.zip *
- cd %APPVEYOR_BUILD_FOLDER%\MPF.Check\bin\Debug\net7.0\win-x64\publish\
- 7z a -tzip %APPVEYOR_BUILD_FOLDER%\MPF.Check_%APPVEYOR_BUILD_NUMBER%_net7.0_win-x64_debug.zip *
- cd %APPVEYOR_BUILD_FOLDER%\MPF.Check\bin\Debug\net7.0\linux-x64\publish\
- 7z a -tzip %APPVEYOR_BUILD_FOLDER%\MPF.Check_%APPVEYOR_BUILD_NUMBER%_net7.0_linux-x64_debug.zip *
- cd %APPVEYOR_BUILD_FOLDER%\MPF.Check\bin\Debug\net7.0\osx-x64\publish\
- 7z a -tzip %APPVEYOR_BUILD_FOLDER%\MPF.Check_%APPVEYOR_BUILD_NUMBER%_net7.0_osx-x64_debug.zip *
# # Create MPF.Check Release archives
# - cd %APPVEYOR_BUILD_FOLDER%\MPF.Check\bin\Release\net48\win7-x64\publish\
# - 7z a -tzip %APPVEYOR_BUILD_FOLDER%\MPF.Check_%APPVEYOR_BUILD_NUMBER%_net48_release.zip *
# - cd %APPVEYOR_BUILD_FOLDER%\MPF.Check\bin\Release\net6.0\win-x64\publish\
# - 7z a -tzip %APPVEYOR_BUILD_FOLDER%\MPF.Check_%APPVEYOR_BUILD_NUMBER%_net6.0_win-x64_release.zip *
# - cd %APPVEYOR_BUILD_FOLDER%\MPF.Check\bin\Release\net6.0\linux-x64\publish\
# - 7z a -tzip %APPVEYOR_BUILD_FOLDER%\MPF.Check_%APPVEYOR_BUILD_NUMBER%_net6.0_linux-x64_release.zip *
# - cd %APPVEYOR_BUILD_FOLDER%\MPF.Check\bin\Release\net6.0\osx-x64\publish\
# - 7z a -tzip %APPVEYOR_BUILD_FOLDER%\MPF.Check_%APPVEYOR_BUILD_NUMBER%_net6.0_osx-x64_release.zip *
# - cd %APPVEYOR_BUILD_FOLDER%\MPF.Check\bin\Release\net7.0\win-x64\publish\
# - 7z a -tzip %APPVEYOR_BUILD_FOLDER%\MPF.Check_%APPVEYOR_BUILD_NUMBER%_net7.0_win-x64_release.zip *
# - cd %APPVEYOR_BUILD_FOLDER%\MPF.Check\bin\Release\net7.0\linux-x64\publish\
# - 7z a -tzip %APPVEYOR_BUILD_FOLDER%\MPF.Check_%APPVEYOR_BUILD_NUMBER%_net7.0_linux-x64_release.zip *
# - cd %APPVEYOR_BUILD_FOLDER%\MPF.Check\bin\Release\net7.0\osx-x64\publish\
# - 7z a -tzip %APPVEYOR_BUILD_FOLDER%\MPF.Check_%APPVEYOR_BUILD_NUMBER%_net7.0_osx-x64_release.zip *
# success/failure tracking
on_success:
@@ -132,46 +81,12 @@ on_failure:
# artifact linking
artifacts:
- path: MPF_%APPVEYOR_BUILD_NUMBER%_net48_debug.zip
name: MPF (.NET Framework 4.8, Debug)
- path: MPF_%APPVEYOR_BUILD_NUMBER%_net6.0_win-x64_debug.zip
name: MPF (.NET 6.0, Debug, Windows x64)
- path: MPF_%APPVEYOR_BUILD_NUMBER%_net7.0_win-x64_debug.zip
name: MPF (.NET 7.0, Debug, Windows x64)
# - path: MPF_%APPVEYOR_BUILD_NUMBER%_net48_release.zip
# name: MPF (.NET Framework 4.8, Release)
# - path: MPF_%APPVEYOR_BUILD_NUMBER%_net6.0_win-x64_release.zip
# name: MPF (.NET 6.0, Release, Windows x64)
# - path: MPF_%APPVEYOR_BUILD_NUMBER%_net7.0_win-x64_release.zip
# name: MPF (.NET 7.0, Release, Windows x64)
- path: MPF.Check_%APPVEYOR_BUILD_NUMBER%_net48_debug.zip
name: MPF Check (.NET Framework 4.8, Debug)
- path: MPF.Check_%APPVEYOR_BUILD_NUMBER%_net6.0_win-x64_debug.zip
name: MPF.Check (.NET 6.0, Debug, Windows x64)
- path: MPF.Check_%APPVEYOR_BUILD_NUMBER%_net6.0_linux-x64_debug.zip
name: MPF.Check (.NET 6.0, Debug, Linux x64)
- path: MPF.Check_%APPVEYOR_BUILD_NUMBER%_net6.0_osx-x64_debug.zip
name: MPF.Check (.NET 6.0, Debug, OSX x64)
- path: MPF.Check_%APPVEYOR_BUILD_NUMBER%_net7.0_win-x64_debug.zip
name: MPF.Check (.NET 7.0, Debug, Windows x64)
- path: MPF.Check_%APPVEYOR_BUILD_NUMBER%_net7.0_linux-x64_debug.zip
name: MPF.Check (.NET 7.0, Debug, Linux x64)
- path: MPF.Check_%APPVEYOR_BUILD_NUMBER%_net7.0_osx-x64_debug.zip
name: MPF.Check (.NET 7.0, Debug, OSX x64)
# - path: MPF.Check_%APPVEYOR_BUILD_NUMBER%_net48_release.zip
# name: MPF Check (.NET Framework 4.8, Release)
# - path: MPF.Check_%APPVEYOR_BUILD_NUMBER%_net6.0_win-x64_release.zip
# name: MPF.Check (.NET 6.0, Release, Windows x64)
# - path: MPF.Check_%APPVEYOR_BUILD_NUMBER%_net6.0_linux-x64_release.zip
# name: MPF.Check (.NET 6.0, Release, Linux x64)
# - path: MPF.Check_%APPVEYOR_BUILD_NUMBER%_net6.0_osx-x64_release.zip
# name: MPF.Check (.NET 6.0, Release, OSX x64)
# - path: MPF.Check_%APPVEYOR_BUILD_NUMBER%_net7.0_win-x64_release.zip
# name: MPF.Check (.NET 7.0, Release, Windows x64)
# - path: MPF.Check_%APPVEYOR_BUILD_NUMBER%_net7.0_linux-x64_release.zip
# name: MPF.Check (.NET 7.0, Release, Linux x64)
# - path: MPF.Check_%APPVEYOR_BUILD_NUMBER%_net7.0_osx-x64_release.zip
# name: MPF.Check (.NET 7.0, Release, OSX x64)