Added EPUB plugin

This commit is contained in:
Marco Gavelli
2018-07-16 09:46:52 +02:00
parent 0e28a4a006
commit a78428c698
61 changed files with 2533 additions and 0 deletions

View File

@@ -0,0 +1,45 @@
<UserControl x:Class="QuickLook.Plugin.EpubViewer.EpubViewerControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:QuickLook.Plugin.EpubViewer"
xmlns:htmlViewer="clr-namespace:TheArtOfDev.HtmlRenderer.WPF;assembly=HtmlRenderer.WPF"
mc:Ignorable="d"
d:DesignHeight="600" d:DesignWidth="800">
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/QuickLook.Common;component/Styles/MainWindowStyles.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<Grid KeyDown="Grid_KeyDown">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<TextBlock FontSize="14"
Text="{Binding Chapter, Mode=OneWay}"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Padding="4"/>
<StackPanel Orientation="Horizontal"
HorizontalAlignment="Right">
<Button VerticalAlignment="Stretch"
Margin="0,0,2,0"
Content="&lt;"
Click="PrevButton_Click"
Style="{DynamicResource CaptionTextButtonStyle}"/>
<Button VerticalAlignment="Stretch"
Content="&gt;"
Click="NextButton_Click"
Style="{DynamicResource CaptionTextButtonStyle}"/>
</StackPanel>
</Grid>
<htmlViewer:HtmlPanel x:Name="pagePanel"
Grid.Row="1"/>
</Grid>
</UserControl>

View File

@@ -0,0 +1,160 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
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.Navigation;
using System.Windows.Shapes;
using VersOne.Epub;
namespace QuickLook.Plugin.EpubViewer
{
/// <summary>
/// Logica di interazione per EpubViewerControl.xaml
/// </summary>
public partial class EpubViewerControl : UserControl, INotifyPropertyChanged
{
private EpubBookRef epubBook;
private List<EpubChapterRef> chapterRefs;
private int currChapter;
public event PropertyChangedEventHandler PropertyChanged;
public string Chapter => $"{chapterRefs?[currChapter].Title} ({currChapter + 1}/{chapterRefs?.Count})";
public EpubViewerControl()
{
InitializeComponent();
// design-time only
Resources.MergedDictionaries.Clear();
this.DataContext = this;
this.pagePanel.ImageLoad += PagePanel_ImageLoad;
}
private void PagePanel_ImageLoad(object sender, TheArtOfDev.HtmlRenderer.WPF.RoutedEvenArgs<TheArtOfDev.HtmlRenderer.Core.Entities.HtmlImageLoadEventArgs> args)
{
var key = this.epubBook.Content.Images.Keys.FirstOrDefault(k => args.Data.Src.IndexOf(k, StringComparison.InvariantCultureIgnoreCase) >= 0);
if (key != null)
{
var img = ImageFromStream(this.epubBook.Content.Images[key].GetContentStream());
args.Data.Callback(img);
args.Handled = true;
}
}
/// <summary>
/// Get image by resource key.
/// </summary>
public static BitmapImage ImageFromStream(Stream stream)
{
var bitmapImage = new BitmapImage();
bitmapImage.BeginInit();
bitmapImage.StreamSource = stream;
bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
bitmapImage.EndInit();
// bitmapImage.Freeze();
return bitmapImage;
}
internal void SetContent(EpubBookRef epubBook)
{
this.epubBook = epubBook;
this.chapterRefs = Flatten(epubBook.GetChapters());
this.currChapter = 0;
this.pagePanel.Text = chapterRefs[currChapter].ReadHtmlContent();
OnPropertyChanged("Chapter");
}
private List<EpubChapterRef> Flatten(List<EpubChapterRef> list)
{
return list.SelectMany(l => new EpubChapterRef[] { l }.Concat(Flatten(l.SubChapters))).ToList();
}
private void NextButton_Click(object sender, RoutedEventArgs e)
{
this.NextChapter();
}
private async void NextChapter()
{
try
{
this.currChapter = Math.Min(this.currChapter + 1, chapterRefs.Count - 1);
this.pagePanel.Text = await chapterRefs[currChapter].ReadHtmlContentAsync();
if (chapterRefs[currChapter].Anchor != null)
{
this.pagePanel.ScrollToElement(chapterRefs[currChapter].Anchor);
}
OnPropertyChanged("Chapter");
}
catch (Exception ex)
{
this.pagePanel.Text = "<div>Invalid chapter.</div>";
OnPropertyChanged("Chapter");
Debug.WriteLine(ex);
}
}
private void PrevButton_Click(object sender, RoutedEventArgs e)
{
this.PrevChapter();
}
private async void PrevChapter()
{
try
{
this.currChapter = Math.Max(this.currChapter - 1, 0);
this.pagePanel.Text = await chapterRefs[currChapter].ReadHtmlContentAsync();
if (chapterRefs[currChapter].Anchor != null)
{
this.pagePanel.ScrollToElement(chapterRefs[currChapter].Anchor);
}
OnPropertyChanged("Chapter");
}
catch (Exception ex)
{
Debug.WriteLine(ex);
this.pagePanel.Text = "<div>Invalid chapter.</div>";
OnPropertyChanged("Chapter");
}
}
// Create the OnPropertyChanged method to raise the event
protected void OnPropertyChanged(string name)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
private void Grid_KeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Left)
{
this.PrevChapter();
e.Handled = true;
}
else if (e.Key == Key.Right)
{
this.NextChapter();
e.Handled = true;
}
else
{
e.Handled = false;
}
}
}
}

View File

@@ -0,0 +1,67 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.ExceptionServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Threading;
using QuickLook.Common.Plugin;
using QuickLook.Plugin.HtmlViewer;
using VersOne.Epub;
namespace QuickLook.Plugin.EpubViewer
{
public class Plugin : IViewer
{
private EpubViewerControl _panel;
public int Priority => int.MaxValue;
public void Init()
{
}
public bool CanHandle(string path)
{
return !Directory.Exists(path) && new[] { ".epub" }.Any(path.ToLower().EndsWith);
}
public void Cleanup()
{
}
public void Prepare(string path, ContextObject context)
{
context.PreferredSize = new Size { Width = 1000, Height = 600 };
}
public void View(string path, ContextObject context)
{
_panel = new EpubViewerControl();
context.ViewerContent = _panel;
Exception exception = null;
_panel.Dispatcher.BeginInvoke(new Action(() =>
{
try
{
// Opens a book
EpubBookRef epubBook = EpubReader.OpenBook(path);
context.Title = epubBook.Title;
_panel.SetContent(epubBook);
context.IsBusy = false;
}
catch (Exception e)
{
exception = e;
}
}), DispatcherPriority.Loaded).Wait();
if (exception != null)
ExceptionDispatchInfo.Capture(exception).Throw();
}
}
}

View File

@@ -0,0 +1,34 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// Le informazioni generali relative a un assembly sono controllate dal seguente
// set di attributi. Modificare i valori di questi attributi per modificare le informazioni
// associate a un assembly.
[assembly: AssemblyTitle("QuickLook.Plugin.EpubViewer")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("QuickLook.Plugin.EpubViewer")]
[assembly: AssemblyCopyright("Copyright © 2018")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Se si imposta ComVisible su false, i tipi in questo assembly non saranno visibili
// ai componenti COM. Se è necessario accedere a un tipo in questo assembly da
// COM, impostare su true l'attributo ComVisible per tale tipo.
[assembly: ComVisible(false)]
// Se il progetto viene esposto a COM, il GUID seguente verrà utilizzato come ID della libreria dei tipi
[assembly: Guid("260c9e70-0582-471f-bfb5-022cfe7984c8")]
// Le informazioni sulla versione di un assembly sono costituite dai seguenti quattro valori:
//
// Versione principale
// Versione secondaria
// Numero di build
// Revisione
//
// È possibile specificare tutti i valori oppure impostare valori predefiniti per i numeri relativi alla revisione e alla build
// usando l'asterisco '*' come illustrato di seguito:
// [assembly: AssemblyVersion("1.0.*")]

View File

@@ -0,0 +1,89 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{260C9E70-0582-471F-BFB5-022CFE7984C8}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>QuickLook.Plugin.EpubViewer</RootNamespace>
<AssemblyName>QuickLook.Plugin.EpubViewer</AssemblyName>
<TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>..\..\Build\Debug\QuickLook.Plugin\QuickLook.Plugin.EpubViewer\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="HtmlRenderer, Version=1.5.0.6, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\packages\HtmlRenderer.Core.1.5.0.6\lib\net45\HtmlRenderer.dll</HintPath>
</Reference>
<Reference Include="HtmlRenderer.WPF, Version=1.5.0.6, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\packages\HtmlRenderer.WPF.1.5.0.6\lib\net45\HtmlRenderer.WPF.dll</HintPath>
</Reference>
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xaml" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
<Reference Include="WindowsBase" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\..\GitVersion.cs">
<Link>Properties\GitVersion.cs</Link>
</Compile>
<Compile Include="EpubViewerControl.xaml.cs">
<DependentUpon>EpubViewerControl.xaml</DependentUpon>
</Compile>
<Compile Include="Plugin.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\QuickLook.Common\QuickLook.Common.csproj">
<Project>{85fdd6ba-871d-46c8-bd64-f6bb0cb5ea95}</Project>
<Name>QuickLook.Common</Name>
</ProjectReference>
<ProjectReference Include="..\QuickLook.Plugin.HtmlViewer\QuickLook.Plugin.HtmlViewer.csproj">
<Project>{ce22a1f3-7f2c-4ec8-bfde-b58d0eb625fc}</Project>
<Name>QuickLook.Plugin.HtmlViewer</Name>
</ProjectReference>
<ProjectReference Include="..\VersOne.Epub\VersOne.Epub.csproj">
<Project>{8bfc120e-7e59-437c-9196-595ab00025e1}</Project>
<Name>VersOne.Epub</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Page Include="EpubViewerControl.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="HtmlRenderer.Core" version="1.5.0.6" targetFramework="net461" />
<package id="HtmlRenderer.WPF" version="1.5.0.6" targetFramework="net461" />
</packages>