From 0772a39ef5af192be3723eb350eca1acce8c3ad0 Mon Sep 17 00:00:00 2001 From: David Khristepher Santos Date: Sat, 20 Apr 2024 15:28:32 -0700 Subject: [PATCH] Refresh folder list after modifying watched Folders Add dialog to scan and remove or mark for deletion of unavailable images --- Diffusion.Database/DataStore.Image.cs | 11 ++ .../Converters/UnavailableConverter.cs | 19 +++ Diffusion.Toolkit/Localization/de-DE.json | 1 - Diffusion.Toolkit/Localization/default.json | 16 +- Diffusion.Toolkit/Localization/en-US.json | 1 - Diffusion.Toolkit/Localization/es-ES.json | 1 - Diffusion.Toolkit/Localization/fr-FR.json | 1 - Diffusion.Toolkit/Localization/ja-JP.json | 1 - Diffusion.Toolkit/MainWindow.xaml | 1 + Diffusion.Toolkit/MainWindow.xaml.Folders.cs | 12 +- Diffusion.Toolkit/MainWindow.xaml.Scanning.cs | 159 ++++++++++++++++++ Diffusion.Toolkit/MainWindow.xaml.cs | 15 ++ Diffusion.Toolkit/Models/FolderViewModel.cs | 7 + Diffusion.Toolkit/Models/MainModel.cs | 7 + Diffusion.Toolkit/Pages/Search.xaml | 3 +- .../Pages/Search.xaml.Folders.cs | 17 +- Diffusion.Toolkit/Themes/Common.xaml | 3 + Diffusion.Toolkit/UnavailableFilesModel.cs | 79 +++++++++ Diffusion.Toolkit/UnavailableFilesWindow.xaml | 79 +++++++++ .../UnavailableFilesWindow.xaml.cs | 80 +++++++++ 20 files changed, 490 insertions(+), 23 deletions(-) create mode 100644 Diffusion.Toolkit/Converters/UnavailableConverter.cs create mode 100644 Diffusion.Toolkit/UnavailableFilesModel.cs create mode 100644 Diffusion.Toolkit/UnavailableFilesWindow.xaml create mode 100644 Diffusion.Toolkit/UnavailableFilesWindow.xaml.cs diff --git a/Diffusion.Database/DataStore.Image.cs b/Diffusion.Database/DataStore.Image.cs index 4412bf0..d7de820 100644 --- a/Diffusion.Database/DataStore.Image.cs +++ b/Diffusion.Database/DataStore.Image.cs @@ -99,6 +99,17 @@ public IEnumerable GetAllPathImages(string path) db.Close(); } + public int CountAllPathImages(string path) + { + using var db = OpenConnection(); + + var count = db.ExecuteScalar("SELECT COUNT(*) FROM Image WHERE PATH LIKE ? || '%'", path); + + db.Close(); + + return count; + } + public IEnumerable GetFolderImages(int folderId) { using var db = OpenConnection(); diff --git a/Diffusion.Toolkit/Converters/UnavailableConverter.cs b/Diffusion.Toolkit/Converters/UnavailableConverter.cs new file mode 100644 index 0000000..a37f444 --- /dev/null +++ b/Diffusion.Toolkit/Converters/UnavailableConverter.cs @@ -0,0 +1,19 @@ +using System; +using System.Globalization; +using System.Windows; +using System.Windows.Data; + +namespace Diffusion.Toolkit.Converters; + +public class UnavailableConverter : IValueConverter +{ + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + return (bool)value ? TextDecorations.Strikethrough : null; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/Diffusion.Toolkit/Localization/de-DE.json b/Diffusion.Toolkit/Localization/de-DE.json index d41a182..93127a4 100644 --- a/Diffusion.Toolkit/Localization/de-DE.json +++ b/Diffusion.Toolkit/Localization/de-DE.json @@ -31,7 +31,6 @@ "Menu.Tools.SearchResults.RemoveMatching": "_Alle Suchergebnisse aus der Datenbank entfernen", "Menu.Tools.AutoTagNSFW": "_NSFW automatisch taggen", "Menu.Tools.Folders": "_Ordner", - "Menu.Tools.Folders.": "_Ordner", "Menu.Tools.Folders.FixMissingImages": "_Fehlende Bilder reparieren", "Menu.Tools.Folders.RemoveExcludedImages": "_Ausgeschlossene Bilder entfernen", "Menu.Tools.Folders.CleanRemovedFolders": "_Entfernte Ordner bereinigen", diff --git a/Diffusion.Toolkit/Localization/default.json b/Diffusion.Toolkit/Localization/default.json index f638b56..bbb6c47 100644 --- a/Diffusion.Toolkit/Localization/default.json +++ b/Diffusion.Toolkit/Localization/default.json @@ -32,10 +32,10 @@ "Menu.Tools.SearchResults.RemoveMatching": "_Remove all query results from the database", "Menu.Tools.AutoTagNSFW": "_Auto tag NSFW", "Menu.Tools.Folders": "_Folders", - "Menu.Tools.Folders.": "_Folders", "Menu.Tools.Folders.FixMissingImages": "_Fix missing images", "Menu.Tools.Folders.RemoveExcludedImages": "_Remove excluded images", "Menu.Tools.Folders.CleanRemovedFolders": "_Clean removed folders", + "Menu.Tools.UnavailableFiles": "Unavailable Files", "Menu.Help": "_Help", "Menu.Help.About": "About", "Menu.Help.GettingStarted": "Getting Started", @@ -47,6 +47,7 @@ "Common.Buttons.Browse": "Browse", "Common.Buttons.Apply": "Apply", "Common.Buttons.Close": "Close", + "Common.Buttons.Start": "Start", "Common.MessageBox.Cancel": "Confirm Cancel", "Common.MessageBox.ConfirmCancelOperation": "Are you sure you want to cancel the operation?", "Common.MessageBox.OperationCancelled": "The operation was cancelled.", @@ -118,6 +119,7 @@ "Search.Buttons.ShowFilter.ToolTip": "Show filter", "Search.Buttons.Clear.ToolTip": "Clear", "Search.Buttons.Refresh.ToolTip": "Refresh", + "Search.Folders.Buttons.Refresh.ToopTip": "Refresh", "Search.Albums.Buttons.SortAlbums.ToolTip": "Sort", "Search.Albums.Buttons.CreateAlbum.ToolTip": "New Album", "Search.AddressBar.Buttons.Home.ToolTip": "Home", @@ -193,5 +195,15 @@ "Messages.Captions.Error": "Error", "Messages.Errors.NoImagePaths": "No image paths configured!", "Main.Status.ImagesInDatabase": "{count} images in database", - "Main.Update.UpdateAvailable": "An update is available. Do you want to install now?" + "Main.Update.UpdateAvailable": "An update is available. Do you want to install now?", + "UnavailableFiles": "Scan for unavailable files", + "UnavailableFiles.Description": "This will scan for unavailable files in the specified locations. You can choose to immediately delete or mark for deletion", + "UnavailableFiles.Sources.SourceLabel": "Scan selected locations:", + "UnavailableFiles.Sources.RootFolders": "Root Folders", + "UnavailableFiles.Sources.SpecificFolders": "Specific Folders", + "UnavailableFiles.Options.RemoveFromUnavailableRootFolders": "Remove files from unavailable root folders", + "UnavailableFiles.Options.DeleteImmediately": "Delete immediately", + "UnavailableFiles.Options.MarkForDeletion": "Mark for deletion", + "UnavailableFiles.Results.Removed": "{count} images removed.", + "UnavailableFiles.Results.MarkedForDeletion": "{count} images marked for deletion." } \ No newline at end of file diff --git a/Diffusion.Toolkit/Localization/en-US.json b/Diffusion.Toolkit/Localization/en-US.json index 5db0425..4943946 100644 --- a/Diffusion.Toolkit/Localization/en-US.json +++ b/Diffusion.Toolkit/Localization/en-US.json @@ -31,7 +31,6 @@ "Menu.Tools.SearchResults.RemoveMatching": "_Remove all query results from the database", "Menu.Tools.AutoTagNSFW": "_Auto tag NSFW", "Menu.Tools.Folders": "_Folders", - "Menu.Tools.Folders.": "_Folders", "Menu.Tools.Folders.FixMissingImages": "_Fix missing images", "Menu.Tools.Folders.RemoveExcludedImages": "_Remove excluded images", "Menu.Tools.Folders.CleanRemovedFolders": "_Clean removed folders", diff --git a/Diffusion.Toolkit/Localization/es-ES.json b/Diffusion.Toolkit/Localization/es-ES.json index 571128e..9ebbfdc 100644 --- a/Diffusion.Toolkit/Localization/es-ES.json +++ b/Diffusion.Toolkit/Localization/es-ES.json @@ -31,7 +31,6 @@ "Menu.Tools.SearchResults.RemoveMatching": "Eliminar todos los resultados de la consulta de la base de datos", "Menu.Tools.AutoTagNSFW": "Etiquetar automáticamente _NSFW", "Menu.Tools.Folders": "_Carpetas", - "Menu.Tools.Folders.": "_Carpetas", "Menu.Tools.Folders.FixMissingImages": "_Corregir imágenes faltantes", "Menu.Tools.Folders.RemoveExcludedImages": "_Eliminar imágenes excluidas", "Menu.Tools.Folders.CleanRemovedFolders": "_Limpiar carpetas eliminadas", diff --git a/Diffusion.Toolkit/Localization/fr-FR.json b/Diffusion.Toolkit/Localization/fr-FR.json index 49097be..d634dbf 100644 --- a/Diffusion.Toolkit/Localization/fr-FR.json +++ b/Diffusion.Toolkit/Localization/fr-FR.json @@ -31,7 +31,6 @@ "Menu.Tools.SearchResults.RemoveMatching": "_Supprimer tous les résultats de la requête de la base de données", "Menu.Tools.AutoTagNSFW": "_Baliser automatiquement comme NSFW", "Menu.Tools.Folders": "_Dossiers", - "Menu.Tools.Folders.": "_Dossiers", "Menu.Tools.Folders.FixMissingImages": "_Réparer les images manquantes", "Menu.Tools.Folders.RemoveExcludedImages": "_Supprimer les images exclues", "Menu.Tools.Folders.CleanRemovedFolders": "_Nettoyer les dossiers supprimés", diff --git a/Diffusion.Toolkit/Localization/ja-JP.json b/Diffusion.Toolkit/Localization/ja-JP.json index 21d57a2..3ad436e 100644 --- a/Diffusion.Toolkit/Localization/ja-JP.json +++ b/Diffusion.Toolkit/Localization/ja-JP.json @@ -31,7 +31,6 @@ "Menu.Tools.SearchResults.RemoveMatching": "データベースからすべてのクエリ結果を削除", "Menu.Tools.AutoTagNSFW": "NSFWを自動タグ付け", "Menu.Tools.Folders": "フォルダ", - "Menu.Tools.Folders.": "フォルダ", "Menu.Tools.Folders.FixMissingImages": "不足している画像を修正", "Menu.Tools.Folders.RemoveExcludedImages": "除外された画像を削除", "Menu.Tools.Folders.CleanRemovedFolders": "削除されたフォルダをクリーンアップ", diff --git a/Diffusion.Toolkit/MainWindow.xaml b/Diffusion.Toolkit/MainWindow.xaml index 7538e3a..32f161e 100644 --- a/Diffusion.Toolkit/MainWindow.xaml +++ b/Diffusion.Toolkit/MainWindow.xaml @@ -119,6 +119,7 @@ + diff --git a/Diffusion.Toolkit/MainWindow.xaml.Folders.cs b/Diffusion.Toolkit/MainWindow.xaml.Folders.cs index 6426765..48e5d67 100644 --- a/Diffusion.Toolkit/MainWindow.xaml.Folders.cs +++ b/Diffusion.Toolkit/MainWindow.xaml.Folders.cs @@ -3,18 +3,9 @@ using System.Collections.ObjectModel; using System.IO; using System.Linq; -using System.Text; -using System.Text.Json.Serialization; -using System.Text.Json; using System.Threading.Tasks; -using Diffusion.Civitai; -using Diffusion.Civitai.Models; -using System.Diagnostics; -using System.Threading; using Diffusion.Toolkit.Classes; using Diffusion.Toolkit.Models; -using static System.Net.Mime.MediaTypeNames; -using System.Windows.Shapes; using SQLite; using Path = System.IO.Path; @@ -290,7 +281,8 @@ private void LoadFolders() Visible = true, Depth = 0, Name = path, - Path = path + Path = path, + IsUnavailable = !Directory.Exists(path) })); } } diff --git a/Diffusion.Toolkit/MainWindow.xaml.Scanning.cs b/Diffusion.Toolkit/MainWindow.xaml.Scanning.cs index da85436..842d35b 100644 --- a/Diffusion.Toolkit/MainWindow.xaml.Scanning.cs +++ b/Diffusion.Toolkit/MainWindow.xaml.Scanning.cs @@ -14,6 +14,165 @@ namespace Diffusion.Toolkit { public partial class MainWindow { + private Task ScanUnavailable(UnavailableFilesModel options) + { + _progressCancellationTokenSource = new CancellationTokenSource(); + + var token = _progressCancellationTokenSource.Token; + + return Task.Run(() => + { + var candidateImages = new List(); + + Dispatcher.Invoke(() => + { + _model.IsBusy = true; + }); + + if (options.UseRootFolders) + { + var rootFolders = options.ImagePaths.Where(f => f.IsSelected); + + var total = 0; + + foreach (var folder in rootFolders) + { + total += _dataStore.CountAllPathImages(folder.Path); + } + + Dispatcher.Invoke(() => + { + _model.CurrentProgress = 0; + _model.TotalProgress = total; + }); + + var current = 0; + + var scanning = GetLocalizedText("Actions.Scanning.Status"); + + foreach (var folder in rootFolders) + { + if (token.IsCancellationRequested) + { + break; + } + + HashSet ignoreFiles = new HashSet(); + + var folderImages = _dataStore.GetAllPathImages(folder.Path).ToDictionary(f => f.Path); + + if (Directory.Exists(folder.Path)) + { + //var filesOnDisk = MetadataScanner.GetFiles(folder.Path, _settings.FileExtensions, null, _settings.RecurseFolders.GetValueOrDefault(true), null); + var filesOnDisk = MetadataScanner.GetFiles(folder.Path, _settings.FileExtensions, ignoreFiles, _settings.RecurseFolders.GetValueOrDefault(true), _settings.ExcludePaths); + + foreach (var file in filesOnDisk) + { + if (token.IsCancellationRequested) + { + break; + } + + if (folderImages.ContainsKey(file)) + { + folderImages.Remove(file); + } + + current++; + + if (current % 113 == 0) + { + + Dispatcher.Invoke(() => + { + _model.CurrentProgress = current; + + var status = scanning + .Replace("{current}", $"{_model.CurrentProgress:#,###,##0}") + .Replace("{total}", $"{_model.TotalProgress:#,###,##0}"); + + _model.Status = status; + }); + } + } + + foreach (var folderImage in folderImages) + { + candidateImages.Add(folderImage.Value.Id); + } + } + else + { + if (options.RemoveFromUnavailableRootFolders) + { + foreach (var folderImage in folderImages) + { + candidateImages.Add(folderImage.Value.Id); + + current++; + + if (current % 113 == 0) + { + Dispatcher.Invoke(() => + { + _model.CurrentProgress = current; + + var status = scanning + .Replace("{current}", $"{_model.CurrentProgress:#,###,##0}") + .Replace("{total}", $"{_model.TotalProgress:#,###,##0}"); + + _model.Status = status; + }); + } + } + } + + } + } + + Dispatcher.Invoke(() => + { + _model.CurrentProgress = total; + _model.TotalProgress = total; + + var unavailableFiles = GetLocalizedText("UnavailableFiles"); + + if (options.DeleteImmediately) + { + _dataStore.RemoveImages(candidateImages); + + var removed = GetLocalizedText("UnavailableFiles.Results.Removed"); + + removed = removed.Replace("{count}", $"{candidateImages.Count:#,###,##0}"); + + _messagePopupManager.Show(removed, unavailableFiles, PopupButtons.OK); + } + else + { + _dataStore.SetDeleted(candidateImages, true); + + var marked = GetLocalizedText("UnavailableFiles.Results.MarkedForDeletion"); + + marked = marked.Replace("{count}", $"{candidateImages.Count:#,###,##0}"); + + _messagePopupManager.Show(marked, unavailableFiles, PopupButtons.OK); + } + + var completed = GetLocalizedText("Actions.Scanning.Completed"); + + _model.IsBusy = true; + _model.Status = completed; + _model.CurrentProgress = 0; + _model.TotalProgress = Int32.MaxValue; + }); + + } + + + }); + + } + private async Task RescanTask(object o) { diff --git a/Diffusion.Toolkit/MainWindow.xaml.cs b/Diffusion.Toolkit/MainWindow.xaml.cs index 6641c87..370df74 100644 --- a/Diffusion.Toolkit/MainWindow.xaml.cs +++ b/Diffusion.Toolkit/MainWindow.xaml.cs @@ -136,6 +136,8 @@ public MainWindow() _model.RemoveExcludedImagesCommand = new RelayCommand((o) => CleanExcludedPaths()); _model.CleanRemovedFoldersCommand = new AsyncCommand(CleanRemovedFolders); + _model.UnavailableFilesCommand = new RelayCommand((o) => UnavailableFiles()); + _model.ShowFilterCommand = new RelayCommand((o) => _search?.ShowFilter()); _model.ToggleAutoRefresh = new RelayCommand((o) => ToggleAutoRefresh()); @@ -188,6 +190,17 @@ public MainWindow() //System.Diagnostics.Debug.Write(str); } + private void UnavailableFiles() + { + var window = new UnavailableFilesWindow(_dataStore, _settings); + window.Owner = this; + window.ShowDialog(); + if (window.DialogResult is true) + { + ScanUnavailable(window.Model); + } + } + private void ToggleNavigationPane() { _model.Settings.NavigationSection.ToggleSection(); @@ -838,6 +851,8 @@ private async void ShowSettings(object obj) CleanRemovedFoldersInternal(); } + LoadFolders(); + await TryScanFolders(); // Rebuild watchers in case paths were added or removed diff --git a/Diffusion.Toolkit/Models/FolderViewModel.cs b/Diffusion.Toolkit/Models/FolderViewModel.cs index 78b3cf6..4de324f 100644 --- a/Diffusion.Toolkit/Models/FolderViewModel.cs +++ b/Diffusion.Toolkit/Models/FolderViewModel.cs @@ -17,6 +17,7 @@ public class FolderViewModel : BaseNotify private bool _visible; private bool _isSelected; private string _name; + private bool _isUnavailable; public FolderState State { @@ -55,6 +56,12 @@ public string Name set => SetField(ref _name, value); } + public bool IsUnavailable + { + get => _isUnavailable; + set => SetField(ref _isUnavailable, value); + } + public override bool Equals(object? obj) { if (obj is FolderViewModel folder) diff --git a/Diffusion.Toolkit/Models/MainModel.cs b/Diffusion.Toolkit/Models/MainModel.cs index e72ad5b..004ac30 100644 --- a/Diffusion.Toolkit/Models/MainModel.cs +++ b/Diffusion.Toolkit/Models/MainModel.cs @@ -476,6 +476,12 @@ public ICommand CleanRemovedFoldersCommand set => SetField(ref _cleanRemovedFoldersCommand, value); } + public ICommand UnavailableFilesCommand + { + get => _unavailableFilesCommand; + set => SetField(ref _unavailableFilesCommand, value); + } + public ICommand ShowFilterCommand { @@ -529,6 +535,7 @@ public Settings Settings private FolderViewModel? _currentFolder; private ICommand _resetLayout; + private ICommand _unavailableFilesCommand; public FolderViewModel? CurrentFolder { diff --git a/Diffusion.Toolkit/Pages/Search.xaml b/Diffusion.Toolkit/Pages/Search.xaml index fd953a1..a20d896 100644 --- a/Diffusion.Toolkit/Pages/Search.xaml +++ b/Diffusion.Toolkit/Pages/Search.xaml @@ -39,6 +39,7 @@ + @@ -272,7 +273,7 @@ - + diff --git a/Diffusion.Toolkit/Pages/Search.xaml.Folders.cs b/Diffusion.Toolkit/Pages/Search.xaml.Folders.cs index dfd8464..6e195cf 100644 --- a/Diffusion.Toolkit/Pages/Search.xaml.Folders.cs +++ b/Diffusion.Toolkit/Pages/Search.xaml.Folders.cs @@ -19,11 +19,11 @@ public partial class Search private void ExpandToPath(string path) { - var root = _model.MainModel.Folders.FirstOrDefault(f => f.Depth == 0 && path.StartsWith(f.Path, StringComparison.InvariantCultureIgnoreCase)); + var root = _model.MainModel.Folders.FirstOrDefault(f => f.Depth == 0 && path.StartsWith(f.Path, StringComparison.InvariantCultureIgnoreCase)); var currentNode = root; - while(currentNode != null && !currentNode.Path.Equals(path, StringComparison.InvariantCultureIgnoreCase)) + while (currentNode != null && !currentNode.Path.Equals(path, StringComparison.InvariantCultureIgnoreCase)) { if (currentNode.State == FolderState.Collapsed) { @@ -74,7 +74,10 @@ private void Expander_OnMouseDown(object sender, MouseButtonEventArgs e) { var folder = ((FrameworkElement)sender).DataContext as FolderViewModel; - ToggleFolder(folder); + if (!folder.IsUnavailable) + { + ToggleFolder(folder); + } e.Handled = true; } @@ -95,6 +98,7 @@ public void OpenFolder(FolderViewModel folder) if (subFolders == null) { + if (folder.IsUnavailable) return; subFolders = new ObservableCollection(GetSubFolders(folder)); folder.HasChildren = subFolders.Any(); folder.Children = subFolders; @@ -134,7 +138,7 @@ private IEnumerable GetSubFolders(FolderViewModel folder) Visible = true, Depth = folder.Depth + 1, Name = path.EndsWith("\\") ? "Root" : Path.GetFileName(path), - Path = path + Path = path, }); } @@ -142,7 +146,10 @@ private void Folder_OnDoubleClick(object sender, MouseButtonEventArgs e) { var folder = ((FolderViewModel)((Button)sender).DataContext); - ToggleFolder(folder); + if (!folder.IsUnavailable) + { + ToggleFolder(folder); + } e.Handled = true; } diff --git a/Diffusion.Toolkit/Themes/Common.xaml b/Diffusion.Toolkit/Themes/Common.xaml index 57322ca..c59aace 100644 --- a/Diffusion.Toolkit/Themes/Common.xaml +++ b/Diffusion.Toolkit/Themes/Common.xaml @@ -858,6 +858,9 @@ + + + diff --git a/Diffusion.Toolkit/UnavailableFilesModel.cs b/Diffusion.Toolkit/UnavailableFilesModel.cs new file mode 100644 index 0000000..46bc8e6 --- /dev/null +++ b/Diffusion.Toolkit/UnavailableFilesModel.cs @@ -0,0 +1,79 @@ +using System.Collections.Generic; +using System.Collections.ObjectModel; + +namespace Diffusion.Toolkit; + +public class ImageFileItem : BaseNotify +{ + private bool _isSelected; + + public bool IsSelected + { + get => _isSelected; + set => SetField(ref _isSelected, value); + } + + public string Path { get; set; } + public string DisplayPath { get; set; } + public bool IsUnavailable { get; set; } +} + +public class UnavailableFilesModel : BaseNotify +{ + private bool _useRootFolders; + private bool _useSpecificFolders; + private ObservableCollection _imagePaths; + private int _selectedIndex; + private bool _removeFromUnavailableRootFolders; + private bool _deleteImmediately; + private bool _markForDeletion; + private bool _isStartEnabled; + + public bool UseRootFolders + { + get => _useRootFolders; + set => SetField(ref _useRootFolders, value); + } + + public bool UseSpecificFolders + { + get => _useSpecificFolders; + set => SetField(ref _useSpecificFolders, value); + } + + public ObservableCollection ImagePaths + { + get => _imagePaths; + set => SetField(ref _imagePaths, value); + } + + public int SelectedIndex + { + get => _selectedIndex; + set => SetField(ref _selectedIndex, value); + } + + public bool RemoveFromUnavailableRootFolders + { + get => _removeFromUnavailableRootFolders; + set => SetField(ref _removeFromUnavailableRootFolders, value); + } + + public bool DeleteImmediately + { + get => _deleteImmediately; + set => SetField(ref _deleteImmediately, value); + } + + public bool MarkForDeletion + { + get => _markForDeletion; + set => SetField(ref _markForDeletion, value); + } + + public bool IsStartEnabled + { + get => _isStartEnabled; + set => SetField(ref _isStartEnabled, value); + } +} \ No newline at end of file diff --git a/Diffusion.Toolkit/UnavailableFilesWindow.xaml b/Diffusion.Toolkit/UnavailableFilesWindow.xaml new file mode 100644 index 0000000..24eaf44 --- /dev/null +++ b/Diffusion.Toolkit/UnavailableFilesWindow.xaml @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Diffusion.Toolkit/UnavailableFilesWindow.xaml.cs b/Diffusion.Toolkit/UnavailableFilesWindow.xaml.cs new file mode 100644 index 0000000..939f11e --- /dev/null +++ b/Diffusion.Toolkit/UnavailableFilesWindow.xaml.cs @@ -0,0 +1,80 @@ +using System; +using System.Collections.ObjectModel; +using System.ComponentModel; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Shapes; +using Diffusion.Database; + +namespace Diffusion.Toolkit +{ + /// + /// Interaction logic for ManageFilesWindow.xaml + /// + public partial class UnavailableFilesWindow : BorderlessWindow + { + private readonly DataStore _dataStore; + public UnavailableFilesModel Model { get; } + + public UnavailableFilesWindow(DataStore dataStore, Settings settings) + { + _dataStore = dataStore; + InitializeComponent(); + + Model = new UnavailableFilesModel(); + Model.DeleteImmediately = false; + Model.MarkForDeletion = false; + Model.RemoveFromUnavailableRootFolders = false; + Model.UseRootFolders = true; + + Model.ImagePaths = new ObservableCollection(settings.ImagePaths.Select(p => new ImageFileItem() + { + Path = p, + IsUnavailable = !Directory.Exists(p) + })); + + foreach (var item in Model.ImagePaths) + { + item.PropertyChanged += ItemOnPropertyChanged; + } + + Model.PropertyChanged += ModelOnPropertyChanged; + + DataContext = Model; + } + + private void ModelOnPropertyChanged(object? sender, PropertyChangedEventArgs e) + { + Model.IsStartEnabled = (Model.MarkForDeletion || Model.DeleteImmediately) && (Model.ImagePaths.Any(p => p.IsSelected)); + } + + private void ItemOnPropertyChanged(object? sender, PropertyChangedEventArgs e) + { + Model.IsStartEnabled = (Model.MarkForDeletion || Model.DeleteImmediately) && (Model.ImagePaths.Any(p => p.IsSelected)); + } + + private void OK_OnClick(object sender, RoutedEventArgs e) + { + if (Model.DeleteImmediately || Model.MarkForDeletion) + { + DialogResult = true; + Close(); + } + } + + private void Cancel_OnClick(object sender, RoutedEventArgs e) + { + DialogResult = false; + Close(); + } + } +}