mirror of
https://github.com/QL-Win/QuickLook.git
synced 2025-09-12 02:09:05 +00:00
async archive loading
This commit is contained in:
@@ -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)
|
||||
|
@@ -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>
|
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
@@ -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)
|
||||
|
@@ -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" />
|
||||
|
Reference in New Issue
Block a user