General UI Cleanup (#438)

* Update Nuget packages to newest stable

* Simplify path selection in UI

* Update changelog

* Fix broken normalization test

* Update drive info before dumping
This commit is contained in:
Matt Nadareski
2022-12-13 11:48:26 -08:00
committed by GitHub
parent 8d29a29591
commit 88cadff9ef
15 changed files with 175 additions and 277 deletions

View File

@@ -7,6 +7,10 @@
- Add .NET 6.0 to tests, remove msbuild args
- Add HD-DVD to speed definitions
- Add PS3 internal serial and version parsing (tjanas)
- Update Nuget packages to newest stable
- Simplify path selection in UI
- Fix broken normalization test
- Update drive info before dumping
### 2.4 (2022-10-26)
- Update to DIC 20211001

View File

@@ -28,7 +28,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="BurnOutSharp" PrivateAssets="build; analyzers" ExcludeAssets="contentFiles" Version="2.3.4" GeneratePathProperty="true">
<PackageReference Include="BurnOutSharp" PrivateAssets="build; analyzers" ExcludeAssets="contentFiles" Version="2.5.0" GeneratePathProperty="true">
<IncludeAssets>runtime; compile; build; native; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Unclassified.NetRevisionTask" Version="0.4.3">

View File

@@ -59,7 +59,7 @@ namespace MPF.Check
if (!string.IsNullOrWhiteSpace(path))
drive = Drive.Create(null, path);
var env = new DumpEnvironment(options, "", filepath, drive, knownSystem, mediaType, null);
var env = new DumpEnvironment(options, filepath, drive, knownSystem, mediaType, null);
// Finally, attempt to do the output dance
var result = env.VerifyAndSaveDumpOutput(resultProgress, protectionProgress).ConfigureAwait(false).GetAwaiter().GetResult();

View File

@@ -56,9 +56,9 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="System.Configuration.ConfigurationManager" Version="6.0.1" />
<PackageReference Include="System.Management" Version="6.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
<PackageReference Include="System.Configuration.ConfigurationManager" Version="7.0.0" />
<PackageReference Include="System.Management" Version="7.0.0" />
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="6.0.0" />
</ItemGroup>

View File

@@ -19,14 +19,9 @@ namespace MPF.Library
#region Output paths
/// <summary>
/// Base output directory to write files to
/// Base output file path to write files to
/// </summary>
public string OutputDirectory { get; private set; }
/// <summary>
/// Base output filename for output
/// </summary>
public string OutputFilename { get; private set; }
public string OutputPath { get; private set; }
#endregion
@@ -87,15 +82,13 @@ namespace MPF.Library
/// Constructor for a full DumpEnvironment object from user information
/// </summary>
/// <param name="options"></param>
/// <param name="outputDirectory"></param>
/// <param name="outputFilename"></param>
/// <param name="outputPath"></param>
/// <param name="drive"></param>
/// <param name="system"></param>
/// <param name="type"></param>
/// <param name="parameters"></param>
public DumpEnvironment(Options options,
string outputDirectory,
string outputFilename,
string outputPath,
Drive drive,
RedumpSystem? system,
MediaType? type,
@@ -105,7 +98,7 @@ namespace MPF.Library
this.Options = options;
// Output paths
(this.OutputDirectory, this.OutputFilename) = InfoTool.NormalizeOutputPaths(outputDirectory, outputFilename);
this.OutputPath = InfoTool.NormalizeOutputPaths(outputPath);
// UI information
this.Drive = drive;
@@ -127,20 +120,26 @@ namespace MPF.Library
if (this.Parameters.InternalProgram != InternalProgram.DiscImageCreator)
return;
// Replace all instances in the output directory
this.OutputDirectory = this.OutputDirectory.Replace('.', '_');
try
{
// Replace all instances in the output directory
string outputDirectory = Path.GetDirectoryName(this.OutputPath);
outputDirectory = outputDirectory.Replace(".", "_");
// Currently, only periods in directories matter
// Leave the following code commented in case filename handling breaks again
// Replace all instances in the output filename
string outputFilename = Path.GetFileNameWithoutExtension(this.OutputPath);
outputFilename = outputFilename.Replace(".", "_");
// Replace all instances in the output filename, except the extension
//string tempFilename = Path.GetFileNameWithoutExtension(this.OutputFilename)
// .Replace('.', '_');
//string tempExtension = Path.GetExtension(this.OutputFilename)?.TrimStart('.');
//this.OutputFilename = $"{tempFilename}.{tempExtension}";
// Get the extension for recreating the path
string outputExtension = Path.GetExtension(this.OutputPath).TrimStart('.');
// Assign the path to the filename as well for dumping
((Modules.DiscImageCreator.Parameters)this.Parameters).Filename = Path.Combine(this.OutputDirectory, this.OutputFilename);
// Rebuild the output path
this.OutputPath = Path.Combine(outputDirectory, $"{outputFilename}.{outputExtension}");
// Assign the path to the filename as well for dumping
((Modules.DiscImageCreator.Parameters)this.Parameters).Filename = this.OutputPath;
}
catch { }
}
/// <summary>
@@ -207,28 +206,27 @@ namespace MPF.Library
return null;
// Set the proper parameters
string filename = OutputDirectory + Path.DirectorySeparatorChar + OutputFilename;
switch (Options.InternalProgram)
{
case InternalProgram.Aaru:
Parameters = new Modules.Aaru.Parameters(System, Type, Drive.Letter, filename, driveSpeed, Options);
Parameters = new Modules.Aaru.Parameters(System, Type, Drive.Letter, this.OutputPath, driveSpeed, Options);
break;
case InternalProgram.DD:
Parameters = new Modules.DD.Parameters(System, Type, Drive.Letter, filename, driveSpeed, Options);
Parameters = new Modules.DD.Parameters(System, Type, Drive.Letter, this.OutputPath, driveSpeed, Options);
break;
case InternalProgram.DiscImageCreator:
Parameters = new Modules.DiscImageCreator.Parameters(System, Type, Drive.Letter, filename, driveSpeed, Options);
Parameters = new Modules.DiscImageCreator.Parameters(System, Type, Drive.Letter, this.OutputPath, driveSpeed, Options);
break;
case InternalProgram.Redumper:
Parameters = new Modules.Redumper.Parameters(System, Type, Drive.Letter, filename, driveSpeed, Options);
Parameters = new Modules.Redumper.Parameters(System, Type, Drive.Letter, this.OutputPath, driveSpeed, Options);
break;
// This should never happen, but it needs a fallback
default:
Parameters = new Modules.DiscImageCreator.Parameters(System, Type, Drive.Letter, filename, driveSpeed, Options);
Parameters = new Modules.DiscImageCreator.Parameters(System, Type, Drive.Letter, this.OutputPath, driveSpeed, Options);
break;
}
@@ -280,7 +278,7 @@ namespace MPF.Library
// Execute internal tool
progress?.Report(Result.Success($"Executing {Options.InternalProgram}... {(Options.ToolsInSeparateWindow ? "please wait!" : "see log for output!")}"));
Directory.CreateDirectory(OutputDirectory);
Directory.CreateDirectory(Path.GetDirectoryName(this.OutputPath));
await Task.Run(() => Parameters.ExecuteInternalProgram(Options.ToolsInSeparateWindow));
progress?.Report(Result.Success($"{Options.InternalProgram} has finished!"));
@@ -313,8 +311,12 @@ namespace MPF.Library
{
resultProgress?.Report(Result.Success("Gathering submission information... please wait!"));
// Get the output directory and filename separately
string outputDirectory = Path.GetDirectoryName(this.OutputPath);
string outputFilename = Path.GetFileName(this.OutputPath);
// Check to make sure that the output had all the correct files
(bool foundFiles, List<string> missingFiles) = InfoTool.FoundAllFiles(this.OutputDirectory, this.OutputFilename, this.Parameters, false);
(bool foundFiles, List<string> missingFiles) = InfoTool.FoundAllFiles(outputDirectory, outputFilename, this.Parameters, false);
if (!foundFiles)
{
resultProgress?.Report(Result.Failure($"There were files missing from the output:\n{string.Join("\n", missingFiles)}"));
@@ -324,8 +326,7 @@ namespace MPF.Library
// Extract the information from the output files
resultProgress?.Report(Result.Success("Extracting output information from output files..."));
SubmissionInfo submissionInfo = await InfoTool.ExtractOutputInformation(
this.OutputDirectory,
this.OutputFilename,
this.OutputPath,
this.Drive,
this.System,
this.Type,
@@ -378,7 +379,7 @@ namespace MPF.Library
// Write the text output
resultProgress?.Report(Result.Success("Writing information to !submissionInfo.txt..."));
(bool txtSuccess, string txtResult) = InfoTool.WriteOutputData(this.OutputDirectory, formattedValues);
(bool txtSuccess, string txtResult) = InfoTool.WriteOutputData(outputDirectory, formattedValues);
if (txtSuccess)
resultProgress?.Report(Result.Success(txtResult));
else
@@ -388,7 +389,7 @@ namespace MPF.Library
if (Options.ScanForProtection && Options.OutputSeparateProtectionFile)
{
resultProgress?.Report(Result.Success("Writing protection to !protectionInfo.txt..."));
bool scanSuccess = InfoTool.WriteProtectionData(this.OutputDirectory, submissionInfo);
bool scanSuccess = InfoTool.WriteProtectionData(outputDirectory, submissionInfo);
if (scanSuccess)
resultProgress?.Report(Result.Success("Writing complete!"));
else
@@ -399,7 +400,7 @@ namespace MPF.Library
if (Options.OutputSubmissionJSON)
{
resultProgress?.Report(Result.Success($"Writing information to !submissionInfo.json{(Options.IncludeArtifacts ? ".gz" : string.Empty)}..."));
bool jsonSuccess = InfoTool.WriteOutputData(this.OutputDirectory, submissionInfo, Options.IncludeArtifacts);
bool jsonSuccess = InfoTool.WriteOutputData(outputDirectory, submissionInfo, Options.IncludeArtifacts);
if (jsonSuccess)
resultProgress?.Report(Result.Success("Writing complete!"));
else
@@ -410,7 +411,7 @@ namespace MPF.Library
if (Options.CompressLogFiles)
{
resultProgress?.Report(Result.Success("Compressing log files..."));
(bool compressSuccess, string compressResult) = InfoTool.CompressLogFiles(this.OutputDirectory, this.OutputFilename, this.Parameters);
(bool compressSuccess, string compressResult) = InfoTool.CompressLogFiles(outputDirectory, outputFilename, this.Parameters);
if (compressSuccess)
resultProgress?.Report(Result.Success(compressResult));
else
@@ -491,12 +492,11 @@ namespace MPF.Library
return Result.Failure("Error! Current configuration is not supported!");
// Fix the output paths, just in case
(OutputDirectory, OutputFilename) = InfoTool.NormalizeOutputPaths(OutputDirectory, OutputFilename);
this.OutputPath = InfoTool.NormalizeOutputPaths(this.OutputPath);
// Validate that the output path isn't on the dumping drive
string fullOutputPath = Path.GetFullPath(Path.Combine(OutputDirectory, OutputFilename));
if (fullOutputPath[0] == Drive.Letter)
return Result.Failure($"Error! Cannot output to same drive that is being dumped!");
if (this.OutputPath[0] == Drive.Letter)
return Result.Failure("Error! Cannot output to same drive that is being dumped!");
// Validate that the required program exists
if (!File.Exists(Parameters.ExecutablePath))
@@ -505,7 +505,7 @@ namespace MPF.Library
// Validate that the dumping drive doesn't contain the executable
string fullExecutablePath = Path.GetFullPath(Parameters.ExecutablePath);
if (fullExecutablePath[0] == Drive.Letter)
return Result.Failure("$Error! Cannot dump same drive that executable resides on!");
return Result.Failure("Error! Cannot dump same drive that executable resides on!");
// Validate that the current configuration is supported
return Tools.GetSupportStatus(System, Type);

View File

@@ -26,8 +26,7 @@ namespace MPF.Library
/// <summary>
/// Extract all of the possible information from a given input combination
/// </summary>
/// <param name="outputDirectory">Output folder to write to</param>
/// <param name="outputFilename">Output filename to use as the base path</param>
/// <param name="outputPath">Output path to write to</param>
/// <param name="drive">Drive object representing the current drive</param>
/// <param name="system">Currently selected system</param>
/// <param name="mediaType">Currently selected media type</param>
@@ -37,8 +36,7 @@ namespace MPF.Library
/// <param name="protectionProgress">Optional protection progress callback</param>
/// <returns>SubmissionInfo populated based on outputs, null on error</returns>
public static async Task<SubmissionInfo> ExtractOutputInformation(
string outputDirectory,
string outputFilename,
string outputPath,
Drive drive,
RedumpSystem? system,
MediaType? mediaType,
@@ -51,6 +49,10 @@ namespace MPF.Library
if (!system.MediaTypes().Contains(mediaType))
return null;
// Split the output path for easier use
string outputDirectory = Path.GetDirectoryName(outputPath);
string outputFilename = Path.GetFileName(outputPath);
// Check that all of the relevant files are there
(bool foundFiles, List<string> missingFiles) = FoundAllFiles(outputDirectory, outputFilename, parameters, false);
if (!foundFiles)
@@ -1655,57 +1657,31 @@ namespace MPF.Library
/// <summary>
/// Normalize a split set of paths
/// </summary>
/// <param name="directory">Directory name to normalize</param>
/// <param name="filename">Filename to normalize</param>
public static (string, string) NormalizeOutputPaths(string directory, string filename)
/// <param name="path">Path value to normalize</param>
public static string NormalizeOutputPaths(string path)
{
// The easy way
try
{
// Cache if we had a directory separator or not
bool endedWithDirectorySeparator = directory.EndsWith(Path.DirectorySeparatorChar.ToString())
|| directory.EndsWith(Path.AltDirectorySeparatorChar.ToString());
// Trim quotes from the path
path = path.Trim('"');
// Combine the path to make things separate easier
string combinedPath = Path.Combine(directory, filename);
// Try getting the combined path and returning that directly
string fullPath = Path.GetFullPath(path);
string fullDirectory = Path.GetDirectoryName(fullPath);
string fullFile = Path.GetFileName(fullPath);
// If we have have a blank path, just return
if (string.IsNullOrWhiteSpace(combinedPath))
return (directory, filename);
// Now get the normalized paths
directory = Path.GetDirectoryName(combinedPath);
filename = Path.GetFileName(combinedPath);
// Take care of extra path characters
directory = new StringBuilder(directory)
.Replace(':', '_', 0, directory.LastIndexOf(':') == -1 ? 0 : directory.LastIndexOf(':'))
.ToString();
// Sanitize the directory path
directory = directory.Replace('?', '_');
// Remove invalid path characters
foreach (char c in Path.GetInvalidPathChars())
directory = directory.Replace(c, '_');
fullDirectory = fullDirectory.Replace(c, '_');
// Sanitize the filename
filename = filename.Replace('?', '_');
// Remove invalid filename characters
foreach (char c in Path.GetInvalidFileNameChars())
filename = filename.Replace(c, '_');
// If we had a directory separator at the end before, add it again
if (endedWithDirectorySeparator)
directory += Path.DirectorySeparatorChar;
// If we have a root directory, sanitize
if (Directory.Exists(directory))
{
var possibleRootDir = new DirectoryInfo(directory);
if (possibleRootDir.Parent == null)
directory = directory.Replace($"{Path.DirectorySeparatorChar}{Path.DirectorySeparatorChar}", $"{Path.DirectorySeparatorChar}");
}
fullFile = fullFile.Replace(c, '_');
}
catch { }
return (directory, filename);
return path;
}
#endregion

View File

@@ -28,10 +28,10 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="BurnOutSharp" PrivateAssets="build; analyzers" ExcludeAssets="contentFiles" Version="2.3.4" GeneratePathProperty="true">
<PackageReference Include="BurnOutSharp" PrivateAssets="build; analyzers" ExcludeAssets="contentFiles" Version="2.5.0" GeneratePathProperty="true">
<IncludeAssets>runtime; compile; build; native; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
<PackageReference Include="System.IO.Compression" Version="4.3.0" />
<PackageReference Include="System.IO.Compression.ZipFile" Version="4.3.0" />
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="6.0.0" />

View File

@@ -242,7 +242,7 @@ namespace MPF.Modules
/// </summary>
/// <param name="parameters">String possibly representing parameters</param>
/// <returns>True if the parameters were set correctly, false otherwise</returns>
protected virtual bool ValidateAndSetParameters(string parameters) => true;
protected virtual bool ValidateAndSetParameters(string parameters) => !string.IsNullOrWhiteSpace(parameters);
#endregion

View File

@@ -24,7 +24,7 @@ namespace MPF.Test.Library
? Drive.Create(InternalDriveType.Floppy, letter.ToString())
: Drive.Create(InternalDriveType.Optical, letter.ToString());
var env = new DumpEnvironment(options, string.Empty, string.Empty, drive, RedumpSystem.IBMPCcompatible, mediaType, parameters);
var env = new DumpEnvironment(options, string.Empty, drive, RedumpSystem.IBMPCcompatible, mediaType, parameters);
bool actual = env.ParametersValid();
Assert.Equal(expected, actual);

View File

@@ -48,19 +48,18 @@ namespace MPF.Test.Library
}
[Theory]
[InlineData(null, null, null, null)]
[InlineData(" ", "", " ", "")]
[InlineData("super", "blah.bin", "super", "blah.bin")]
[InlineData("super\\hero", "blah.bin", "super\\hero", "blah.bin")]
[InlineData("super.hero", "blah.bin", "super.hero", "blah.bin")]
[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")]
public void NormalizeOutputPathsTest(string outputDirectory, string outputFilename, string expectedOutputDirectory, string expectedOutputFilename)
[InlineData(null, null)]
[InlineData(" ", " ")]
[InlineData("super\\blah.bin", "super\\blah.bin")]
[InlineData("super\\hero\\blah.bin", "super\\hero\\blah.bin")]
[InlineData("super.hero\\blah.bin", "super.hero\\blah.bin")]
[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")]
public void NormalizeOutputPathsTest(string outputPath, string expectedPath)
{
(string actualOutputDirectory, string actualOutputFilename) = InfoTool.NormalizeOutputPaths(outputDirectory, outputFilename);
Assert.Equal(expectedOutputDirectory, actualOutputDirectory);
Assert.Equal(expectedOutputFilename, actualOutputFilename);
string actualPath = InfoTool.NormalizeOutputPaths(outputPath);
Assert.Equal(expectedPath, actualPath);
}
[Fact]

View File

@@ -35,12 +35,12 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CodeCoverage" Version="17.3.2" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="Microsoft.CodeCoverage" Version="17.4.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.4.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
<PackageReference Include="xunit" Version="2.4.2" />
<PackageReference Include="xunit.abstractions" Version="2.0.3" />
<PackageReference Include="xunit.analyzers" Version="1.0.0" />
<PackageReference Include="xunit.analyzers" Version="1.1.0" />
<PackageReference Include="xunit.assert" Version="2.4.2" />
<PackageReference Include="xunit.core" Version="2.4.2" />
<PackageReference Include="xunit.extensibility.core" Version="2.4.2" />

View File

@@ -20,6 +20,7 @@
<NrtRevisionFormat>$(Version)-{chash:8}</NrtRevisionFormat>
<NrtResolveSimpleAttributes>true</NrtResolveSimpleAttributes>
<NrtShowRevision>false</NrtShowRevision>
<UserSecretsId>27abb4ca-bf7a-431e-932f-49153303d5ff</UserSecretsId>
</PropertyGroup>
<ItemGroup>

View File

@@ -27,10 +27,10 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="BurnOutSharp" PrivateAssets="build; analyzers" ExcludeAssets="contentFiles" Version="2.3.4" GeneratePathProperty="true">
<PackageReference Include="BurnOutSharp" PrivateAssets="build; analyzers" ExcludeAssets="contentFiles" Version="2.5.0" GeneratePathProperty="true">
<IncludeAssets>runtime; compile; build; native; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="System.Configuration.ConfigurationManager" Version="6.0.1" />
<PackageReference Include="System.Configuration.ConfigurationManager" Version="7.0.0" />
<PackageReference Include="Unclassified.NetRevisionTask" Version="0.4.3">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>

View File

@@ -60,11 +60,6 @@ namespace MPF.UI.ViewModels
/// </summary>
private bool _canExecuteSelectionChanged = false;
/// <summary>
/// Indicates if TextChanged events can be executed
/// </summary>
private bool _canExecuteTextChanged = false;
#endregion
/// <summary>
@@ -249,11 +244,11 @@ namespace MPF.UI.ViewModels
public void ExitApplication() => Application.Current.Shutdown();
/// <summary>
/// Set the output directory from a dialog box
/// Set the output path from a dialog box
/// </summary>
public void SetOutputDirectory()
public void SetOutputPath()
{
BrowseFolder();
BrowseFile();
EnsureDiscInformation();
}
@@ -572,7 +567,7 @@ namespace MPF.UI.ViewModels
App.Instance.EnableParametersCheckBox.Click += EnableParametersCheckBoxClick;
App.Instance.MediaScanButton.Click += MediaScanButtonClick;
App.Instance.UpdateVolumeLabel.Click += UpdateVolumeLabelClick;
App.Instance.OutputDirectoryBrowseButton.Click += OutputDirectoryBrowseButtonClick;
App.Instance.OutputPathBrowseButton.Click += OutputPathBrowseButtonClick;
App.Instance.StartStopButton.Click += StartStopButtonClick;
// User Area SelectionChanged
@@ -580,10 +575,6 @@ namespace MPF.UI.ViewModels
App.Instance.MediaTypeComboBox.SelectionChanged += MediaTypeComboBoxSelectionChanged;
App.Instance.DriveLetterComboBox.SelectionChanged += DriveLetterComboBoxSelectionChanged;
App.Instance.DriveSpeedComboBox.SelectionChanged += DriveSpeedComboBoxSelectionChanged;
// User Area TextChanged
App.Instance.OutputFilenameTextBox.TextChanged += OutputFilenameTextBoxTextChanged;
App.Instance.OutputDirectoryTextBox.TextChanged += OutputDirectoryTextBoxTextChanged;
}
/// <summary>
@@ -592,7 +583,6 @@ namespace MPF.UI.ViewModels
private void EnableEventHandlers()
{
_canExecuteSelectionChanged = true;
EnablePathEventHandlers();
}
/// <summary>
@@ -601,23 +591,6 @@ namespace MPF.UI.ViewModels
private void DisableEventHandlers()
{
_canExecuteSelectionChanged = false;
DisablePathEventHandlers();
}
/// <summary>
/// Enable path textbox event handlers
/// </summary>
private void EnablePathEventHandlers()
{
_canExecuteTextChanged = true;
}
/// <summary>
/// Disable path textbox event handlers
/// </summary>
private void DisablePathEventHandlers()
{
_canExecuteTextChanged = false;
}
/// <summary>
@@ -628,9 +601,8 @@ namespace MPF.UI.ViewModels
App.Instance.OptionsMenuItem.IsEnabled = false;
App.Instance.SystemTypeComboBox.IsEnabled = false;
App.Instance.MediaTypeComboBox.IsEnabled = false;
App.Instance.OutputFilenameTextBox.IsEnabled = false;
App.Instance.OutputDirectoryTextBox.IsEnabled = false;
App.Instance.OutputDirectoryBrowseButton.IsEnabled = false;
App.Instance.OutputPathTextBox.IsEnabled = false;
App.Instance.OutputPathBrowseButton.IsEnabled = false;
App.Instance.DriveLetterComboBox.IsEnabled = false;
App.Instance.DriveSpeedComboBox.IsEnabled = false;
App.Instance.EnableParametersCheckBox.IsEnabled = false;
@@ -648,9 +620,8 @@ namespace MPF.UI.ViewModels
App.Instance.OptionsMenuItem.IsEnabled = true;
App.Instance.SystemTypeComboBox.IsEnabled = true;
App.Instance.MediaTypeComboBox.IsEnabled = true;
App.Instance.OutputFilenameTextBox.IsEnabled = true;
App.Instance.OutputDirectoryTextBox.IsEnabled = true;
App.Instance.OutputDirectoryBrowseButton.IsEnabled = true;
App.Instance.OutputPathTextBox.IsEnabled = true;
App.Instance.OutputPathBrowseButton.IsEnabled = true;
App.Instance.DriveLetterComboBox.IsEnabled = true;
App.Instance.DriveSpeedComboBox.IsEnabled = true;
App.Instance.EnableParametersCheckBox.IsEnabled = true;
@@ -798,24 +769,37 @@ namespace MPF.UI.ViewModels
#region Helpers
/// <summary>
/// Browse for an output folder
/// Browse for an output file path
/// </summary>
private void BrowseFolder()
private void BrowseFile()
{
string currentPath = App.Options.DefaultOutputPath;
if (string.IsNullOrWhiteSpace(currentPath) || !Directory.Exists(currentPath))
currentPath = System.AppDomain.CurrentDomain.BaseDirectory;
// Get the current path, if possible
string currentPath = App.Instance.OutputPathTextBox.Text;
if (string.IsNullOrWhiteSpace(currentPath))
currentPath = Path.Combine(App.Options.DefaultOutputPath, "track.bin");
if (string.IsNullOrWhiteSpace(currentPath))
currentPath = Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "track.bin");
WinForms.FolderBrowserDialog folderDialog = new WinForms.FolderBrowserDialog
// Get the full path
currentPath = Path.GetFullPath(currentPath);
// Get the directory
string directory = Path.GetDirectoryName(currentPath);
Directory.CreateDirectory(directory);
// Get the filename
string filename = Path.GetFileName(currentPath);
WinForms.FileDialog fileDialog = new WinForms.SaveFileDialog
{
ShowNewFolderButton = false,
SelectedPath = currentPath,
FileName = filename,
InitialDirectory = directory,
};
WinForms.DialogResult result = folderDialog.ShowDialog();
WinForms.DialogResult result = fileDialog.ShowDialog();
if (result == WinForms.DialogResult.OK)
{
App.Instance.OutputDirectoryTextBox.Text = folderDialog.SelectedPath;
App.Instance.OutputPathTextBox.Text = fileDialog.FileName;
}
}
@@ -881,39 +865,12 @@ namespace MPF.UI.ViewModels
/// <returns>Filled DumpEnvironment instance</returns>
private DumpEnvironment DetermineEnvironment()
{
// Populate the new environment
var env = new DumpEnvironment(App.Options,
App.Instance.OutputDirectoryTextBox.Text,
App.Instance.OutputFilenameTextBox.Text,
return new DumpEnvironment(App.Options,
App.Instance.OutputPathTextBox.Text,
App.Instance.DriveLetterComboBox.SelectedItem as Drive,
App.Instance.SystemTypeComboBox.SelectedItem as RedumpSystemComboBoxItem,
App.Instance.MediaTypeComboBox.SelectedItem as Element<MediaType>,
App.Instance.ParametersTextBox.Text);
// Disable automatic reprocessing of the textboxes until we're done
DisablePathEventHandlers();
// Save the current cursor positions
int outputDirectorySelectionStart = App.Instance.OutputDirectoryTextBox.SelectionStart;
int outputFilenameSelectionStart = App.Instance.OutputFilenameTextBox.SelectionStart;
// Set the new text
App.Instance.OutputDirectoryTextBox.Text = env.OutputDirectory;
App.Instance.OutputFilenameTextBox.Text = env.OutputFilename;
// Set the cursor position back to where it was
App.Instance.OutputDirectoryTextBox.SelectionStart = outputDirectorySelectionStart;
App.Instance.OutputDirectoryTextBox.SelectionLength = 0;
App.Instance.OutputFilenameTextBox.SelectionStart = outputFilenameSelectionStart;
App.Instance.OutputFilenameTextBox.SelectionLength = 0;
// Re-enable automatic reprocessing of textboxes
EnablePathEventHandlers();
// Ensure the UI gets updated
App.Instance.UpdateLayout();
return env;
}
/// <summary>
@@ -991,33 +948,25 @@ namespace MPF.UI.ViewModels
// Get the extension for the file for the next two statements
string extension = Env.Parameters?.GetDefaultExtension(mediaType);
// Disable automatic reprocessing of the textboxes until we're done
DisablePathEventHandlers();
// Set the output filename, if it's not already
if (string.IsNullOrEmpty(App.Instance.OutputPathTextBox.Text))
{
string label = drive?.FormattedVolumeLabel ?? systemType.LongName();
string directory = App.Options.DefaultOutputPath;
string filename = $"{label}{extension ?? ".bin"}";
// Save the current cursor positions
int outputDirectorySelectionStart = App.Instance.OutputDirectoryTextBox.SelectionStart;
int outputFilenameSelectionStart = App.Instance.OutputFilenameTextBox.SelectionStart;
App.Instance.OutputPathTextBox.Text = Path.Combine(directory, label, filename);
}
// Set the output filename, if we changed drives or it's not already
if (driveChanged || string.IsNullOrEmpty(App.Instance.OutputFilenameTextBox.Text))
App.Instance.OutputFilenameTextBox.Text = (drive?.FormattedVolumeLabel ?? systemType.LongName()) + (extension ?? ".bin");
// Set the output filename, if we changed drives
else if (driveChanged)
{
string label = drive?.FormattedVolumeLabel ?? systemType.LongName();
string directory = Path.GetDirectoryName(App.Instance.OutputPathTextBox.Text);
string filename = $"{label}{extension ?? ".bin"}";
// If the extension for the file changed, update that automatically
else if (Path.GetExtension(App.Instance.OutputFilenameTextBox.Text) != extension)
App.Instance.OutputFilenameTextBox.Text = Path.GetFileNameWithoutExtension(App.Instance.OutputFilenameTextBox.Text) + (extension ?? ".bin");
// Set the output directory, if we changed drives or it's not already
if (driveChanged || string.IsNullOrEmpty(App.Instance.OutputDirectoryTextBox.Text))
App.Instance.OutputDirectoryTextBox.Text = Path.Combine(App.Options.DefaultOutputPath, Path.GetFileNameWithoutExtension(App.Instance.OutputFilenameTextBox.Text) ?? string.Empty);
// Set the cursor position back to where it was
App.Instance.OutputDirectoryTextBox.SelectionStart = outputDirectorySelectionStart;
App.Instance.OutputDirectoryTextBox.SelectionLength = 0;
App.Instance.OutputFilenameTextBox.SelectionStart = outputFilenameSelectionStart;
App.Instance.OutputFilenameTextBox.SelectionLength = 0;
// Re-enable automatic reprocessing of textboxes
EnablePathEventHandlers();
App.Instance.OutputPathTextBox.Text = Path.Combine(directory, label, filename);
}
// Ensure the UI gets updated
App.Instance.UpdateLayout();
@@ -1047,34 +996,9 @@ namespace MPF.UI.ViewModels
else
Env.Parameters.Speed = App.Instance.DriveSpeedComboBox.SelectedValue as int?;
// Disable automatic reprocessing of the textboxes until we're done
DisablePathEventHandlers();
// Save the current cursor positions
int outputDirectorySelectionStart = App.Instance.OutputDirectoryTextBox.SelectionStart;
int outputFilenameSelectionStart = App.Instance.OutputFilenameTextBox.SelectionStart;
string trimmedPath = Env.Parameters.OutputPath?.Trim('"') ?? string.Empty;
string outputDirectory = Path.GetDirectoryName(trimmedPath);
string outputFilename = Path.GetFileName(trimmedPath);
(outputDirectory, outputFilename) = InfoTool.NormalizeOutputPaths(outputDirectory, outputFilename);
if (!string.IsNullOrWhiteSpace(outputDirectory))
App.Instance.OutputDirectoryTextBox.Text = outputDirectory;
else
outputDirectory = App.Instance.OutputDirectoryTextBox.Text;
if (!string.IsNullOrWhiteSpace(outputFilename))
App.Instance.OutputFilenameTextBox.Text = outputFilename;
else
outputFilename = App.Instance.OutputFilenameTextBox.Text;
// Set the cursor position back to where it was
App.Instance.OutputDirectoryTextBox.SelectionStart = outputDirectorySelectionStart;
App.Instance.OutputDirectoryTextBox.SelectionLength = 0;
App.Instance.OutputFilenameTextBox.SelectionStart = outputFilenameSelectionStart;
App.Instance.OutputFilenameTextBox.SelectionLength = 0;
// Re-enable automatic reprocessing of textboxes
EnablePathEventHandlers();
trimmedPath = InfoTool.NormalizeOutputPaths(trimmedPath);
App.Instance.OutputPathTextBox.Text = trimmedPath;
MediaType? mediaType = Env.Parameters.GetMediaType();
int mediaTypeIndex = MediaTypes.FindIndex(m => m == mediaType);
@@ -1271,6 +1195,10 @@ namespace MPF.UI.ViewModels
// Disable all UI elements apart from dumping button
DisableAllUIElements();
// Refresh the drive, if it wasn't null
if (Env.Drive != null)
Env.Drive.RefreshDrive();
// Output to the label and log
App.Instance.StatusLabel.Text = "Starting dumping process... Please wait!";
App.Logger.LogLn("Starting dumping process... Please wait!");
@@ -1330,6 +1258,14 @@ namespace MPF.UI.ViewModels
/// <returns>True if dumping should start, false otherwise</returns>
private bool ValidateBeforeDumping()
{
// Validate that we have an output path of any sort
if (string.IsNullOrWhiteSpace(Env.OutputPath))
{
MessageBoxResult mbresult = CustomMessageBox.Show("No output path was provided so dumping cannot continue.", "Missing Path", MessageBoxButton.OK, MessageBoxImage.Exclamation);
App.Logger.LogLn("Dumping aborted!");
return false;
}
// Validate that the user explicitly wants an inactive drive to be considered for dumping
if (!Env.Drive.MarkedActive)
{
@@ -1345,8 +1281,12 @@ namespace MPF.UI.ViewModels
}
}
// Pre-split the output path
string outputDirectory = Path.GetDirectoryName(Env.OutputPath);
string outputFilename = Path.GetFileName(Env.OutputPath);
// If a complete dump already exists
(bool foundFiles, List<string> _) = InfoTool.FoundAllFiles(Env.OutputDirectory, Env.OutputFilename, Env.Parameters, true);
(bool foundFiles, List<string> _) = InfoTool.FoundAllFiles(outputDirectory, outputFilename, Env.Parameters, true);
if (foundFiles)
{
MessageBoxResult mbresult = CustomMessageBox.Show("A complete dump already exists! Are you sure you want to overwrite?", "Overwrite?", MessageBoxButton.YesNo, MessageBoxImage.Exclamation);
@@ -1359,7 +1299,7 @@ namespace MPF.UI.ViewModels
// Validate that at least some space exists
// TODO: Tie this to the size of the disc, type of disc, etc.
string fullPath = Path.GetFullPath(Env.OutputDirectory);
string fullPath = Path.GetFullPath(outputDirectory);
var driveInfo = new DriveInfo(Path.GetPathRoot(fullPath));
if (driveInfo.AvailableFreeSpace < Math.Pow(2, 30))
{
@@ -1514,28 +1454,10 @@ namespace MPF.UI.ViewModels
}
/// <summary>
/// Handler for OutputDirectoryBrowseButton Click event
/// Handler for OutputPathBrowseButton Click event
/// </summary>
private void OutputDirectoryBrowseButtonClick(object sender, RoutedEventArgs e) =>
SetOutputDirectory();
/// <summary>
/// Handler for OutputFilenameTextBox TextInput event
/// </summary>
private void OutputDirectoryTextBoxTextChanged(object sender, TextChangedEventArgs e)
{
if (_canExecuteTextChanged)
EnsureDiscInformation();
}
/// <summary>
/// Handler for OutputFilenameTextBox TextInput event
/// </summary>
private void OutputFilenameTextBoxTextChanged(object sender, TextChangedEventArgs e)
{
if (_canExecuteTextChanged)
EnsureDiscInformation();
}
private void OutputPathBrowseButtonClick(object sender, RoutedEventArgs e) =>
SetOutputPath();
/// <summary>
/// Handler for StartStopButton Click event

View File

@@ -119,7 +119,6 @@
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Label x:Name="SystemMediaTypeLabel" Grid.Row="0" Grid.Column="0" VerticalAlignment="Center" Content="System/Media Type" />
@@ -136,16 +135,13 @@
</ComboBox>
<ComboBox x:Name="MediaTypeComboBox" Grid.Row="0" Grid.Column="1" Height="22" Width="140" HorizontalAlignment="Right" Style="{DynamicResource CustomComboBoxStyle}" />
<Label x:Name="OutputFilenameLabel" Grid.Row="1" Grid.Column="0" VerticalAlignment="Center" Content="Output Filename"/>
<TextBox x:Name="OutputFilenameTextBox" Grid.Row="1" Grid.Column="1" Height="22" VerticalContentAlignment="Center" />
<Label x:Name="OutputDirectoryLabel" Grid.Row="2" Grid.Column="0" VerticalAlignment="Center" Content="Output Directory"/>
<TextBox x:Name="OutputDirectoryTextBox" Grid.Row="2" Grid.Column="1" Height="22" Width="345" HorizontalAlignment="Left" VerticalContentAlignment="Center" />
<Button x:Name="OutputDirectoryBrowseButton" Grid.Row="2" Grid.Column="1" Height="22" Width="50" HorizontalAlignment="Right" Content="Browse"
<Label x:Name="OutputPathLabel" Grid.Row="1" Grid.Column="0" VerticalAlignment="Center" Content="Output Path"/>
<TextBox x:Name="OutputPathTextBox" Grid.Row="1" Grid.Column="1" Height="22" Width="345" HorizontalAlignment="Left" VerticalContentAlignment="Center" />
<Button x:Name="OutputPathBrowseButton" Grid.Row="1" Grid.Column="1" Height="22" Width="50" HorizontalAlignment="Right" Content="Browse"
Style="{DynamicResource CustomButtonStyle}"/>
<Label x:Name="DriveLetterLabel" Grid.Row="3" Grid.Column="0" VerticalAlignment="Center" Content="Drive Letter"/>
<ComboBox x:Name="DriveLetterComboBox" Grid.Row="3" Grid.Column="1" Height="22" Width="60" HorizontalAlignment="Left" Style="{DynamicResource CustomComboBoxStyle}">
<Label x:Name="DriveLetterLabel" Grid.Row="2" Grid.Column="0" VerticalAlignment="Center" Content="Drive Letter"/>
<ComboBox x:Name="DriveLetterComboBox" Grid.Row="2" Grid.Column="1" Height="22" Width="60" HorizontalAlignment="Left" Style="{DynamicResource CustomComboBoxStyle}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Letter}" />
@@ -153,12 +149,12 @@
</ComboBox.ItemTemplate>
</ComboBox>
<Label x:Name="DriveSpeedLabel" Grid.Row="4" Grid.Column="0" VerticalAlignment="Center" Content="Drive Speed"/>
<ComboBox x:Name="DriveSpeedComboBox" Grid.Row="4" Grid.Column="1" Height="22" Width="60" HorizontalAlignment="Left" Style="{DynamicResource CustomComboBoxStyle}" />
<Label x:Name="DriveSpeedLabel" Grid.Row="3" Grid.Column="0" VerticalAlignment="Center" Content="Drive Speed"/>
<ComboBox x:Name="DriveSpeedComboBox" Grid.Row="3" Grid.Column="1" Height="22" Width="60" HorizontalAlignment="Left" Style="{DynamicResource CustomComboBoxStyle}" />
<Label x:Name="ParametersLabel" Grid.Row="5" Grid.Column="0" VerticalAlignment="Center" Content="Parameters"/>
<TextBox x:Name="ParametersTextBox" Grid.Row="5" Grid.Column="1" Height="22" Width="370" HorizontalAlignment="Left" IsEnabled="False" VerticalContentAlignment="Center" />
<CheckBox x:Name="EnableParametersCheckBox" Grid.Row="5" Grid.Column="1" Height="22" HorizontalAlignment="Right" IsChecked="False" />
<Label x:Name="ParametersLabel" Grid.Row="4" Grid.Column="0" VerticalAlignment="Center" Content="Parameters"/>
<TextBox x:Name="ParametersTextBox" Grid.Row="4" Grid.Column="1" Height="22" Width="370" HorizontalAlignment="Left" IsEnabled="False" VerticalContentAlignment="Center" />
<CheckBox x:Name="EnableParametersCheckBox" Grid.Row="4" Grid.Column="1" Height="22" HorizontalAlignment="Right" IsChecked="False" />
</Grid>
</GroupBox>