feat: Implement AI CSV overwrite confirmation and update CSV output path based on destination
This commit is contained in:
parent
6e05869b04
commit
f3ac1ea920
3 changed files with 214 additions and 0 deletions
|
|
@ -22,6 +22,7 @@ using System.Text.RegularExpressions;
|
|||
using AutoMapper;
|
||||
using MaddoShared;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
namespace ImageCatalog_2
|
||||
{
|
||||
|
|
@ -82,6 +83,8 @@ namespace ImageCatalog_2
|
|||
|
||||
private sealed record ParsedFaceMatcherRow(string PhotoId, double? Score, string RawRow, string DebugSummary);
|
||||
|
||||
private const string AiCsvOverwriteDialogTitle = "File CSV gia esistente";
|
||||
|
||||
// ComboBox collections
|
||||
public List<string> AvailableFonts { get; }
|
||||
public List<string> VerticalPositions { get; } = new() { "Alto", "Centro", "Basso" };
|
||||
|
|
@ -145,6 +148,12 @@ namespace ImageCatalog_2
|
|||
|
||||
private async Task StartAiAsync()
|
||||
{
|
||||
if (!await ConfirmAiCsvOverwriteIfNeededAsync().ConfigureAwait(false))
|
||||
{
|
||||
await InvokeOnUiThreadAsync(() => NumberAiStatsSummary = "OCR annullato.").ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
|
||||
MainToken = new CancellationTokenSource();
|
||||
try
|
||||
{
|
||||
|
|
@ -267,6 +276,8 @@ namespace ImageCatalog_2
|
|||
set => _ai.CsvOutputPath = value;
|
||||
}
|
||||
|
||||
public Func<string, string, Task<bool>>? ConfirmAiCsvOverwriteAsync { get; set; }
|
||||
|
||||
public bool UseNumberAiGpu
|
||||
{
|
||||
get => _ai.UseNumberAiGpu;
|
||||
|
|
@ -641,6 +652,11 @@ namespace ImageCatalog_2
|
|||
return;
|
||||
}
|
||||
|
||||
if (string.Equals(e.PropertyName, nameof(PathSettingsViewModel.DestinationPath), StringComparison.Ordinal))
|
||||
{
|
||||
UpdateAiCsvOutputPathForDestination();
|
||||
}
|
||||
|
||||
NotifyPropertyChanged(e.PropertyName);
|
||||
}
|
||||
|
||||
|
|
@ -2403,6 +2419,103 @@ namespace ImageCatalog_2
|
|||
});
|
||||
}
|
||||
|
||||
internal async Task<bool> ConfirmAiCsvOverwriteIfNeededAsync()
|
||||
{
|
||||
var csvOutputPath = NormalizeFilePathArgument(CsvOutputPath);
|
||||
if (string.IsNullOrWhiteSpace(csvOutputPath) || !File.Exists(csvOutputPath))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
var confirmOverwrite = ConfirmAiCsvOverwriteAsync;
|
||||
if (confirmOverwrite is null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
var message = $"Il file CSV esiste gia:\n{csvOutputPath}\n\nVuoi sovrascriverlo? Se scegli Annulla l'operazione OCR non verra avviata.";
|
||||
return await confirmOverwrite(AiCsvOverwriteDialogTitle, message).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
internal void UpdateAiCsvOutputPathForDestination()
|
||||
{
|
||||
var updatedPath = BuildAiCsvOutputPathForDestination(CsvOutputPath, DestinationPath);
|
||||
if (string.Equals(updatedPath, CsvOutputPath, StringComparison.Ordinal))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CsvOutputPath = updatedPath;
|
||||
}
|
||||
|
||||
internal static string BuildAiCsvOutputPathForDestination(string currentCsvOutputPath, string destinationPath)
|
||||
{
|
||||
var normalizedCsvPath = NormalizeFilePathArgument(currentCsvOutputPath);
|
||||
if (string.IsNullOrWhiteSpace(normalizedCsvPath))
|
||||
{
|
||||
return currentCsvOutputPath;
|
||||
}
|
||||
|
||||
var directory = Path.GetDirectoryName(normalizedCsvPath);
|
||||
var destinationFolderName = GetDestinationFolderName(destinationPath);
|
||||
if (string.IsNullOrWhiteSpace(destinationFolderName))
|
||||
{
|
||||
return normalizedCsvPath;
|
||||
}
|
||||
|
||||
var extension = Path.GetExtension(normalizedCsvPath);
|
||||
if (string.IsNullOrWhiteSpace(extension))
|
||||
{
|
||||
extension = ".csv";
|
||||
}
|
||||
|
||||
var safeFileName = SanitizeFileName(destinationFolderName) + extension;
|
||||
return string.IsNullOrWhiteSpace(directory)
|
||||
? safeFileName
|
||||
: Path.Combine(directory, safeFileName);
|
||||
}
|
||||
|
||||
private static string GetDestinationFolderName(string destinationPath)
|
||||
{
|
||||
var normalizedDestinationPath = NormalizeDirectoryPathArgument(destinationPath);
|
||||
if (string.IsNullOrWhiteSpace(normalizedDestinationPath))
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
var trimmedPath = normalizedDestinationPath.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
|
||||
if (string.IsNullOrWhiteSpace(trimmedPath))
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
var rootPath = Path.GetPathRoot(trimmedPath)?.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
|
||||
if (!string.IsNullOrWhiteSpace(rootPath)
|
||||
&& string.Equals(trimmedPath, rootPath, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
return Path.GetFileName(trimmedPath);
|
||||
}
|
||||
|
||||
private static string SanitizeFileName(string value)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(value))
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
var invalidFileNameChars = Path.GetInvalidFileNameChars();
|
||||
var builder = new StringBuilder(value.Length);
|
||||
foreach (var character in value)
|
||||
{
|
||||
builder.Append(Array.IndexOf(invalidFileNameChars, character) >= 0 ? '_' : character);
|
||||
}
|
||||
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
private void SetUseFaceGpu(bool value)
|
||||
{
|
||||
var currentValue = _ai.UseFaceGpu;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue