using System.Collections.ObjectModel; using System.Collections.Specialized; using System.ComponentModel; using System.IO; using System.Runtime.CompilerServices; namespace Futonizer.Models; /// /// The four states shown as an icon in the file queue list. /// public enum FileLoadState { /// Currently being scanned with mkvmerge -J. Loading, /// Scan finished (or failed) but track selection isn't evaluated as correct/incorrect yet. Loaded, /// Exactly one audio track and one subtitle track are selected to be kept. Correct, /// Anything other than exactly one audio + one subtitle selected. Incorrect, } /// /// Represents one MKV file in the processing queue. /// public class QueuedFileItem : INotifyPropertyChanged { private string _status = string.Empty; private bool _isScanning; private bool _hasError; public string FilePath { get; } public string FileName => Path.GetFileName(FilePath); public ObservableCollection Tracks { get; } = new(); public string Status { get => _status; set { _status = value; OnPropertyChanged(); } } public bool IsScanning { get => _isScanning; set { _isScanning = value; OnPropertyChanged(); NotifyLoadState(); } } public bool HasError { get => _hasError; set { _hasError = value; OnPropertyChanged(); NotifyLoadState(); } } public FileLoadState LoadState { get { if (_isScanning) return FileLoadState.Loading; if (_hasError || Tracks.Count == 0) return FileLoadState.Loaded; int audioSelected = Tracks.Count(t => t.Type == "audio" && t.Copy); int subtitleSelected = Tracks.Count(t => t.Type == "subtitles" && t.Copy); return audioSelected == 1 && subtitleSelected == 1 ? FileLoadState.Correct : FileLoadState.Incorrect; } } public bool IsLoading => LoadState == FileLoadState.Loading; public bool IsLoadedNeutral => LoadState == FileLoadState.Loaded; public bool IsCorrect => LoadState == FileLoadState.Correct; public bool IsIncorrect => LoadState == FileLoadState.Incorrect; public QueuedFileItem(string filePath) { FilePath = filePath; Tracks.CollectionChanged += OnTracksChanged; } private void OnTracksChanged(object? sender, NotifyCollectionChangedEventArgs e) { if (e.NewItems != null) { foreach (TrackItem t in e.NewItems) t.PropertyChanged += TrackPropertyChanged; } if (e.OldItems != null) { foreach (TrackItem t in e.OldItems) t.PropertyChanged -= TrackPropertyChanged; } NotifyLoadState(); } private void TrackPropertyChanged(object? sender, PropertyChangedEventArgs e) { if (e.PropertyName == nameof(TrackItem.Copy)) NotifyLoadState(); } private void NotifyLoadState() { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(LoadState))); PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsLoading))); PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsLoadedNeutral))); PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsCorrect))); PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsIncorrect))); } public event PropertyChangedEventHandler? PropertyChanged; private void OnPropertyChanged([CallerMemberName] string? name = null) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name)); }