async archive loading

This commit is contained in:
Paddy Xu
2017-12-22 13:19:49 +02:00
parent dedac98702
commit 97b749e64f
5 changed files with 157 additions and 55 deletions

View File

@@ -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)

View File

@@ -7,7 +7,27 @@
mc:Ignorable="d"
x:Name="infoPanel"
d:DesignHeight="600" d:DesignWidth="800">
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<!-- only for design -->
<ResourceDictionary Source="/QuickLook;component/Styles/MainWindowStyles.xaml" />
</ResourceDictionary.MergedDictionaries>
<local:Percent100ToVisibilityVisibleConverter x:Key="Percent100ToVisibilityVisibleConverter" />
<local:Percent100ToVisibilityCollapsedConverter x:Key="Percent100ToVisibilityCollapsedConverter" />
</ResourceDictionary>
</UserControl.Resources>
<Grid>
<Grid ZIndex="9999"
Visibility="{Binding ElementName=infoPanel, Path=LoadPercent, Mode=OneWay, Converter={StaticResource Percent100ToVisibilityCollapsedConverter}}">
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<Label FontSize="14" HorizontalAlignment="Center">Loading archive ...</Label>
<ProgressBar Height="13" Width="150"
Value="{Binding ElementName=infoPanel, Path=LoadPercent, Mode=OneWay}" />
</StackPanel>
</Grid>
<Grid
Visibility="{Binding ElementName=infoPanel, Path=LoadPercent, Mode=OneWay, Converter={StaticResource Percent100ToVisibilityVisibleConverter}}">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="30" />
@@ -19,9 +39,10 @@
<ColumnDefinition Width="30*" />
<ColumnDefinition Width="30*" />
</Grid.ColumnDefinitions>
<Label x:Name="archiveCount" Grid.Column="0" HorizontalAlignment="Center" VerticalAlignment="Center">9 folders and 10 files, solid, password-protected</Label>
<Label x:Name="archiveSizeC" Grid.Column="1" HorizontalAlignment="Center" VerticalAlignment="Center">Compressed size 9999 bytes</Label>
<Label x:Name="archiveSizeU" Grid.Column="2" HorizontalAlignment="Center" VerticalAlignment="Center">Uncompressed size 99999 bytes</Label>
<Label x:Name="archiveCount" Grid.Column="0" HorizontalAlignment="Center" VerticalAlignment="Center">0 folders and 0 files, solid, password-protected</Label>
<Label x:Name="archiveSizeC" Grid.Column="1" HorizontalAlignment="Center" VerticalAlignment="Center">Compressed size 0 bytes</Label>
<Label x:Name="archiveSizeU" Grid.Column="2" HorizontalAlignment="Center" VerticalAlignment="Center">Uncompressed size 0 bytes</Label>
</Grid>
</Grid>
</Grid>
</UserControl>

View File

@@ -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
/// <summary>
/// Interaction logic for ArchiveInfoPanel.xaml
/// </summary>
public partial class ArchiveInfoPanel : UserControl, IDisposable
public partial class ArchiveInfoPanel : UserControl, IDisposable, INotifyPropertyChanged
{
private readonly Dictionary<string, ArchiveFileEntry> _fileEntries = new Dictionary<string, ArchiveFileEntry>();
private bool _disposed;
private double _loadPercent;
private ulong _totalZippedSize;
private string _type;
@@ -40,28 +46,48 @@ 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)
{
new Task(() =>
{
_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
@@ -87,11 +113,21 @@ namespace QuickLook.Plugin.ArchiveViewer
else
t = $", {d}{f}";
Dispatcher.Invoke(() =>
{
if (_disposed)
return;
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)}";
});
LoadPercent = 100d;
}).Start();
}
private void LoadItemsFromArchive(string path)
@@ -107,26 +143,30 @@ 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
{
var archive = ArchiveFactory.Open(stream, new ChardetReaderOptions());
_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);
}
}
}
}
private void ProcessByLevel(IEntry 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));
}
}
}

View File

@@ -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)

View File

@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="SharpCompress" version="0.18.2" targetFramework="net462" />
<package id="UTF.Unknown" version="1.0.0-beta1" targetFramework="net462" />