diff --git a/QuickLook.Plugin/QuickLook.Plugin.ArchiveViewer/ArchiveFileListView.xaml.cs b/QuickLook.Plugin/QuickLook.Plugin.ArchiveViewer/ArchiveFileListView.xaml.cs index 8f4afea..1298514 100644 --- a/QuickLook.Plugin/QuickLook.Plugin.ArchiveViewer/ArchiveFileListView.xaml.cs +++ b/QuickLook.Plugin/QuickLook.Plugin.ArchiveViewer/ArchiveFileListView.xaml.cs @@ -46,7 +46,7 @@ namespace QuickLook.Plugin.ArchiveViewer { treeGrid.DataContext = context; - treeView.Loaded += (sender, e) => + treeView.LayoutUpdated += (sender, e) => { // return when empty if (treeView.Items.Count == 0) diff --git a/QuickLook.Plugin/QuickLook.Plugin.ArchiveViewer/ArchiveInfoPanel.xaml b/QuickLook.Plugin/QuickLook.Plugin.ArchiveViewer/ArchiveInfoPanel.xaml index 8689762..cdcfd86 100644 --- a/QuickLook.Plugin/QuickLook.Plugin.ArchiveViewer/ArchiveInfoPanel.xaml +++ b/QuickLook.Plugin/QuickLook.Plugin.ArchiveViewer/ArchiveInfoPanel.xaml @@ -7,21 +7,42 @@ mc:Ignorable="d" x:Name="infoPanel" d:DesignHeight="600" d:DesignWidth="800"> + + + + + + + + + + - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/QuickLook.Plugin/QuickLook.Plugin.ArchiveViewer/ArchiveInfoPanel.xaml.cs b/QuickLook.Plugin/QuickLook.Plugin.ArchiveViewer/ArchiveInfoPanel.xaml.cs index 02643d8..c999dc2 100644 --- a/QuickLook.Plugin/QuickLook.Plugin.ArchiveViewer/ArchiveInfoPanel.xaml.cs +++ b/QuickLook.Plugin/QuickLook.Plugin.ArchiveViewer/ArchiveInfoPanel.xaml.cs @@ -17,9 +17,13 @@ using System; using System.Collections.Generic; +using System.ComponentModel; using System.IO; using System.Linq; +using System.Runtime.CompilerServices; +using System.Threading.Tasks; using System.Windows.Controls; +using QuickLook.Annotations; using QuickLook.ExtensionMethods; using SharpCompress.Archives; using SharpCompress.Common; @@ -30,9 +34,11 @@ namespace QuickLook.Plugin.ArchiveViewer /// /// Interaction logic for ArchiveInfoPanel.xaml /// - public partial class ArchiveInfoPanel : UserControl, IDisposable + public partial class ArchiveInfoPanel : UserControl, IDisposable, INotifyPropertyChanged { private readonly Dictionary _fileEntries = new Dictionary(); + private bool _disposed; + private double _loadPercent; private ulong _totalZippedSize; private string _type; @@ -40,58 +46,88 @@ namespace QuickLook.Plugin.ArchiveViewer { InitializeComponent(); - LoadArchive(path); + // design-time only + Resources.MergedDictionaries.Clear(); - fileListView.SetDataContext(_fileEntries[""].Children.Keys); + BeginLoadArchive(path); + } + + public double LoadPercent + { + get => _loadPercent; + private set + { + if (value == _loadPercent) return; + _loadPercent = value; + OnPropertyChanged(); + } } public void Dispose() { GC.SuppressFinalize(this); - _fileEntries.Clear(); + _disposed = true; + fileListView.Dispose(); } + public event PropertyChangedEventHandler PropertyChanged; + ~ArchiveInfoPanel() { Dispose(); } - private void LoadArchive(string path) + private void BeginLoadArchive(string path) { - _totalZippedSize = (ulong) new FileInfo(path).Length; - - LoadItemsFromArchive(path); - - var folders = -1; // do not count root node - var files = 0; - ulong sizeU = 0L; - _fileEntries.ForEach(e => + new Task(() => { - if (e.Value.IsFolder) - folders++; + _totalZippedSize = (ulong) new FileInfo(path).Length; + + var root = new ArchiveFileEntry(Path.GetFileName(path), true); + _fileEntries.Add("", root); + + LoadItemsFromArchive(path); + + var folders = -1; // do not count root node + var files = 0; + ulong sizeU = 0L; + _fileEntries.ForEach(e => + { + if (e.Value.IsFolder) + folders++; + else + files++; + + sizeU += e.Value.Size; + }); + + string t; + var d = folders != 0 ? $"{folders} folders" : string.Empty; + var f = files != 0 ? $"{files} files" : string.Empty; + if (!string.IsNullOrEmpty(d) && !string.IsNullOrEmpty(f)) + t = $", {d} and {f}"; + else if (string.IsNullOrEmpty(d) && string.IsNullOrEmpty(f)) + t = string.Empty; else - files++; + t = $", {d}{f}"; - sizeU += e.Value.Size; - }); + Dispatcher.Invoke(() => + { + if (_disposed) + return; - string t; - var d = folders != 0 ? $"{folders} folders" : string.Empty; - var f = files != 0 ? $"{files} files" : string.Empty; - if (!string.IsNullOrEmpty(d) && !string.IsNullOrEmpty(f)) - t = $", {d} and {f}"; - else if (string.IsNullOrEmpty(d) && string.IsNullOrEmpty(f)) - t = string.Empty; - else - t = $", {d}{f}"; + fileListView.SetDataContext(_fileEntries[""].Children.Keys); + archiveCount.Content = + $"{_type} archive{t}"; + archiveSizeC.Content = + $"Compressed size {((long) _totalZippedSize).ToPrettySize(2)}"; + archiveSizeU.Content = $"Uncompressed size {((long) sizeU).ToPrettySize(2)}"; + }); - archiveCount.Content = - $"{_type} archive{t}"; - archiveSizeC.Content = - $"Compressed size {((long) _totalZippedSize).ToPrettySize(2)}"; - archiveSizeU.Content = $"Uncompressed size {((long) sizeU).ToPrettySize(2)}"; + LoadPercent = 100d; + }).Start(); } private void LoadItemsFromArchive(string path) @@ -107,11 +143,13 @@ namespace QuickLook.Plugin.ArchiveViewer _type = reader.ArchiveType.ToString(); - var root = new ArchiveFileEntry(Path.GetFileName(path), true); - _fileEntries.Add("", root); - while (reader.MoveToNextEntry()) + { + if (_disposed) + return; + LoadPercent = 100d * stream.Position / stream.Length; ProcessByLevel(reader.Entry); + } } else { @@ -119,11 +157,13 @@ namespace QuickLook.Plugin.ArchiveViewer _type = archive.Type.ToString(); - var root = new ArchiveFileEntry(Path.GetFileName(path), true); - _fileEntries.Add("", root); - foreach (var entry in archive.Entries) + { + if (_disposed) + return; + LoadPercent = 100d * stream.Position / stream.Length; ProcessByLevel(entry); + } } } } @@ -140,7 +180,7 @@ namespace QuickLook.Plugin.ArchiveViewer if (_fileEntries.ContainsKey(f)) return; - _fileEntries.TryGetValue(GetDirectoryName(f), out ArchiveFileEntry parent); + _fileEntries.TryGetValue(GetDirectoryName(f), out var parent); var afe = new ArchiveFileEntry(Path.GetFileName(f), true, parent); @@ -152,7 +192,7 @@ namespace QuickLook.Plugin.ArchiveViewer { var file = pf.Last(); - _fileEntries.TryGetValue(GetDirectoryName(file), out ArchiveFileEntry parent); + _fileEntries.TryGetValue(GetDirectoryName(file), out var parent); _fileEntries.Add(file, new ArchiveFileEntry(Path.GetFileName(entry.Key), false, parent) { @@ -179,5 +219,11 @@ namespace QuickLook.Plugin.ArchiveViewer return frags.Select((s, i) => frags.Take(i + 1).Aggregate((a, b) => a + "\\" + b)).ToArray(); } + + [NotifyPropertyChangedInvocator] + protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } } } \ No newline at end of file diff --git a/QuickLook.Plugin/QuickLook.Plugin.ArchiveViewer/Converters.cs b/QuickLook.Plugin/QuickLook.Plugin.ArchiveViewer/Converters.cs index ba6b58e..1a6ea10 100644 --- a/QuickLook.Plugin/QuickLook.Plugin.ArchiveViewer/Converters.cs +++ b/QuickLook.Plugin/QuickLook.Plugin.ArchiveViewer/Converters.cs @@ -23,6 +23,40 @@ using QuickLook.ExtensionMethods; namespace QuickLook.Plugin.ArchiveViewer { + public class Percent100ToVisibilityVisibleConverter : DependencyObject, IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + if (value == null) + value = 0; + + var percent = (double) value; + return Math.Abs(percent - 100) < 0.00001 ? Visibility.Visible : Visibility.Collapsed; + } + + public object ConvertBack(object value, Type targetTypes, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } + + public class Percent100ToVisibilityCollapsedConverter : DependencyObject, IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + if (value == null) + value = 0; + + var percent = (double) value; + return Math.Abs(percent - 100) < 0.00001 ? Visibility.Collapsed : Visibility.Visible; + } + + public object ConvertBack(object value, Type targetTypes, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } + public class LevelToIndentConverter : DependencyObject, IMultiValueConverter { public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) diff --git a/QuickLook.Plugin/QuickLook.Plugin.ArchiveViewer/packages.config b/QuickLook.Plugin/QuickLook.Plugin.ArchiveViewer/packages.config index 910e51e..dc55c71 100644 --- a/QuickLook.Plugin/QuickLook.Plugin.ArchiveViewer/packages.config +++ b/QuickLook.Plugin/QuickLook.Plugin.ArchiveViewer/packages.config @@ -1,4 +1,5 @@  +